Ansible Playbook的重构
首先
使用Ansible时我喜欢的一点是,尽管可以偷懒,但也可以改进代码,写得更漂亮。
因此,我会写下我实际进行的代码重构。(内容有些改动)
我正在CentOS 7上进行确认。
Ansible以前的版本
第一步如下所示。
- /etc/profile に以下の内容を書き込む
if [ "$USER" != "foo" ]; then
export FOO=BAR
fi
从这里开始。
首先坦率地实施
使用Ansible原生方式实现时,可以使用blockinfile命令编写如下内容:
- name: /etc/profile に環境設定を追加
blockinfile:
path: /etc/profile
block: |
if [ "$USER" != "foo" ]; then
export FOO=BAR
fi
become: yes
在这种情况下,将以下内容写入/etc/profile的末尾。
# BEGIN ANSIBLE MANAGED BLOCK
if [ "$USER" != "foo" ]; then
export FOO=BAR
fi
# END ANSIBLE MANAGED BLOCK
blockinfile是代碼中的難聞味道
这样也没问题。冪等性得到保证。
然而,”BEGIN ANSIBLE MANAGED BLOCK”和”END ANSIBLE MANAGED BLOCK”的存在感觉有点不太好。如果有人不小心删除它们,会产生奇怪的结果。
在我看来,blockinfile模块很难处理,所以我会尽量避免使用它。但并不意味着这个模块本身有问题。这只是给人一种可以改进的信号。也就是所谓的代码异味。
blockinfile → lineinfile + copy
blockinfile 可以被替换为 lineinfile 加上 copy。
所以我们首先决定使用lineinfile。
就像这样。
- name: foo.shを /etc/profile.foo としてコピー
copy:
src: foo.sh
dest: /etc/profile.foo
become: yes
- name: profile.fooを読み込み
lineinfile:
path: /etc/profile
line: source /etc/profile.foo
become: yes
尽管blockinfile已经不再使用,但现在分散成两个部分,
导致了想要做什么变得不太清楚。
使用lineinfile + copy指令进行复制。
然而从根本上说,并不需要修改 /etc/profile。
只需按照 /etc/profile 中所述,在 /etc/profile.d 目录下放置扩展名为 .sh 或 sh.local 的文件,它将自动读取并执行。
for i in /etc/profile.d/*.sh /etc/profile.d/sh.local ; do
if [ -r "$i" ]; then
if [ "${-#*i}" != "$-" ]; then
. "$i"
else
. "$i" >/dev/null
fi
fi
done
所以,只需将文件复制即可。
- name: foo.sh を /etc/profile.d 以下にコピー(bash起動時に読み込まれる)
copy:
src: foo.sh
dest: /etc/profile.d/foo.sh
become: yes
通过了解操作系统的机制,我能够以更简洁的方式进行写作。
最后
虽然这次例子相对简单,但Ansible不仅可以实现基于代码的自动化,还能够发现改进点。
如果通过 failed_when: false 等手段进行掩饰,
那么存在终止代码非零的程序。
如果在file模块中设置了force=yes,
则可能会存在步骤先后颠倒的情况。
Ansible以YAML为编写语言,因此其可编程元素较低。然而,我们不应该将此视为缺点,而应该将其视为提供改进机会的信号。
所以我很喜欢使用Ansible,感觉很愉快呢( ´ω`)