Repository: ansible/ansible

Issue:
iptables module make policy and flush changes in check mode
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
iptables module

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.0.0
  config file = /etc/ansible/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).
-->

##### 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.
-->
linux

##### SUMMARY
<!--- Explain the problem briefly -->

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```
ansible-playbook /vagrant/play.yml -l localhost --check
```
```yaml
 - hosts: all
   tasks:
     - iptables:
         chain: INPUT
         policy: DROP
       become: yes
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
```
ansible-playbook /vagrant/play.yml -l localhost --check

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [iptables] ****************************************************************
changed: [localhost]
```
```
sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   
```

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
```
ansible-playbook /vagrant/play.yml -l localhost --check

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [iptables] ****************************************************************
ok: [localhost]

```
<!--- Paste verbatim command output between quotes below -->
```
sudo iptables -L
Chain INPUT (policy DROP)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination   
```



Discussion:
cc @LinusU
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/system/iptables.py b/lib/ansible/modules/system/iptables.py
--- a/lib/ansible/modules/system/iptables.py
+++ b/lib/ansible/modules/system/iptables.py
@@ -342,6 +342,9 @@
     protocol: tcp
 '''
 
+# import module snippets
+from ansible.module_utils.basic import AnsibleModule
+
 def append_param(rule, param, flag, is_list):
     if is_list:
         for item in param:
@@ -519,46 +522,39 @@ def main():
 
     # Check if chain option is required
     if args['flush'] is False and args['chain'] is None:
-        module.fail_json(
-            msg="Either chain or flush parameter must be specified.")
+        module.fail_json( msg="Either chain or flush parameter must be specified.")
 
     # Flush the table
-    if args['flush'] is True:
-        flush_table(iptables_path, module, module.params)
-        module.exit_json(**args)
+    if args['flush']:
+        args['changed'] = True
+        if not module.check_mode:
+            flush_table(iptables_path, module, module.params)
 
     # Set the policy
-    if module.params['policy']:
-        set_chain_policy(iptables_path, module, module.params)
-        module.exit_json(**args)
-
-    insert = (module.params['action'] == 'insert')
-    rule_is_present = check_present(iptables_path, module, module.params)
-    should_be_present = (args['state'] == 'present')
-
-    # Check if target is up to date
-    args['changed'] = (rule_is_present != should_be_present)
-
-    # Check only; don't modify
-    if module.check_mode:
-        module.exit_json(changed=args['changed'])
-
-    # Target is already up to date
-    if args['changed'] is False:
-        module.exit_json(**args)
-
-    if should_be_present:
-        if insert:
-            insert_rule(iptables_path, module, module.params)
-        else:
-            append_rule(iptables_path, module, module.params)
+    elif module.params['policy']:
+        args['changed'] = True
+        if not module.check_mode:
+            set_chain_policy(iptables_path, module, module.params)
+
+    # Chain
     else:
-        remove_rule(iptables_path, module, module.params)
+        insert = (module.params['action'] == 'insert')
+        rule_is_present = check_present(iptables_path, module, module.params)
+        should_be_present = (args['state'] == 'present')
+
+        # Check if target is up to date
+        args['changed'] = (rule_is_present != should_be_present)
+
+        if args['changed'] and not module.check_mode:
+            if should_be_present:
+                if insert:
+                    insert_rule(iptables_path, module, module.params)
+                else:
+                    append_rule(iptables_path, module, module.params)
+            else:
+                remove_rule(iptables_path, module, module.params)
 
     module.exit_json(**args)
 
-# import module snippets
-from ansible.module_utils.basic import *
-
 if __name__ == '__main__':
     main()


Test patch: