AWS
elb
Ansible
boto3
ALB

ansibleのelb_target_group_factsの検索は全一致になるらしい(というか boto3 elbv2のdescribe_load_balancersが全一致)

TL;DR

  • elbv2のdescribe_load_balancersは存在しないELBを検索しようとするとLoadBalancerNotFoundException
  • 検索したいload balancer nameを1つずつfor文で回すしかない

経緯

AWSのALBの情報を取得するansibleを書いていたのですが、elbv2describe_load_balancersの仕様にはまったのでメモ。

問題点

ansibleのALBの情報取得をするelb_application_lb_factsで以下のように書いたのですが、

- elb_application_lb_facts:
    aws_access_key: hoge
    aws_secret_key: fuga
    region: ap-northeast-1
    names:
      - "alb-blue"
      - "alb-green"
  register: alb_result

load balancerの情報を取得できない。。

"load_balancers": []

実際のlibraryを確認してみると、LoadBalancerNotFoundが発生した場合は空で返すとのこと。
つまり検索候補のうち、片方が存在しない名前のLoad Balancerの場合、エラーを吐くらしい。きつい。
https://github.com/ansible/ansible/blob/stable-2.7/lib/ansible/modules/cloud/amazon/elb_application_lb_facts.py#L222

一応自分でpythonで以下のように試してみたのですが、

import boto3

access_key = 'hoge'
secret_key = 'fuga'
client = boto3.client(
    'elbv2', 
    region_name='ap-northeast-1',
    aws_access_key_id = access_key,
    aws_secret_access_key = secret_key
)
response = client.describe_load_balancers(
    Names=[
        'alb-blue',
        'alb-green'
    ]
)
print(response)

やっぱりLoadBalancerNotFoundExceptionが出てしまう。避けられない仕様らしい。

botocore.errorfactory.LoadBalancerNotFoundException: An error occurred (LoadBalancerNotFound) when calling the DescribeLoadBalancers operation

結局以下のように無理やりloopにして対応しました。

- set_fact: 
    alb_list: []

- elb_application_lb_facts:
    aws_access_key: hoge
    aws_secret_key: fuga
    region: ap-northeast-1
    names:
      - "{{ item }}"
  register: alb_result
  with_items:
    - "alb-blue"
    - "alb-green"

- set_fact:
    alb_list: "{{ alb_list }} + {{ item['load_balancers'] }}"
  when: item['load_balancers'] | length > 0
  with_items: "{{ alb_result['results'] }}"

結論

elbv2のdescribe_load_balancersは全一致しか許さない、という鬼仕様でした。
今回はansibleのyml側で制御する方法を取ったのですが、
elb_application_lb_factsを多用するのであれば、custom moduleを作成して、
python内部でfor文を回した方が保守性が良くなりそうです。