※当サイトの記事には、広告・プロモーションが含まれます。

YAMLファイルの特定のkeyのvalueを編集できるAnsibleのモジュールはまだない

nazology.kusuguru.co.jp

中国の吉林大学と中山大学による研究によって、長らく幻とされてきた「六方晶ダイヤモンド」の安定合成に世界で初めて成功しました。

天然ダイヤモンドよりも硬い人工ダイヤモンドを開発 - ナゾロジー

一般的に知られる立方晶のダイヤモンドを上回る硬度を持つと理論的に予測されながら、これまで大型で純度の高いサンプルを得るのは困難とされてきました。

天然ダイヤモンドよりも硬い人工ダイヤモンドを開発 - ナゾロジー

しかし今回、黒鉛グラファイト)を高圧・高温下で変質させる革新的な手法を確立し、ミリメートルサイズの高純度六方晶ダイヤモンドの合成に成功。

天然ダイヤモンドよりも硬い人工ダイヤモンドを開発 - ナゾロジー

⇧ amazing...

YAMLファイルの特定のkeyのvalueを編集できるAnsibleのモジュールはまだない

実現したいこととしては、

  1. 雛形の設定ファイル(YAML
  2. 案件毎の共通な設定ファイル(YAML
    1. 案件0001の設定ファイル(YAML
    2. 案件0002の設定ファイル(YAML
    3. ...
    4. 案件Nの設定ファイル(YAML

と言うような感じで、各々の案件の設定ファイル(YAML)を完成させるということで、「YAML」の「key」で共通な部分のみ「value」を変えたいってことなんだが、「Ansible」の「モジュール」で用意されてるやろ、と思っていたのですが、

stackoverflow.com

⇧ stackoverflowの話が真実だとするならば、まさかの用意されていないという...

そして、分り辛いのだが、

stackoverflow.com

⇧ 「host_vars」や「group_vars」については、サブディレクトリ構成にすることができますと。

で、前回、

ts0818.hatenablog.com

⇧ 泥沼にハマったのだが、「インベントリー」の「YAML」ファイルの処理される仕組みが分からないのもあるのだが、

  1. Ansibleで用意されている変数名
  2. ユーザーが定義する変数名

「インベントリー」で「変数」を明示的に設定していない場合、「1. Ansibleで用意されている変数名」を使用している必要があった。

あと、「Linux」の「mv」コマンド相当の機能を実現する「Ansible」の「モジュール」も無さそうということで、「Ansible」がカバーしている機能が非常に分り辛いのよね...

というわけで、前回のディレクトリ構成から変更して、以下のような構成になっている。

ディレクトリ構成

/home/ts0818/work/
ansible/
  ├── inventory/
  │    ├── group_vars/
  │    │    └── all.yml 
  │    ├── host_vars/
  │    │    └── nijyo  
  │    │          ├── config.yml
  │    │          └── nijyo.yml
  ├── roles/
  │    └── modify_yaml/
  │          └── tasks/
  │                └── main.yml
  ├── test_modify_yaml.yml
  └── test_ssh_jump_playbook.yml
app/
  ├── config/
  │    └── config.yml
  └── src/

 

■/home/ts0818/work/app/config/config.yml

server:
  url: "[案件毎に異なる]"

github:
  endpoint_url: https://api.github.com
  repository:
    owner: "[案件毎に異なる]"
    name: "[案件毎に異なる]"    

■/home/ts0818/work/inventory/host_vars/nijyo/config.yml

server:
  url: "https://nijyo.com"

github:
  repository:
    owner: "nijyo"
    name: "nijyo-tech-info"    

■/home/ts0818/work/roles/modify_yaml/tasks/main.yml

---
- name: YAMLファイルのキー値を差し替えて対象ホストに配置
  block:
    - name: ファイル1を対象ホストにコピー
      ansible.builtin.copy:
        src: '/home/ts0818/work/app/config/config.yml'  # ローカルのファイル1
        dest: '/tmp/file1.yml'  # 対象ホストに配置する場所
        owner: root
        group: root
        mode: '0644'

    - name: ファイル1を対象ホストから読み込む
      ansible.builtin.slurp:
        src: '/tmp/file1.yml'
      register: file1_slurp

    - name: ファイル1の内容をYAMLに変換
      ansible.builtin.set_fact:
        file1_content: "{{ file1_slurp.content | b64decode | from_yaml }}"

    - name: ファイル1の内容を確認する
      ansible.builtin.debug:
        msg: "file1_content {{ file1_content | to_nice_yaml(sort_keys=False) }}"

    - name: ファイル2を読み込む
      ansible.builtin.set_fact:
        file2_content: "{{ lookup('file', '/home/ts0818/work/ansible/inventory/host_vars/nijyo/config.yml') | from_yaml }}"

    - name: ファイル2の内容を確認する
      ansible.builtin.debug:
        msg: "file2_content {{ file2_content | to_nice_yaml(sort_keys=False)  }}"

    - name: 共通のキーをファイル2の値で差し替え、残りはファイル1の値を使用
      ansible.builtin.set_fact:
        merged_content: >
          {{
            file1_content | combine(file2_content, recursive=True)
          }}

    - name: 更新用のファイルの内容を確認する
      ansible.builtin.debug:
        msg: "merged_content {{ merged_content | to_nice_yaml(sort_keys=False)  }}"

    - name: 変更後の内容を対象ホストに書き戻す
      ansible.builtin.copy:
        dest: '/tmp/file1.yml'  # 変更後のファイル1を上書き
        content: "{{ merged_content | to_nice_yaml(sort_keys=False)  }}"
        owner: root
        group: root
        mode: '0644'

    # - name: 対象ホストに変更後のファイル1を最終的な場所に移動
    #   block:
    #     - name: ファイルの更新日時(更新前)
    #       ansible.builtin.stat:
    #         path: /home/vagrant/file1.yml
    #       register: file_stat_before

    #     - name: ファイルをコピー(リモート内)
    #       ansible.builtin.copy:
    #         remote_src: true
    #         src: /tmp/file1.yml
    #         dest: /home/vagrant/file1.yml
    #         force: true

    #     - name: ファイルの更新日時(更新後)
    #       ansible.builtin.stat:
    #         path: /home/vagrant/file1.yml
    #       register: file_stat_after

    #     - name: ファイルの更新前後の差分をテーブル形式でデバッグログに出力
    #       ansible.builtin.debug:
    #         msg: |
    #           +---------------------+---------------------+---------------------+---------------------+---------------------+
    #           |       項目          |   更新前の状態      |   更新後の状態      |   差分              |
    #           +---------------------+---------------------+---------------------+---------------------+---------------------+
    #           | atime               | {{ file_stat_before.stat.atime }} | {{ file_stat_after.stat.atime }} | {{ file_stat_after.stat.atime | int - file_stat_before.stat.atime | int }} |
    #           | ctime               | {{ file_stat_before.stat.ctime }} | {{ file_stat_after.stat.ctime }} | {{ file_stat_after.stat.ctime | int - file_stat_before.stat.ctime | int }} |
    #           | mtime               | {{ file_stat_before.stat.mtime }} | {{ file_stat_after.stat.mtime }} | {{ file_stat_after.stat.mtime | int - file_stat_before.stat.mtime | int }} |
    #           | size                | {{ file_stat_before.stat.size }}  | {{ file_stat_after.stat.size }}  | {{ file_stat_after.stat.size | int - file_stat_before.stat.size | int }}  |
    #           | uid                 | {{ file_stat_before.stat.uid }}   | {{ file_stat_after.stat.uid }}   | N/A                 |
    #           | gid                 | {{ file_stat_before.stat.gid }}   | {{ file_stat_after.stat.gid }}   | N/A                 |
    #           | mode                | {{ file_stat_before.stat.mode }}  | {{ file_stat_after.stat.mode }}  | N/A                 |
    #           +---------------------+---------------------+---------------------+---------------------+---------------------+

    #     - name: /tmpディレクトリに配置していた一時ファイルを削除
    #       ansible.builtin.file:
    #         path: /tmp/file1.yml
    #         state: absent

    - name: 対象ホストに変更後のファイル1を最終的な場所に移動
      block:
        - name: ファイルの更新日時(更新前)
          ansible.builtin.stat:
            path: /home/vagrant/file1.yml
          register: file_stat_before

        - name: ファイルの更新
          ansible.builtin.command: |
            mv /tmp/file1.yml /home/vagrant/file1.yml
    #        creates: /home/vagrant/file1.yml

        - name: ファイルの更新日時(更新後)
          ansible.builtin.stat:
            path: /home/vagrant/file1.yml
          register: file_stat_after

        - name: ファイルの更新前後の差分をテーブル形式でデバッグログに出力
          ansible.builtin.debug:
            msg: |
              +---------------------+---------------------+---------------------+---------------------+---------------------+
              |       項目          |   更新前の状態      |   更新後の状態      |   差分              |
              +---------------------+---------------------+---------------------+---------------------+---------------------+
              | atime               | {{ file_stat_before.stat.atime }} | {{ file_stat_after.stat.atime }} | {{ file_stat_after.stat.atime | int - file_stat_before.stat.atime | int }} |
              | ctime               | {{ file_stat_before.stat.ctime }} | {{ file_stat_after.stat.ctime }} | {{ file_stat_after.stat.ctime | int - file_stat_before.stat.ctime | int }} |
              | mtime               | {{ file_stat_before.stat.mtime }} | {{ file_stat_after.stat.mtime }} | {{ file_stat_after.stat.mtime | int - file_stat_before.stat.mtime | int }} |
              | size                | {{ file_stat_before.stat.size }}  | {{ file_stat_after.stat.size }}  | {{ file_stat_after.stat.size | int - file_stat_before.stat.size | int }}  |
              | uid                 | {{ file_stat_before.stat.uid }}   | {{ file_stat_after.stat.uid }}   | N/A                 |
              | gid                 | {{ file_stat_before.stat.gid }}   | {{ file_stat_after.stat.gid }}   | N/A                 |
              | mode                | {{ file_stat_before.stat.mode }}  | {{ file_stat_after.stat.mode }}  | N/A                 |
              +---------------------+---------------------+---------------------+---------------------+---------------------+    

■/home/ts0818/work/test_modify_yaml.yml

---
- name: Test SSH Jump
  hosts: nijyo
  become: true
#  roles:
#    role: modify_yaml


  tasks:
    - name: Modify yaml file
      ansible.builtin.include_role:
        name: modify_yaml    

⇧ が新たに追加した内容。

で、対象のホストについても「仮想マシンVM:Virtual Machine)」が稼働しているのを確認してから、

「Ansible」の「Playbook」を実行。

対象のホストを確認してみると、

⇧ ファイルも編集して配置できていそうです。
「Ansible」の「モジュール」で対応してくれている機能が分らんので、「車輪の再発明」になってしまうことが多そうな気がしてならない...

車輪の再発明(しゃりんのさいはつめい、reinventing the wheel)とは、「広く受け入れられ確立されている技術や解決法を(知らずに、または意図的に無視して)再び一から作ること」を指すための慣用句。誰でも直観的にその意味が分かるように、車輪という誰でも知っていて古くから広く使われている既存の技術を比喩の題材として使った慣用表現で、世界中で使われている。

車輪の再発明 - Wikipedia

IT業界

車輪の再発明」の語は、IT業界では耳にすることが多いフレーズでもあるソフトウェア開発におけるアンチパターンの1つに分類される。

車輪の再発明 - Wikipedia

アンチパターンの1つに数えられるということは、それだけ多くの人々が苦い体験を繰り返して失敗してきたということでもあるが、「車輪の再発明」は繰り返されてしまう

車輪の再発明 - Wikipedia

ITエンジニアにとっては「開発は楽しいものだから」という理由や、「自分のソフトウェアのことは自分が一番に理解している」というITエンジニアの想い、自分で作りたいという欲求からくるのではないかともいわれる

車輪の再発明 - Wikipedia

また、「車輪の再発明」を避けようとするあまり、逆に労力が増す結果になることもある。一例として、GitHubで見つけたライブラリを組み込んで開発しようとする場合、そのライブラリがテストを充分にされていない粗悪品だったなら、開発完了までの想定した以上の時間がかかる可能性も高く、完成後もメンテナンスのたびに同様の苦労が発生すると考えられる

車輪の再発明 - Wikipedia

⇧「ライブラリ」側で対応していない機能を実現するために独自にカスタマイズせざるを得なくて、開発コストが膨れ上がるのはあるあるで、まさに、「Ansible」の「モジュール」未対応の話も、このあたりの話に関わってくるのよね...

とは言え、「Ansible」の「モジュール」で対応できていない機能が多そうなので、結局のところ、力業で実現しなければいけないことが多くなってきそうなのよね...

何となく、対応していて欲しい機能に限って、ほぼ対応されていないようなイメージなのよね...

毎度モヤモヤ感が半端ない…

今回はこのへんで。