web-dev-qa-db-ja.com

プレイ間でansible変数を共有する

この質問 のフォローアップです。

一連のEC2インスタンスをプロビジョニングする劇があります。必要に応じて、hosts値はlocalhost(実行時にホストがないため)であり、playはec2hostsと呼ばれる新しいホストリストを作成し、ホストIPを生成してホスト名マップこれは、情報が利用可能になる最初で唯一の時間であるためset_factを使用して保存します。このホストリストは、その後のフォローアップの対象となります。問題は、2回目のプレイでプロビジョニングプレイ中に作成されたhostname_map辞書を使用する必要があることです。これを行う方法がわかりません。

これが最初の遊びです:

- hosts: localhost
  connection: local
  gather_facts: False

  tasks:
    - name: Provision a set of instances
      ec2:
        key_name: marcus
        instance_type: t2.micro
        image: "{{ AMI_id }}"
        wait: true
        exact_count: "{{ server_count }}"
        count_tag:
          Tutorial: "{{ tutorial_name }}"
        instance_tags:
          Tutorial: "{{ tutorial_name }}"
        groups: ['SSH', 'Web']
      register: ec2

    - name: Add all instance public IPs to Host group
      add_Host:
        hostname: "{{ item.public_ip }}"
        groups: ec2hosts
      loop: "{{ ec2.instances }}"

    - name: Build an IP to hostname map
      set_fact:
        hostname_map: "{{ hostname_map | combine({item.0.public_ip: (item.1 + '.' + tutorial_domain)}) }}"
      loop: "{{ ec2.instances|Zip(hostnames)|list }}"

    - name: Debug hostname_map
      debug:
        msg: "{{ hostname_map }}"

この最後に、hostname_mapには次のようなマップが含まれています。

{
    "18.184.109.70": "Host1.example.com", 
    "18.196.135.59": "Host2.example.com"
}

変数スコープに関するansible docsを読むと、同じホストのセットに適用されていない限り、プレイで定義された変数はそのプレイ外では利用できないと述べています。この場合、それは不可能なので、グローバルスコープでvarを使用する必要があります。私が読んだことから、set_factが適切な方法です。そのため、/group_vars/allに空の変数を作成し、その変数がすべての演劇にアクセスできるようにしました。

hostname_map: {}

次の演劇は(動的に作成したホストリストを使用して)新しく作成された各インスタンスに接続し、内部からホスト名を設定します。

- hosts: ec2hosts
  gather_facts: yes
  tasks:
    - name: Debug hostname_map
      debug:
        msg: "{{ hostname_map }}"
    - name: Set hostnames
      hostname:
        name: "{{ hostname_map[ansible_Host] }}"

ただし、hostname_mapが空であるため、これは失敗します

TASK [Debug hostname_map]
ok: [18.184.109.70] => {
    "msg": {}
}
ok: [18.196.135.59] => {
    "msg": {}
}

だから私はこのエラーを受け取ります:

致命的:[18.184.109.70]:失敗しました! => {"msg": "タスクに未定義の変数を持つオプションが含まれています。エラーは次のとおりです: 'dictオブジェクト'には属性u'18.184.109.70 'がありません

変数をグローバルに定義しない場合でも、奇妙なことに、同じデバッグ出力とエラーが表示されます

私がすべて読んだ他の記事では、値をvarsに明示的に列挙する必要があると示唆していますが、データは動的で実行時まで不明であるため、これを行うことはできません。同様に、同じ理由でコマンドラインでextra_varsを使用して提供することはできません。

2番目のプレイでこの変数を使用できるようにするにはどうすればよいですか?ローカルファイルを書き出してから読み込むといった、不格好な解決策は避けたいです。

また、これを完全に異なる方法で行うための提案も受け入れます。「これ」は、任意の数のEC2インスタンスを作成し、静的リストから取得したホスト名を割り当てることです。

3
Synchro

set_factで設定した値は、異なるプレイ間で使用できます。 set_factは特定のホストに設定であることに注意してください。最初のプレイはlocalhostに対して実行されるため、事実はlocalhosts変数の一部です。したがって、次のプレイでは、このようなタスクでそれにアクセスできるはずです。

- debug:
    var: hostvars['localhost']['hostmap']
7
Zoredache