We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Cisco ASA_ACL "NameError: global name 'candidate' is not defined"
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME

asa_acl
##### ANSIBLE VERSION

```
root@osboxes:~/asa# ansible-playbook -i inventory acl.yml

PLAY [Test ASA] ****************************************************************

TASK [Create object to ACL-ANSIBLE] ********************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: NameError: global name 'candidate' is not defined
fatal: [asa]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_JUM9ib/ansible_module_asa_acl.py\", line 202, in <module>\n    main()\n  File \"/tmp/ansible_JUM9ib/ansible_module_asa_acl.py\", line 184, in main\n    commands = candidate.difference(config)\nNameError: global name 'candidate' is not defined\n", "module_stdout": "", "msg": "MODULE FAILURE"}

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

root@osboxes:~/asa#

```
##### CONFIGURATION
##### OS / ENVIRONMENT

Ubuntu
##### SUMMARY

Attempting to run asa_acl using ansible dev version results in above errors. asa_command and asa_config work with no issues. 
##### STEPS TO REPRODUCE

```

---

- name: Test ASA
  hosts: asa
  connection: local
  gather_facts: false

  tasks:

    - name: Create object to ACL-ANSIBLE
      asa_acl:
        lines:
          - "access-list ACL-ANSIBLE extended permit tcp any any eq 74"
        username: "ntc"
        host: "{{ inventory_hostname }}"
        authorize: true
        auth_pass: "\n"
```

```
ansible-playbook -i inventory acl.yml
```
##### EXPECTED RESULTS

ACL to be updated 
##### ACTUAL RESULTS

```
root@osboxes:~/asa# ansible-playbook -i inventory acl.yml -vvvv
Using /etc/ansible/ansible.cfg as config file
Loading callback plugin default of type stdout, v2.0 from /tmp/ansible/lib/ansible/plugins/callback/__init__.pyc

PLAYBOOK: acl.yml **************************************************************
1 plays in acl.yml

PLAY [Test ASA] ****************************************************************

TASK [Create object to ACL-ANSIBLE] ********************************************
task path: /root/asa/acl.yml:10
Using module file /tmp/ansible/lib/ansible/modules/extras/network/asa/asa_acl.py
<asa> ESTABLISH LOCAL CONNECTION FOR USER: root
<asa> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872 `" && echo ansible-tmp-1473449999.57-34289925616872="` echo $HOME/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872 `" ) && sleep 0'
<asa> PUT /tmp/tmpu2hszs TO /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/asa_acl.py
<asa> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/ /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/asa_acl.py && sleep 0'
<asa> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/asa_acl.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/" > /dev/null 2>&1 && sleep 0'
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
  File "/tmp/ansible_o9grpZ/ansible_module_asa_acl.py", line 202, in <module>
    main()
  File "/tmp/ansible_o9grpZ/ansible_module_asa_acl.py", line 184, in main
    commands = candidate.difference(config)
NameError: global name 'candidate' is not defined

fatal: [asa]: FAILED! => {
    "changed": false,
    "failed": true,
    "invocation": {
        "module_name": "asa_acl"
    },
    "module_stderr": "Traceback (most recent call last):\n  File \"/tmp/ansible_o9grpZ/ansible_module_asa_acl.py\", line 202, in <module>\n    main()\n  File \"/tmp/ansible_o9grpZ/ansible_module_asa_acl.py\", line 184, in main\n    commands = candidate.difference(config)\nNameError: global name 'candidate' is not defined\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE"
}

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


```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `network/asa/asa_acl.py`
Content:
```
1 #!/usr/bin/python
2 #
3 # This file is part of Ansible
4 #
5 # Ansible is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Ansible is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
17 #
18 
19 DOCUMENTATION = """
20 ---
21 module: asa_acl
22 version_added: "2.2"
23 author: "Patrick Ogenstad (@ogenstad)"
24 short_description: Manage access-lists on a Cisco ASA
25 description:
26   - This module allows you to work with access-lists on a Cisco ASA device.
27 extends_documentation_fragment: asa
28 options:
29   lines:
30     description:
31       - The ordered set of commands that should be configured in the
32         section.  The commands must be the exact same commands as found
33         in the device running-config.  Be sure to note the configuration
34         command syntanx as some commands are automatically modified by the
35         device config parser.
36     required: true
37   before:
38     description:
39       - The ordered set of commands to push on to the command stack if
40         a change needs to be made.  This allows the playbook designer
41         the opportunity to perform configuration commands prior to pushing
42         any changes without affecting how the set of commands are matched
43         against the system
44     required: false
45     default: null
46   after:
47     description:
48       - The ordered set of commands to append to the end of the command
49         stack if a changed needs to be made.  Just like with I(before) this
50         allows the playbook designer to append a set of commands to be
51         executed after the command set.
52     required: false
53     default: null
54   match:
55     description:
56       - Instructs the module on the way to perform the matching of
57         the set of commands against the current device config.  If
58         match is set to I(line), commands are matched line by line.  If
59         match is set to I(strict), command lines are matched with respect
60         to position.  Finally if match is set to I(exact), command lines
61         must be an equal match.
62     required: false
63     default: line
64     choices: ['line', 'strict', 'exact']
65   replace:
66     description:
67       - Instructs the module on the way to perform the configuration
68         on the device.  If the replace argument is set to I(line) then
69         the modified lines are pushed to the device in configuration
70         mode.  If the replace argument is set to I(block) then the entire
71         command block is pushed to the device in configuration mode if any
72         line is not correct
73     required: false
74     default: line
75     choices: ['line', 'block']
76   force:
77     description:
78       - The force argument instructs the module to not consider the
79         current devices running-config.  When set to true, this will
80         cause the module to push the contents of I(src) into the device
81         without first checking if already configured.
82     required: false
83     default: false
84     choices: ['yes', 'no']
85   config:
86     description:
87       - The module, by default, will connect to the remote device and
88         retrieve the current running-config to use as a base for comparing
89         against the contents of source.  There are times when it is not
90         desirable to have the task get the current running-config for
91         every task in a playbook.  The I(config) argument allows the
92         implementer to pass in the configuruation to use as the base
93         config for comparision.
94     required: false
95     default: null
96 """
97 
98 EXAMPLES = """
99 
100 - asa_acl:
101     lines:
102       - access-list ACL-ANSIBLE extended permit tcp any any eq 82
103       - access-list ACL-ANSIBLE extended permit tcp any any eq www
104       - access-list ACL-ANSIBLE extended permit tcp any any eq 97
105       - access-list ACL-ANSIBLE extended permit tcp any any eq 98
106       - access-list ACL-ANSIBLE extended permit tcp any any eq 99
107     before: clear configure access-list ACL-ANSIBLE
108     match: strict
109     replace: block
110 
111 - asa_acl:
112     lines:
113       - access-list ACL-OUTSIDE extended permit tcp any any eq www
114       - access-list ACL-OUTSIDE extended permit tcp any any eq https
115      context: customer_a
116 """
117 
118 RETURN = """
119 updates:
120   description: The set of commands that will be pushed to the remote device
121   returned: always
122   type: list
123   sample: ['...', '...']
124 
125 responses:
126   description: The set of responses from issuing the commands on the device
127   retured: when not check_mode
128   type: list
129   sample: ['...', '...']
130 """
131 from ansible.module_utils.netcfg import NetworkConfig
132 from ansible.module_utils.asa import NetworkModule
133 
134 
135 def get_config(module):
136     config = module.params['config'] or dict()
137     if not config and not module.params['force']:
138         config = module.config
139     return config
140 
141 
142 def check_input_acl(lines, module):
143     first_line = True
144     for line in lines:
145         ace = line.split()
146         if ace[0] != 'access-list':
147             module.fail_json(msg='All lines/commands must begin with "access-list" %s is not permitted' % ace[0])
148         if len(ace) <= 1:
149             module.fail_json(msg='All lines/commainds must contain the name of the access-list')
150         if first_line:
151             acl_name = ace[1]
152         else:
153             if acl_name != ace[1]:
154                 module.fail_json(msg='All lines/commands must use the same access-list %s is not %s' % (ace[1], acl_name))
155         first_line = False
156 
157     return 'access-list %s' % acl_name
158 
159 def main():
160 
161     argument_spec = dict(
162         lines=dict(aliases=['commands'], required=True, type='list'),
163         before=dict(type='list'),
164         after=dict(type='list'),
165         match=dict(default='line', choices=['line', 'strict', 'exact']),
166         replace=dict(default='line', choices=['line', 'block']),
167         force=dict(default=False, type='bool'),
168         config=dict()
169     )
170 
171     module = NetworkModule(argument_spec=argument_spec,
172                            supports_check_mode=True)
173 
174     lines = module.params['lines']
175 
176     before = module.params['before']
177     after = module.params['after']
178 
179     match = module.params['match']
180     replace = module.params['replace']
181 
182     module.filter = check_input_acl(lines, module)
183     if not module.params['force']:
184         commands = candidate.difference(config)
185         commands = dumps(commands, 'commands').split('\n')
186         commands = [str(c) for c in commands if c]
187     else:
188         commands = str(candidate).split('\n')
189 
190     if commands:
191         if not module.check_mode:
192             response = module.config(commands)
193             result['responses'] = response
194         result['changed'] = True
195 
196     result['updates'] = commands
197 
198     module.exit_json(**result)
199 
200 
201 if __name__ == '__main__':
202     main()
203
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/network/asa/asa_acl.py b/network/asa/asa_acl.py
--- a/network/asa/asa_acl.py
+++ b/network/asa/asa_acl.py
@@ -128,8 +128,10 @@
   type: list
   sample: ['...', '...']
 """
+import ansible.module_utils.asa
+
 from ansible.module_utils.netcfg import NetworkConfig
-from ansible.module_utils.asa import NetworkModule
+from ansible.module_utils.network import NetworkModule
 
 
 def get_config(module):
@@ -179,16 +181,22 @@
     match = module.params['match']
     replace = module.params['replace']
 
+    candidate = NetworkConfig(indent=1)
+    candidate.add(lines)
+
     module.filter = check_input_acl(lines, module)
+
     if not module.params['force']:
+        contents = get_config(module)
+        config = NetworkConfig(indent=1, contents=contents)
         commands = candidate.difference(config)
         commands = dumps(commands, 'commands').split('\n')
-        commands = [str(c) for c in commands if c]
     else:
         commands = str(candidate).split('\n')
 
     if commands:
         if not module.check_mode:
+            commands = [str(c) for c in commands if c]
             response = module.config(commands)
             result['responses'] = response
         result['changed'] = True

{"golden_diff": "diff --git a/network/asa/asa_acl.py b/network/asa/asa_acl.py\n--- a/network/asa/asa_acl.py\n+++ b/network/asa/asa_acl.py\n@@ -128,8 +128,10 @@\n   type: list\n   sample: ['...', '...']\n \"\"\"\n+import ansible.module_utils.asa\n+\n from ansible.module_utils.netcfg import NetworkConfig\n-from ansible.module_utils.asa import NetworkModule\n+from ansible.module_utils.network import NetworkModule\n \n \n def get_config(module):\n@@ -179,16 +181,22 @@\n     match = module.params['match']\n     replace = module.params['replace']\n \n+    candidate = NetworkConfig(indent=1)\n+    candidate.add(lines)\n+\n     module.filter = check_input_acl(lines, module)\n+\n     if not module.params['force']:\n+        contents = get_config(module)\n+        config = NetworkConfig(indent=1, contents=contents)\n         commands = candidate.difference(config)\n         commands = dumps(commands, 'commands').split('\\n')\n-        commands = [str(c) for c in commands if c]\n     else:\n         commands = str(candidate).split('\\n')\n \n     if commands:\n         if not module.check_mode:\n+            commands = [str(c) for c in commands if c]\n             response = module.config(commands)\n             result['responses'] = response\n         result['changed'] = True\n", "issue": "Cisco ASA_ACL \"NameError: global name 'candidate' is not defined\"\n##### ISSUE TYPE\n- Bug Report\n##### COMPONENT NAME\n\nasa_acl\n##### ANSIBLE VERSION\n\n```\nroot@osboxes:~/asa# ansible-playbook -i inventory acl.yml\n\nPLAY [Test ASA] ****************************************************************\n\nTASK [Create object to ACL-ANSIBLE] ********************************************\nAn exception occurred during task execution. To see the full traceback, use -vvv. The error was: NameError: global name 'candidate' is not defined\nfatal: [asa]: FAILED! => {\"changed\": false, \"failed\": true, \"module_stderr\": \"Traceback (most recent call last):\\n  File \\\"/tmp/ansible_JUM9ib/ansible_module_asa_acl.py\\\", line 202, in <module>\\n    main()\\n  File \\\"/tmp/ansible_JUM9ib/ansible_module_asa_acl.py\\\", line 184, in main\\n    commands = candidate.difference(config)\\nNameError: global name 'candidate' is not defined\\n\", \"module_stdout\": \"\", \"msg\": \"MODULE FAILURE\"}\n\nPLAY RECAP *********************************************************************\nasa                        : ok=0    changed=0    unreachable=0    failed=1\n\nroot@osboxes:~/asa#\n\n```\n##### CONFIGURATION\n##### OS / ENVIRONMENT\n\nUbuntu\n##### SUMMARY\n\nAttempting to run asa_acl using ansible dev version results in above errors. asa_command and asa_config work with no issues. \n##### STEPS TO REPRODUCE\n\n```\n\n---\n\n- name: Test ASA\n  hosts: asa\n  connection: local\n  gather_facts: false\n\n  tasks:\n\n    - name: Create object to ACL-ANSIBLE\n      asa_acl:\n        lines:\n          - \"access-list ACL-ANSIBLE extended permit tcp any any eq 74\"\n        username: \"ntc\"\n        host: \"{{ inventory_hostname }}\"\n        authorize: true\n        auth_pass: \"\\n\"\n```\n\n```\nansible-playbook -i inventory acl.yml\n```\n##### EXPECTED RESULTS\n\nACL to be updated \n##### ACTUAL RESULTS\n\n```\nroot@osboxes:~/asa# ansible-playbook -i inventory acl.yml -vvvv\nUsing /etc/ansible/ansible.cfg as config file\nLoading callback plugin default of type stdout, v2.0 from /tmp/ansible/lib/ansible/plugins/callback/__init__.pyc\n\nPLAYBOOK: acl.yml **************************************************************\n1 plays in acl.yml\n\nPLAY [Test ASA] ****************************************************************\n\nTASK [Create object to ACL-ANSIBLE] ********************************************\ntask path: /root/asa/acl.yml:10\nUsing module file /tmp/ansible/lib/ansible/modules/extras/network/asa/asa_acl.py\n<asa> ESTABLISH LOCAL CONNECTION FOR USER: root\n<asa> EXEC /bin/sh -c '( umask 77 && mkdir -p \"` echo $HOME/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872 `\" && echo ansible-tmp-1473449999.57-34289925616872=\"` echo $HOME/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872 `\" ) && sleep 0'\n<asa> PUT /tmp/tmpu2hszs TO /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/asa_acl.py\n<asa> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/ /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/asa_acl.py && sleep 0'\n<asa> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/asa_acl.py; rm -rf \"/root/.ansible/tmp/ansible-tmp-1473449999.57-34289925616872/\" > /dev/null 2>&1 && sleep 0'\nAn exception occurred during task execution. The full traceback is:\nTraceback (most recent call last):\n  File \"/tmp/ansible_o9grpZ/ansible_module_asa_acl.py\", line 202, in <module>\n    main()\n  File \"/tmp/ansible_o9grpZ/ansible_module_asa_acl.py\", line 184, in main\n    commands = candidate.difference(config)\nNameError: global name 'candidate' is not defined\n\nfatal: [asa]: FAILED! => {\n    \"changed\": false,\n    \"failed\": true,\n    \"invocation\": {\n        \"module_name\": \"asa_acl\"\n    },\n    \"module_stderr\": \"Traceback (most recent call last):\\n  File \\\"/tmp/ansible_o9grpZ/ansible_module_asa_acl.py\\\", line 202, in <module>\\n    main()\\n  File \\\"/tmp/ansible_o9grpZ/ansible_module_asa_acl.py\\\", line 184, in main\\n    commands = candidate.difference(config)\\nNameError: global name 'candidate' is not defined\\n\",\n    \"module_stdout\": \"\",\n    \"msg\": \"MODULE FAILURE\"\n}\n\nPLAY RECAP *********************************************************************\nasa                        : ok=0    changed=0    unreachable=0    failed=1\n\n\n```\n\n", "before_files": [{"content": "#!/usr/bin/python\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n#\n\nDOCUMENTATION = \"\"\"\n---\nmodule: asa_acl\nversion_added: \"2.2\"\nauthor: \"Patrick Ogenstad (@ogenstad)\"\nshort_description: Manage access-lists on a Cisco ASA\ndescription:\n  - This module allows you to work with access-lists on a Cisco ASA device.\nextends_documentation_fragment: asa\noptions:\n  lines:\n    description:\n      - The ordered set of commands that should be configured in the\n        section.  The commands must be the exact same commands as found\n        in the device running-config.  Be sure to note the configuration\n        command syntanx as some commands are automatically modified by the\n        device config parser.\n    required: true\n  before:\n    description:\n      - The ordered set of commands to push on to the command stack if\n        a change needs to be made.  This allows the playbook designer\n        the opportunity to perform configuration commands prior to pushing\n        any changes without affecting how the set of commands are matched\n        against the system\n    required: false\n    default: null\n  after:\n    description:\n      - The ordered set of commands to append to the end of the command\n        stack if a changed needs to be made.  Just like with I(before) this\n        allows the playbook designer to append a set of commands to be\n        executed after the command set.\n    required: false\n    default: null\n  match:\n    description:\n      - Instructs the module on the way to perform the matching of\n        the set of commands against the current device config.  If\n        match is set to I(line), commands are matched line by line.  If\n        match is set to I(strict), command lines are matched with respect\n        to position.  Finally if match is set to I(exact), command lines\n        must be an equal match.\n    required: false\n    default: line\n    choices: ['line', 'strict', 'exact']\n  replace:\n    description:\n      - Instructs the module on the way to perform the configuration\n        on the device.  If the replace argument is set to I(line) then\n        the modified lines are pushed to the device in configuration\n        mode.  If the replace argument is set to I(block) then the entire\n        command block is pushed to the device in configuration mode if any\n        line is not correct\n    required: false\n    default: line\n    choices: ['line', 'block']\n  force:\n    description:\n      - The force argument instructs the module to not consider the\n        current devices running-config.  When set to true, this will\n        cause the module to push the contents of I(src) into the device\n        without first checking if already configured.\n    required: false\n    default: false\n    choices: ['yes', 'no']\n  config:\n    description:\n      - The module, by default, will connect to the remote device and\n        retrieve the current running-config to use as a base for comparing\n        against the contents of source.  There are times when it is not\n        desirable to have the task get the current running-config for\n        every task in a playbook.  The I(config) argument allows the\n        implementer to pass in the configuruation to use as the base\n        config for comparision.\n    required: false\n    default: null\n\"\"\"\n\nEXAMPLES = \"\"\"\n\n- asa_acl:\n    lines:\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 82\n      - access-list ACL-ANSIBLE extended permit tcp any any eq www\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 97\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 98\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 99\n    before: clear configure access-list ACL-ANSIBLE\n    match: strict\n    replace: block\n\n- asa_acl:\n    lines:\n      - access-list ACL-OUTSIDE extended permit tcp any any eq www\n      - access-list ACL-OUTSIDE extended permit tcp any any eq https\n     context: customer_a\n\"\"\"\n\nRETURN = \"\"\"\nupdates:\n  description: The set of commands that will be pushed to the remote device\n  returned: always\n  type: list\n  sample: ['...', '...']\n\nresponses:\n  description: The set of responses from issuing the commands on the device\n  retured: when not check_mode\n  type: list\n  sample: ['...', '...']\n\"\"\"\nfrom ansible.module_utils.netcfg import NetworkConfig\nfrom ansible.module_utils.asa import NetworkModule\n\n\ndef get_config(module):\n    config = module.params['config'] or dict()\n    if not config and not module.params['force']:\n        config = module.config\n    return config\n\n\ndef check_input_acl(lines, module):\n    first_line = True\n    for line in lines:\n        ace = line.split()\n        if ace[0] != 'access-list':\n            module.fail_json(msg='All lines/commands must begin with \"access-list\" %s is not permitted' % ace[0])\n        if len(ace) <= 1:\n            module.fail_json(msg='All lines/commainds must contain the name of the access-list')\n        if first_line:\n            acl_name = ace[1]\n        else:\n            if acl_name != ace[1]:\n                module.fail_json(msg='All lines/commands must use the same access-list %s is not %s' % (ace[1], acl_name))\n        first_line = False\n\n    return 'access-list %s' % acl_name\n\ndef main():\n\n    argument_spec = dict(\n        lines=dict(aliases=['commands'], required=True, type='list'),\n        before=dict(type='list'),\n        after=dict(type='list'),\n        match=dict(default='line', choices=['line', 'strict', 'exact']),\n        replace=dict(default='line', choices=['line', 'block']),\n        force=dict(default=False, type='bool'),\n        config=dict()\n    )\n\n    module = NetworkModule(argument_spec=argument_spec,\n                           supports_check_mode=True)\n\n    lines = module.params['lines']\n\n    before = module.params['before']\n    after = module.params['after']\n\n    match = module.params['match']\n    replace = module.params['replace']\n\n    module.filter = check_input_acl(lines, module)\n    if not module.params['force']:\n        commands = candidate.difference(config)\n        commands = dumps(commands, 'commands').split('\\n')\n        commands = [str(c) for c in commands if c]\n    else:\n        commands = str(candidate).split('\\n')\n\n    if commands:\n        if not module.check_mode:\n            response = module.config(commands)\n            result['responses'] = response\n        result['changed'] = True\n\n    result['updates'] = commands\n\n    module.exit_json(**result)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "network/asa/asa_acl.py"}], "after_files": [{"content": "#!/usr/bin/python\n#\n# This file is part of Ansible\n#\n# Ansible is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Ansible is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.\n#\n\nDOCUMENTATION = \"\"\"\n---\nmodule: asa_acl\nversion_added: \"2.2\"\nauthor: \"Patrick Ogenstad (@ogenstad)\"\nshort_description: Manage access-lists on a Cisco ASA\ndescription:\n  - This module allows you to work with access-lists on a Cisco ASA device.\nextends_documentation_fragment: asa\noptions:\n  lines:\n    description:\n      - The ordered set of commands that should be configured in the\n        section.  The commands must be the exact same commands as found\n        in the device running-config.  Be sure to note the configuration\n        command syntanx as some commands are automatically modified by the\n        device config parser.\n    required: true\n  before:\n    description:\n      - The ordered set of commands to push on to the command stack if\n        a change needs to be made.  This allows the playbook designer\n        the opportunity to perform configuration commands prior to pushing\n        any changes without affecting how the set of commands are matched\n        against the system\n    required: false\n    default: null\n  after:\n    description:\n      - The ordered set of commands to append to the end of the command\n        stack if a changed needs to be made.  Just like with I(before) this\n        allows the playbook designer to append a set of commands to be\n        executed after the command set.\n    required: false\n    default: null\n  match:\n    description:\n      - Instructs the module on the way to perform the matching of\n        the set of commands against the current device config.  If\n        match is set to I(line), commands are matched line by line.  If\n        match is set to I(strict), command lines are matched with respect\n        to position.  Finally if match is set to I(exact), command lines\n        must be an equal match.\n    required: false\n    default: line\n    choices: ['line', 'strict', 'exact']\n  replace:\n    description:\n      - Instructs the module on the way to perform the configuration\n        on the device.  If the replace argument is set to I(line) then\n        the modified lines are pushed to the device in configuration\n        mode.  If the replace argument is set to I(block) then the entire\n        command block is pushed to the device in configuration mode if any\n        line is not correct\n    required: false\n    default: line\n    choices: ['line', 'block']\n  force:\n    description:\n      - The force argument instructs the module to not consider the\n        current devices running-config.  When set to true, this will\n        cause the module to push the contents of I(src) into the device\n        without first checking if already configured.\n    required: false\n    default: false\n    choices: ['yes', 'no']\n  config:\n    description:\n      - The module, by default, will connect to the remote device and\n        retrieve the current running-config to use as a base for comparing\n        against the contents of source.  There are times when it is not\n        desirable to have the task get the current running-config for\n        every task in a playbook.  The I(config) argument allows the\n        implementer to pass in the configuruation to use as the base\n        config for comparision.\n    required: false\n    default: null\n\"\"\"\n\nEXAMPLES = \"\"\"\n\n- asa_acl:\n    lines:\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 82\n      - access-list ACL-ANSIBLE extended permit tcp any any eq www\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 97\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 98\n      - access-list ACL-ANSIBLE extended permit tcp any any eq 99\n    before: clear configure access-list ACL-ANSIBLE\n    match: strict\n    replace: block\n\n- asa_acl:\n    lines:\n      - access-list ACL-OUTSIDE extended permit tcp any any eq www\n      - access-list ACL-OUTSIDE extended permit tcp any any eq https\n     context: customer_a\n\"\"\"\n\nRETURN = \"\"\"\nupdates:\n  description: The set of commands that will be pushed to the remote device\n  returned: always\n  type: list\n  sample: ['...', '...']\n\nresponses:\n  description: The set of responses from issuing the commands on the device\n  retured: when not check_mode\n  type: list\n  sample: ['...', '...']\n\"\"\"\nimport ansible.module_utils.asa\n\nfrom ansible.module_utils.netcfg import NetworkConfig\nfrom ansible.module_utils.network import NetworkModule\n\n\ndef get_config(module):\n    config = module.params['config'] or dict()\n    if not config and not module.params['force']:\n        config = module.config\n    return config\n\n\ndef check_input_acl(lines, module):\n    first_line = True\n    for line in lines:\n        ace = line.split()\n        if ace[0] != 'access-list':\n            module.fail_json(msg='All lines/commands must begin with \"access-list\" %s is not permitted' % ace[0])\n        if len(ace) <= 1:\n            module.fail_json(msg='All lines/commainds must contain the name of the access-list')\n        if first_line:\n            acl_name = ace[1]\n        else:\n            if acl_name != ace[1]:\n                module.fail_json(msg='All lines/commands must use the same access-list %s is not %s' % (ace[1], acl_name))\n        first_line = False\n\n    return 'access-list %s' % acl_name\n\ndef main():\n\n    argument_spec = dict(\n        lines=dict(aliases=['commands'], required=True, type='list'),\n        before=dict(type='list'),\n        after=dict(type='list'),\n        match=dict(default='line', choices=['line', 'strict', 'exact']),\n        replace=dict(default='line', choices=['line', 'block']),\n        force=dict(default=False, type='bool'),\n        config=dict()\n    )\n\n    module = NetworkModule(argument_spec=argument_spec,\n                           supports_check_mode=True)\n\n    lines = module.params['lines']\n\n    before = module.params['before']\n    after = module.params['after']\n\n    match = module.params['match']\n    replace = module.params['replace']\n\n    candidate = NetworkConfig(indent=1)\n    candidate.add(lines)\n\n    module.filter = check_input_acl(lines, module)\n\n    if not module.params['force']:\n        contents = get_config(module)\n        config = NetworkConfig(indent=1, contents=contents)\n        commands = candidate.difference(config)\n        commands = dumps(commands, 'commands').split('\\n')\n    else:\n        commands = str(candidate).split('\\n')\n\n    if commands:\n        if not module.check_mode:\n            commands = [str(c) for c in commands if c]\n            response = module.config(commands)\n            result['responses'] = response\n        result['changed'] = True\n\n    result['updates'] = commands\n\n    module.exit_json(**result)\n\n\nif __name__ == '__main__':\n    main()\n", "path": "network/asa/asa_acl.py"}]}