diff options
Diffstat (limited to 'roles')
23 files changed, 1039 insertions, 850 deletions
diff --git a/roles/lib_openshift/library/oc_sdnvalidator.py b/roles/lib_openshift/library/oc_objectvalidator.py index bc7487b95..f6802a9b3 100644 --- a/roles/lib_openshift/library/oc_sdnvalidator.py +++ b/roles/lib_openshift/library/oc_objectvalidator.py @@ -50,14 +50,14 @@ from ansible.module_utils.basic import AnsibleModule # -*- -*- -*- End included fragment: lib/import.py -*- -*- -*- -# -*- -*- -*- Begin included fragment: doc/sdnvalidator -*- -*- -*- +# -*- -*- -*- Begin included fragment: doc/objectvalidator -*- -*- -*- DOCUMENTATION = ''' --- -module: oc_sdnvalidator -short_description: Validate SDN objects +module: oc_objectvalidator +short_description: Validate OpenShift objects description: - - Validate SDN objects + - Validate OpenShift objects options: kubeconfig: description: @@ -71,13 +71,13 @@ extends_documentation_fragment: [] ''' EXAMPLES = ''' -oc_version: -- name: get oc sdnvalidator - sdnvalidator: - register: oc_sdnvalidator +oc_objectvalidator: +- name: run oc_objectvalidator + oc_objectvalidator: + register: oc_objectvalidator ''' -# -*- -*- -*- End included fragment: doc/sdnvalidator -*- -*- -*- +# -*- -*- -*- End included fragment: doc/objectvalidator -*- -*- -*- # -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*- # pylint: disable=undefined-variable,missing-docstring @@ -1307,25 +1307,25 @@ class OpenShiftCLIConfig(object): # -*- -*- -*- End included fragment: lib/base.py -*- -*- -*- -# -*- -*- -*- Begin included fragment: class/oc_sdnvalidator.py -*- -*- -*- +# -*- -*- -*- Begin included fragment: class/oc_objectvalidator.py -*- -*- -*- # pylint: disable=too-many-instance-attributes -class OCSDNValidator(OpenShiftCLI): +class OCObjectValidator(OpenShiftCLI): ''' Class to wrap the oc command line tools ''' def __init__(self, kubeconfig): - ''' Constructor for OCSDNValidator ''' - # namespace has no meaning for SDN validation, hardcode to 'default' - super(OCSDNValidator, self).__init__('default', kubeconfig) + ''' Constructor for OCObjectValidator ''' + # namespace has no meaning for object validation, hardcode to 'default' + super(OCObjectValidator, self).__init__('default', kubeconfig) - def get(self, kind, invalid_filter): - ''' return SDN information ''' + def get_invalid(self, kind, invalid_filter): + ''' return invalid object information ''' rval = self._get(kind) if rval['returncode'] != 0: return False, rval, [] - return True, rval, filter(invalid_filter, rval['results'][0]['items']) + return True, rval, list(filter(invalid_filter, rval['results'][0]['items'])) # wrap filter with list for py3 # pylint: disable=too-many-return-statements @staticmethod @@ -1335,10 +1335,24 @@ class OCSDNValidator(OpenShiftCLI): params comes from the ansible portion of this module ''' - sdnvalidator = OCSDNValidator(params['kubeconfig']) + objectvalidator = OCObjectValidator(params['kubeconfig']) all_invalid = {} failed = False + def _is_invalid_namespace(namespace): + # check if it uses a reserved name + name = namespace['metadata']['name'] + if not any((name == 'kube', + name == 'openshift', + name.startswith('kube-'), + name.startswith('openshift-'),)): + return False + + # determine if the namespace was created by a user + if 'annotations' not in namespace['metadata']: + return False + return 'openshift.io/requester' in namespace['metadata']['annotations'] + checks = ( ( 'hostsubnet', @@ -1350,10 +1364,15 @@ class OCSDNValidator(OpenShiftCLI): lambda x: x['metadata']['name'] != x['netname'], u'netnamespaces where metadata.name != netname', ), + ( + 'namespace', + _is_invalid_namespace, + u'namespaces that use reserved names and were not created by infrastructure components', + ), ) for resource, invalid_filter, invalid_msg in checks: - success, rval, invalid = sdnvalidator.get(resource, invalid_filter) + success, rval, invalid = objectvalidator.get_invalid(resource, invalid_filter) if not success: return {'failed': True, 'msg': 'Failed to GET {}.'.format(resource), 'state': 'list', 'results': rval} if invalid: @@ -1361,17 +1380,17 @@ class OCSDNValidator(OpenShiftCLI): all_invalid[invalid_msg] = invalid if failed: - return {'failed': True, 'msg': 'All SDN objects are not valid.', 'state': 'list', 'results': all_invalid} + return {'failed': True, 'msg': 'All objects are not valid.', 'state': 'list', 'results': all_invalid} - return {'msg': 'All SDN objects are valid.'} + return {'msg': 'All objects are valid.'} -# -*- -*- -*- End included fragment: class/oc_sdnvalidator.py -*- -*- -*- +# -*- -*- -*- End included fragment: class/oc_objectvalidator.py -*- -*- -*- -# -*- -*- -*- Begin included fragment: ansible/oc_sdnvalidator.py -*- -*- -*- +# -*- -*- -*- Begin included fragment: ansible/oc_objectvalidator.py -*- -*- -*- def main(): ''' - ansible oc module for validating OpenShift SDN objects + ansible oc module for validating OpenShift objects ''' module = AnsibleModule( @@ -1382,7 +1401,7 @@ def main(): ) - rval = OCSDNValidator.run_ansible(module.params) + rval = OCObjectValidator.run_ansible(module.params) if 'failed' in rval: module.fail_json(**rval) @@ -1391,4 +1410,4 @@ def main(): if __name__ == '__main__': main() -# -*- -*- -*- End included fragment: ansible/oc_sdnvalidator.py -*- -*- -*- +# -*- -*- -*- End included fragment: ansible/oc_objectvalidator.py -*- -*- -*- diff --git a/roles/lib_openshift/src/ansible/oc_sdnvalidator.py b/roles/lib_openshift/src/ansible/oc_objectvalidator.py index e91417d63..658bb5ded 100644 --- a/roles/lib_openshift/src/ansible/oc_sdnvalidator.py +++ b/roles/lib_openshift/src/ansible/oc_objectvalidator.py @@ -3,7 +3,7 @@ def main(): ''' - ansible oc module for validating OpenShift SDN objects + ansible oc module for validating OpenShift objects ''' module = AnsibleModule( @@ -14,7 +14,7 @@ def main(): ) - rval = OCSDNValidator.run_ansible(module.params) + rval = OCObjectValidator.run_ansible(module.params) if 'failed' in rval: module.fail_json(**rval) diff --git a/roles/lib_openshift/src/class/oc_objectvalidator.py b/roles/lib_openshift/src/class/oc_objectvalidator.py new file mode 100644 index 000000000..b76fc995e --- /dev/null +++ b/roles/lib_openshift/src/class/oc_objectvalidator.py @@ -0,0 +1,77 @@ +# pylint: skip-file +# flake8: noqa + +# pylint: disable=too-many-instance-attributes +class OCObjectValidator(OpenShiftCLI): + ''' Class to wrap the oc command line tools ''' + + def __init__(self, kubeconfig): + ''' Constructor for OCObjectValidator ''' + # namespace has no meaning for object validation, hardcode to 'default' + super(OCObjectValidator, self).__init__('default', kubeconfig) + + def get_invalid(self, kind, invalid_filter): + ''' return invalid object information ''' + + rval = self._get(kind) + if rval['returncode'] != 0: + return False, rval, [] + + return True, rval, list(filter(invalid_filter, rval['results'][0]['items'])) # wrap filter with list for py3 + + # pylint: disable=too-many-return-statements + @staticmethod + def run_ansible(params): + ''' run the idempotent ansible code + + params comes from the ansible portion of this module + ''' + + objectvalidator = OCObjectValidator(params['kubeconfig']) + all_invalid = {} + failed = False + + def _is_invalid_namespace(namespace): + # check if it uses a reserved name + name = namespace['metadata']['name'] + if not any((name == 'kube', + name == 'openshift', + name.startswith('kube-'), + name.startswith('openshift-'),)): + return False + + # determine if the namespace was created by a user + if 'annotations' not in namespace['metadata']: + return False + return 'openshift.io/requester' in namespace['metadata']['annotations'] + + checks = ( + ( + 'hostsubnet', + lambda x: x['metadata']['name'] != x['host'], + u'hostsubnets where metadata.name != host', + ), + ( + 'netnamespace', + lambda x: x['metadata']['name'] != x['netname'], + u'netnamespaces where metadata.name != netname', + ), + ( + 'namespace', + _is_invalid_namespace, + u'namespaces that use reserved names and were not created by infrastructure components', + ), + ) + + for resource, invalid_filter, invalid_msg in checks: + success, rval, invalid = objectvalidator.get_invalid(resource, invalid_filter) + if not success: + return {'failed': True, 'msg': 'Failed to GET {}.'.format(resource), 'state': 'list', 'results': rval} + if invalid: + failed = True + all_invalid[invalid_msg] = invalid + + if failed: + return {'failed': True, 'msg': 'All objects are not valid.', 'state': 'list', 'results': all_invalid} + + return {'msg': 'All objects are valid.'} diff --git a/roles/lib_openshift/src/class/oc_sdnvalidator.py b/roles/lib_openshift/src/class/oc_sdnvalidator.py deleted file mode 100644 index da923337b..000000000 --- a/roles/lib_openshift/src/class/oc_sdnvalidator.py +++ /dev/null @@ -1,58 +0,0 @@ -# pylint: skip-file -# flake8: noqa - -# pylint: disable=too-many-instance-attributes -class OCSDNValidator(OpenShiftCLI): - ''' Class to wrap the oc command line tools ''' - - def __init__(self, kubeconfig): - ''' Constructor for OCSDNValidator ''' - # namespace has no meaning for SDN validation, hardcode to 'default' - super(OCSDNValidator, self).__init__('default', kubeconfig) - - def get(self, kind, invalid_filter): - ''' return SDN information ''' - - rval = self._get(kind) - if rval['returncode'] != 0: - return False, rval, [] - - return True, rval, filter(invalid_filter, rval['results'][0]['items']) - - # pylint: disable=too-many-return-statements - @staticmethod - def run_ansible(params): - ''' run the idempotent ansible code - - params comes from the ansible portion of this module - ''' - - sdnvalidator = OCSDNValidator(params['kubeconfig']) - all_invalid = {} - failed = False - - checks = ( - ( - 'hostsubnet', - lambda x: x['metadata']['name'] != x['host'], - u'hostsubnets where metadata.name != host', - ), - ( - 'netnamespace', - lambda x: x['metadata']['name'] != x['netname'], - u'netnamespaces where metadata.name != netname', - ), - ) - - for resource, invalid_filter, invalid_msg in checks: - success, rval, invalid = sdnvalidator.get(resource, invalid_filter) - if not success: - return {'failed': True, 'msg': 'Failed to GET {}.'.format(resource), 'state': 'list', 'results': rval} - if invalid: - failed = True - all_invalid[invalid_msg] = invalid - - if failed: - return {'failed': True, 'msg': 'All SDN objects are not valid.', 'state': 'list', 'results': all_invalid} - - return {'msg': 'All SDN objects are valid.'} diff --git a/roles/lib_openshift/src/doc/sdnvalidator b/roles/lib_openshift/src/doc/objectvalidator index 0b1862ed1..98861e261 100644 --- a/roles/lib_openshift/src/doc/sdnvalidator +++ b/roles/lib_openshift/src/doc/objectvalidator @@ -3,10 +3,10 @@ DOCUMENTATION = ''' --- -module: oc_sdnvalidator -short_description: Validate SDN objects +module: oc_objectvalidator +short_description: Validate OpenShift objects description: - - Validate SDN objects + - Validate OpenShift objects options: kubeconfig: description: @@ -20,8 +20,8 @@ extends_documentation_fragment: [] ''' EXAMPLES = ''' -oc_version: -- name: get oc sdnvalidator - sdnvalidator: - register: oc_sdnvalidator +oc_objectvalidator: +- name: run oc_objectvalidator + oc_objectvalidator: + register: oc_objectvalidator ''' diff --git a/roles/lib_openshift/src/sources.yml b/roles/lib_openshift/src/sources.yml index c72fd4ea8..f16b3c8de 100644 --- a/roles/lib_openshift/src/sources.yml +++ b/roles/lib_openshift/src/sources.yml @@ -218,12 +218,12 @@ oc_version.py: - class/oc_version.py - ansible/oc_version.py -oc_sdnvalidator.py: +oc_objectvalidator.py: - doc/generated - doc/license - lib/import.py -- doc/sdnvalidator +- doc/objectvalidator - ../../lib_utils/src/class/yedit.py - lib/base.py -- class/oc_sdnvalidator.py -- ansible/oc_sdnvalidator.py +- class/oc_objectvalidator.py +- ansible/oc_objectvalidator.py diff --git a/roles/lib_openshift/src/test/unit/oc_sdnvalidator.py b/roles/lib_openshift/src/test/unit/oc_sdnvalidator.py deleted file mode 100755 index 49e2aadb2..000000000 --- a/roles/lib_openshift/src/test/unit/oc_sdnvalidator.py +++ /dev/null @@ -1,481 +0,0 @@ -#!/usr/bin/env python2 -''' - Unit tests for oc sdnvalidator -''' -# To run -# ./oc_sdnvalidator.py -# -# .... -# ---------------------------------------------------------------------- -# Ran 4 tests in 0.002s -# -# OK - -import os -import sys -import unittest -import mock - -# Removing invalid variable names for tests so that I can -# keep them brief -# pylint: disable=invalid-name,no-name-in-module -# Disable import-error b/c our libraries aren't loaded in jenkins -# pylint: disable=import-error -# place class in our python path -module_path = os.path.join('/'.join(os.path.realpath(__file__).split('/')[:-4]), 'library') # noqa: E501 -sys.path.insert(0, module_path) -from oc_sdnvalidator import OCSDNValidator # noqa: E402 - - -class OCSDNValidatorTest(unittest.TestCase): - ''' - Test class for OCSDNValidator - ''' - - @mock.patch('oc_sdnvalidator.Utils.create_tmpfile_copy') - @mock.patch('oc_sdnvalidator.OCSDNValidator._run') - def test_no_data(self, mock_cmd, mock_tmpfile_copy): - ''' Testing when both SDN objects are empty ''' - - # Arrange - - # run_ansible input parameters - params = { - 'kubeconfig': '/etc/origin/master/admin.kubeconfig', - } - - empty = '''{ - "apiVersion": "v1", - "items": [], - "kind": "List", - "metadata": {}, - "resourceVersion": "", - "selfLink": "" -}''' - - # Return values of our mocked function call. These get returned once per call. - mock_cmd.side_effect = [ - # First call to mock - (0, empty, ''), - - # Second call to mock - (0, empty, ''), - ] - - mock_tmpfile_copy.side_effect = [ - '/tmp/mocked_kubeconfig', - ] - - # Act - results = OCSDNValidator.run_ansible(params) - - # Assert - self.assertNotIn('failed', results) - self.assertEqual(results['msg'], 'All SDN objects are valid.') - - # Making sure our mock was called as we expected - mock_cmd.assert_has_calls([ - mock.call(['oc', '-n', 'default', 'get', 'hostsubnet', '-o', 'json'], None), - mock.call(['oc', '-n', 'default', 'get', 'netnamespace', '-o', 'json'], None), - ]) - - @mock.patch('oc_sdnvalidator.Utils.create_tmpfile_copy') - @mock.patch('oc_sdnvalidator.OCSDNValidator._run') - def test_error_code(self, mock_cmd, mock_tmpfile_copy): - ''' Testing when both we fail to get SDN objects ''' - - # Arrange - - # run_ansible input parameters - params = { - 'kubeconfig': '/etc/origin/master/admin.kubeconfig', - } - - # Return values of our mocked function call. These get returned once per call. - mock_cmd.side_effect = [ - # First call to mock - (1, '', 'Error.'), - ] - - mock_tmpfile_copy.side_effect = [ - '/tmp/mocked_kubeconfig', - ] - - error_results = { - 'returncode': 1, - 'stderr': 'Error.', - 'stdout': '', - 'cmd': 'oc -n default get hostsubnet -o json', - 'results': [{}] - } - - # Act - results = OCSDNValidator.run_ansible(params) - - # Assert - self.assertTrue(results['failed']) - self.assertEqual(results['msg'], 'Failed to GET hostsubnet.') - self.assertEqual(results['state'], 'list') - self.assertEqual(results['results'], error_results) - - # Making sure our mock was called as we expected - mock_cmd.assert_has_calls([ - mock.call(['oc', '-n', 'default', 'get', 'hostsubnet', '-o', 'json'], None), - ]) - - @mock.patch('oc_sdnvalidator.Utils.create_tmpfile_copy') - @mock.patch('oc_sdnvalidator.OCSDNValidator._run') - def test_valid_both(self, mock_cmd, mock_tmpfile_copy): - ''' Testing when both SDN objects are valid ''' - - # Arrange - - # run_ansible input parameters - params = { - 'kubeconfig': '/etc/origin/master/admin.kubeconfig', - } - - valid_hostsubnet = '''{ - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "host": "bar0", - "hostIP": "1.1.1.1", - "kind": "HostSubnet", - "metadata": { - "creationTimestamp": "2017-02-16T18:47:09Z", - "name": "bar0", - "namespace": "", - "resourceVersion": "986", - "selfLink": "/oapi/v1/hostsubnetsbar0", - "uid": "528dbb41-f478-11e6-aae0-507b9dac97ff" - }, - "subnet": "1.1.0.0/24" - }, - { - "apiVersion": "v1", - "host": "bar1", - "hostIP": "1.1.1.1", - "kind": "HostSubnet", - "metadata": { - "creationTimestamp": "2017-02-16T18:47:18Z", - "name": "bar1", - "namespace": "", - "resourceVersion": "988", - "selfLink": "/oapi/v1/hostsubnetsbar1", - "uid": "57710d84-f478-11e6-aae0-507b9dac97ff" - }, - "subnet": "1.1.0.0/24" - }, - { - "apiVersion": "v1", - "host": "bar2", - "hostIP": "1.1.1.1", - "kind": "HostSubnet", - "metadata": { - "creationTimestamp": "2017-02-16T18:47:26Z", - "name": "bar2", - "namespace": "", - "resourceVersion": "991", - "selfLink": "/oapi/v1/hostsubnetsbar2", - "uid": "5c59a28c-f478-11e6-aae0-507b9dac97ff" - }, - "subnet": "1.1.0.0/24" - } - ], - "kind": "List", - "metadata": {}, - "resourceVersion": "", - "selfLink": "" - }''' - - valid_netnamespace = '''{ - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "kind": "NetNamespace", - "metadata": { - "creationTimestamp": "2017-02-16T18:45:16Z", - "name": "foo0", - "namespace": "", - "resourceVersion": "959", - "selfLink": "/oapi/v1/netnamespacesfoo0", - "uid": "0f1c85b2-f478-11e6-aae0-507b9dac97ff" - }, - "netid": 100, - "netname": "foo0" - }, - { - "apiVersion": "v1", - "kind": "NetNamespace", - "metadata": { - "creationTimestamp": "2017-02-16T18:45:26Z", - "name": "foo1", - "namespace": "", - "resourceVersion": "962", - "selfLink": "/oapi/v1/netnamespacesfoo1", - "uid": "14effa0d-f478-11e6-aae0-507b9dac97ff" - }, - "netid": 100, - "netname": "foo1" - }, - { - "apiVersion": "v1", - "kind": "NetNamespace", - "metadata": { - "creationTimestamp": "2017-02-16T18:45:36Z", - "name": "foo2", - "namespace": "", - "resourceVersion": "965", - "selfLink": "/oapi/v1/netnamespacesfoo2", - "uid": "1aabdf84-f478-11e6-aae0-507b9dac97ff" - }, - "netid": 100, - "netname": "foo2" - } - ], - "kind": "List", - "metadata": {}, - "resourceVersion": "", - "selfLink": "" - }''' - - # Return values of our mocked function call. These get returned once per call. - mock_cmd.side_effect = [ - # First call to mock - (0, valid_hostsubnet, ''), - - # Second call to mock - (0, valid_netnamespace, ''), - ] - - mock_tmpfile_copy.side_effect = [ - '/tmp/mocked_kubeconfig', - ] - - # Act - results = OCSDNValidator.run_ansible(params) - - # Assert - self.assertNotIn('failed', results) - self.assertEqual(results['msg'], 'All SDN objects are valid.') - - # Making sure our mock was called as we expected - mock_cmd.assert_has_calls([ - mock.call(['oc', '-n', 'default', 'get', 'hostsubnet', '-o', 'json'], None), - mock.call(['oc', '-n', 'default', 'get', 'netnamespace', '-o', 'json'], None), - ]) - - @mock.patch('oc_sdnvalidator.Utils.create_tmpfile_copy') - @mock.patch('oc_sdnvalidator.OCSDNValidator._run') - def test_invalid_both(self, mock_cmd, mock_tmpfile_copy): - ''' Testing when both SDN objects are invalid ''' - - # Arrange - - # run_ansible input parameters - params = { - 'kubeconfig': '/etc/origin/master/admin.kubeconfig', - } - - invalid_hostsubnet = '''{ - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "host": "bar0", - "hostIP": "1.1.1.1", - "kind": "HostSubnet", - "metadata": { - "creationTimestamp": "2017-02-16T18:47:09Z", - "name": "bar0", - "namespace": "", - "resourceVersion": "986", - "selfLink": "/oapi/v1/hostsubnetsbar0", - "uid": "528dbb41-f478-11e6-aae0-507b9dac97ff" - }, - "subnet": "1.1.0.0/24" - }, - { - "apiVersion": "v1", - "host": "bar1", - "hostIP": "1.1.1.1", - "kind": "HostSubnet", - "metadata": { - "creationTimestamp": "2017-02-16T18:47:18Z", - "name": "bar1", - "namespace": "", - "resourceVersion": "988", - "selfLink": "/oapi/v1/hostsubnetsbar1", - "uid": "57710d84-f478-11e6-aae0-507b9dac97ff" - }, - "subnet": "1.1.0.0/24" - }, - { - "apiVersion": "v1", - "host": "bar2", - "hostIP": "1.1.1.1", - "kind": "HostSubnet", - "metadata": { - "creationTimestamp": "2017-02-16T18:47:26Z", - "name": "bar2", - "namespace": "", - "resourceVersion": "991", - "selfLink": "/oapi/v1/hostsubnetsbar2", - "uid": "5c59a28c-f478-11e6-aae0-507b9dac97ff" - }, - "subnet": "1.1.0.0/24" - }, - { - "apiVersion": "v1", - "host": "baz1", - "hostIP": "1.1.1.1", - "kind": "HostSubnet", - "metadata": { - "creationTimestamp": "2017-02-16T18:47:49Z", - "name": "baz0", - "namespace": "", - "resourceVersion": "996", - "selfLink": "/oapi/v1/hostsubnetsbaz0", - "uid": "69f75f87-f478-11e6-aae0-507b9dac97ff" - }, - "subnet": "1.1.0.0/24" - } - ], - "kind": "List", - "metadata": {}, - "resourceVersion": "", - "selfLink": "" -}''' - - invalid_netnamespace = '''{ - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "kind": "NetNamespace", - "metadata": { - "creationTimestamp": "2017-02-16T18:45:52Z", - "name": "bar0", - "namespace": "", - "resourceVersion": "969", - "selfLink": "/oapi/v1/netnamespacesbar0", - "uid": "245d416e-f478-11e6-aae0-507b9dac97ff" - }, - "netid": 100, - "netname": "bar1" - }, - { - "apiVersion": "v1", - "kind": "NetNamespace", - "metadata": { - "creationTimestamp": "2017-02-16T18:45:16Z", - "name": "foo0", - "namespace": "", - "resourceVersion": "959", - "selfLink": "/oapi/v1/netnamespacesfoo0", - "uid": "0f1c85b2-f478-11e6-aae0-507b9dac97ff" - }, - "netid": 100, - "netname": "foo0" - }, - { - "apiVersion": "v1", - "kind": "NetNamespace", - "metadata": { - "creationTimestamp": "2017-02-16T18:45:26Z", - "name": "foo1", - "namespace": "", - "resourceVersion": "962", - "selfLink": "/oapi/v1/netnamespacesfoo1", - "uid": "14effa0d-f478-11e6-aae0-507b9dac97ff" - }, - "netid": 100, - "netname": "foo1" - }, - { - "apiVersion": "v1", - "kind": "NetNamespace", - "metadata": { - "creationTimestamp": "2017-02-16T18:45:36Z", - "name": "foo2", - "namespace": "", - "resourceVersion": "965", - "selfLink": "/oapi/v1/netnamespacesfoo2", - "uid": "1aabdf84-f478-11e6-aae0-507b9dac97ff" - }, - "netid": 100, - "netname": "foo2" - } - ], - "kind": "List", - "metadata": {}, - "resourceVersion": "", - "selfLink": "" -}''' - - invalid_results = { - 'hostsubnets where metadata.name != host': [{ - 'apiVersion': 'v1', - 'host': 'baz1', - 'hostIP': '1.1.1.1', - 'kind': 'HostSubnet', - 'metadata': { - 'creationTimestamp': '2017-02-16T18:47:49Z', - 'name': 'baz0', - 'namespace': '', - 'resourceVersion': '996', - 'selfLink': '/oapi/v1/hostsubnetsbaz0', - 'uid': '69f75f87-f478-11e6-aae0-507b9dac97ff' - }, - 'subnet': '1.1.0.0/24' - }], - 'netnamespaces where metadata.name != netname': [{ - 'apiVersion': 'v1', - 'kind': 'NetNamespace', - 'metadata': { - 'creationTimestamp': '2017-02-16T18:45:52Z', - 'name': 'bar0', - 'namespace': '', - 'resourceVersion': '969', - 'selfLink': '/oapi/v1/netnamespacesbar0', - 'uid': '245d416e-f478-11e6-aae0-507b9dac97ff' - }, - 'netid': 100, - 'netname': 'bar1' - }], - } - - # Return values of our mocked function call. These get returned once per call. - mock_cmd.side_effect = [ - # First call to mock - (0, invalid_hostsubnet, ''), - - # Second call to mock - (0, invalid_netnamespace, ''), - ] - - mock_tmpfile_copy.side_effect = [ - '/tmp/mocked_kubeconfig', - ] - - # Act - results = OCSDNValidator.run_ansible(params) - - # Assert - self.assertTrue(results['failed']) - self.assertEqual(results['msg'], 'All SDN objects are not valid.') - self.assertEqual(results['state'], 'list') - self.assertEqual(results['results'], invalid_results) - - # Making sure our mock was called as we expected - mock_cmd.assert_has_calls([ - mock.call(['oc', '-n', 'default', 'get', 'hostsubnet', '-o', 'json'], None), - mock.call(['oc', '-n', 'default', 'get', 'netnamespace', '-o', 'json'], None), - ]) - - -if __name__ == '__main__': - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oadm_manage_node.py b/roles/lib_openshift/src/test/unit/test_oadm_manage_node.py index 761c849fb..27d98b869 100755 --- a/roles/lib_openshift/src/test/unit/test_oadm_manage_node.py +++ b/roles/lib_openshift/src/test/unit/test_oadm_manage_node.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oadm_manage_node ''' -# To run -# python -m unittest version -# -# . -# Ran 2 tests in 0.001s -# -# OK import os import six @@ -32,10 +24,6 @@ class ManageNodeTest(unittest.TestCase): Test class for oadm_manage_node ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oadm_manage_node.Utils.create_tmpfile_copy') @mock.patch('oadm_manage_node.ManageNode.openshift_cmd') def test_list_pods(self, mock_openshift_cmd, mock_tmpfile_copy): @@ -287,11 +275,3 @@ class ManageNodeTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_env.py b/roles/lib_openshift/src/test/unit/test_oc_env.py index 45a3ef1eb..2f416c05e 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_env.py +++ b/roles/lib_openshift/src/test/unit/test_oc_env.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc_env ''' -# To run: -# ./oc_env.py -# -# . -# Ran 1 test in 0.002s -# -# OK import os import six @@ -32,10 +24,6 @@ class OCEnvTest(unittest.TestCase): Test class for OCEnv ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_env.locate_oc_binary') @mock.patch('oc_env.Utils.create_tmpfile_copy') @mock.patch('oc_env.OCEnv._run') @@ -558,11 +546,3 @@ class OCEnvTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_label.py b/roles/lib_openshift/src/test/unit/test_oc_label.py index 933b5f221..5453266c1 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_label.py +++ b/roles/lib_openshift/src/test/unit/test_oc_label.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc label ''' -# To run -# python -m unittest version -# -# . -# Ran 1 test in 0.597s -# -# OK import os import six @@ -32,10 +24,6 @@ class OCLabelTest(unittest.TestCase): Test class for OCLabel ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_label.Utils.create_tmpfile_copy') @mock.patch('oc_label.OCLabel._run') def test_state_list(self, mock_cmd, mock_tmpfile_copy): @@ -295,11 +283,3 @@ class OCLabelTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_objectvalidator.py b/roles/lib_openshift/src/test/unit/test_oc_objectvalidator.py new file mode 100755 index 000000000..a97d0493e --- /dev/null +++ b/roles/lib_openshift/src/test/unit/test_oc_objectvalidator.py @@ -0,0 +1,903 @@ +''' + Unit tests for oc_objectvalidator +''' + +import os +import sys +import unittest +import mock + +# Removing invalid variable names for tests so that I can +# keep them brief +# pylint: disable=invalid-name,no-name-in-module +# Disable import-error b/c our libraries aren't loaded in jenkins +# pylint: disable=import-error +# place class in our python path +module_path = os.path.join('/'.join(os.path.realpath(__file__).split('/')[:-4]), 'library') # noqa: E501 +sys.path.insert(0, module_path) +from oc_objectvalidator import OCObjectValidator # noqa: E402 + + +class OCObjectValidatorTest(unittest.TestCase): + ''' + Test class for OCObjectValidator + ''' + + maxDiff = None + + @mock.patch('oc_objectvalidator.Utils.create_tmpfile_copy') + @mock.patch('oc_objectvalidator.OCObjectValidator._run') + def test_no_data(self, mock_cmd, mock_tmpfile_copy): + ''' Testing when both all objects are empty ''' + + # Arrange + + # run_ansible input parameters + params = { + 'kubeconfig': '/etc/origin/master/admin.kubeconfig', + } + + empty = '''{ + "apiVersion": "v1", + "items": [], + "kind": "List", + "metadata": {}, + "resourceVersion": "", + "selfLink": "" +}''' + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + # First call to mock + (0, empty, ''), + + # Second call to mock + (0, empty, ''), + + # Third call to mock + (0, empty, ''), + ] + + mock_tmpfile_copy.side_effect = [ + '/tmp/mocked_kubeconfig', + ] + + # Act + results = OCObjectValidator.run_ansible(params) + + # Assert + self.assertNotIn('failed', results) + self.assertEqual(results['msg'], 'All objects are valid.') + + # Making sure our mock was called as we expected + mock_cmd.assert_has_calls([ + mock.call(['oc', 'get', 'hostsubnet', '-o', 'json', '-n', 'default'], None), + mock.call(['oc', 'get', 'netnamespace', '-o', 'json', '-n', 'default'], None), + mock.call(['oc', 'get', 'namespace', '-o', 'json', '-n', 'default'], None), + ]) + + @mock.patch('oc_objectvalidator.Utils.create_tmpfile_copy') + @mock.patch('oc_objectvalidator.OCObjectValidator._run') + def test_error_code(self, mock_cmd, mock_tmpfile_copy): + ''' Testing when we fail to get objects ''' + + # Arrange + + # run_ansible input parameters + params = { + 'kubeconfig': '/etc/origin/master/admin.kubeconfig', + } + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + # First call to mock + (1, '', 'Error.'), + ] + + mock_tmpfile_copy.side_effect = [ + '/tmp/mocked_kubeconfig', + ] + + error_results = { + 'returncode': 1, + 'stderr': 'Error.', + 'stdout': '', + 'cmd': 'oc get hostsubnet -o json -n default', + 'results': [{}] + } + + # Act + results = OCObjectValidator.run_ansible(params) + + # Assert + self.assertTrue(results['failed']) + self.assertEqual(results['msg'], 'Failed to GET hostsubnet.') + self.assertEqual(results['state'], 'list') + self.assertEqual(results['results'], error_results) + + # Making sure our mock was called as we expected + mock_cmd.assert_has_calls([ + mock.call(['oc', 'get', 'hostsubnet', '-o', 'json', '-n', 'default'], None), + ]) + + @mock.patch('oc_objectvalidator.Utils.create_tmpfile_copy') + @mock.patch('oc_objectvalidator.OCObjectValidator._run') + def test_valid_both(self, mock_cmd, mock_tmpfile_copy): + ''' Testing when both all objects are valid ''' + + # Arrange + + # run_ansible input parameters + params = { + 'kubeconfig': '/etc/origin/master/admin.kubeconfig', + } + + valid_hostsubnet = '''{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "host": "bar0", + "hostIP": "1.1.1.1", + "kind": "HostSubnet", + "metadata": { + "creationTimestamp": "2017-02-16T18:47:09Z", + "name": "bar0", + "namespace": "", + "resourceVersion": "986", + "selfLink": "/oapi/v1/hostsubnetsbar0", + "uid": "528dbb41-f478-11e6-aae0-507b9dac97ff" + }, + "subnet": "1.1.0.0/24" + }, + { + "apiVersion": "v1", + "host": "bar1", + "hostIP": "1.1.1.1", + "kind": "HostSubnet", + "metadata": { + "creationTimestamp": "2017-02-16T18:47:18Z", + "name": "bar1", + "namespace": "", + "resourceVersion": "988", + "selfLink": "/oapi/v1/hostsubnetsbar1", + "uid": "57710d84-f478-11e6-aae0-507b9dac97ff" + }, + "subnet": "1.1.0.0/24" + }, + { + "apiVersion": "v1", + "host": "bar2", + "hostIP": "1.1.1.1", + "kind": "HostSubnet", + "metadata": { + "creationTimestamp": "2017-02-16T18:47:26Z", + "name": "bar2", + "namespace": "", + "resourceVersion": "991", + "selfLink": "/oapi/v1/hostsubnetsbar2", + "uid": "5c59a28c-f478-11e6-aae0-507b9dac97ff" + }, + "subnet": "1.1.0.0/24" + } + ], + "kind": "List", + "metadata": {}, + "resourceVersion": "", + "selfLink": "" + }''' + + valid_netnamespace = '''{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "NetNamespace", + "metadata": { + "creationTimestamp": "2017-02-16T18:45:16Z", + "name": "foo0", + "namespace": "", + "resourceVersion": "959", + "selfLink": "/oapi/v1/netnamespacesfoo0", + "uid": "0f1c85b2-f478-11e6-aae0-507b9dac97ff" + }, + "netid": 100, + "netname": "foo0" + }, + { + "apiVersion": "v1", + "kind": "NetNamespace", + "metadata": { + "creationTimestamp": "2017-02-16T18:45:26Z", + "name": "foo1", + "namespace": "", + "resourceVersion": "962", + "selfLink": "/oapi/v1/netnamespacesfoo1", + "uid": "14effa0d-f478-11e6-aae0-507b9dac97ff" + }, + "netid": 100, + "netname": "foo1" + }, + { + "apiVersion": "v1", + "kind": "NetNamespace", + "metadata": { + "creationTimestamp": "2017-02-16T18:45:36Z", + "name": "foo2", + "namespace": "", + "resourceVersion": "965", + "selfLink": "/oapi/v1/netnamespacesfoo2", + "uid": "1aabdf84-f478-11e6-aae0-507b9dac97ff" + }, + "netid": 100, + "netname": "foo2" + } + ], + "kind": "List", + "metadata": {}, + "resourceVersion": "", + "selfLink": "" + }''' + + valid_namespace = '''{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/sa.scc.mcs": "s0:c1,c0", + "openshift.io/sa.scc.supplemental-groups": "1000000000/10000", + "openshift.io/sa.scc.uid-range": "1000000000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:49Z", + "name": "default", + "namespace": "", + "resourceVersion": "165", + "selfLink": "/api/v1/namespacesdefault", + "uid": "23c0c6aa-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/sa.scc.mcs": "s0:c3,c2", + "openshift.io/sa.scc.supplemental-groups": "1000010000/10000", + "openshift.io/sa.scc.uid-range": "1000010000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:49Z", + "name": "kube-system", + "namespace": "", + "resourceVersion": "533", + "selfLink": "/api/v1/namespaceskube-system", + "uid": "23c21758-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/description": "", + "openshift.io/display-name": "", + "openshift.io/requester": "developer", + "openshift.io/sa.scc.mcs": "s0:c9,c4", + "openshift.io/sa.scc.supplemental-groups": "1000080000/10000", + "openshift.io/sa.scc.uid-range": "1000080000/10000" + }, + "creationTimestamp": "2017-03-02T02:17:16Z", + "name": "myproject", + "namespace": "", + "resourceVersion": "2898", + "selfLink": "/api/v1/namespacesmyproject", + "uid": "5ae3764d-feee-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "openshift.io/origin", + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/sa.scc.mcs": "s0:c6,c0", + "openshift.io/sa.scc.supplemental-groups": "1000030000/10000", + "openshift.io/sa.scc.uid-range": "1000030000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:51Z", + "name": "openshift", + "namespace": "", + "resourceVersion": "171", + "selfLink": "/api/v1/namespacesopenshift", + "uid": "24f7b34d-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/sa.scc.mcs": "s0:c5,c0", + "openshift.io/sa.scc.supplemental-groups": "1000020000/10000", + "openshift.io/sa.scc.uid-range": "1000020000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:51Z", + "name": "openshift-infra", + "namespace": "", + "resourceVersion": "169", + "selfLink": "/api/v1/namespacesopenshift-infra", + "uid": "24a2ed75-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/description": "", + "openshift.io/display-name": "", + "openshift.io/requester": "developer1", + "openshift.io/sa.scc.mcs": "s0:c10,c0", + "openshift.io/sa.scc.supplemental-groups": "1000090000/10000", + "openshift.io/sa.scc.uid-range": "1000090000/10000" + }, + "creationTimestamp": "2017-03-02T02:17:56Z", + "name": "yourproject", + "namespace": "", + "resourceVersion": "2955", + "selfLink": "/api/v1/namespacesyourproject", + "uid": "72df7fb9-feee-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "openshift.io/origin", + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + } + ], + "kind": "List", + "metadata": {}, + "resourceVersion": "", + "selfLink": "" +}''' + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + # First call to mock + (0, valid_hostsubnet, ''), + + # Second call to mock + (0, valid_netnamespace, ''), + + # Third call to mock + (0, valid_namespace, ''), + ] + + mock_tmpfile_copy.side_effect = [ + '/tmp/mocked_kubeconfig', + ] + + # Act + results = OCObjectValidator.run_ansible(params) + + # Assert + self.assertNotIn('failed', results) + self.assertEqual(results['msg'], 'All objects are valid.') + + # Making sure our mock was called as we expected + mock_cmd.assert_has_calls([ + mock.call(['oc', 'get', 'hostsubnet', '-o', 'json', '-n', 'default'], None), + mock.call(['oc', 'get', 'netnamespace', '-o', 'json', '-n', 'default'], None), + mock.call(['oc', 'get', 'namespace', '-o', 'json', '-n', 'default'], None), + ]) + + @mock.patch('oc_objectvalidator.Utils.create_tmpfile_copy') + @mock.patch('oc_objectvalidator.OCObjectValidator._run') + def test_invalid_both(self, mock_cmd, mock_tmpfile_copy): + ''' Testing when all objects are invalid ''' + + # Arrange + + # run_ansible input parameters + params = { + 'kubeconfig': '/etc/origin/master/admin.kubeconfig', + } + + invalid_hostsubnet = '''{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "host": "bar0", + "hostIP": "1.1.1.1", + "kind": "HostSubnet", + "metadata": { + "creationTimestamp": "2017-02-16T18:47:09Z", + "name": "bar0", + "namespace": "", + "resourceVersion": "986", + "selfLink": "/oapi/v1/hostsubnetsbar0", + "uid": "528dbb41-f478-11e6-aae0-507b9dac97ff" + }, + "subnet": "1.1.0.0/24" + }, + { + "apiVersion": "v1", + "host": "bar1", + "hostIP": "1.1.1.1", + "kind": "HostSubnet", + "metadata": { + "creationTimestamp": "2017-02-16T18:47:18Z", + "name": "bar1", + "namespace": "", + "resourceVersion": "988", + "selfLink": "/oapi/v1/hostsubnetsbar1", + "uid": "57710d84-f478-11e6-aae0-507b9dac97ff" + }, + "subnet": "1.1.0.0/24" + }, + { + "apiVersion": "v1", + "host": "bar2", + "hostIP": "1.1.1.1", + "kind": "HostSubnet", + "metadata": { + "creationTimestamp": "2017-02-16T18:47:26Z", + "name": "bar2", + "namespace": "", + "resourceVersion": "991", + "selfLink": "/oapi/v1/hostsubnetsbar2", + "uid": "5c59a28c-f478-11e6-aae0-507b9dac97ff" + }, + "subnet": "1.1.0.0/24" + }, + { + "apiVersion": "v1", + "host": "baz1", + "hostIP": "1.1.1.1", + "kind": "HostSubnet", + "metadata": { + "creationTimestamp": "2017-02-16T18:47:49Z", + "name": "baz0", + "namespace": "", + "resourceVersion": "996", + "selfLink": "/oapi/v1/hostsubnetsbaz0", + "uid": "69f75f87-f478-11e6-aae0-507b9dac97ff" + }, + "subnet": "1.1.0.0/24" + } + ], + "kind": "List", + "metadata": {}, + "resourceVersion": "", + "selfLink": "" +}''' + + invalid_netnamespace = '''{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "NetNamespace", + "metadata": { + "creationTimestamp": "2017-02-16T18:45:52Z", + "name": "bar0", + "namespace": "", + "resourceVersion": "969", + "selfLink": "/oapi/v1/netnamespacesbar0", + "uid": "245d416e-f478-11e6-aae0-507b9dac97ff" + }, + "netid": 100, + "netname": "bar1" + }, + { + "apiVersion": "v1", + "kind": "NetNamespace", + "metadata": { + "creationTimestamp": "2017-02-16T18:45:16Z", + "name": "foo0", + "namespace": "", + "resourceVersion": "959", + "selfLink": "/oapi/v1/netnamespacesfoo0", + "uid": "0f1c85b2-f478-11e6-aae0-507b9dac97ff" + }, + "netid": 100, + "netname": "foo0" + }, + { + "apiVersion": "v1", + "kind": "NetNamespace", + "metadata": { + "creationTimestamp": "2017-02-16T18:45:26Z", + "name": "foo1", + "namespace": "", + "resourceVersion": "962", + "selfLink": "/oapi/v1/netnamespacesfoo1", + "uid": "14effa0d-f478-11e6-aae0-507b9dac97ff" + }, + "netid": 100, + "netname": "foo1" + }, + { + "apiVersion": "v1", + "kind": "NetNamespace", + "metadata": { + "creationTimestamp": "2017-02-16T18:45:36Z", + "name": "foo2", + "namespace": "", + "resourceVersion": "965", + "selfLink": "/oapi/v1/netnamespacesfoo2", + "uid": "1aabdf84-f478-11e6-aae0-507b9dac97ff" + }, + "netid": 100, + "netname": "foo2" + } + ], + "kind": "List", + "metadata": {}, + "resourceVersion": "", + "selfLink": "" +}''' + + invalid_namespace = '''{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/sa.scc.mcs": "s0:c1,c0", + "openshift.io/sa.scc.supplemental-groups": "1000000000/10000", + "openshift.io/sa.scc.uid-range": "1000000000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:49Z", + "name": "default", + "namespace": "", + "resourceVersion": "165", + "selfLink": "/api/v1/namespacesdefault", + "uid": "23c0c6aa-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/requester": "", + "openshift.io/sa.scc.mcs": "s0:c3,c2", + "openshift.io/sa.scc.supplemental-groups": "1000010000/10000", + "openshift.io/sa.scc.uid-range": "1000010000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:49Z", + "name": "kube-system", + "namespace": "", + "resourceVersion": "3052", + "selfLink": "/api/v1/namespaceskube-system", + "uid": "23c21758-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/description": "", + "openshift.io/display-name": "", + "openshift.io/requester": "developer", + "openshift.io/sa.scc.mcs": "s0:c9,c4", + "openshift.io/sa.scc.supplemental-groups": "1000080000/10000", + "openshift.io/sa.scc.uid-range": "1000080000/10000" + }, + "creationTimestamp": "2017-03-02T02:17:16Z", + "name": "myproject", + "namespace": "", + "resourceVersion": "2898", + "selfLink": "/api/v1/namespacesmyproject", + "uid": "5ae3764d-feee-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "openshift.io/origin", + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/requester": "", + "openshift.io/sa.scc.mcs": "s0:c6,c0", + "openshift.io/sa.scc.supplemental-groups": "1000030000/10000", + "openshift.io/sa.scc.uid-range": "1000030000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:51Z", + "name": "openshift", + "namespace": "", + "resourceVersion": "3057", + "selfLink": "/api/v1/namespacesopenshift", + "uid": "24f7b34d-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/description": "", + "openshift.io/display-name": "", + "openshift.io/requester": "system:admin", + "openshift.io/sa.scc.mcs": "s0:c10,c5", + "openshift.io/sa.scc.supplemental-groups": "1000100000/10000", + "openshift.io/sa.scc.uid-range": "1000100000/10000" + }, + "creationTimestamp": "2017-03-02T02:21:15Z", + "name": "openshift-fancy", + "namespace": "", + "resourceVersion": "3072", + "selfLink": "/api/v1/namespacesopenshift-fancy", + "uid": "e958063c-feee-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "openshift.io/origin", + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/sa.scc.mcs": "s0:c5,c0", + "openshift.io/sa.scc.supplemental-groups": "1000020000/10000", + "openshift.io/sa.scc.uid-range": "1000020000/10000" + }, + "creationTimestamp": "2017-03-02T00:49:51Z", + "name": "openshift-infra", + "namespace": "", + "resourceVersion": "169", + "selfLink": "/api/v1/namespacesopenshift-infra", + "uid": "24a2ed75-fee2-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "kubernetes", + "openshift.io/origin" + ] + }, + "status": { + "phase": "Active" + } + }, + { + "apiVersion": "v1", + "kind": "Namespace", + "metadata": { + "annotations": { + "openshift.io/description": "", + "openshift.io/display-name": "", + "openshift.io/requester": "developer1", + "openshift.io/sa.scc.mcs": "s0:c10,c0", + "openshift.io/sa.scc.supplemental-groups": "1000090000/10000", + "openshift.io/sa.scc.uid-range": "1000090000/10000" + }, + "creationTimestamp": "2017-03-02T02:17:56Z", + "name": "yourproject", + "namespace": "", + "resourceVersion": "2955", + "selfLink": "/api/v1/namespacesyourproject", + "uid": "72df7fb9-feee-11e6-b45a-507b9dac97ff" + }, + "spec": { + "finalizers": [ + "openshift.io/origin", + "kubernetes" + ] + }, + "status": { + "phase": "Active" + } + } + ], + "kind": "List", + "metadata": {}, + "resourceVersion": "", + "selfLink": "" +}''' + + invalid_results = { + 'hostsubnets where metadata.name != host': [{ + 'apiVersion': 'v1', + 'host': 'baz1', + 'hostIP': '1.1.1.1', + 'kind': 'HostSubnet', + 'metadata': { + 'creationTimestamp': '2017-02-16T18:47:49Z', + 'name': 'baz0', + 'namespace': '', + 'resourceVersion': '996', + 'selfLink': '/oapi/v1/hostsubnetsbaz0', + 'uid': '69f75f87-f478-11e6-aae0-507b9dac97ff' + }, + 'subnet': '1.1.0.0/24' + }], + 'netnamespaces where metadata.name != netname': [{ + 'apiVersion': 'v1', + 'kind': 'NetNamespace', + 'metadata': { + 'creationTimestamp': '2017-02-16T18:45:52Z', + 'name': 'bar0', + 'namespace': '', + 'resourceVersion': '969', + 'selfLink': '/oapi/v1/netnamespacesbar0', + 'uid': '245d416e-f478-11e6-aae0-507b9dac97ff' + }, + 'netid': 100, + 'netname': 'bar1' + }], + 'namespaces that use reserved names and were not created by infrastructure components': [{ + 'apiVersion': 'v1', + 'kind': 'Namespace', + 'metadata': {'annotations': {'openshift.io/requester': '', + 'openshift.io/sa.scc.mcs': 's0:c3,c2', + 'openshift.io/sa.scc.supplemental-groups': '1000010000/10000', + 'openshift.io/sa.scc.uid-range': '1000010000/10000'}, + 'creationTimestamp': '2017-03-02T00:49:49Z', + 'name': 'kube-system', + 'namespace': '', + 'resourceVersion': '3052', + 'selfLink': '/api/v1/namespaceskube-system', + 'uid': '23c21758-fee2-11e6-b45a-507b9dac97ff'}, + 'spec': {'finalizers': ['kubernetes', 'openshift.io/origin']}, + 'status': {'phase': 'Active'}}, + {'apiVersion': 'v1', + 'kind': 'Namespace', + 'metadata': {'annotations': {'openshift.io/requester': '', + 'openshift.io/sa.scc.mcs': 's0:c6,c0', + 'openshift.io/sa.scc.supplemental-groups': '1000030000/10000', + 'openshift.io/sa.scc.uid-range': '1000030000/10000'}, + 'creationTimestamp': '2017-03-02T00:49:51Z', + 'name': 'openshift', + 'namespace': '', + 'resourceVersion': '3057', + 'selfLink': '/api/v1/namespacesopenshift', + 'uid': '24f7b34d-fee2-11e6-b45a-507b9dac97ff'}, + 'spec': {'finalizers': ['kubernetes', 'openshift.io/origin']}, + 'status': {'phase': 'Active'}}, + {'apiVersion': 'v1', + 'kind': 'Namespace', + 'metadata': {'annotations': {'openshift.io/description': '', + 'openshift.io/display-name': '', + 'openshift.io/requester': 'system:admin', + 'openshift.io/sa.scc.mcs': 's0:c10,c5', + 'openshift.io/sa.scc.supplemental-groups': '1000100000/10000', + 'openshift.io/sa.scc.uid-range': '1000100000/10000'}, + 'creationTimestamp': '2017-03-02T02:21:15Z', + 'name': 'openshift-fancy', + 'namespace': '', + 'resourceVersion': '3072', + 'selfLink': '/api/v1/namespacesopenshift-fancy', + 'uid': 'e958063c-feee-11e6-b45a-507b9dac97ff'}, + 'spec': {'finalizers': ['openshift.io/origin', 'kubernetes']}, + 'status': {'phase': 'Active'} + }], + } + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + # First call to mock + (0, invalid_hostsubnet, ''), + + # Second call to mock + (0, invalid_netnamespace, ''), + + # Third call to mock + (0, invalid_namespace, ''), + ] + + mock_tmpfile_copy.side_effect = [ + '/tmp/mocked_kubeconfig', + ] + + # Act + results = OCObjectValidator.run_ansible(params) + + # Assert + self.assertTrue(results['failed']) + self.assertEqual(results['msg'], 'All objects are not valid.') + self.assertEqual(results['state'], 'list') + self.assertEqual(results['results'], invalid_results) + + # Making sure our mock was called as we expected + mock_cmd.assert_has_calls([ + mock.call(['oc', 'get', 'hostsubnet', '-o', 'json', '-n', 'default'], None), + mock.call(['oc', 'get', 'netnamespace', '-o', 'json', '-n', 'default'], None), + mock.call(['oc', 'get', 'namespace', '-o', 'json', '-n', 'default'], None), + ]) diff --git a/roles/lib_openshift/src/test/unit/test_oc_process.py b/roles/lib_openshift/src/test/unit/test_oc_process.py index c4b36928b..d887f7636 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_process.py +++ b/roles/lib_openshift/src/test/unit/test_oc_process.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc process ''' -# To run -# python -m unittest version -# -# . -# Ran 1 test in 0.597s -# -# OK import os import six @@ -254,10 +246,6 @@ class OCProcessTest(unittest.TestCase): } }''' - def setUp(self): - ''' setup method will set to known configuration ''' - pass - @mock.patch('oc_process.Utils.create_tmpfile_copy') @mock.patch('oc_process.OCProcess._run') def test_state_list(self, mock_cmd, mock_tmpfile_copy): @@ -582,11 +570,3 @@ class OCProcessTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_project.py b/roles/lib_openshift/src/test/unit/test_oc_project.py index 50d81e6a6..5155101cb 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_project.py +++ b/roles/lib_openshift/src/test/unit/test_oc_project.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc project ''' -# To run: -# ./oc_secret.py -# -# . -# Ran 1 test in 0.002s -# -# OK import os import sys @@ -31,10 +23,6 @@ class OCProjectTest(unittest.TestCase): Test class for OCSecret ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_project.locate_oc_binary') @mock.patch('oc_project.Utils.create_tmpfile_copy') @mock.patch('oc_project.Utils._write') @@ -120,11 +108,3 @@ class OCProjectTest(unittest.TestCase): mock.call(['oc', 'get', 'namespace', 'operations', '-o', 'json'], None), ]) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_route.py b/roles/lib_openshift/src/test/unit/test_oc_route.py index e0f6d2f3c..09c52a461 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_route.py +++ b/roles/lib_openshift/src/test/unit/test_oc_route.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc route ''' -# To run: -# ./oc_serviceaccount.py -# -# . -# Ran 1 test in 0.002s -# -# OK import os import six @@ -32,10 +24,6 @@ class OCRouteTest(unittest.TestCase): Test class for OCServiceAccount ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_route.locate_oc_binary') @mock.patch('oc_route.Utils.create_tmpfile_copy') @mock.patch('oc_route.OCRoute._run') @@ -377,11 +365,3 @@ metadata: mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_scale.py b/roles/lib_openshift/src/test/unit/test_oc_scale.py index b2dec2fbe..d810735f2 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_scale.py +++ b/roles/lib_openshift/src/test/unit/test_oc_scale.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc scale ''' -# To run -# python -m unittest version -# -# . -# Ran 1 test in 0.597s -# -# OK import os import six @@ -32,10 +24,6 @@ class OCScaleTest(unittest.TestCase): Test class for OCVersion ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_scale.Utils.create_tmpfile_copy') @mock.patch('oc_scale.OCScale.openshift_cmd') def test_state_list(self, mock_openshift_cmd, mock_tmpfile_copy): @@ -266,11 +254,3 @@ class OCScaleTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_secret.py b/roles/lib_openshift/src/test/unit/test_oc_secret.py index bf496769a..e31393793 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_secret.py +++ b/roles/lib_openshift/src/test/unit/test_oc_secret.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc secret ''' -# To run: -# ./oc_secret.py -# -# . -# Ran 1 test in 0.002s -# -# OK import os import six @@ -32,10 +24,6 @@ class OCSecretTest(unittest.TestCase): Test class for OCSecret ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_secret.locate_oc_binary') @mock.patch('oc_secret.Utils.create_tmpfile_copy') @mock.patch('oc_secret.Utils._write') @@ -200,11 +188,3 @@ class OCSecretTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_service.py b/roles/lib_openshift/src/test/unit/test_oc_service.py index 8974eb6c6..e74c66665 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_service.py +++ b/roles/lib_openshift/src/test/unit/test_oc_service.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc service ''' -# To run -# python -m unittest version -# -# . -# Ran 1 test in 0.597s -# -# OK import os import six @@ -33,10 +25,6 @@ class OCServiceTest(unittest.TestCase): Test class for OCService ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_service.Utils.create_tmpfile_copy') @mock.patch('oc_service.OCService._run') def test_state_list(self, mock_cmd, mock_tmpfile_copy): @@ -315,11 +303,3 @@ class OCServiceTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_serviceaccount.py b/roles/lib_openshift/src/test/unit/test_oc_serviceaccount.py index 3572a6728..5772d2f00 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_serviceaccount.py +++ b/roles/lib_openshift/src/test/unit/test_oc_serviceaccount.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc serviceaccount ''' -# To run: -# ./oc_serviceaccount.py -# -# . -# Ran 1 test in 0.002s -# -# OK import os import six @@ -32,10 +24,6 @@ class OCServiceAccountTest(unittest.TestCase): Test class for OCServiceAccount ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_serviceaccount.locate_oc_binary') @mock.patch('oc_serviceaccount.Utils.create_tmpfile_copy') @mock.patch('oc_serviceaccount.OCServiceAccount._run') @@ -223,11 +211,3 @@ class OCServiceAccountTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_serviceaccount_secret.py b/roles/lib_openshift/src/test/unit/test_oc_serviceaccount_secret.py index d78349e34..b22525068 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_serviceaccount_secret.py +++ b/roles/lib_openshift/src/test/unit/test_oc_serviceaccount_secret.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc secret add ''' -# To run: -# ./oc_serviceaccount_secret.py -# -# . -# Ran 1 test in 0.002s -# -# OK import os import six @@ -38,10 +30,6 @@ class OCServiceAccountSecretTest(unittest.TestCase): Test class for OCServiceAccountSecret ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_serviceaccount_secret.locate_oc_binary') @mock.patch('oc_serviceaccount_secret.Utils.create_tmpfile_copy') @mock.patch('oc_serviceaccount_secret.Yedit._write') @@ -424,11 +412,3 @@ secrets: mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_openshift/src/test/unit/test_oc_version.py b/roles/lib_openshift/src/test/unit/test_oc_version.py index 6daf5b00d..c287bad0b 100755 --- a/roles/lib_openshift/src/test/unit/test_oc_version.py +++ b/roles/lib_openshift/src/test/unit/test_oc_version.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for oc version ''' -# To run -# python -m unittest version -# -# . -# Ran 1 test in 0.597s -# -# OK import os import six @@ -32,10 +24,6 @@ class OCVersionTest(unittest.TestCase): Test class for OCVersion ''' - def setUp(self): - ''' setup method will create a file and set to known configuration ''' - pass - @mock.patch('oc_version.Utils.create_tmpfile_copy') @mock.patch('oc_version.OCVersion.openshift_cmd') def test_get(self, mock_openshift_cmd, mock_tmpfile_copy): @@ -172,11 +160,3 @@ class OCVersionTest(unittest.TestCase): mock_shutil_which.side_effect = lambda _f, path=None: oc_bin self.assertEqual(locate_oc_binary(), oc_bin) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_utils/src/test/unit/test_repoquery.py b/roles/lib_utils/src/test/unit/test_repoquery.py index c487ab254..e39d9d83f 100755 --- a/roles/lib_utils/src/test/unit/test_repoquery.py +++ b/roles/lib_utils/src/test/unit/test_repoquery.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for repoquery ''' -# To run: -# ./repoquery.py -# -# . -# Ran 1 test in 0.002s -# -# OK import os import sys @@ -31,10 +23,6 @@ class RepoQueryTest(unittest.TestCase): Test class for RepoQuery ''' - def setUp(self): - ''' setup method for other tests ''' - pass - @mock.patch('repoquery._run') def test_querying_a_package(self, mock_cmd): ''' Testing querying a package ''' @@ -77,11 +65,3 @@ class RepoQueryTest(unittest.TestCase): mock_cmd.assert_has_calls([ mock.call(['/usr/bin/repoquery', '--plugins', '--quiet', '--pkgnarrow=repos', '--queryformat=%{version}|%{release}|%{arch}|%{repo}|%{version}-%{release}', 'bash']), ]) - - def tearDown(self): - '''TearDown method''' - pass - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/lib_utils/src/test/unit/test_yedit.py b/roles/lib_utils/src/test/unit/test_yedit.py index a22cdee56..23a3f7353 100755 --- a/roles/lib_utils/src/test/unit/test_yedit.py +++ b/roles/lib_utils/src/test/unit/test_yedit.py @@ -1,14 +1,6 @@ -#!/usr/bin/env python2 ''' Unit tests for yedit ''' -# To run -# python -m unittest yedit_test -# -# ............................. -# ---------------------------------------------------------------------- -# Ran 29 tests in 0.133s -# OK import os import sys @@ -288,7 +280,3 @@ class YeditTest(unittest.TestCase): def tearDown(self): '''TearDown method''' os.unlink(YeditTest.filename) - - -if __name__ == "__main__": - unittest.main() diff --git a/roles/openshift_logging/meta/main.yaml b/roles/openshift_logging/meta/main.yaml index 9c480f73a..ab57242c8 100644 --- a/roles/openshift_logging/meta/main.yaml +++ b/roles/openshift_logging/meta/main.yaml @@ -13,4 +13,5 @@ galaxy_info: - cloud dependencies: - role: lib_openshift +- role: openshift_master_facts - role: openshift_facts |