将Ansible任务模块的名称转换为FQCN格式

请提供以下要点 or 要简述一下

我会介绍一个脚本,它可以阅读Ansible任务的yaml文件,并将模块名称转换为FQCN格式后保存。

讲解

推荐从Ansible 2.10版本开始,在任务中使用完全限定类名来写模块名称。实际上,由于后向兼容性重定向器的作用,传统的写法也可以正常运行,没有问题。

因为逐个更改很麻烦,所以我写了一个Python脚本来读取文件并提取模块名称,然后将其转换为FQCN(完全限定类名)并进行重定向设置。 这段代码并不复杂,但既然已经写了,就分享给大家。

功能可以被简单定义为某物或某人的作用、用途或能力。

    • 指定したディレクトリの指定したglobパターンのファイルを対象として処理する。

 

    • ファイルをテキストとして読み込んで正規表現で置換するので、YAMLの文法チェックなどは行わない。

 

    • 各タスクのnameキーの次のキーをモジュール名と見做し、指定したリダイレクタの設定(ansible_builtin_runtime.yml)で変換して書き換える。

従ってnameキーの無いタスクは無視される。

debug・templateなどリダイレクタの設定に無いものは変換しない。
変換の結果ファイル単位で差分があれば上書き保存する。

策划之目的

环境

    • Python 3.7以上

 

    Ansible 2.10

情报

将以下三个信息定义为脚本开头的常量。

    • バージョンアップ先のAnsibleライブラリのansible_builtin_runtime.ymlのパス(例: site-packages/ansible/config/ansible_builtin_runtime.yml)

 

    • 対象となるAnsibleプロジェクトのディレクトリのパス

 

    そのディレクトリからのタスクYAMLを示すglobパターン(例:**/tasks/*.yml)

由于不确认先前所述的情况下进行文件更改,建议在提交重要代码之前先清理工作区。

限制事项

    • 本来はプラグインやフィルターもFQCNに変換するべきらしい(リダイレクタを無効にするとこれらも旧名では機能しない)が、あくまでもタスクのみが対象です。

 

    一切の保証はありません。ころんでも泣かない。

请在中国本土参考

    • [Ansible] モジュールの指定などを FQCN 表記に移行する手順 – てくなべ (tekunabe)

 

    • Ansible 2.10 Porting Guide — Ansible Documentation

 

    Conversion to Collection – YAML roundtrip with ruamel | Linux System Roles

执行示例

目标任务文件

---

- hosts: win_host
  gather_facts: yes
  tasks:
    - name: get terminal service behaviour on failure
      win_command: sc qfailure TermService
      register: qfailure
      changed_when: no

    - name: debug
      debug: var=qfailure

执行

$ python convert2fqcn.py
processing old.yml
  checking win_command...
    converted to ansible.windows.win_command
  checking debug...
    not found.

结果 (jié guǒ)

win_command被转换为ansible.windows.win_command,值部分没有改变。同时,debug也没有被转换。

为了显示差异,会在转换前后更改文件名,但实际上会覆盖原文件,请注意。

--- old.yml 2021-03-25 10:01:46.297632163 +0900
+++ new.yml 2021-03-25 09:55:20.492025609 +0900
@@ -7 +7 @@
-      win_command: sc qfailure TermService
+      ansible.windows.win_command: sc qfailure TermService

脚本

from pathlib import Path
import re
import yaml

'''
python  convert2fqcn.py

Ansibleタスクのモジュール名をFQCN形式に変換します。以下に指定したディレクトリ配下に見つかった
ファイルを直接書き換えます。

'''


# Ansibleモジュールのリダイレクト用config 'ansible_builtin_runtime.yml'へのパス
CONVERTION_MAP_PATH = './ansible-2.10-venv/lib/python3.6/site-packages/ansible/config/ansible_builtin_runtime.yml.back'
# 置換を行うパス
TARGET_DIR = 'roles/'
# 置換を行うタスクファイルのglobパターン。前項からの相対パスで表す。
TASKS_GLOB_PATTERN = '**/tasks/*.yml'

map_cache = {}

# nameキーで始まるオブジェクトにマッチ
name_line_regex = ' *- name:.*\n'
# 次の行のコロンまでをモジュール名と判定
module_line_regex = '([\S_]+):'
module_name_regex = f'({ name_line_regex } *){module_line_regex}'


def main():
    role_path = Path(TARGET_DIR).rglob(TASKS_GLOB_PATTERN)
    for path in role_path:
        with open(path, 'r') as role_file:
            print(f'processing {path}')
            task_data = role_file.read()
            new_task_data = replace(task_data)
        if new_task_data != task_data:
            with open(path, 'w') as role_file:
                role_file.write(new_task_data)


def load_covertion_map(convertion_map_path):
    runtime_data = yaml.load(open(convertion_map_path))
    lis = runtime_data.get('plugin_routing').get('modules')
    return lis


def replace(task_data):
    r = re.compile(module_name_regex)
    return re.sub(r, convert_task, task_data)


def convert_task(match_obj):
    res = None
    if match_obj.groups():
        prev_lines, old_key = match_obj.groups()
        print(f'  checking {old_key}...')
        entry = query(old_key)
    else:
        # マッチしなければ呼ばれないのでここには来ないはず。
        return None
    if entry:
        new_key = entry.get('redirect')
        print(f'    converted to {new_key}')
        key = new_key
    else:
        print('    not found.')
        key = old_key
    # キー区切りのコロンまでマッチしているので必ず付ける。
    return prev_lines + key + ':'


def query(key):
    cached = map_cache.get(key)
    if cached:
        return cached
    entry = CONVERTION_MAP.get(key)
    map_cache[key] = entry
    return entry


if __name__ == '__main__':
    CONVERTION_MAP = load_covertion_map(CONVERTION_MAP_PATH)
    main()

广告
将在 10 秒后关闭
bannerAds