接上篇,完成了Playbook的初级入门,但还是没有完全解决痛点问题,说实话,上篇的那个小feature用Playbook实现有点大材小用了。

不过问题还是要解决,既然已经入了歧途,就要一条路走到黑(这什么逻辑??)。所以为了处理这样一个bug,我引入了另一个bug——用shell写个脚本,进一步实现配置自动化。

本篇旨在验证通过运行shell脚本调用Playbook,在有交互的情况下实现上篇中基于Playbook进行指定IP段计费功能配置下发功能。

环境

Centos7(Ansible server)

Ansible-Playbook

过程

确定shell结构

首先确定shell要实现的功能:此case需要终端与使用者交互,使用者通过shell输入IP地址,shell将IP地址传给Playbook。

那么,shell里需要体现交互的过程,需要将用户输入的IP转化为内部变量,需要判断IP地址是否合法,如果不合法,需要做出响应。

如果IP地址内部检测合法,下一步则需要将地址变量传给Playbook后执行剧本并反馈执行结果,完活。

所以实现这个Feature的难点在IP地址的输入与检测,还有逻辑结构的建立。

好在网上一大把现成的函数,剩下的工作就是把网上的代码拿过来改吧改吧粘合在一起,然后写个逻辑结构就好了。

shell的各个功能模块

读取输入IP

可以通过 shell内置的 read 实现。

用户通过IO设备(键盘)输入的参数,可以通过read获取并传递给内置变量,这些变量和shell内部的变量没有区别。

read在不加参数的情况下默认可传递一个参数到变量,通过-p参数,可以实现传递多个参数,e.g.

 #!/bin/bash
 # entering multiple variables
 read -p "Enter your name:" first last
 echo "Checking data for $last, $first"

IP地址校验

要求shell脚本具有简单的IP地址校验能力,即强制程序只接受点分十进制格式的参数输入,此功能通过网上找到的函数实现。

It is showed as follow:

function isValidIp() {
  local ip=$1
  local ret=1

  if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    ip=(${ip//\./ })
    [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
    ret=$?
  fi

  return $ret
}

其中:

line 5 中的 ~ 用于引出正则表达式,^……$ 用于界定正则表达式的范围;

line 6 中的//X/Y 是shell语法,功能是用Y将X代替,在此函数中的具体功能是用空格代替IP地址中的“.”,终极目的是将IP地址的四段分割成数组。

逻辑结构

因为懒,就不画流程图了,罗列一下流程:

1.用户输入起始和终止IP地址;

2.将IP地址赋予变量;

3.执行校验函数,按照顺序进行IP地址校验;

4.任何一步校验失败即退出程序;

5.如果校验成功,则将参数传递给Playbook;

6.执行Playbook并得倒反馈。

其中,退出程序功能使用shell内建的 exit 实现。

完整代码

[root@localhost ~]# cat test.sh
#!/bin/bash
function isValidIp() {
  local ip=$1
  local ret=1

  if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    ip=(${ip//\./ })
    [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
    ret=$?
  fi

  return $ret
}

echo -n "Input The Start IP Address:"
read a_ip

if ! isValidIp $a_ip; then
  echo "$a_ip Is Invalid!!!"
  exit 0
else
  echo -n "Input The End IP Address:"
  read z_ip
  if ! isValidIp $z_ip; then
    echo "$z_ip Is Invalid!!!"
    exit 0
  fi
fi

ansible-playbook -e "a_ip=$a_ip z_ip=$z_ip" bas_add_ip_segments.yml

整个程序使用了天下最简单的IF逻辑完成,本质上就是执行用户输入的始末两个IP校验然后传参数给Playbook。

程序执行过程

结论

实现了预期效果,但程序还不完善,比如关于如何处理错误返回的问题在这里完全没有考虑。

下一步。。。评估一下是否需要写个批处理,让运维组的同志们用最简单的方式调用这个功能模块。

不过,关于这个单独功能的专门研究该告一段落了,我觉得再这样下去,这个简单的问题会被我搞得更加复杂,很难想象执行一条命令需要:batch 调用 shell 调用 playbook 来实现,这是纯粹的强行加戏。。。可耻可耻。。。

所以总结一下在2019年第24周的这三篇技术日志实际上只研究了一个问题:如何用相对友好的方式进行一条奇葩配置命令的下发。最终我给出的解决方案是通过shell调用ansible-palybook实现。可能在目前限定的场景下此方案没有任何优势(废话),但是在需要进行系统配置多条命令的场景下,该方案可在一定程度上简化工作流程并减少实际工作量。

P.S. 今天猛龙打败勇士夺冠了,tag一下。

参考资料

shell校验IP地址

shell之read用法