如何告诉 community.aws.elb_application_lb 保持特定侦听器的 DefaultActions 不变

How to tell community.aws.elb_application_lb to leave untouched the DefaultActions of specific listener

Ansible 版本:2.9.16

我在 AWS 账户中有多个应用程序负载均衡器,我正在尝试向来自这些负载均衡器的某些侦听器添加新规则。我正在使用 community.aws.elb_application_lb_info 插件来收集有关负载平衡器的信息,并找到要添加新规则的目标侦听器。

community.aws.elb_application_lb_info 返回的 json 中,某些侦听器的默认操作如下所示:

"default_actions":[
                  {
                     "target_group_arn":"some-arn",
                     "type":"forward",
                     "order":1,
                     "forward_config":{
                        "target_group_stickiness_config":{
                           "enabled":false
                        },
                        "target_groups":[
                           {
                              "target_group_arn":"some-arn",
                              "weight":1
                           }
                        ]
                     }
                  }
               ]

而其他人看起来像这样:

"default_actions":[
                  {
                     "redirect_config":{
                        "host":"some-host",
                        "protocol":"HTTPS",
                        "path":"/",
                        "status_code":"HTTP_302",
                        "query":"",
                        "port":"443"
                     },
                     "type":"redirect",
                     "order":1
                  }
               ]

然后我使用 community.aws.elb_application_lb 插件将规则添加到侦听器。

现在的问题是:参数 listeners: - DefaultActionscommunity.aws.elb_application_lb 中是必需的。我试图通过从 community.aws.elb_application_lb_info 生成的 json 中提取它来指定它,所以我的代码如下所示:

# load_balancer_name var is defined somewhere else
- name: "Gather information about the following ALB: {{ load_balancer_name }}"
  community.aws.elb_application_lb_info:
    ...
    names: "{{ load_balancer_name }}"
  register: elb_application_lb_info_ret

...

- name: Get the HTTPS:443 listener from ALB
  vars:
    listener_port: 443
    listener_protocol: "HTTPS"
  set_fact:
    listener: "{{ elb_application_lb_info_ret.load_balancers[0].listeners | selectattr('protocol', 'equalto', listener_protocol) | selectattr('port', 'equalto', listener_port) | list | first }}"

...
  
- name: Create the listener rule in the load balancer
  community.aws.elb_application_lb:
    name: "{{ load_balancer_name }}"
    .....
    listeners:
      - Protocol: "{{ listener.protocol }}"
        Port: "{{ listener.port }}"
        ....
        DefaultActions: "{{ listener.default_actions[0] }}"
        Rules:
          - Conditions:
              ....

但我收到以下错误:

TASK [xxx : Create the listener rule in the load balancer] *******************************************************************************************************************************************
fatal: [xxx]: FAILED! => {
    "changed": false
}

MSG:

argument DefaultActions is of type <class 'dict'> found in 'listeners'. and we were unable to convert to list: <class 'dict'> cannot be converted to a list

如果在上面的剧本中我将 DefaultActions: "{{ listener.default_actions[0] }}" 更改为 DefaultActions: "{{ listener.default_actions }}" 我会收到以下错误:

TASK [xxx : Create the listener rule in the load balancer] *******************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: KeyError: 'Type'
fatal: [xxx]: FAILED! => {
    "changed": false,
    "rc": 1
}

MSG:

MODULE FAILURE
See stdout/stderr for the exact error


MODULE_STDERR:

Traceback (most recent call last):
  ...
KeyError: 'Type'

So, looks like my approach is not good.

是否有可能只告诉 community.aws.elb_application_lb 为我要添加规则的侦听器使用已经定义的 DefaultActions?我所有的负载均衡器都已经存在并且定义了默认操作。所以我只希望我的脚本添加一个规则并保持默认操作与它们定义的完全一致。

我想可以从 json 中提取每个默认操作的数据并每次都重新创建默认操作,但代码会变得非常复杂。

因此,我最终重新创建了 DefaultActions。这不是一个很好的解决方案,但到目前为止我想不出更好的办法。但至少它有效。

# code to get the target 'listener' via the community.aws.elb_application_lb_info plugin

... 

# there are two types of default actions: redirect or forward
- name: Check if default action of listener is "redirect"
  vars:
    default_action: "{{ listener.default_actions[0] }}"
  when: default_action.type == 'redirect'
  set_fact:
    default_actions:
      - Type: "redirect"
        RedirectConfig:
          Protocol: "{{ default_action.redirect_config.protocol }}"
          Port: "{{ default_action.redirect_config.port }}"
          Host: "{{ default_action.redirect_config.host }}"
          Path: "{{ default_action.redirect_config.path }}"
          Query: "{{ default_action.redirect_config.query }}"
          StatusCode: "{{ default_action.redirect_config.status_code }}"

- name: Check if default action of listener is "forward"
  vars:
    default_action: "{{ listener.default_actions[0] }}"
  when: default_action.type == 'forward'
  set_fact:
    default_actions:
      - Type: "forward"
        TargetGroupArn: "{{ default_action.target_group_arn }}"
  
- name: Create/modify the listener rule in the load balancer
  community.aws.elb_application_lb:
    ...
    listeners:
      - Protocol: "{{ listener.protocol }}"
        ...
        DefaultActions: "{{ default_actions }}"
        Rules:
          ...