Search code examples
amazon-web-servicesansibleamazon-elbaws-application-load-balancer

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


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.


Solution

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