0

Ansible version: 2.9.16

I have several application load balancers in the AWS account and I'm trying to add a new rule to certain listeners from these load balancers. I'm using the community.aws.elb_application_lb_info plugin to gather information about the load balancers and locate the target listeners where to add the new rule.

In the json returned by community.aws.elb_application_lb_info the default actions of some listeners look like this:

"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
                           }
                        ]
                     }
                  }
               ]

while others look like this:

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

Then I'm using community.aws.elb_application_lb plugin to add the rule to the listener.

Now the problem: the parameter listeners: - DefaultActions is mandatory in community.aws.elb_application_lb. I'm trying to specify it by extracting it from the json generated by community.aws.elb_application_lb_info, so my code looks like this:

# 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:
              ....

but I get the following error:

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

If in the playbook above I change DefaultActions: "{{ listener.default_actions[0] }}" to DefaultActions: "{{ listener.default_actions }}" I get the following error:

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.

Is there any possibility to just tell community.aws.elb_application_lb to use the already defined DefaultActions for a listener to which I want to add a rule? All my load balancers already exist and have default actions defined. So I just want my script to add a rule and keep the default actions exactly as they are defined.

I guess it is possible to extract the data for each default action from json and recreate the default action each time, but the code would get pretty complicated.

Ciprian Stoica
  • 2,309
  • 5
  • 22
  • 36

1 Answers1

0

So, I ended up re-creating DefaultActions. Not a nice solution but I couldn't come up with something better so far. But at least it works.

# 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:
          ...
Ciprian Stoica
  • 2,309
  • 5
  • 22
  • 36