From 9fe20123cf63df29bb286786eb5c0020c674946d Mon Sep 17 00:00:00 2001
From: Ingate Systems <44266467+ingatesystems@users.noreply.github.com>
Date: Fri, 26 Oct 2018 06:17:58 +0200
Subject: [PATCH] modules: network: Add initial support for Ingate modules
(#47494)
* modules: network: Add initial support for Ingate modules
* modules: network: Add ingate module ig_unit_information
* module_utils: network: ingate: Use default 'v1' for version
* modules: network: ingate: Remove unused code
---
.../module_utils/network/ingate/__init__.py | 0
.../module_utils/network/ingate/common.py | 98 ++++++++++
.../modules/network/ingate/__init__.py | 0
.../network/ingate/ig_unit_information.py | 172 ++++++++++++++++++
.../utils/module_docs_fragments/ingate.py | 68 +++++++
test/units/modules/network/ingate/__init__.py | 0
.../fixtures/test_ig_unit_information.json | 21 +++
.../modules/network/ingate/ingate_module.py | 83 +++++++++
.../ingate/test_ig_unit_information.py | 62 +++++++
9 files changed, 504 insertions(+)
create mode 100644 lib/ansible/module_utils/network/ingate/__init__.py
create mode 100644 lib/ansible/module_utils/network/ingate/common.py
create mode 100644 lib/ansible/modules/network/ingate/__init__.py
create mode 100644 lib/ansible/modules/network/ingate/ig_unit_information.py
create mode 100644 lib/ansible/utils/module_docs_fragments/ingate.py
create mode 100644 test/units/modules/network/ingate/__init__.py
create mode 100644 test/units/modules/network/ingate/fixtures/test_ig_unit_information.json
create mode 100644 test/units/modules/network/ingate/ingate_module.py
create mode 100644 test/units/modules/network/ingate/test_ig_unit_information.py
diff --git a/lib/ansible/module_utils/network/ingate/__init__.py b/lib/ansible/module_utils/network/ingate/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/ansible/module_utils/network/ingate/common.py b/lib/ansible/module_utils/network/ingate/common.py
new file mode 100644
index 00000000000..25674013a47
--- /dev/null
+++ b/lib/ansible/module_utils/network/ingate/common.py
@@ -0,0 +1,98 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2018, Ingate Systems AB
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+try:
+ from ingate import ingatesdk
+ HAS_INGATESDK = True
+except ImportError:
+ HAS_INGATESDK = False
+
+
+def ingate_argument_spec(**kwargs):
+ client_options = dict(
+ version=dict(choices=['v1'], default='v1'),
+ scheme=dict(choices=['http', 'https'], required=True),
+ address=dict(type='str', required=True),
+ username=dict(type='str', required=True),
+ password=dict(type='str', required=True, no_log=True),
+ port=dict(type='int'),
+ timeout=dict(type='int'),
+ verify_ssl=dict(default=True, type='bool'),
+ )
+ argument_spec = dict(
+ client=dict(type='dict', required=True,
+ options=client_options),
+ )
+ argument_spec.update(kwargs)
+ return argument_spec
+
+
+def ingate_create_client(**kwargs):
+ if not HAS_INGATESDK:
+ raise ImportError("The Ingate Python SDK module is required")
+
+ client_params = kwargs['client']
+
+ # Create API client.
+ api_client = ingatesdk.Client(client_params['version'],
+ client_params['scheme'],
+ client_params['address'],
+ client_params['username'],
+ client_params['password'],
+ port=client_params['port'],
+ timeout=client_params['timeout'])
+
+ # Check if we should skip SSL Certificate verification.
+ verify_ssl = client_params.get('verify_ssl')
+ if verify_ssl is not None and not verify_ssl:
+ api_client.skip_verify_certificate()
+
+ # Authenticate and get hold of a security token.
+ api_client.authenticate()
+
+ # Return the client.
+ return api_client
+
+
+def ingate_create_client_noauth(**kwargs):
+ if not HAS_INGATESDK:
+ raise ImportError("The Ingate Python SDK module is required")
+
+ client_params = kwargs['client']
+
+ # Create API client.
+ api_client = ingatesdk.Client(client_params['version'],
+ client_params['scheme'],
+ client_params['address'],
+ client_params['username'],
+ client_params['password'],
+ port=client_params['port'],
+ timeout=client_params['timeout'])
+
+ # Check if we should skip SSL Certificate verification.
+ verify_ssl = client_params.get('verify_ssl')
+ if verify_ssl and not verify_ssl:
+ api_client.skip_verify_certificate()
+
+ # Return the client.
+ return api_client
diff --git a/lib/ansible/modules/network/ingate/__init__.py b/lib/ansible/modules/network/ingate/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/ansible/modules/network/ingate/ig_unit_information.py b/lib/ansible/modules/network/ingate/ig_unit_information.py
new file mode 100644
index 00000000000..46aa0bab59d
--- /dev/null
+++ b/lib/ansible/modules/network/ingate/ig_unit_information.py
@@ -0,0 +1,172 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2018, Ingate Systems AB
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+ANSIBLE_METADATA = {'status': ['preview'],
+ 'supported_by': 'community',
+ 'metadata_version': '1.1'}
+
+DOCUMENTATION = '''
+---
+module: ig_unit_information
+short_description: Get unit information from an Ingate SBC.
+description:
+ - Get unit information from an Ingate SBC.
+version_added: 2.8
+extends_documentation_fragment: ingate
+author:
+ - Ingate Systems AB (@ingatesystems)
+'''
+
+EXAMPLES = '''
+- name: Get unit information
+ ig_unit_information:
+ client:
+ version: v1
+ scheme: http
+ address: 192.168.1.1
+ username: alice
+ password: foobar
+'''
+
+RETURN = '''
+unit-information:
+ description: Information about the unit
+ returned: success
+ type: complex
+ contains:
+ installid:
+ description: The installation identifier
+ returned: success
+ type: string
+ sample: any
+ interfaces:
+ description: List of interface names
+ returned: success
+ type: string
+ sample: eth0 eth1 eth2 eth3 eth4 eth5
+ lang:
+ description: The unit's language
+ returned: success
+ type: string
+ sample: en
+ lic_email:
+ description: License email information
+ returned: success
+ type: string
+ sample: example@example.com
+ lic_mac:
+ description: License MAC information
+ returned: success
+ type: string
+ sample: any
+ lic_name:
+ description: License name information
+ returned: success
+ type: string
+ sample: Example Inc
+ macaddr:
+ description: The MAC address of the first interface
+ returned: success
+ type: string
+ sample: 52:54:00:4c:e2:07
+ mode:
+ description: Operational mode of the unit
+ returned: success
+ type: string
+ sample: Siparator
+ modules:
+ description: Installed module licenses
+ returned: success
+ type: string
+ sample: failover vpn sip qturn ems qos rsc voipsm
+ patches:
+ description: Installed patches on the unit
+ returned: success
+ type: list
+ sample: []
+ product:
+ description: The product name
+ returned: success
+ type: string
+ sample: Software SIParator/Firewall
+ serial:
+ description: The serial number of the unit
+ returned: success
+ type: string
+ sample: IG-200-839-2008-0
+ systemid:
+ description: The system identifier of the unit
+ returned: success
+ type: string
+ sample: IG-200-839-2008-0
+ unitname:
+ description: The name of the unit
+ returned: success
+ type: string
+ sample: Testname
+ version:
+ description: Firmware version
+ returned: success
+ type: string
+ sample: 6.2.0-beta2
+'''
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.network.ingate.common import (ingate_argument_spec,
+ ingate_create_client)
+
+try:
+ from ingate import ingatesdk
+ HAS_INGATESDK = True
+except ImportError:
+ HAS_INGATESDK = False
+
+
+def make_request(module):
+ # Create client and authenticate.
+ api_client = ingate_create_client(**module.params)
+
+ # Get unit information.
+ response = api_client.unit_information()
+ return response
+
+
+def main():
+ argument_spec = ingate_argument_spec()
+ module = AnsibleModule(argument_spec=argument_spec,
+ supports_check_mode=False)
+ if not HAS_INGATESDK:
+ module.fail_json(msg='The Ingate Python SDK module is required')
+
+ result = dict(changed=False)
+ try:
+ response = make_request(module)
+ result.update(response[0])
+ except ingatesdk.SdkError as e:
+ module.fail_json(msg=str(e))
+ module.exit_json(**result)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/lib/ansible/utils/module_docs_fragments/ingate.py b/lib/ansible/utils/module_docs_fragments/ingate.py
new file mode 100644
index 00000000000..1b07d2dd5f6
--- /dev/null
+++ b/lib/ansible/utils/module_docs_fragments/ingate.py
@@ -0,0 +1,68 @@
+# Copyright (c) 2018, Ingate Systems AB
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+
+class ModuleDocFragment(object):
+ DOCUMENTATION = '''
+options:
+ client:
+ description:
+ - A dict object containing connection details.
+ suboptions:
+ version:
+ description:
+ - REST API version.
+ choices: [v1]
+ default: v1
+ required: true
+ scheme:
+ description:
+ - Which HTTP protocol to use.
+ choices: [http, https]
+ required: true
+ address:
+ description:
+ - The hostname or IP address to the unit.
+ required: true
+ username:
+ description:
+ - The username of the REST API user.
+ required: true
+ password:
+ description:
+ - The password for the REST API user.
+ required: true
+ port:
+ description:
+ - Which HTTP(S) port to connect to.
+ required: false
+ timeout:
+ description:
+ - The timeout (in seconds) for REST API requests.
+ required: false
+ verify_ssl:
+ description:
+ - Verify the unit's HTTPS certificate.
+ default: true
+ required: false
+notes:
+ - This module requires that the Ingate Python SDK is installed on the
+ host. To install the SDK use the pip command from your shell
+ C(pip install ingatesdk).
+requirements:
+ - ingatesdk >= 1.0.6
+'''
diff --git a/test/units/modules/network/ingate/__init__.py b/test/units/modules/network/ingate/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/test/units/modules/network/ingate/fixtures/test_ig_unit_information.json b/test/units/modules/network/ingate/fixtures/test_ig_unit_information.json
new file mode 100644
index 00000000000..dc5e451c17c
--- /dev/null
+++ b/test/units/modules/network/ingate/fixtures/test_ig_unit_information.json
@@ -0,0 +1,21 @@
+[
+ {
+ "unit-information": {
+ "lic_email": "dev@ingate.com",
+ "lang": "en",
+ "product": "Software SIParator/Firewall",
+ "installid": "any",
+ "patches": [],
+ "lic_mac": "any",
+ "unitname": "testname",
+ "interfaces": "eth0 eth1 eth2 eth3 eth4 eth5",
+ "modules": "failover vpn sip qturn ems qos rsc voipsm idsips siptrunk sipswitch",
+ "lic_name": "Ingate",
+ "macaddr": "52:54:00:4c:e2:07",
+ "version": "6.2.0-erik",
+ "systemid": "IG-200-840-5001-0",
+ "mode": "Firewall",
+ "serial": "IG-200-840-5001-0"
+ }
+ }
+]
diff --git a/test/units/modules/network/ingate/ingate_module.py b/test/units/modules/network/ingate/ingate_module.py
new file mode 100644
index 00000000000..6e11cadbdcf
--- /dev/null
+++ b/test/units/modules/network/ingate/ingate_module.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2018, Ingate Systems AB
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+
+from units.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase
+
+
+fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
+fixture_data = {}
+
+
+def load_fixture(name):
+ path = os.path.join(fixture_path, name)
+
+ if path in fixture_data:
+ return fixture_data[path]
+
+ with open(path) as file_desc:
+ data = file_desc.read()
+
+ try:
+ data = json.loads(data)
+ except:
+ pass
+
+ fixture_data[path] = data
+ return data
+
+
+class TestIngateModule(ModuleTestCase):
+
+ def execute_module(self, failed=False, changed=False, fixture=None):
+
+ self.load_fixtures(fixture)
+
+ if failed:
+ result = self.failed()
+ self.assertTrue(result['failed'], result)
+ else:
+ result = self.changed(changed)
+ self.assertEqual(result['changed'], changed, result)
+
+ return result
+
+ def failed(self):
+ with self.assertRaises(AnsibleFailJson) as exc:
+ self.module.main()
+
+ result = exc.exception.args[0]
+ self.assertTrue(result['failed'], result)
+ return result
+
+ def changed(self, changed=False):
+ with self.assertRaises(AnsibleExitJson) as exc:
+ self.module.main()
+
+ result = exc.exception.args[0]
+ self.assertEqual(result['changed'], changed, result)
+ return result
+
+ def load_fixtures(self, module_name=None):
+ pass
diff --git a/test/units/modules/network/ingate/test_ig_unit_information.py b/test/units/modules/network/ingate/test_ig_unit_information.py
new file mode 100644
index 00000000000..4c32aa09407
--- /dev/null
+++ b/test/units/modules/network/ingate/test_ig_unit_information.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2018, Ingate Systems AB
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see .
+
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+
+from units.compat.mock import patch
+from ansible.modules.network.ingate import ig_unit_information
+from units.modules.utils import set_module_args
+from .ingate_module import TestIngateModule, load_fixture
+
+
+class TestUnitInformationModule(TestIngateModule):
+
+ module = ig_unit_information
+
+ def setUp(self):
+ super(TestUnitInformationModule, self).setUp()
+
+ self.mock_make_request = patch('ansible.modules.network.ingate.'
+ 'ig_unit_information.make_request')
+ self.make_request = self.mock_make_request.start()
+ # ATM the Ingate Python SDK is not needed in this unit test.
+ self.module.HAS_INGATESDK = True
+
+ def tearDown(self):
+ super(TestUnitInformationModule, self).tearDown()
+ self.mock_make_request.stop()
+
+ def load_fixtures(self, fixture=None):
+ self.make_request.side_effect = [load_fixture(fixture)]
+
+ def test_ig_unit_information(self):
+ set_module_args(dict(
+ client=dict(
+ version='v1',
+ address='127.0.0.1',
+ scheme='http',
+ username='alice',
+ password='foobar'
+ )))
+ fixture = '%s.%s' % (os.path.basename(__file__).split('.')[0], 'json')
+ result = self.execute_module(fixture=fixture)
+ self.assertTrue('unit-information' in result)