prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  network _template not checking arguments correctly
  ##### ISSUE TYPE
  - Bug Report
  ##### COMPONENT NAME
  
  lib/ansible/plugins/action/net_template.py
  ##### ANSIBLE VERSION
  
  devel
  ##### CONFIGURATION
  ##### OS / ENVIRONMENT
  ##### SUMMARY
  ##### STEPS TO REPRODUCE
  
  ```
  
  ---
  - name: Backup existing configuration
    eos_template:
      backup: yes
  ```
  
  No other `vars` set
  
  same for `ios_template`
  ##### EXPECTED RESULTS
  
  `msg": "missing required arguments: host"` (or src)
  ##### ACTUAL RESULTS
  
  ```
    File "/home/gundalow/git/ansible-inc/ansible/lib/ansible/plugins/action/net_template.py", line 43, in run
      self._handle_template()
    File "/home/gundalow/git/ansible-inc/ansible/lib/ansible/plugins/action/net_template.py", line 80, in _handle_template
      if os.path.isabs(src) or urlparse.urlsplit('src').scheme:
    File "/usr/lib/python2.7/posixpath.py", line 54, in isabs
      return s.startswith('/')
  AttributeError: 'NoneType' object has no attribute 'startswith'
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `lib/ansible/plugins/action/net_template.py`
  Content:
  ```
  1 #
  2 # Copyright 2015 Peter Sprygada <psprygada@ansible.com>
  3 #
  4 # This file is part of Ansible
  5 #
  6 # Ansible is free software: you can redistribute it and/or modify
  7 # it under the terms of the GNU General Public License as published by
  8 # the Free Software Foundation, either version 3 of the License, or
  9 # (at your option) any later version.
  10 #
  11 # Ansible is distributed in the hope that it will be useful,
  12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 # GNU General Public License for more details.
  15 #
  16 # You should have received a copy of the GNU General Public License
  17 # along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
  18 #
  19 from __future__ import (absolute_import, division, print_function)
  20 __metaclass__ = type
  21 
  22 import sys
  23 import os
  24 import time
  25 import glob
  26 import urlparse
  27 
  28 from ansible.plugins.action import ActionBase
  29 from ansible.utils.boolean import boolean
  30 from ansible.utils.unicode import to_unicode
  31 
  32 BOOLEANS = ('true', 'false', 'yes', 'no')
  33 
  34 class ActionModule(ActionBase):
  35 
  36     TRANSFERS_FILES = False
  37 
  38     def run(self, tmp=None, task_vars=None):
  39         result = super(ActionModule, self).run(tmp, task_vars)
  40         result['changed'] = False
  41 
  42         try:
  43             self._handle_template()
  44         except ValueError as exc:
  45             return dict(failed=True, msg=exc.message)
  46 
  47         result.update(self._execute_module(module_name=self._task.action,
  48             module_args=self._task.args, task_vars=task_vars))
  49 
  50         if self._task.args.get('backup') and result.get('_backup'):
  51             # User requested backup and no error occurred in module.
  52             # NOTE: If there is a parameter error, _backup key may not be in results.
  53             self._write_backup(task_vars['inventory_hostname'], result['_backup'])
  54 
  55         if '_backup' in result:
  56             del result['_backup']
  57 
  58         return result
  59 
  60     def _get_working_path(self):
  61         cwd = self._loader.get_basedir()
  62         if self._task._role is not None:
  63             cwd = self._task._role._role_path
  64         return cwd
  65 
  66     def _write_backup(self, host, contents):
  67         backup_path = self._get_working_path() + '/backup'
  68         if not os.path.exists(backup_path):
  69             os.mkdir(backup_path)
  70         for fn in glob.glob('%s/%s*' % (backup_path, host)):
  71             os.remove(fn)
  72         tstamp = time.strftime("%Y-%m-%d@%H:%M:%S", time.localtime(time.time()))
  73         filename = '%s/%s_config.%s' % (backup_path, host, tstamp)
  74         open(filename, 'w').write(contents)
  75 
  76     def _handle_template(self):
  77         src = self._task.args.get('src')
  78         working_path = self._get_working_path()
  79 
  80         if os.path.isabs(src) or urlparse.urlsplit('src').scheme:
  81             source = src
  82         else:
  83             source = self._loader.path_dwim_relative(working_path, 'templates', src)
  84             if not source:
  85                 source = self._loader.path_dwim_relative(working_path, src)
  86 
  87         if not os.path.exists(source):
  88             return
  89 
  90         try:
  91             with open(source, 'r') as f:
  92                 template_data = to_unicode(f.read())
  93         except IOError:
  94             return dict(failed=True, msg='unable to load src file')
  95 
  96         # Create a template search path in the following order:
  97         # [working_path, self_role_path, dependent_role_paths, dirname(source)]
  98         searchpath = [working_path]
  99         if self._task._role is not None:
  100             searchpath.append(self._task._role._role_path)
  101             dep_chain = self._task._block.get_dep_chain()
  102             if dep_chain is not None:
  103                 for role in dep_chain:
  104                     searchpath.append(role._role_path)
  105         searchpath.append(os.path.dirname(source))
  106         self._templar.environment.loader.searchpath = searchpath
  107         self._task.args['src'] = self._templar.template(template_data)
  108 
  109 
  110
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/lib/ansible/plugins/action/net_template.py b/lib/ansible/plugins/action/net_template.py
  --- a/lib/ansible/plugins/action/net_template.py
  +++ b/lib/ansible/plugins/action/net_template.py
  @@ -41,7 +41,7 @@
   
           try:
               self._handle_template()
  -        except ValueError as exc:
  +        except (ValueError, AttributeError) as exc:
               return dict(failed=True, msg=exc.message)
   
           result.update(self._execute_module(module_name=self._task.action,
  @@ -75,9 +75,12 @@
   
       def _handle_template(self):
           src = self._task.args.get('src')
  +        if not src:
  +            raise ValueError('missing required arguments: src')
  +
           working_path = self._get_working_path()
   
  -        if os.path.isabs(src) or urlparse.urlsplit('src').scheme:
  +        if os.path.isabs(src) or urlparse.urlsplit(src).scheme:
               source = src
           else:
               source = self._loader.path_dwim_relative(working_path, 'templates', src)
  
verification_info: {"golden_diff": "diff --git a/lib/ansible/plugins/action/net_template.py b/lib/ansible/plugins/action/net_template.py\n--- a/lib/ansible/plugins/action/net_template.py\n+++ b/lib/ansible/plugins/action/net_template.py\n@@ -41,7 +41,7 @@\n \n         try:\n             self._handle_template()\n-        except ValueError as exc:\n+        except (ValueError, AttributeError) as exc:\n             return dict(failed=True, msg=exc.message)\n \n         result.update(self._execute_module(module_name=self._task.action,\n@@ -75,9 +75,12 @@\n \n     def _handle_template(self):\n         src = self._task.args.get('src')\n+        if not src:\n+            raise ValueError('missing required arguments: src')\n+\n         working_path = self._get_working_path()\n \n-        if os.path.isabs(src) or urlparse.urlsplit('src').scheme:\n+        if os.path.isabs(src) or urlparse.urlsplit(src).scheme:\n             source = src\n         else:\n             source = self._loader.path_dwim_relative(working_path, 'templates', src)\n", "issue": "network _template not checking arguments correctly\n##### ISSUE TYPE\n- Bug Report\n##### COMPONENT NAME\n\nlib/ansible/plugins/action/net_template.py\n##### ANSIBLE VERSION\n\ndevel\n##### CONFIGURATION\n##### OS / ENVIRONMENT\n##### SUMMARY\n##### STEPS TO REPRODUCE\n\n```\n\n---\n- name: Backup existing configuration\n  eos_template:\n    backup: yes\n```\n\nNo other `vars` set\n\nsame for `ios_template`\n##### EXPECTED RESULTS\n\n`msg\": \"missing required arguments: host\"` (or src)\n##### ACTUAL RESULTS\n\n```\n  File \"/home/gundalow/git/ansible-inc/ansible/lib/ansible/plugins/action/net_template.py\", line 43, in run\n    self._handle_template()\n  File \"/home/gundalow/git/ansible-inc/ansible/lib/ansible/plugins/action/net_template.py\", line 80, in _handle_template\n    if os.path.isabs(src) or urlparse.urlsplit('src').scheme:\n  File \"/usr/lib/python2.7/posixpath.py\", line 54, in isabs\n    return s.startswith('/')\nAttributeError: 'NoneType' object has no attribute 'startswith'\n```\n\n", "before_files": [{"content": "#\n# Copyright 2015 Peter Sprygada <psprygada@ansible.com>\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#\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\nimport sys\nimport os\nimport time\nimport glob\nimport urlparse\n\nfrom ansible.plugins.action import ActionBase\nfrom ansible.utils.boolean import boolean\nfrom ansible.utils.unicode import to_unicode\n\nBOOLEANS = ('true', 'false', 'yes', 'no')\n\nclass ActionModule(ActionBase):\n\n    TRANSFERS_FILES = False\n\n    def run(self, tmp=None, task_vars=None):\n        result = super(ActionModule, self).run(tmp, task_vars)\n        result['changed'] = False\n\n        try:\n            self._handle_template()\n        except ValueError as exc:\n            return dict(failed=True, msg=exc.message)\n\n        result.update(self._execute_module(module_name=self._task.action,\n            module_args=self._task.args, task_vars=task_vars))\n\n        if self._task.args.get('backup') and result.get('_backup'):\n            # User requested backup and no error occurred in module.\n            # NOTE: If there is a parameter error, _backup key may not be in results.\n            self._write_backup(task_vars['inventory_hostname'], result['_backup'])\n\n        if '_backup' in result:\n            del result['_backup']\n\n        return result\n\n    def _get_working_path(self):\n        cwd = self._loader.get_basedir()\n        if self._task._role is not None:\n            cwd = self._task._role._role_path\n        return cwd\n\n    def _write_backup(self, host, contents):\n        backup_path = self._get_working_path() + '/backup'\n        if not os.path.exists(backup_path):\n            os.mkdir(backup_path)\n        for fn in glob.glob('%s/%s*' % (backup_path, host)):\n            os.remove(fn)\n        tstamp = time.strftime(\"%Y-%m-%d@%H:%M:%S\", time.localtime(time.time()))\n        filename = '%s/%s_config.%s' % (backup_path, host, tstamp)\n        open(filename, 'w').write(contents)\n\n    def _handle_template(self):\n        src = self._task.args.get('src')\n        working_path = self._get_working_path()\n\n        if os.path.isabs(src) or urlparse.urlsplit('src').scheme:\n            source = src\n        else:\n            source = self._loader.path_dwim_relative(working_path, 'templates', src)\n            if not source:\n                source = self._loader.path_dwim_relative(working_path, src)\n\n        if not os.path.exists(source):\n            return\n\n        try:\n            with open(source, 'r') as f:\n                template_data = to_unicode(f.read())\n        except IOError:\n            return dict(failed=True, msg='unable to load src file')\n\n        # Create a template search path in the following order:\n        # [working_path, self_role_path, dependent_role_paths, dirname(source)]\n        searchpath = [working_path]\n        if self._task._role is not None:\n            searchpath.append(self._task._role._role_path)\n            dep_chain = self._task._block.get_dep_chain()\n            if dep_chain is not None:\n                for role in dep_chain:\n                    searchpath.append(role._role_path)\n        searchpath.append(os.path.dirname(source))\n        self._templar.environment.loader.searchpath = searchpath\n        self._task.args['src'] = self._templar.template(template_data)\n\n\n", "path": "lib/ansible/plugins/action/net_template.py"}], "after_files": [{"content": "#\n# Copyright 2015 Peter Sprygada <psprygada@ansible.com>\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#\nfrom __future__ import (absolute_import, division, print_function)\n__metaclass__ = type\n\nimport sys\nimport os\nimport time\nimport glob\nimport urlparse\n\nfrom ansible.plugins.action import ActionBase\nfrom ansible.utils.boolean import boolean\nfrom ansible.utils.unicode import to_unicode\n\nBOOLEANS = ('true', 'false', 'yes', 'no')\n\nclass ActionModule(ActionBase):\n\n    TRANSFERS_FILES = False\n\n    def run(self, tmp=None, task_vars=None):\n        result = super(ActionModule, self).run(tmp, task_vars)\n        result['changed'] = False\n\n        try:\n            self._handle_template()\n        except (ValueError, AttributeError) as exc:\n            return dict(failed=True, msg=exc.message)\n\n        result.update(self._execute_module(module_name=self._task.action,\n            module_args=self._task.args, task_vars=task_vars))\n\n        if self._task.args.get('backup') and result.get('_backup'):\n            # User requested backup and no error occurred in module.\n            # NOTE: If there is a parameter error, _backup key may not be in results.\n            self._write_backup(task_vars['inventory_hostname'], result['_backup'])\n\n        if '_backup' in result:\n            del result['_backup']\n\n        return result\n\n    def _get_working_path(self):\n        cwd = self._loader.get_basedir()\n        if self._task._role is not None:\n            cwd = self._task._role._role_path\n        return cwd\n\n    def _write_backup(self, host, contents):\n        backup_path = self._get_working_path() + '/backup'\n        if not os.path.exists(backup_path):\n            os.mkdir(backup_path)\n        for fn in glob.glob('%s/%s*' % (backup_path, host)):\n            os.remove(fn)\n        tstamp = time.strftime(\"%Y-%m-%d@%H:%M:%S\", time.localtime(time.time()))\n        filename = '%s/%s_config.%s' % (backup_path, host, tstamp)\n        open(filename, 'w').write(contents)\n\n    def _handle_template(self):\n        src = self._task.args.get('src')\n        if not src:\n            raise ValueError('missing required arguments: src')\n\n        working_path = self._get_working_path()\n\n        if os.path.isabs(src) or urlparse.urlsplit(src).scheme:\n            source = src\n        else:\n            source = self._loader.path_dwim_relative(working_path, 'templates', src)\n            if not source:\n                source = self._loader.path_dwim_relative(working_path, src)\n\n        if not os.path.exists(source):\n            return\n\n        try:\n            with open(source, 'r') as f:\n                template_data = to_unicode(f.read())\n        except IOError:\n            return dict(failed=True, msg='unable to load src file')\n\n        # Create a template search path in the following order:\n        # [working_path, self_role_path, dependent_role_paths, dirname(source)]\n        searchpath = [working_path]\n        if self._task._role is not None:\n            searchpath.append(self._task._role._role_path)\n            dep_chain = self._task._block.get_dep_chain()\n            if dep_chain is not None:\n                for role in dep_chain:\n                    searchpath.append(role._role_path)\n        searchpath.append(os.path.dirname(source))\n        self._templar.environment.loader.searchpath = searchpath\n        self._task.args['src'] = self._templar.template(template_data)\n\n\n", "path": "lib/ansible/plugins/action/net_template.py"}]}