0

I get an unexpected type error, for what I assume to be the "origins" argument to the community.aws.cloudfront_distribution module: "Error validating distribution origins: 'list' object has no attribute 'get'"

I filed a bug report: https://github.com/ansible-collections/community.aws/issues/504

The documentation says that origins should be a list with dictionary elements, which is what I have.

Is this a bug, or a syntax error on my part? I've checked my indentation and yaml thoroughly.

The error message:

    "msg": "Error validating distribution origins: 'list' object has no attribute 'get'"

Ansible version:

ansible 2.10.7
  config file = /home/bryant/src/api_guys/ansible-deploy-vst/ansible.cfg
  configured module search path = ['/home/bryant/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/bryant/.pyenv/versions/vst-ansible-deployment/lib/python3.9/site-packages/ansible
  executable location = /home/bryant/.pyenv/versions/vst-ansible-deployment/bin/ansible
  python version = 3.9.1 (default, Feb 16 2021, 14:25:16) [GCC 9.3.0]

My code, using community.aws.cloudfront_distribution: (it's long, but the error is in the origins: parameter, I believe)

- name: Create Cloudfront distribution for the interface and api reverse proxy
  community.aws.cloudfront_distribution:
    profile: "{{ vst_nongov_boto_profile }}"
    state: present
    enabled: yes
    caller_reference: "{{ cloudfront_domain_alias }}" 
    alias: "{{ cloudfront_domain_alias }}" 
    aliases:
      - "{{ cloudfront_domain_alias }}"
    origins:
      # reverse proxy for api
      - id: "{{ base_domain }}"
        domain_name: "{{ base_domain }}"
        custom_origin_config:
          http_port: 80
          https_port: 443
          origin_keepalive_timeout: 5
          origin_protocol_policy: "https-only"
          origin_read_timeout: 10
          origin_ssl_protocols:
            - "TLSv1.2"
      # s3 bucket for interface
      - id: "{{ s3_bucket_www_domain_name }}"
        domain_name: "{{ s3_bucket_domain_name }}" 
        custom_origin_config:
          http_port: 80
          https_port: 443
          origin_keepalive_timeout: 5
          origin_protocol_policy: "http-only"
          origin_read_timeout: 10
          origin_ssl_protocols:
            - "TLSv1.2"
    default_cache_behavior:
      #   this contains as many settings as possible that are able to be
      # replicated from the UI option caching policy
      # "Managed-CachingOptimized"; some are guesses, which may need to be
      # changed if we notice performance issues
      target_origin_id: "{{ s3_bucket_domain_name }}" 
      forwarded_values:
        allowed_methods:
          - GET
          - HEAD
        items:
          - GET
          - HEAD
        compress: yes
        cookies:
          forward: none
        default_ttl: 86400
        max_ttl: 31536000
        min_ttl: 1
        query_string: no
        smooth_streaming: no
        trusted_signers:
          enabled: no
        viewer_protocol_policy: "redirect-to-https"
    cache_behaviors:
      - path_pattern: "api/*"
        target_origin_id: "{{ base_domain }}" 
        forwarded_values:
          allowed_methods:
            - GET
            - HEAD
          items:
            - GET
            - HEAD
            - OPTIONS
            - PUT
            - POST
            - PATCH
            - DELETE
          compress: no
          cookies:
            forward: all
          default_ttl: 0
          headers:
            - Authorization
            - Referer
            - User-Agent
          max_ttl: 0
          min_ttl: 0
          query_string: yes
          query_string_cache_keys:
            - '*'
          smooth_streaming: no
          trusted_signers:
            enabled: no
          viewer_protocol_policy: "redirect-to-https"
      - path_pattern: "testapi*"
        target_origin_id: "{{ base_domain }}" 
        forwarded_values:
          allowed_methods:
            - GET
            - HEAD
          items:
            - GET
            - HEAD
          compress: no
          cookies:
            forward: all
          default_ttl: 0
          headers:
            - Authorization
            - User-Agent
          max_ttl: 0
          min_ttl: 0
          query_string: yes
          query_string_cache_keys:
            - '*'
          smooth_streaming: no
          trusted_signers:
            enabled: no
          viewer_protocol_policy: "redirect-to-https"
    custom_error_responses:
      - error_caching_min_ttl: 10
        error_code: 403
        response_code: 200
        response_page_path: "/index.html"
      - error_caching_min_ttl: 10
        error_code: 404
        response_code: 200
        response_page_path: "/index.html"
    viewer_certificate:
      acm_certificate_arn: "{{ nongov_acm_cert_upload_result.certificate.arn }}"
      cloudfront_default_certificate: no
      minimum_protocol_version: "TLSv1.2_2019"
      ssl_support_method: "sni-only"
    http_version: http2
    ipv6_enabled: no
    tags:
      Name: "{{ generic_name_tag }}"
    wait: yes
    default_root_object: "index.html"
    price_class: "{{ cloudfront_price_class }}"
    comment: "Cloudfront distribution for {{ base_interface_domain }} interface and API reverse proxy"
  notify: primary_cloudfront_invalidation
  tags: cloudfront

The full output, including the error:

TASK [aws_full_deployment : Create Cloudfront distribution for the interface and api reverse proxy] ***
task path: /home/bryant/src/api_guys/ansible-deploy-vst/roles/aws_full_deployment/tasks/main.yml:501
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: bryant
<127.0.0.1> EXEC /bin/sh -c 'echo ~bryant && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/bryant/.ansible/tmp `"&& mkdir "` echo /home/bryant/.ansible/tmp/ansible-tmp-1616796020.2343066-177081-217806658917877 `" && echo ansible-tmp-1616796020.2343066-177081-217806658917877="` echo /home/bryant/.ansible/tmp/ansible-tmp-1616796020.2343066-177081-217806658917877 `" ) && sleep 0'
Using module file /home/bryant/.ansible/collections/ansible_collections/community/aws/plugins/modules/cloudfront_distribution.py
<127.0.0.1> PUT /home/bryant/.ansible/tmp/ansible-local-175967cbvvbt8u/tmpamrug82t TO /home/bryant/.ansible/tmp/ansible-tmp-1616796020.2343066-177081-217806658917877/AnsiballZ_cloudfront_distribution.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/bryant/.ansible/tmp/ansible-tmp-1616796020.2343066-177081-217806658917877/ /home/bryant/.ansible/tmp/ansible-tmp-1616796020.2343066-177081-217806658917877/AnsiballZ_cloudfront_distribution.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/home/bryant/.pyenv/versions/vst-ansible-deployment/bin/python /home/bryant/.ansible/tmp/ansible-tmp-1616796020.2343066-177081-217806658917877/AnsiballZ_cloudfront_distribution.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/bryant/.ansible/tmp/ansible-tmp-1616796020.2343066-177081-217806658917877/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_community.aws.cloudfront_distribution_payload_vqd_hi9m/ansible_community.aws.cloudfront_distribution_payload.zip/ansible_collections/community/aws/plugins/modules/cloudfront_distribution.py", line 1665, in validate_origins
  File "/tmp/ansible_community.aws.cloudfront_distribution_payload_vqd_hi9m/ansible_community.aws.cloudfront_distribution_payload.zip/ansible_collections/community/aws/plugins/modules/cloudfront_distribution.py", line 1729, in validate_origin
AttributeError: 'list' object has no attribute 'get'
fatal: [localhost]: FAILED! => {
    "boto3_version": "1.16.25",
    "botocore_version": "1.19.25",
    "changed": false,
    "invocation": {
        "module_args": {
            "alias": "v6-full-deployment.icloudcms.com",
            "aliases": [
                "v6-full-deployment.icloudcms.com"
            ],
            "aws_access_key": null,
            "aws_ca_bundle": null,
            "aws_config": null,
            "aws_secret_key": null,
            "cache_behaviors": [
                {
                    "forwarded_values": {
                        "allowed_methods": [
                            "GET",
                            "HEAD"
                        ],
                        "compress": false,
                        "cookies": {
                            "forward": "all"
                        },
                        "default_ttl": 0,
                        "headers": [
                            "Authorization",
                            "Referer",
                            "User-Agent"
                        ],
                        "items": [
                            "GET",
                            "HEAD",
                            "OPTIONS",
                            "PUT",
                            "POST",
                            "PATCH",
                            "DELETE"
                        ],
                        "max_ttl": 0,
                        "min_ttl": 0,
                        "query_string": true,
                        "query_string_cache_keys": [
                            "*"
                        ],
                        "smooth_streaming": false,
                        "trusted_signers": {
                            "enabled": false
                        },
                        "viewer_protocol_policy": "redirect-to-https"
                    },
                    "path_pattern": "api/*",
                    "target_origin_id": "api.v6-full-deployment.icloudcms.com"
                },
                {
                    "forwarded_values": {
                        "allowed_methods": [
                            "GET",
                            "HEAD"
                        ],
                        "compress": false,
                        "cookies": {
                            "forward": "all"
                        },
                        "default_ttl": 0,
                        "headers": [
                            "Authorization",
                            "User-Agent"
                        ],
                        "items": [
                            "GET",
                            "HEAD"
                        ],
                        "max_ttl": 0,
                        "min_ttl": 0,
                        "query_string": true,
                        "query_string_cache_keys": [
                            "*"
                        ],
                        "smooth_streaming": false,
                        "trusted_signers": {
                            "enabled": false
                        },
                        "viewer_protocol_policy": "redirect-to-https"
                    },
                    "path_pattern": "testapi*",
                    "target_origin_id": "api.v6-full-deployment.icloudcms.com"
                }
            ],
            "caller_reference": "v6-full-deployment.icloudcms.com",
            "comment": "Cloudfront distribution for v6-full-deployment.icloudcms.com interface and API reverse proxy",
            "custom_error_responses": [
                {
                    "error_caching_min_ttl": 10,
                    "error_code": 403,
                    "response_code": 200,
                    "response_page_path": "/index.html"
                },
                {
                    "error_caching_min_ttl": 10,
                    "error_code": 404,
                    "response_code": 200,
                    "response_page_path": "/index.html"
                }
            ],
            "debug_botocore_endpoint_logs": false,
            "default_cache_behavior": {
                "forwarded_values": {
                    "allowed_methods": [
                        "GET",
                        "HEAD"
                    ],
                    "compress": true,
                    "cookies": {
                        "forward": "none"
                    },
                    "default_ttl": 86400,
                    "items": [
                        "GET",
                        "HEAD"
                    ],
                    "max_ttl": 31536000,
                    "min_ttl": 1,
                    "query_string": false,
                    "smooth_streaming": false,
                    "trusted_signers": {
                        "enabled": false
                    },
                    "viewer_protocol_policy": "redirect-to-https"
                },
                "target_origin_id": "v6-full-deployment-s3-bucket.s3-website-us-gov-west-1.amazonaws.com"
            },
            "default_origin_domain_name": null,
            "default_origin_path": null,
            "default_root_object": "index.html",
            "distribution_id": null,
            "e_tag": null,
            "ec2_url": null,
            "enabled": true,
            "http_version": "http2",
            "ipv6_enabled": false,
            "logging": null,
            "origins": [
                {
                    "custom_headers": {
                        "quantity": 0
                    },
                    "custom_origin_config": {
                        "h_t_t_p_port": 80,
                        "h_t_t_p_s_port": 443,
                        "origin_keepalive_timeout": 5,
                        "origin_protocol_policy": "https-only",
                        "origin_read_timeout": 10,
                        "origin_ssl_protocols": [
                            "TLSv1.2"
                        ]
                    },
                    "domain_name": "api.v6-full-deployment.icloudcms.com",
                    "id": "api.v6-full-deployment.icloudcms.com",
                    "origin_path": ""
                },
                {
                    "custom_origin_config": {
                        "http_port": 80,
                        "https_port": 443,
                        "origin_keepalive_timeout": 5,
                        "origin_protocol_policy": "http-only",
                        "origin_read_timeout": 10,
                        "origin_ssl_protocols": [
                            "TLSv1.2"
                        ]
                    },
                    "domain_name": "v6-full-deployment-s3-bucket.s3-website-us-gov-west-1.amazonaws.com",
                    "id": "v6-full-deployment-s3-bucket-www.s3-website-us-gov-west-1.amazonaws.com"
                }
            ],
            "price_class": "PriceClass_100",
            "profile": "vst_nongov",
            "purge_aliases": false,
            "purge_cache_behaviors": false,
            "purge_custom_error_responses": false,
            "purge_origins": false,
            "purge_tags": false,
            "region": null,
            "restrictions": null,
            "security_token": null,
            "state": "present",
            "tags": {
                "Name": "v6-full-deployment"
            },
            "validate_certs": true,
            "viewer_certificate": {
                "acm_certificate_arn": "xxxxxxxxxxOBFUSCATED",
                "cloudfront_default_certificate": false,
                "minimum_protocol_version": "TLSv1.2_2019",
                "ssl_support_method": "sni-only"
            },
            "wait": true,
            "wait_timeout": 1800,
            "web_acl_id": null
        }
    },
    "msg": "Error validating distribution origins: 'list' object has no attribute 'get'"
}
0

It's a bug; origin_ssl_protocols is defined as a list here, then the code tries to treat it as a dict here (which is the line referenced in your stack trace.)

As a workaround, it looks like the code might accept

          origin_ssl_protocols:
            items:
             - "TLSv1.2"
1
  • I see; thanks for looking into it, I see the activity on the bug report; I'd love to be able to contribute to this, but I'm still learning how to debug stack traces and run the development version of ansible modules. Using the exact modules and line numbers from the stack trace is a lesson learned. I'm still not sure how you go about testing aws modules...what kind of testing framework is there? Or are you actually testing on a live aws account? I'll look at the community aws contributing guidelines. – Life5ign Apr 12 at 18:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.