2017-09-06 14 views
0

この質問は、AWSではなくAnsibleのループについてですが、わかりやすくするためにAWSデプロイメントの問題を例として使用します。Ansibleでネストされた値を置き換える方法

私たちの展開スクリプトでは、Amazon EC2コンテナサービスのいくつかのクラスタをループしています。私が最終的に行うことは、クラスタ上の各サービスを再起動することです。サービス名を指定すると、サービスを再開できます。しかし、私は完全なARNではなく単純な名前が必要です。だから私は、クラスタあたりのサービスを検索し、このような何かを得る:

results: 
- _ansible_item_result: true 
    _ansible_no_log: false 
    _ansible_parsed: true 
    ansible_facts: 
    services: 
    - arn:aws:ecs:eu-central-1:55:service/test-services 
    changed: false 
    failed: false 
    invocation: 
    module_args: 
     aws_access_key: null 
     aws_secret_key: null 
     cluster: services 
     details: false 
     ec2_url: null 
     profile: null 
     region: null 
     security_token: null 
     service: null 
     validate_certs: true 
    item: services 
- _ansible_item_result: true 
    _ansible_no_log: false 
    _ansible_parsed: true 
    ansible_facts: 
    services: 
    - arn:aws:ecs:eu-central-1:55:service/test-service 
    - arn:aws:ecs:eu-central-1:55:service/frontend 
    - arn:aws:ecs:eu-central-1:55:service/beats 
    changed: false 
    failed: false 
    invocation: 
    module_args: 
     aws_access_key: null 
     aws_secret_key: null 
     cluster: test-service 
     details: false 
     ec2_url: null 
     profile: null 
     region: null 
     security_token: null 
     service: null 
     validate_certs: true 
    item: test-service module_args: 
    aws_access_key: null 
    aws_secret_key: null 
    cluster: test-service 
    details: false 
    ec2_url: null 
    profile: null 
    region: null 
    security_token: null 
    service: null 
    validate_certs: true 

項目:テストサービス

を今私はサービスの短い名前で各ARNを交換したいです。たとえば、arn:aws:ecs:eu-central-1:55:service/test-servicetest-serviceになります。私は、サービス上でループを行うと、(後で私は再び背中にそれらを有効にします)0に希望数を設定することで、それらをオフにすることができ、交換後

taskdefinitionsは、簡単な辞書のIである
- name: "Turn services off" 
    ecs_service: 
    name: "{{ item[1]}}" 
    desired_count: 0 
    task_definition: "{{ taskdefinitions[item[1]] }}" 
    cluster: "{{ item[0].item }}" 
    state: present 
with_subelements: 
    - "{{ result.results }}" 
    - ansible_facts.services 
register: turnOffServiceResult 

脚本に定義されている:

taskdefinitions: 
    services: 
    - test-services 
    test-xde-worker-service: 
    - test-service 

だから私は、私は次のようにして置き換えるとregexしようと変数resultに上に示したAWSのリストを取得した後:

を3210
- set_fact: 
    result: 
    results: 
     ansible_facts: 
     services: "{{ result.results.1.ansible_facts.services | map('regex_replace', '.*/(.*?)$', '\\1') | list }}" 

これはうまくいきますが、明らかに1つのクラスタのサービス名のみが置き換えられ、dictの他のフィールドは失われますansible_facts。後者は受け入れ可能で、前者は受け入れられません。だからここに質問があります:入れ子にされたリストのテキストをどのように置き換えることができますか?別の問題は、taskdefinitionsに含まれていないサービスを無効にすることをスキップすることですが、それは手元の問題ではありません。

+0

ecs_service' 'に渡すときに、なぜ全体の辞書内の値を交換しませんか? –

+0

良い点は、変数を渡すときにフィルタを使用しようとしましたが、動作しないようです。 task_definitionを調べるために、名前付きインデックスとして 'item [1]'を使用することに気づくでしょう。フィルタをどのように適用できるか教えていただけたら、とてもうれしくてうまくいきませんでした。また、ある時点で誰かがネストされたリストの値をフィルタリングする必要があることは確かです。したがって、より一般的な質問です。 – titusn

答えて

2

私は、複雑なオブジェクト内の任意のアイテムをインプレース(少なくとも現在のAnsible 2.3では)で変更する組み込みの方法は知らない。

元のオブジェクト(selectmap(attribute=...)json_queryなど)から必要なアイテムを選択し、その縮小セット/リスト内のアイテムを変更します。あなたの仮説例では、result.results[].ansible_facts.services[]のようにJMESPathを使用して、すべてのクラスタのすべてのサービスを選択し、map('regex_replace',...このリストを選択します。

または複雑なオブジェクトを反復処理し、例えば、ループ内で変更を適用します。

- name: "Turn services off" 
    ecs_service: 
    name: "{{ myname }}" 
    desired_count: 0 
    task_definition: "{{ taskdefinitions[myname] }}" 
    cluster: "{{ mycluster }}" 
    state: present 
    vars: 
    mycluster: "{{ item[0].item }}" 
    myname: "{{ item[1] | regex_search('[^/]*$') }}" 
    with_subelements: 
    - "{{ result.results }}" 
    - ansible_facts.services 
+0

それは有望ですが、私はそれを試してここに戻ってきます。 – titusn

+0

はい、varsを使用していました。私の前の試みもうまくいったことが分かりますが、UpdateService操作を呼び出すときにエラーが発生しました(エラー:ClientException):ファミリに無効な文字が含まれています。単一の値の代わりに正規表現の改善にも良い1つ。 – titusn

+0

ちょうど好奇心から、あなたは私が有効なデータを提供していないという答えを書いたのですか?私はすべてが疑問に思った、私はちょうど私達の口座番号といくつかのサービス名を匿名化した。 – titusn

関連する問題