Repository: ansible/ansible-modules-extras

Issue:
os_stack module seems to be lacking idempotency
<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE

<!--- Pick one below and delete the rest: -->
- Bug Report
##### COMPONENT NAME

os_stack
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
ansible 2.2.0
  config file = /root/.ansible.cfg
  configured module search path = Default w/o overrides
```
##### CONFIGURATION

<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->

```
[root@2f4037fae5f7 ~]# cat ~/.ansible.cfg 
[defaults]
roles_path= /root/repository/rhc-ose/rhc-ose-ansible/roles:/root/repository/openshift-ansible/roles
filter_plugins= /usr/share/ansible_plugins/filter_plugins:/root/repository/openshift-ansible/filter_plugins
host_key_checking = False
```
##### OS / ENVIRONMENT

<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

RHEL/Centos/Fedora in OpenStack
##### SUMMARY

<!--- Explain the problem briefly -->

I am attempting to design a role around the `os_stack` module to do idempotent provisioning. When I run the role (invoked via this playbook: https://github.com/etsauer/casl-ansible/blob/openstack-heat/roles/openstack-stack/test/stack-create-test.yml) for the first time, it works great. If I try to run it a second time, the run fails with some errors about missing parameters.
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->

Clone my repo, and run the playbook here: https://github.com/etsauer/casl-ansible/blob/openstack-heat/roles/openstack-stack/test/stack-create-test.yml

```
[root@2f4037fae5f7 ~]# ansible-playbook -i ./repository/casl-ansible/inventory/openstack-stack-test ./repository/casl-ansible/roles/openstack-stack/test/stack-create-test.yml
 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [openstack-stack : create stack] ******************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0   

[root@2f4037fae5f7 ~]# ansible-playbook -i ./repository/casl-ansible/inventory/openstack-stack-test ./repository/casl-ansible/roles/openstack-stack/test/stack-create-test.yml
 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [localhost] ***************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [openstack-stack : create stack] ******************************************
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "Error updating stack test-stack: ERROR: The Parameter (dns_image) was not provided."}
        to retry, use: --limit @./repository/casl-ansible/roles/openstack-stack/test/stack-create-test.retry

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=1   

```

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->

A second successful run, changing nothing because the module can detect that what I'm asking for has already been provisioned.
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with high verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->

```
TASK [openstack-stack : create stack] ******************************************
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "Error updating stack test-stack: ERROR: The Parameter (dns_image) was not provided."}
        to retry, use: --limit @./repository/casl-ansible/roles/openstack-stack/test/stack-create-test.retry
```



Discussion:
<!-- @etsauer: Thanks for filing this bug report! -->

@emonty, @shrews, @juliakreger, @j2sol, @rcarrillocruz, ping. This issue is waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_bug_new --->

@emonty, @shrews, @juliakreger, @j2sol, @rcarrillocruz, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->

@emonty, @shrews, @juliakreger, @j2sol, @rcarrillocruz, ping. This issue is still waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_renotify_maintainer --->


Resolving patch:
diff --git a/cloud/openstack/os_stack.py b/cloud/openstack/os_stack.py
--- a/cloud/openstack/os_stack.py
+++ b/cloud/openstack/os_stack.py
@@ -180,7 +180,8 @@ def _update_stack(module, stack, cloud):
             environment_files=module.params['environment'],
             timeout=module.params['timeout'],
             rollback=module.params['rollback'],
-            wait=module.params['wait'])
+            wait=module.params['wait'],
+            **module.params['parameters'])
 
         if stack['stack_status'] == 'UPDATE_COMPLETE':
             return stack


Test patch: