Ansible:一部のファイルが存在しないときにvars_filesを使用できますか


17

それは一部です:

vars_files:
  - vars/vars.default.yml
  - vars/vars.yml

ファイルvars/vars.ymlが存在しない場合-これはエラーです。

ERROR: file could not read: /.../vars/vars.yml

このファイルが存在する場合にのみ、このファイルから追加の変数をロードするにはどうすればよいですか?(エラーなし)

回答:


27

本当に簡単です。異なるvars_filesアイテムを1つのタプルに押しつぶすことができます。Ansibleは、存在するファイルを見つけてロードするまで、各アイテムを自動的に通過します。例:

vars_files:
  - [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]

4
Ansible開発者によると、このソリューションは最初に見つかったファイルだけでなく、すべてのファイルをロードします。
tjanez

10

Ansible開発者によると、これを解決する適切な方法は次のようなものを使用することです:

vars_files_locs: ['../path/to/file1', '../path/to/file2', ...]

- include_vars: "{{ item }}"
  with_first_found: vars_files_locs

さらに、彼らは言う

上記は、最初に見つかったファイルのみを適切にロードし、vars_files言語キーワードでこれを行うよりも柔軟です。


「最初のファイルのみが見つかりました。」 -アイデアはすべてではない彼らの、いくつかの変数を再定義することだった
セルゲイ

@セルゲイ、あなたの質問をもう一度読んで、私はあなたが望んでいたものが少し異なっていることがわかります。これを指摘してくれてありがとう。他の誰かがそれを役に立つと思うならば、私は答えをそのままにします。
tjanez 14年

1
ただしinclude_vars、タスクでは、ロールと比較して変数の優先順位が高くなります。defaultsまたはvars
Alex F

2

同じ物理サーバー(ここでは仮想マシンは許可されません)に複数のデプロイメント環境(ライブ、デモ、サンドボックス)を作成する必要があるセットアップでこの問題が発生し、任意のsvnリポジトリをデプロイするスクリプト

これには、(オプションの)variable.ymlファイルのディレクトリツリーが必要でした。これは、互いの上にマージされ、欠落している場合は例外をスローしません。

ansibleで変数のマージを有効にすることから始めます-これは浅いハッシュマージ(1レベルの深さ)を行い、完全な再帰的なマージではないことに注意してください

ansible.cfg

[defaults]
hash_behaviour=merge ;; merge rather than replace dictionaries http://docs.ansible.com/ansible/intro_configuration.html###hash-behaviour

Ansibleディレクトリレイアウト

/group_vars
└── all.yml

/playbooks
├── boostrap.yml
├── demo.yml
├── live.yml
└── sandbox.yml

/roles/deploy/
├── files
├── tasks
│   ├── includes.yml
│   ├── main.yml
└── vars
    ├── main.yml
    ├── project_1.yml
    ├── project_2.yml
    ├── demo
    │   ├── project_1.yml
    │   ├── project_2.yml   
    │   └── main.yml
    ├── live
    │   ├── project_1.yml
    │   ├── project_2.yml   
    │   └── main.yml
    └── sandbox
        ├── project_1.yml
        ├── project_2.yml   
        └── main.yml

roles / deploy / tasks / includes.yml

これは、オプションの変数ファイルのディレクトリツリーのメインロジックです。

;; imports in this order:
;; - /roles/deploy/vars/main.yml
;; - /roles/deploy/vars/{{ project_name }}.yml
;; - /roles/deploy/vars/{{ project_name }}/main.yml
;; - /roles/deploy/vars/{{ project_name }}/{{ project_env }}.yml
- include_vars:
    dir: 'vars'
    files_matching: "{{ item }}"
    depth: 1
  with_items:
    - "main.yml"
    - "{{ project_name }}.yml"

- include_vars:
    dir: 'vars/{{ env_name }}'
    files_matching: "{{ item }}"
    depth: 1
  with_items:
    - "main.yml"
    - "{{ project_name }}.yml"

group_vars / all.yml

プロジェクトおよびさまざまなユーザーと環境のデフォルト変数を構成する

project_users:
    bootstrap:
        env:   bootstrap
        user:  ansible
        group: ansible
        mode:  755
        root:  /cs/ansible/
        home:  /cs/ansible/home/ansible/
        directories:
            - /cs/ansible/
            - /cs/ansible/home/

    live:
        env:   live
        user:  ansible-live
        group: ansible
        mode:  755
        root:  /cs/ansible/live/
        home:  /cs/ansible/home/ansible-live/

    demo:
        env:   demo
        user:  ansible-demo
        group: ansible
        mode:  755
        root:  /cs/ansible/demo/
        home:  /cs/ansible/home/ansible-demo/

    sandbox:
        env:   sandbox
        user:  ansible-sandbox
        group: ansible
        mode:  755
        root:  /cs/ansible/sandbox/
        home:  /cs/ansible/home/ansible-sandbox/    

project_env:  bootstrap
project_user: "{{ ansible_users[project_env] }}" ;; this will be retroactively updated if project_env is redefined later

roles / deploy / vars / main.yml

プロジェクトのデフォルト

ansible_project:
  node_env:   development
  node_port:  4200
  nginx_port: 4400

roles / deploy / vars / project_1.yml

project_1のデフォルト

ansible_project:
  node_port:  4201
  nginx_port: 4401

roles / deploy / vars / live / main.yml

ライブ環境のデフォルト、プロジェクトのデフォルトを上書き

ansible_project:
  node_env: production

roles / deploy / vars / live / project_1.yml

ライブ環境でのproject_1の最終的なオーバーライド

ansible_project:
  nginx_port: 80

playbooks / demo.yml

環境ごとに個別のプレイブックを構成する

- hosts: shared_server
  remote_user: ansible-demo
  vars:
    project_env: demo
  pre_tasks:
    - debug: "msg='{{ facter_gid }}@{{ facter_fqdn }} ({{ server_pseudonym }})'"
    - debug: var=project_ssh_user
  roles:
    - { role: deploy, project_name: project_1 }

警告:すべての環境は単一のホストに存在するため、すべてのプレイブックは個別に実行する必要があります。すべてのスクリプトを順番に実行する必要がある場合は、xargsを使用して、それぞれを個別のコマンドとして実行します。

find ./playbooks/*.yml | xargs -L1 time ansible-playbook

1
- hosts: all
  vars_files: vars/vars.default.yml
  vars:
    optional_vars_file: "{{ lookup('first_found', 'vars/vars.yml', errors='ignore') }}"
  tasks:
  - when: optional_vars_file is file
    include_vars: "{{ optional_vars_file }}"

注:パステスト(ファイル、存在、...)は、ansible-playbookコマンドを実行するときに、絶対パスまたは現在の作業ディレクトリに相対的なパスでのみ機能します。これがルックアップを使用した理由です。ルックアップは、プレイブックディレクトリへの相対パスを受け入れ、ファイルが存在する場合は絶対パスを返します。


0

または、よりyamlの方法で:

- hosts: webservers
  vars:
    paths_to_vars_files:
      - vars/{{ ansible_hostname }}.yml
      - vars/default.yml
  tasks:
    - include_vars: "{{ item }}"
      with_first_found: "{{ paths_to_vars_files }}"

つまり、次のように角括弧で1行に配列を書く代わりに:

['path/to/file1', 'path/to/file2', ...]

次のように、複数行に配列値を書き込むyamlの方法を使用します。

- path/to/file1
- path/to/file2

前述のように、これはという名前のvarsファイルを探し、{{ ansible_hostname }}.yml存在しない場合はdefault.yml


この答えは、異なるデータを使用することを除いて、これと同じコードを使用します。つまり、{{ ansible_hostname }}.ymlファイル名の代わりに../path/to/file1。ポイントは何ですか?追加できる入力ファイル名の数に制限はありません。
テクラフ16

@techraf:わかりました、新しい回答が提出された理由に関する説明/増幅を追加しました。これは、serverfaultコメントが複数行のコードスニペットをサポートしていないためです。また、yaml配列は複数行で(できれば)頻繁に記述されることを指摘していました。以前の回答が編集されていて、複数行の配列形式が表示されていたとしても、私はよく見ますが、大丈夫です。その後、私の回答を削除できます。
ドンリー

両方の表記は、Ansible docsのYAML Basicsの章で指定されています。あなたが他の人よりも頻繁に見るという事実は、まだこれを新しい答えにしません。
テクラフ16

0

さまざまな部分をつなぎ合わせます... include_varsには、ファイルが存在するときにtrueになるwhen句が含まれます。すなわち

vars:
  file_to_include: /path/to/file
tasks:
  - include_vars: "{{ file_to_include }}"
    when: file_to_include is exists

0

最新のAnsibleバージョンに基づいた新しい回答-基本的に、が使用されwith_first_foundskip: trueファイルが見つからない場合はタスクをスキップする必要があります。

- name: Include vars file if one exists meeting our condition.
  include_vars: "{{ item }}"
  with_first_found:
    - files:
        - vars/{{ variable_here }}.yml
      skip: true

これにより、フォールバックvarsファイルをそのリストに含める必要がなくなります。

関連を参照してください:https : //stackoverflow.com/a/39544405/100134

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.