- module_defaults:
    group/aws:
      aws_access_key: "{{ aws_access_key }}"
      aws_secret_key: "{{ aws_secret_key }}"
      security_token: "{{ security_token | default(omit) }}"
    cloudfront_distribution:
      alias: "{{ cloudfront_alias | default(omit) }}"
      viewer_certificate: "{{ cloudfront_viewer_cert | default(omit) }}"
  collections:
    - amazon.aws

  block:

  - name: create cloudfront distribution using defaults
    cloudfront_distribution:
      origins:
      - domain_name: "{{ cloudfront_hostname }}-origin.example.com"
        id: "{{ cloudfront_hostname }}-origin.example.com"
      default_cache_behavior:
        target_origin_id: "{{ cloudfront_hostname }}-origin.example.com"
      state: present
      purge_origins: yes
    register: cf_distribution

  - set_fact:
      distribution_id: '{{ cf_distribution.id }}'

  - name: re-run cloudfront distribution with same defaults
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ cloudfront_hostname }}-origin.example.com"
      state: present
    register: cf_dist_no_update

  - name: ensure distribution was not updated
    assert:
      that:
        - not cf_dist_no_update.changed

  - name: re-run cloudfront distribution using distribution id
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      purge_origins: no
      state: present
    register: cf_dist_with_id

  - name: ensure distribution was not updated
    assert:
      that:
        - not cf_dist_with_id.changed

  - name: update origin http port
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ cloudfront_hostname }}-origin.example.com"
        custom_origin_config:
          http_port: 8080
      state: present
    register: update_origin_http_port

  - name: ensure http port was updated
    assert:
      that:
        - update_origin_http_port.changed

  - name: update restrictions
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      restrictions:
        geo_restriction:
          restriction_type: "whitelist"
          items:
            - "US"
      state: present
    register: update_restrictions

  - name: ensure restrictions was updated
    assert:
      that:
        - update_restrictions.changed

  - name: set a random comment
    set_fact:
      comment: "{{'ABCDEFabcdef123456'|shuffle|join }}"

  - name: update comment
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      comment: "{{ comment }}"
      state: present
    register: cf_comment

  - name: ensure comment was updated
    assert:
      that:
        - cf_comment.changed
        - 'cf_comment.comment == comment'

  - name: create second origin
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
        id: "{{ resource_prefix }}2.example.com"
      default_root_object: index.html
      state: present
      wait: yes
    register: cf_add_origin

  - name: ensure origin was added
    assert:
      that:
        - cf_add_origin.origins.quantity == 2
        - cf_add_origin.changed
        - "cf_add_origin.default_root_object == 'index.html'"

  - name: re-run second origin
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ cloudfront_hostname }}-origin.example.com"
        custom_origin_config:
          http_port: 8080
      - domain_name: "{{ resource_prefix }}2.example.com"
      default_root_object: index.html
      wait: yes
      state: present
    register: cf_rerun_second_origin

  - name: ensure nothing changed after re-run
    assert:
      that:
        - cf_rerun_second_origin.origins.quantity == 2
        - not cf_rerun_second_origin.changed

  - name: run with origins in reverse order
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      - domain_name: "{{ cloudfront_hostname }}-origin.example.com"
        custom_origin_config:
          http_port: 8080
      state: present
    register: cf_rerun_second_origin_reversed

  - name: ensure nothing changed after reversed re-run
    assert:
      that:
        - cf_rerun_second_origin_reversed.origins.quantity == 2
        - not cf_rerun_second_origin_reversed.changed


  - name: purge first origin
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      default_cache_behavior:
        target_origin_id: "{{ resource_prefix }}2.example.com"
      purge_origins: yes
      state: present
    register: cf_purge_origin

  - name: ensure origin was removed
    assert:
      that:
        - cf_purge_origin.origins.quantity == 1
        - cf_purge_origin.changed

  - name: update default_root_object of existing distribution
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      default_root_object: index.php
      state: present
    register: cf_update_default_root_object

  - name: ensure origin was updated
    assert:
      that:
        - "cf_update_default_root_object.default_root_object == 'index.php'"
        - cf_update_default_root_object.changed

  - name: add tags to existing distribution
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      tags:
        ATag: tag1
        Another: tag
      default_root_object: index.php
      state: present
    register: cf_add_tags

  - name: ensure tags were added
    assert:
      that:
        - cf_add_tags.changed
        - cf_add_tags.tags|length == 2

  - name: delete distribution
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      enabled: no
      wait: yes
      state: absent

  - name: create distribution with tags
    cloudfront_distribution:
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
        id: "{{ resource_prefix }}2.example.com"
      tags:
        ATag: tag1
        Another: tag
      state: present
    register: cf_second_distribution

  - set_fact:
      distribution_id: '{{ cf_second_distribution.id }}'

  - name: ensure tags were set on creation
    assert:
      that:
        - cf_second_distribution.changed
        - cf_second_distribution.tags|length == 2
        - "'ATag' in cf_second_distribution.tags"
        - "'Another' in cf_second_distribution.tags"

  - name: re-run create distribution with same tags and purge_tags
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
        id: "{{ resource_prefix }}2.example.com"
      tags:
        ATag: tag1
        Another: tag
      purge_tags: yes
      state: present
    register: rerun_with_purge_tags

  - name: ensure that re-running didn't change
    assert:
      that:
        - not rerun_with_purge_tags.changed
        - rerun_with_purge_tags.tags|length == 2

  - name: add new tag to distribution
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      tags:
        Third: thing
      purge_tags: no
      state: present
    register: update_with_new_tag

  - name: ensure tags are correct
    assert:
      that:
        - update_with_new_tag.changed
        - "'Third' in update_with_new_tag.tags"
        - "'Another' in update_with_new_tag.tags"
        - "'ATag' in update_with_new_tag.tags"
        - update_with_new_tag.tags|length == 3

  - name: create some cache behaviors
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      cache_behaviors: "{{ cloudfront_test_cache_behaviors }}"
      state: present
    register: add_cache_behaviors

  - name: reverse some cache behaviors
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      cache_behaviors: "{{ cloudfront_test_cache_behaviors|reverse|list }}"
      state: present
    register: reverse_cache_behaviors

  - name: check that reversing cache behaviors changes nothing when purge_cache_behaviors unset
    assert:
      that:
        - not reverse_cache_behaviors.changed
        - reverse_cache_behaviors.cache_behaviors|length == 2

  - name: reverse some cache behaviors properly
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}2.example.com"
      cache_behaviors: "{{ cloudfront_test_cache_behaviors|reverse|list }}"
      purge_cache_behaviors: yes
      state: present
    register: reverse_cache_behaviors_with_purge

  - name: check that reversing cache behaviors changes nothing when purge_cache_behaviors unset
    assert:
      that:
        - reverse_cache_behaviors_with_purge.changed
        - reverse_cache_behaviors_with_purge.cache_behaviors|length == 2

  - name: update origin that changes target id (failure expected)
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}3.example.com"
        id: "{{ resource_prefix }}3.example.com"
      purge_origins: yes
      state: present
    register: remove_origin_in_use
    ignore_errors: yes

  - name: check that removing in use origin fails
    assert:
      that:
        - remove_origin_in_use.failed

  # FIXME: This currently fails due to AWS side problems
  # not clear whether to hope they fix or prevent this issue from happening
  #- name: update origin and update cache behavior to point to new origin
  #  cloudfront_distribution:
  #    origins:
  #    - domain_name: "{{ resource_prefix }}3.example.com"
  #      id: "{{ resource_prefix }}3.example.com"
  #    cache_behaviors:
  #      - path_pattern: /test/path
  #        target_origin_id: "{{ resource_prefix }}3.example.com"
  #      - path_pattern: /another/path
  #        target_origin_id: "{{ resource_prefix }}3.example.com"
  #    state: present
  #    aws_access_key: "{{ aws_access_key|default(omit) }}"
  #    aws_secret_key: "{{ aws_secret_key|default(omit) }}"
  #    security_token: "{{ security_token|default(omit) }}"
  #    profile: "{{ profile|default(omit) }}"
  #  register: update_cache_behaviors in use

  - name: create an s3 bucket for next test
    # note that although public-read allows reads that we want to stop with origin_access_identity,
    # we also need to test without origin_access_identity and it's hard to change bucket perms later
    aws_s3:
      bucket: "{{ resource_prefix }}-bucket"
      mode: create

  - name: update origin to point to the s3 bucket
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}-bucket.s3.amazonaws.com"
        id: "{{ resource_prefix }}3.example.com"
        s3_origin_access_identity_enabled: yes
      state: present
    register: update_origin_to_s3

  - name: check that s3 origin access is in result
    assert:
      that:
        - item.s3_origin_config.origin_access_identity.startswith('origin-access-identity/cloudfront/')
    when: "'s3_origin_config' in item"
    loop: "{{ update_origin_to_s3.origins['items'] }}"

  - name: update origin to remove s3 origin access identity
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}-bucket.s3.amazonaws.com"
        id: "{{ resource_prefix }}3.example.com"
        s3_origin_access_identity_enabled: no
      state: present
    register: update_origin_to_s3_without_origin_access

  - name: check that s3 origin access is not in result
    assert:
      that:
        - not item.s3_origin_config.origin_access_identity
    when: "'s3_origin_config' in item"
    loop: "{{ update_origin_to_s3_without_origin_access.origins['items'] }}"

  - name: delete the s3 bucket
    aws_s3:
      bucket: "{{ resource_prefix }}-bucket"
      mode: delete

  - name: check that custom_origin_config can't be used with origin_access_identity enabled
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
      - domain_name: "{{ resource_prefix }}-bucket.s3.amazonaws.com"
        id: "{{ resource_prefix }}3.example.com"
        s3_origin_access_identity_enabled: yes
        custom_origin_config:
          origin_protocol_policy: 'http-only'
      state: present
    register: update_origin_to_s3_with_origin_access_and_with_custom_origin_config
    ignore_errors: True

  - name: check that custom origin with origin access identity fails
    assert:
      that:
        - update_origin_to_s3_with_origin_access_and_with_custom_origin_config.failed

  - name: Update distribution to use specific access identity
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      origins:
        - id: "{{ resource_prefix }}"
          domain_name: "{{ resource_prefix }}.s3.amazonaws.com"
          s3_origin_access_identity_enabled: true
          s3_origin_config:
            origin_access_identity: origin-access-identity/cloudfront/ANYTHING
    register: update_distribution_with_specific_access_identity

  - name: check that custom origin uses the provided origin_access_identity
    assert:
      that:
        - update_distribution_with_specific_access_identity.changed
        - update_distribution_with_specific_access_identity.origins.items[0].s3_origin_config.origin_access_identity == 'origin-access-identity/cloudfront/ANYTHING'

  always:
  # TEARDOWN STARTS HERE
  - name: delete the s3 bucket
    aws_s3:
      bucket: "{{ resource_prefix }}-bucket"
      mode: delete

  - name: clean up cloudfront distribution
    cloudfront_distribution:
      distribution_id: "{{ distribution_id }}"
      enabled: no
      wait: yes
      state: absent
