Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws cloudformation_stack_set module not idempotent #103

Open
naslanidis opened this issue Jun 17, 2020 · 3 comments
Open

aws cloudformation_stack_set module not idempotent #103

naslanidis opened this issue Jun 17, 2020 · 3 comments
Labels
affects_2.10 bug This issue/PR relates to a bug python3

Comments

@naslanidis
Copy link

naslanidis commented Jun 17, 2020

SUMMARY

On running the cloudformation_stack_set module the first time it successfully creates the stackset and deploys the stack instances. On future runs of the play without nothing changed an additional update operation is run and changed is returned as true.

On each run it creates a new operation in the stackets console, again despite nothing being changed.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

cloudformation_stack_set AWS module

ANSIBLE VERSION
ansible 2.9.2
  config file = None
  configured module search path = ['/home/naslanidis/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/naslanidis/code/github/aws-organizations-poc/env/lib/python3.6/site-packages/ansible
  executable location = /home/naslanidis/code/github/aws-organizations-poc/env/bin/ansible
  python version = 3.6.9 (default, Apr 18 2020, 01:56:04) [GCC 8.4.0]
CONFIGURATION
$ ansible-config dump --only-changed
$ 
OS / ENVIRONMENT

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic

STEPS TO REPRODUCE
- name: Create test stackset
  cloudformation_stack_set:
    name: iam-core-stackset.yml
    description: Test stack in two accounts
    region: ap-southeast-2    
    state: present
    capabilities: CAPABILITY_NAMED_IAM
    template: "{{role_path}}/templates/iam-core-stackset.yml"
    accounts: [12345679878]
    regions:
    - ap-southeast-2
EXPECTED RESULTS

On first run it works fine:

TASK [baseline-stacksets : Create test core stackset] *****************************************************************************************************************************************************************************
changed: [localhost]

PLAY RECAP ************************************************************************************************************************************************************************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

On second run without change it chould be changed=0 and nothing changes.

ACTUAL RESULTS

On the 2nd (and any future) run of the play:

TASK [baseline-stacksets : Create test core stackset] *****************************************************************************************************************************************************************************
changed: [localhost]

PLAY RECAP ************************************************************************************************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Each time I run the module a new stackset operation is created. This should not happen when nothing has changed in the task.

It's possible this was a design choice but essentially there's no comparison being done to compare the existing stack facts against the arguments in the ansible task. In the below, if there's no existing_stack_set, one is created. Else, the update_stack_set function is called. I feel there should be some comparison being done between the stack_params dict and the existing_stack_set dict to determine if an update is required.

    if state == 'present':
        if not existing_stack_set:
            # on create this parameter has a different name, and cannot be referenced later in the job log
            stack_params['ClientRequestToken'] = 'Ansible-StackSet-Create-{0}'.format(operation_uuid)
            changed = True
            create_stack_set(module, stack_params, cfn)
        else:
            stack_params['OperationId'] = 'Ansible-StackSet-Update-{0}'.format(operation_uuid)
            operation_ids.append(stack_params['OperationId'])
            if module.params.get('regions'):
                stack_params['OperationPreferences'] = get_operation_preferences(module)
            changed |= update_stack_set(module, stack_params, cfn)

additional operations for each run

@naslanidis
Copy link
Author

NOTE I updated this report as I discovered the original error I was getting in addition to the above issue was caused by not having wait: True set.

@goneri
Copy link
Member

goneri commented Feb 3, 2021

Hi @naslanidis, How would you compare the deployed stack to know if an update is actually required?

@fschroder-slyp
Copy link

fschroder-slyp commented Nov 22, 2022

Hi @goneri, I would create a change_set, just like with a normal stack. However, I believe this functionality is not available in AWS (for stack sets), so it would be a custom implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
affects_2.10 bug This issue/PR relates to a bug python3
Projects
None yet
Development

No branches or pull requests

4 participants