当詹金斯重写其配置时,如何使这个可靠的詹金斯脚本幂等?
How to make this ansible jenkins script idempotent, when jenkins is rewriting its configuration?
我有一个部署 jenkins 的 ansible 剧本,其中 jenkins config.xml
jinja2 模板文件包含用于 AD 身份验证的此片段:
<securityRealm class="hudson.plugins.active_directory.ActiveDirectorySecurityRealm" plugin="active-directory@1.39">
<domain>{{ ldap_hostname }}/domain>
<bindName>{{ ldap_bind_user }}</bindName>
<bindPassword>{{ ldap_password }}</bindPassword>
<server>{{ ldap_hostname }}:{{ ldap_port }}</server>
<groupLookupStrategy>RECURSIVE</groupLookupStrategy>
<removeIrrelevantGroups>false</removeIrrelevantGroups>
</securityRealm>
{{ ldap_password }}
是来自保管库的明文密码。
问题是当 jenkins 在 config.xml 部署后启动时,它通过用密码哈希替换明文密码来重写它。 (哈希值似乎取决于目标主机,因为我们在不同的虚拟机上获得不同的哈希值)。虽然这通常是一件好事,但它会使剧本的每次执行都将模板操作标记为已更改。
如何使这个播放脚本幂等?
我真的想不出一个干净利落的方法来做到这一点,所以这可能会让人觉得有点受折磨。
这里有几个选项,具体取决于 "correct" 您希望如何使用它。
首先,您可以简单地告诉 Ansible 您不关心您是否正在对此文件进行任何更改,因此始终标记为未更改(绿色)。您可以在任务中使用 changed_when: False
执行此操作。
或者你可以说你只想在第一个 运行 上模板化这个文件,然后它就不在 Ansible 的手中了。这种方法对于引导安装然后想要管理自己的文件的东西很有用,你永远不会考虑再次更改它们。为此,您可以使用以下内容:
- name: check if jenkins config.xml file is there
stat:
path: path/to/config.xml
register: config-xml_stat
- name: template jenkins config.xml if not already there
template:
src: path/to/config.xml.j2
dest: path/to/config.xml
when: config-xml_stat.exists == false
考虑一下您正在对某些内容进行模板化,然后积极期待特定行在 Ansible 的控制之外发生变化。这里的另一个选择是将文件模板化到与 Jenkins 期望的不同的文件路径(然后可以像往常一样幂等),将其与 Jenkins 正在使用的文件进行比较,然后如果除该行之外的任何其他内容不同复制 Jenkins 文件的顶部。你可以使用这样的东西来做到这一点:
- name: template jenkins config.xml.template
template:
src: path/to/config.xml.j2
dest: path/to/config.xml.template
# We are expecting bindPassword to have changed so we can exclude this from the diff line count
- name: diff jenkins config.xml and config.xml.template
shell: diff path/to/config.xml.template path/to/config.xml | grep -v bindPassword | wc -l
register: config-xml_diff
# Diff will also output 2 extra lines that we don't care about. If there's more lines than this then we need to retemplate the config.xml
- name: template jenkins config.xml
template:
src: path/to/config.xml.j2
dest: path/to/config.xml
when: config-xml_diff.stdout != 2
最后一个有点笨拙,但 "more correct" 因为它正在主动检查文件的更改是否超出我们的预期,如果是,则重新模板化它。
如果您决定走第三条路线,那么我建议结合检查以查看它是否存在于第二个选项中,以使其在执行的操作中更加明显。没有它,如果 config.xml 文件不存在,那么你的 diff 任务将输出一行 (diff: config.xml: No such file or directory
),这仍然意味着你的第三个任务的条件评估没问题,但它有点误导。
我有一个部署 jenkins 的 ansible 剧本,其中 jenkins config.xml
jinja2 模板文件包含用于 AD 身份验证的此片段:
<securityRealm class="hudson.plugins.active_directory.ActiveDirectorySecurityRealm" plugin="active-directory@1.39">
<domain>{{ ldap_hostname }}/domain>
<bindName>{{ ldap_bind_user }}</bindName>
<bindPassword>{{ ldap_password }}</bindPassword>
<server>{{ ldap_hostname }}:{{ ldap_port }}</server>
<groupLookupStrategy>RECURSIVE</groupLookupStrategy>
<removeIrrelevantGroups>false</removeIrrelevantGroups>
</securityRealm>
{{ ldap_password }}
是来自保管库的明文密码。
问题是当 jenkins 在 config.xml 部署后启动时,它通过用密码哈希替换明文密码来重写它。 (哈希值似乎取决于目标主机,因为我们在不同的虚拟机上获得不同的哈希值)。虽然这通常是一件好事,但它会使剧本的每次执行都将模板操作标记为已更改。
如何使这个播放脚本幂等?
我真的想不出一个干净利落的方法来做到这一点,所以这可能会让人觉得有点受折磨。
这里有几个选项,具体取决于 "correct" 您希望如何使用它。
首先,您可以简单地告诉 Ansible 您不关心您是否正在对此文件进行任何更改,因此始终标记为未更改(绿色)。您可以在任务中使用 changed_when: False
执行此操作。
或者你可以说你只想在第一个 运行 上模板化这个文件,然后它就不在 Ansible 的手中了。这种方法对于引导安装然后想要管理自己的文件的东西很有用,你永远不会考虑再次更改它们。为此,您可以使用以下内容:
- name: check if jenkins config.xml file is there
stat:
path: path/to/config.xml
register: config-xml_stat
- name: template jenkins config.xml if not already there
template:
src: path/to/config.xml.j2
dest: path/to/config.xml
when: config-xml_stat.exists == false
考虑一下您正在对某些内容进行模板化,然后积极期待特定行在 Ansible 的控制之外发生变化。这里的另一个选择是将文件模板化到与 Jenkins 期望的不同的文件路径(然后可以像往常一样幂等),将其与 Jenkins 正在使用的文件进行比较,然后如果除该行之外的任何其他内容不同复制 Jenkins 文件的顶部。你可以使用这样的东西来做到这一点:
- name: template jenkins config.xml.template
template:
src: path/to/config.xml.j2
dest: path/to/config.xml.template
# We are expecting bindPassword to have changed so we can exclude this from the diff line count
- name: diff jenkins config.xml and config.xml.template
shell: diff path/to/config.xml.template path/to/config.xml | grep -v bindPassword | wc -l
register: config-xml_diff
# Diff will also output 2 extra lines that we don't care about. If there's more lines than this then we need to retemplate the config.xml
- name: template jenkins config.xml
template:
src: path/to/config.xml.j2
dest: path/to/config.xml
when: config-xml_diff.stdout != 2
最后一个有点笨拙,但 "more correct" 因为它正在主动检查文件的更改是否超出我们的预期,如果是,则重新模板化它。
如果您决定走第三条路线,那么我建议结合检查以查看它是否存在于第二个选项中,以使其在执行的操作中更加明显。没有它,如果 config.xml 文件不存在,那么你的 diff 任务将输出一行 (diff: config.xml: No such file or directory
),这仍然意味着你的第三个任务的条件评估没问题,但它有点误导。