范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

使用shell,python,go来实现ansible的自定义模块

  一、自定义模块运行原理 二、自定义模块实战 2.1 shell方式 2.2 python方式 2.3 golang方式 三、测试验证 3.1 shell方式验证 3.2 python方式验证 3.3 golang方式验证
  ansible已经提供了非常多的模块,涵盖了系统、网络、数据库、容器、以及其他的方方面面的领域,几乎可以不用重复造轮子,只要你能想的到的,官方基本上都已经提供了,可以说极大的提高了我们的自动化效率,但是总会有些情况无法满足我们的需求,因此我们需要学会如何去编写一个自定义的模块
  在下文的介绍中,会介绍下自定义模块的工作原理,分别以 shell , python , golang 等来实现自定义模块,通过这三种写法来实现修改主机的hosts文件的功能。 一、自定义模块运行原理
  首先我们可以通过修改配置文件来设置自定义模块的位置,默认配置文件位置: /etc/ansible/ansible.cfg ,例如如下配置: [defaults]  # some basic default values... library        = /opt/workspace/ansible/library  # 此目录可以随意设置
  这里我通过修改 ansible 的配置文件,来配置我们存放自定义模块的目录,也就是说我们所编写的自定义模块,可以存放至此目录中,在使用自定义模块时就会从此目录进行拷贝 ,注意是拷贝 。
  下面我们在 /opt/workspace/ansible/library 这个目录中编写一个shell 脚本,看看ansible在运行时做了什么? #!/bin/bash  echo "hello world"
  保存为文件: test_mod.sh ,此时我们的模块名称就叫做:test_mod ,接下来我们以ad-hoc 的方式运行下这个模块,看看会发生什么? # ansible localhost -m test_mod -a "name=tom age=18" localhost | FAILED! => {     "changed": false,      "module_stderr": "",      "module_stdout": "hello world ",      "msg": "MODULE FAILURE See stdout/stderr for the exact error",      "rc": 0 }
  可以看到,我们在通过 ad-hoc 执行模块时,传入了两个参数:name 和age ,这两个参数是我随意设置的,执行之后ansible 输出了一段结果,看格式应该是一个json ,其中module_stdout 输出了我们脚本里的命令输出,msg 却输出了一段内容:MODULE FAILURE See stdout/stderr for the exact error ,关于为什么会输出这个错误,这里先不说明,到后面大家就会明白。
  接下来,我们开启 debug 来看看会发生什么?
  总结大概经历了这么几个步骤:  在被控端创建临时目录,用于存放自定义模块、以及传入的参数  将自定义模块拷贝到被控端  将传入的参数拷贝到被控端  给被控端的自定义模块和传入的参数设置可执行权限  以传惨的方式在被控端执行自定义模块  删除临时目录
  看到这里你应该就大概明白了原来 ansible 其实就把我们写的脚本拷贝到了目标机器上执行而已。
  回到上面那个报错: MODULE FAILURE See stdout/stderr for the exact error ,这个报错实际上是因为我们没有输出内容到标准输出或标准错误,接下来我们改下test_mod.sh 这个脚本,再来执行下试试 #!/bin/bash  _stdout() {     local changed=$1     local failed=$2     local rc=$3     local msg=$4     cat < {     "changed": true,      "msg": "sucess",      "rc": 0 }
  总结下如何自定义一个模块:  编写代码逻辑实现我们所需的功能  代码的执行结果必须输出一个json,其中字段需要包括: changed , failed , rc , msg 等字段,当然不是必须的。 编写完成后,文件名就是我们的模块名称  使用模块时,设置的参数会以json字符串的方式传给对应的模块,也就是说代码在去执行时,需要解析json内容,来获取所传入的参数内容  二、自定义模块实战
  需求:修改本地hosts文件,来添加自定义的解析,要求传入两个参数,分别为 host 和domain 表示要设置的ip地址和主机名称 2.1 shell方式模块(文件)名称: set_hosts_by_shell  #!/bin/bash # 导入变量文件 source $1   # 定义一个全局的输出格式 _stdout() {     local changed=$1     local failed=$2     local rc=$3     local msg=$4     cat << EOF     {         "changed": ${changed},         "failed": ${failed},         "rc": ${rc},         "msg": "${msg}"     } EOF }   # 检查传参,没有就报异常 _check_args() {    if [[ x"$host" == x ]];then        _stdout false true 1 "Missing args host"        exit 1    fi    if [[ x"$domain" == x ]];then        _stdout false true 1 "Missing args domain"        exit 1    fi }   # 检查是否已经存在行,并给出返回码 _check_line() {     grep -Eo "$hosts+$domain" /etc/hosts >/dev/null     return $? }   # 开始添加行 add_line() {     _check_args     _check_line     res=$?     # 为了幂等,已存在的行不再添加     if [[ $res -eq 1 ]];then         echo "$host $domain" >> /etc/hosts         _stdout true false 0 "Add $host $domain"     elif [[ $res -eq 0 ]];then         _stdout false false 0 "$host $domain existing!"     fi }   # 执行函数 add_line
  在脚本的开头我执行了一个 source $1 ,这个是因为执行脚本传参的时候,在shell中会以类似kv的方式传入,也就是说内容类似于: domain=www.baidu.com host=1.1.1.1 a=xxxx c=adsasda
  所以当我执行 source 的时候,就会把这些参数注册到环境变量中。 2.2 python方式模块名称: set_hosts_by_python  #!/usr/bin/env python   from __future__ import absolute_import, pision, print_function from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.common.text.converters import to_native   def add_lines(module, host, domain):     option_file = "/etc/hosts"     option_content = host + " " + domain     with open(option_file, "r+") as f:         contents = f.read()          if option_content in contents:             module.exit_json(changed=False, stdout="%s 已存在,无需添加" % option_content)         else:             f.write("%s " % option_content)             module.exit_json(changed=True, stdout="%s 已添加" % option_content)     return   def main():     module = AnsibleModule(         argument_spec=dict(             host=dict(type="str", required=True),             domain=dict(type="str", required=True),         )     )     host = module.params["host"]     domain = module.params["domain"]      try:         add_lines(module, host, domain)     except Exception as e:         module.fail_json(msg="Exception error: %s" % to_native(e))   if __name__ == "__main__":     main()
  通过python来实现时,ansible提供了已经封装好的类 AnsibleModule ,通过实例化这个类,可以将所需的参数传入进去,同时输出执行结果时也提供了module.exit_json 和module.fail_json 的方法 2.3 golang方式模块名称: set_hosts_by_go  package main  import (  "bufio"  "bytes"  "encoding/json"  "fmt"  "io"  "io/ioutil"  "os"  "strings" )  type ModuleResult struct {  Changed bool   `json:"changed"`  Fail    bool   `json:"fail"`  Msg     string `json:"msg"`  RC      int    `json:"rc"` }  // 定义要传入的参数 type AllArgs struct {  Domain string `json:"domain"`  Host   string `json:"host"` }  func addLines(host, domain string) (string, error) {  filename := "/etc/hosts"  content := host + " " + domain  data, err := ioutil.ReadFile(filename)  if err != nil {   return "", err  }  isExist := false   scanner := bufio.NewScanner(bytes.NewReader(data))   for scanner.Scan() {   line := scanner.Text()   if strings.Contains(line, content) {    isExist = true    return "已存在,无需添加", nil   }  }  if !isExist {   f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY, 0644)   if err != nil {    return "未知错误", err   }   defer f.Close()   if _, err := f.WriteString(content + " "); err != nil {    return "write error", err   }  }  return "write sucess", nil }  func outPut(module ModuleResult, status int) {  module.RC = status  var out io.Writer  if status == 0 {   out = os.Stdout  } else {   out = os.Stderr  }  contents, _ := json.Marshal(module)  fmt.Fprint(out, string(contents))  os.Exit(status) }  func parseArg(module ModuleResult, f string) (args AllArgs) {  fobj, err := os.Open(f)  if err != nil {   module.Changed = false   module.Fail = true   module.Msg = ""   outPut(module, 2)  }   defer fobj.Close()   content, err := ioutil.ReadAll(fobj)   if err != nil {   module.Changed = false   module.Fail = true   module.Msg = ""   outPut(module, 2)  }   err = json.Unmarshal(content, &args)  if err != nil {   module.Changed = false   module.Fail = true   module.Msg = ""   outPut(module, 2)  }  return }  func main() {  module := ModuleResult{}  var argfile = os.Args[1]  var parsearg = parseArg(module, argfile)  host := parsearg.Host  domain := parsearg.Domain   res, err := addLines(host, domain)  if err != nil {   module.Changed = false   module.Fail = true   module.Msg = "添加失败 " + err.Error()   outPut(module, 2)  }  module.Changed = true  module.Fail = false  module.Msg = res  outPut(module, 0) }
  注意在使用 go 语言编写自定义模块时,不可以使用打印,例如使用fmt.Pringln 来打印一些值,这种会造成执行中断,因为这会误导ansible,以为该模块已经执行完成,因为ansible会捕获标准输出。 三、测试验证
  下面分别来验证下分别使用 shell , python , golang 来实现的自定义模块是否能完成我们的需求 3.1 shell方式验证
  3.2 python方式验证
  3.3 golang方式验证
  在使用golang编写模块时,需要先编译成二进制文件
  欢迎关注公众号:feelwow

200万吨增至400万吨!缅甸计划三年内将大米出口翻一番新加坡联合早报7月6日援引彭博报道,缅甸大米联合会主席叶敏昂说,缅甸已经设定目标,通过专注于更高质量的品种,在三年内将大米出口翻一番。缅甸计划在三年内将大米出口翻一番图源参考消息网6月新能源车销量公布,比亚迪势不可挡,蔚小理再创新高?6月份经历了疫情的好转后,销量数据格外引人关注2022年已正式进入下半年,各大新能源车企纷纷亮出了上个月的成绩单。整体来说,得益于疫情的有效控制和各地的政策激励,汽车行业开始呈现明江苏经济总量超韩国了,看下江苏制造业的结构我们都知道我国的广东省经济总量已经超过韩国了,但是2021年我国江苏省的经济总量也超过了韩国,韩国在2021年的经济总量接近1。8万亿美元,而江苏省的经济总量为全年实现116364三星电子将发二季度财报预计利润涨15。6芯片大赚?CNMO新闻据韩联社报道,三星电子预计将于本周晚些时候(很有可能是本周四)发布其第二季度财务报告,有分析师预计其营业利润将较去年同期增长15。6。三星据金融数据公司Infomax估2022年最佳直面屏手机排行这三款堪称行业天花板,直屏才是优选虽然说现如今很多手机的旗舰机都是采用的曲面屏设计,但是对于很多喜欢直屏手机的朋友来讲,直面屏手机体验才完美。但是面对曲面屏当道的手机市场,买到心仪的直面屏手机却是一个很难的问题,今360扫地机器人X95打造智慧避障系统由于生活和工作节奏的加快,扫地机器人是家庭清洁的首选。与此同时备受关注的是在购买扫地机器人时对性能的不了解以及不知道哪个牌子好成为了消费者头疼的主要问题。2020年6月,360推出2021年中国内容机构(MCN)行业市场分析,商业变现形式单一一内容机构(MCN)行业概述1定义MCN(MultiChannelNetwork),即多频道网络,一种多网络的产品形态,是一种新的运作模式。这种模式将不同和内容的(专业生产内容)联遇事的处理方式面缓声静心安稳得住脚,收得住音,静得下心。有句话说泰山崩于前而色不变,黄河决于顶而面不惊。遇事的处理方式就是稳得住脚,收得住音,静得下心。凡事首要面缓看过一句话说生活中的10是由发生在一个人身创维55A5Pro智慧屏客厅有它才有档次客厅配上一台什么样的电视才显得更有档次呢?如果你还犹豫不定,不妨看看笔者给大家推荐的这款创维55A5Pro智慧屏。外观上,创维55A5Pro智慧屏采用了全景屏工艺设计,兼具力学工程主播玩游戏开G巅峰!不仅国标是P的,局内数据也靠P某牙王者荣耀主播耀扬是出名的情感大师,他曾用帮助网友们解决不少与王者荣耀相关的情感问题,并以此收获不少粉丝和人气,一跃成为某牙王者荣耀版块的大主播之一。虽然挂着情感大师的名头,但耀国务院拓展电子营业执照在纳税招投标等高频服务领域应用,选择部分城市探索居民电子身份证试点每经记者李明明每经编辑陈旭7月6日,国务院总理李克强主持召开国务院常务会议,部署中央预算执行和其他财政收支审计查出问题整改工作确定有序推进电子证照应用的举措,激发市场主体活力。随着
科尔在这个联盟我们随时都可能要走人除了库里直播吧10月22日讯科尔在今日赛前接受了媒体群访,期间被问到了球队未来的阵容构建。我们就是专注于明天,我们会庆祝个人的成就,所以当这些家伙签下续约合同时,我们会庆祝一下,因为这对他辛有志积极布局人才培育第三届百城千家敬老所万人爱心公益活动人才对于一个行业的未来发展来说至关重要,尤其是对直播电商行业这种新兴业态来说,无论人才数量还是质量,缺口都较大。如何规范化培养和储备人才是行业内外相关人员都在思考的问题。在行业头部李宇春金钱也换不来健康娱评大赏近日,李宇春在一档电视节目中,自爆已经患上强直性脊柱炎,最严重的时候每天出行都需要坐轮椅。她在接受采访时说到世界上最贵的品牌汽车躺在我的车库里,但我必须坐在轮椅上,我的房子孩子叛逆装病逃学玩手机成瘾可能是患了抑郁症北京大学第六医院儿童病房里,孩子们正在医护人员的带领下进行集体治疗。这里收治的孩子,最小的只有4岁,最大的不满18岁,其中以1216岁处于青春期的孩子居多,他们大都患有严重的精神障油价10月25日,全国各地9295号汽油价格10月25日0时,国内成品油价格再次上调,具体为国内汽油价格每吨提高185元柴油价格每吨提高175元。折合成升,全国平均来看,92号汽油价格每升上调0。15元,95号汽油0号柴油同高秀敏去世后,承诺帮她养女儿的赵本山,17年过去,做到了吗?2005年,46岁的演员高秀敏因突发心脏病离世。在她的葬礼上有两个男人哭得不能自己,一个是伴多年的亲密爱人何庆魁。另一个就是昔日铁三角的搭档赵本山。面对高秀敏的遗像,两个男人同时承超级新人仅出场4分钟,北京男篮要放弃幻想,球队需要培养新人北京时间10月25日,CBA联赛继续进行。其中的一场比赛中,北京首钢男篮7571惊险战胜青岛男篮。整场比赛,两支球队都是处于均势之中。最终,北京首钢男篮还是依靠出色的防守能力限制住内河运输开启纯电动时代!江苏这样打开船舶产业发展新空间全国首艘120标箱纯电动内河集装箱船江远百合号不久前在太仓投用以来,一直往返于太仓港和京杭运河苏州工业园区港间。作为航运新历史的书写者之一,船长何广科兴奋地表示,电动船零排放零污染花开不止在春天在人们的眼中,春天是百花齐放争奇斗艳,是万物复苏,欣欣向荣。可它们不知道的是花开不止在春天,成功亦不止在舞台。人们常说,大学,是梦开始的地方。它奠定了我们闯荡人生的基石,架起了我们UEFI的诞生与优势UEFI的诞生随着CPU及其他硬件设备的技术革新,CPU和操作系统已支持到64位,而BIOS却还停留在16位主板上更加丰富多样的扩展设备,也让BIOS愈加无能为力,使得硬件无法完成金球奖得分公布本泽马549分领先优势非历史最大C罗0分北京时间本周二,2022年金球奖颁奖礼在法国巴黎进行,皇家马德里前锋本泽马毫无悬念地获得了金球奖。日前,法国足球公布了金球奖的得分情况,本泽马一共得到549分,比第二名马内高出35