免责声明:
- 我(显然!)以下合集的作者,该合集是为了回应上述问题而创建的
- 查找插件尚未经过彻底测试,对于特定模块可能会失败。
由于这是一个非常好的主意,而且什么都不存在,所以我决定尝试一下。这一切最终都集中在一个集合中,现在称为thoteam.var_as_file
这是可用的在 github 仓库中 https://github.com/ansible-ThoTeam/thoteam.var_as_file。我不会将所有文件粘贴到这个答案中,因为它们都可以在提到的存储库中使用完整的自述文件 https://github.com/ansible-ThoTeam/thoteam.var_as_file/blob/main/README.md安装、测试和使用。
全球的想法如下:
- 创建一个查找插件,负责推送具有给定内容的新临时文件并返回使用它们的路径。
- 在 playbook 运行结束时清理创建的文件。对于这一步,我创建了一个回调插件,它启动监听的清理操作
v2_playbook_on_stats
events.
我仍然对并发性(尚未清理的文件存储在磁盘上的静态 json 文件中)和可靠性(不确定stats
阶段在所有情况下都会发生,尤其是在崩溃时)。我也不完全确定使用回调是一个好的实践/最佳选择。
同时,编写代码非常有趣并且它完成了工作。我将看看这项工作是否被其他人使用,并且可能会在接下来的几周内很好地增强所有这些(如果您有 PR 来修复已知的问题,我很乐意接受它们)。
安装并启用回调插件后(请参阅https://github.com/ansible-ThoTeam/thoteam.var_as_file#installing-the-collection https://github.com/ansible-ThoTeam/thoteam.var_as_file#installing-the-collection),可以在任何地方使用查找来获取包含传递内容的文件路径。例如:
- name: Get a filename with the given content for later use
ansible.builtin.set_fact:
my_tmp_file: "{{ lookup('thoteam.var_as_file.var_as_file', some_variable) }}"
- name: Use in place in a module where a file is mandatory and you have the content in a var
community.general.java_cert:
pkcs12_path: "{{ lookup('thoteam.var_as_file.var_as_file', pkcs12_store_from_vault) }}"
cert_alias: default
keystore_path: /path/to/my/keystore.jks
keystore_pass: changeit
keystore_create: yes
state: present
这些是两个插件文件的相关部分。我删除了 ansible 文档变量(为了简洁),如果您愿意,您可以直接在 git 存储库中找到它。
plugins/lookup/var_as_file.py https://github.com/ansible-ThoTeam/thoteam.var_as_file/blob/main/plugins/lookup/var_as_file.py
from ansible.errors import AnsibleError
from ansible.plugins.lookup import LookupBase
from ansible.module_utils.common.text.converters import to_native
from ansible_collections.thoteam.var_as_file.plugins.module_utils.var_as_file import VAR_AS_FILE_TRACK_FILE
from hashlib import sha256
import tempfile
import json
import os
def _hash_content(content):
"""
Returns the hex digest of the sha256 sum of content
"""
return sha256(content.encode()).hexdigest()
class LookupModule(LookupBase):
created_files = dict()
def _load_created(self):
if os.path.exists(VAR_AS_FILE_TRACK_FILE):
with open(VAR_AS_FILE_TRACK_FILE, 'r') as jfp:
self.created_files = json.load(jfp)
def _store_created(self):
"""
serialize the created files as json in tracking file
"""
with open(VAR_AS_FILE_TRACK_FILE, 'w') as jfp:
json.dump(self.created_files, jfp)
def run(self, terms, variables=None, **kwargs):
'''
terms contains the content to be written to the temporary file
'''
try:
self._load_created()
ret = []
for content in terms:
content_sig = _hash_content(content)
file_exists = False
# Check if file was already create for this content and check it.
if content_sig in self.created_files:
if os.path.exists(self.created_files[content_sig]):
with open(self.created_files[content_sig], 'r') as efh:
if content_sig == _hash_content(efh.read()):
file_exists = True
ret.append(self.created_files[content_sig])
else:
os.remove(self.created_files[content_sig])
# Create / Replace the file
if not file_exists:
temp_handle, temp_path = tempfile.mkstemp(text=True)
with os.fdopen(temp_handle, 'a') as temp_file:
temp_file.write(content)
self.created_files[content_sig] = temp_path
ret.append(temp_path)
self._store_created()
return ret
except Exception as e:
raise AnsibleError(to_native(repr(e)))
plugins/callback/clean_var_as_file.py https://github.com/ansible-ThoTeam/thoteam.var_as_file/blob/main/plugins/callback/clean_var_as_file.py
from ansible.plugins.callback import CallbackBase
from ansible_collections.thoteam.var_as_file.plugins.module_utils.var_as_file import VAR_AS_FILE_TRACK_FILE
from ansible.module_utils.common.text.converters import to_native
from ansible.errors import AnsibleError
import os
import json
def _make_clean():
"""Clean all files listed in VAR_AS_FILE_TRACK_FILE"""
try:
with open(VAR_AS_FILE_TRACK_FILE, 'r') as jfp:
files = json.load(jfp)
for f in files.values():
os.remove(f)
os.remove(VAR_AS_FILE_TRACK_FILE)
except Exception as e:
raise AnsibleError(to_native(repr(e)))
class CallbackModule(CallbackBase):
''' This Ansible callback plugin cleans-up files created by the thoteam.var_as_file.var_as_file lookup '''
CALLBACK_VERSION = 2.0
CALLBACK_TYPE = 'utility'
CALLBACK_NAME = 'thoteam.var_as_file.clean_var_as_file'
CALLBACK_NEEDS_WHITELIST = False
# This one doesn't work for a collection plugin
# Needs to be enabled anyway in ansible.cfg callbacks_enabled option
CALLBACK_NEEDS_ENABLED = False
def v2_playbook_on_stats(self, stats):
_make_clean()
如果您尝试一下,我将很高兴收到任何反馈。