Repository: ansible/ansible

Issue:
iptables module: match=conntrack with ctstate not working
<!---
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.1.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.
-->
- Host OS: Linux Mint 17 (Ubuntu 14.04) 
- Guest OS: Debian 8 (Jessie)

##### SUMMARY
<!--- Explain the problem briefly -->

When running the following task:

```
     - iptables:
         chain: INPUT
         match: conntrack
         ctstate: ESTABLISHED,RELATED
         jump: ACCEPT
```

I get the following error:

```
fatal: [default]: FAILED! => {"changed": false, "cmd": "/sbin/iptables -t filter -A INPUT -m conntrack -j ACCEPT -m state --state ESTABLISHED,RELATED", "failed": true, "msg": "iptables v1.4.21: conntrack: At least one option is required\nTry `iptables -h' or 'iptables --help' for more information.", "rc": 2, "stderr": "iptables v1.4.21: conntrack: At least one option is required\nTry `iptables -h' or 'iptables --help' for more information.\n", "stdout": "", "stdout_lines": []}
```

The right `iptables` command should be:

```
/sbin/iptables -t filter -A INPUT -m conntrack -j ACCEPT --ctstate ESTABLISHED,RELATED
```

##### 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 -->
```yaml
    - iptables: 
        chain: INPUT 
        match: conntrack 
        ctstate: ESTABLISHED,RELATED 
        jump: ACCEPT
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->

```
/sbin/iptables -t filter -A INPUT -m conntrack -j ACCEPT --ctstate ESTABLISHED,RELATED
```

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
fatal: [default]: FAILED! => {"changed": false, "cmd": "/sbin/iptables -t filter -A INPUT -m conntrack -j ACCEPT -m state --state ESTABLISHED,RELATED", "failed": true, "msg": "iptables v1.4.21: conntrack: At least one option is required\nTry `iptables -h' or 'iptables --help' for more information.", "rc": 2, "stderr": "iptables v1.4.21: conntrack: At least one option is required\nTry `iptables -h' or 'iptables --help' for more information.\n", "stdout": "", "stdout_lines": []}
```



Discussion:
cc @LinusU
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

not sure what is going on with how this module creates options, but this might be a fix
```
diff --git a/lib/ansible/modules/system/iptables.py b/lib/ansible/modules/system/iptables.py
index e22328e..21aa09d 100644
--- a/lib/ansible/modules/system/iptables.py
+++ b/lib/ansible/modules/system/iptables.py
@@ -399,8 +399,8 @@ def construct_rule(params):
         False)
     append_match(rule, params['comment'], 'comment')
     append_param(rule, params['comment'], '--comment', False)
-    append_match(rule, params['ctstate'], 'state')
-    append_csv(rule, params['ctstate'], '--state')
+    append_match(rule, params['ctstate'], 'ctstate')
+    append_csv(rule, params['ctstate'], '--ctstate')
     append_match(rule, params['limit'] or params['limit_burst'], 'limit')
     append_param(rule, params['limit'], '--limit', False)
     append_param(rule, params['limit_burst'], '--limit-burst', False)
```
See here: http://unix.stackexchange.com/questions/108169/what-is-the-difference-between-m-conntrack-ctstate-and-m-state-state

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
@@ -399,8 +399,15 @@ def construct_rule(params):
         False)
     append_match(rule, params['comment'], 'comment')
     append_param(rule, params['comment'], '--comment', False)
-    append_match(rule, params['ctstate'], 'state')
-    append_csv(rule, params['ctstate'], '--state')
+    if 'conntrack' in params['match']:
+        append_csv(rule, params['ctstate'], '--ctstate')
+    elif 'state' in params['match']:
+        append_csv(rule, params['ctstate'], '--state')
+    elif params['ctstate']:
+        append_match(rule, params['ctstate'], 'conntrack')
+        append_csv(rule, params['ctstate'], '--ctstate')
+    else:
+        return False
     append_match(rule, params['limit'] or params['limit_burst'], 'limit')
     append_param(rule, params['limit'], '--limit', False)
     append_param(rule, params['limit_burst'], '--limit-burst', False)


Test patch: