6

次のタスクがあります。

- name: copy server.xml
  template: src=server.xml dest=/var/containers/{{ item.key }}/conf
  with_dict: containers

また、group_vars にコンテナ ディクショナリを追加しました

containers:
  frontend:
    http_port: 8080
  backend:
    http_port: 8081

最後に、server.xml からの関連するスニペットを次に示します。

<Connector port="{{ http_port }}" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

私がしたいことは、関連する http_port がテンプレートモジュールで使用されることです。しかし、代わりにエラーが発生します:

fatal: [localhost] => {'msg': "AnsibleUndefinedVariable: 1 つ以上の未定義の変数: 'http_port' は未定義です", 'failed': True}

これは可能ですか?アイテムの値を変数置換に活用するにはどうすればよいですか?

4

1 に答える 1

6

使用する{{ item.value.http_port }}ことはまさに正しい解決策です。

with_dict を渡すと、コンテナ ディクショナリ内の各アイテムを として渡すタスクをループします{{ item }}。ここで、アイテムにはキーがあり、ディクショナリ アイテムに含まれるすべての値があります。この場合、キーが http_port であるキーと値のペアです。値はこれらの 2 つの異なる整数です。ただし、{{ item.value.http_port }}思いついた構文でアクセスすることがさらに重要になる、非常に複雑なネストされた辞書を渡すことができます。

より複雑なテンプレートを使用する際に注意すべきことは、あるホスト (またはコンテナーなど) に対してテンプレート化する追加の変数があり、別のホストに対してテンプレート化しない場合に、さまざまなものを混ぜてデフォルトを設定し、if ステートメントを使用する方法です。

これを理解するには、Ansible がテンプレートを解釈する言語である Jinja2 を読んでください。良い例は、フロントエンドで SSL を介してファイルを提供し、バックエンドでは提供しないようなものです。Ansible が未定義の変数を使用しようとして怒るのを避けるために、構文 like{{ foo | default('bar') }}を使用し、必要なものだけをテンプレート化するように if ステートメントを使用します。

大まかなスケッチ - あなたが持っていたとしましょう:

containers:
  frontend:
    http_port: 8080
    https_port: 8443
    ssl_cert: ./files/keystore
    ssl_pass: "{{ vaulted_vars.ssl_pass }}" 
  backend:
    http_port: 8081

その場合、必要に応じてそのキーストアをファイルシステムにコピーするタスクがあると想像すると、次の行に沿って何かを使用できます。

<Connector port="{{ item.value.http_port }}" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="{{ item.value.https_port | default('8443')" />
           {% if item.value.ssl_cert is defined %} 
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="${user.home}/.keystore" keystorePass="{{ item.value.ssl_pass }}"
           clientAuth="false" sslProtocol="TLS"/>
           {% endif %}

ハッピーテンプレ!

于 2015-09-01T18:55:01.707 に答える