From d338c1aefc702919e6fac553c60a69455ae37d05 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Tue, 7 Feb 2017 21:44:47 -0500 Subject: Adding oc_env to lib_openshift. --- roles/lib_openshift/src/ansible/oc_env.py | 32 +++ roles/lib_openshift/src/class/oc_env.py | 144 ++++++++++ roles/lib_openshift/src/doc/env | 76 +++++ roles/lib_openshift/src/sources.yml | 11 + roles/lib_openshift/src/test/unit/oc_env.py | 430 ++++++++++++++++++++++++++++ 5 files changed, 693 insertions(+) create mode 100644 roles/lib_openshift/src/ansible/oc_env.py create mode 100644 roles/lib_openshift/src/class/oc_env.py create mode 100644 roles/lib_openshift/src/doc/env create mode 100755 roles/lib_openshift/src/test/unit/oc_env.py (limited to 'roles/lib_openshift/src') diff --git a/roles/lib_openshift/src/ansible/oc_env.py b/roles/lib_openshift/src/ansible/oc_env.py new file mode 100644 index 000000000..4a58f7ec1 --- /dev/null +++ b/roles/lib_openshift/src/ansible/oc_env.py @@ -0,0 +1,32 @@ +# pylint: skip-file + +def main(): + ''' + ansible oc module for environment variables + ''' + + module = AnsibleModule( + argument_spec=dict( + kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'), + state=dict(default='present', type='str', + choices=['present', 'absent', 'list']), + debug=dict(default=False, type='bool'), + kind=dict(default='rc', choices=['dc', 'rc', 'pods'], type='str'), + namespace=dict(default='default', type='str'), + name=dict(default=None, required=True, type='str'), + env_vars=dict(default=None, type='dict'), + ), + mutually_exclusive=[["content", "files"]], + + supports_check_mode=True, + ) + results = OCEnv.run_ansible(module.params, module.check_mode) + + if 'failed' in results: + module.fail_json(**results) + + module.exit_json(**results) + + +if __name__ == '__main__': + main() diff --git a/roles/lib_openshift/src/class/oc_env.py b/roles/lib_openshift/src/class/oc_env.py new file mode 100644 index 000000000..a7ea0c9eb --- /dev/null +++ b/roles/lib_openshift/src/class/oc_env.py @@ -0,0 +1,144 @@ +# pylint: skip-file + +# pylint: disable=too-many-instance-attributes +class OCEnv(OpenShiftCLI): + ''' Class to wrap the oc command line tools ''' + + container_path = {"pod": "spec.containers[0].env", + "dc": "spec.template.spec.containers[0].env", + "rc": "spec.template.spec.containers[0].env", + } + + # pylint allows 5. we need 6 + # pylint: disable=too-many-arguments + def __init__(self, + namespace, + kind, + env_vars, + resource_name=None, + kubeconfig='/etc/origin/master/admin.kubeconfig', + verbose=False): + ''' Constructor for OpenshiftOC ''' + super(OCEnv, self).__init__(namespace, kubeconfig) + self.kind = kind + self.name = resource_name + self.namespace = namespace + self.env_vars = env_vars + self.kubeconfig = kubeconfig + self.verbose = verbose + self._resource = None + + @property + def resource(self): + ''' property function for resource var''' + if not self._resource: + self.get() + return self._resource + + @resource.setter + def resource(self, data): + ''' setter function for resource var''' + self._resource = data + + def value_exists(self, key, value): + ''' return whether a key, value pair exists ''' + return self.resource.exists_env_value(key, value) + + def key_exists(self, key): + ''' return whether a key, value pair exists ''' + return self.resource.exists_env_key(key) + + def get(self): + '''return a environment variables ''' + result = self._get(self.kind, self.name) + if result['returncode'] == 0: + if self.kind == 'dc': + self.resource = DeploymentConfig(content=result['results'][0]) + result['results'] = self.resource.get(OCEnv.container_path[self.kind]) or [] + return result + + def delete(self): + '''return all pods ''' + #yed.put(OCEnv.container_path[self.kind], env_vars_array) + if self.resource.delete_env_var(self.env_vars.keys()): + return self._replace_content(self.kind, self.name, self.resource.yaml_dict) + + return {'returncode': 0, 'changed': False} + + # pylint: disable=too-many-function-args + def put(self): + '''place env vars into dc ''' + for update_key, update_value in self.env_vars.items(): + self.resource.update_env_var(update_key, update_value) + + return self._replace_content(self.kind, self.name, self.resource.yaml_dict) + + @staticmethod + def run_ansible(params, check_mode): + '''run the idempotent ansible code''' + + ocenv = OCEnv(params['namespace'], + params['kind'], + params['env_vars'], + resource_name=params['name'], + kubeconfig=params['kubeconfig'], + verbose=params['debug']) + + state = params['state'] + + api_rval = ocenv.get() + + ##### + # Get + ##### + if state == 'list': + return {'changed': False, 'results': api_rval['results'], 'state': "list"} + + ######## + # Delete + ######## + if state == 'absent': + for key in params.get('env_vars', {}).keys(): + if ocenv.resource.exists_env_key(key): + + if check_mode: + return {'changed': False, + 'msg': 'CHECK_MODE: Would have performed a delete.'} + + api_rval = ocenv.delete() + + return {'changed': True, 'results': results, 'state': 'absent'} + + return {'changed': False, 'state': 'absent'} + + if state == 'present': + ######## + # Create + ######## + for key, value in params.get('env_vars', {}).items(): + if not ocenv.value_exists(key, value): + + if check_mode: + return {'changed': False, + 'msg': 'CHECK_MODE: Would have performed a create.'} + + # Create it here + api_rval = ocenv.put() + + if api_rval['returncode'] != 0: + return {'failed': True, 'msg': api_rval} + + # return the created object + api_rval = ocenv.get() + + if api_rval['returncode'] != 0: + return {'failed': True, 'msg': api_rval} + + return {'changed': True, 'results': results, 'state': 'present'} + + return {'changed': False, 'results': results, 'state': 'present'} + + + return {'failed': True, + 'changed': False, + 'msg': 'Unknown state passed. %s' % state} diff --git a/roles/lib_openshift/src/doc/env b/roles/lib_openshift/src/doc/env new file mode 100644 index 000000000..0544014e6 --- /dev/null +++ b/roles/lib_openshift/src/doc/env @@ -0,0 +1,76 @@ +# flake8: noqa +# pylint: skip-file + +DOCUMENTATION = ''' +--- +module: oc_env +short_description: Modify, and idempotently manage openshift environment variables on pods, deploymentconfigs, and replication controllers. +description: + - Modify openshift environment variables programmatically. +options: + state: + description: + - Supported states, present, absent, list + - present - will ensure object is created or updated to the value specified + - list - will return a list of environment variables + - absent - will remove the environment varibale from the object + required: False + default: present + choices: ["present", 'absent', 'list'] + aliases: [] + kubeconfig: + description: + - The path for the kubeconfig file to use for authentication + required: false + default: /etc/origin/master/admin.kubeconfig + aliases: [] + debug: + description: + - Turn on debug output. + required: false + default: False + aliases: [] + name: + description: + - Name of the object that is being queried. + required: false + default: None + aliases: [] + namespace: + description: + - The namespace where the object lives. + required: false + default: str + aliases: [] + kind: + description: + - The kind attribute of the object. + required: False + default: dc + choices: + - rc + - dc + - pods + aliases: [] +author: +- "Kenny Woodson " +extends_documentation_fragment: [] +''' + +EXAMPLES = ''' +- name: query a list of env vars on dc + oc_env: + kind: dc + name: myawesomedc + namespace: phpapp + +- name: Set the following variables. + oc_env: + kind: dc + name: myawesomedc + namespace: phpapp + env_vars: + SUPER_TURBO_MODE: 'true' + ENABLE_PORTS: 'false' + SERVICE_PORT: 9999 +''' diff --git a/roles/lib_openshift/src/sources.yml b/roles/lib_openshift/src/sources.yml index aa02ce120..badb1b1a4 100644 --- a/roles/lib_openshift/src/sources.yml +++ b/roles/lib_openshift/src/sources.yml @@ -19,6 +19,17 @@ oc_edit.py: - class/oc_edit.py - ansible/oc_edit.py +oc_env.py: +- doc/generated +- doc/license +- lib/import.py +- doc/env +- ../../lib_utils/src/class/yedit.py +- lib/base.py +- lib/deploymentconfig.py +- class/oc_env.py +- ansible/oc_env.py + oc_label.py: - doc/generated - doc/license diff --git a/roles/lib_openshift/src/test/unit/oc_env.py b/roles/lib_openshift/src/test/unit/oc_env.py new file mode 100755 index 000000000..5661065b9 --- /dev/null +++ b/roles/lib_openshift/src/test/unit/oc_env.py @@ -0,0 +1,430 @@ +#!/usr/bin/env python2 +''' + Unit tests for oc_env +''' +# To run: +# ./oc_env.py +# +# . +# Ran 1 test 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,wrong-import-position +# 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_env import OCEnv # noqa: E402 + + +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.OCEnv._run') + def test_listing_all_env_vars(self, mock_cmd): + ''' Testing listing all environment variables from a dc''' + + # Arrange + + # run_ansible input parameters + params = { + 'state': 'list', + 'namespace': 'default', + 'name': 'router', + 'kind': 'dc', + 'list_all': False, + 'env_vars': None, + 'kubeconfig': '/etc/origin/master/admin.kubeconfig', + 'debug': False, + } + + dc_results = '''{ + "apiVersion": "v1", + "kind": "DeploymentConfig", + "metadata": { + "creationTimestamp": "2017-02-02T15:58:49Z", + "generation": 8, + "labels": { + "router": "router" + }, + "name": "router", + "namespace": "default", + "resourceVersion": "513678", + "selfLink": "/oapi/v1/namespaces/default/deploymentconfigs/router", + "uid": "7c705902-e960-11e6-b041-0ed9df7abc38" + }, + "spec": { + "replicas": 2, + "selector": { + "router": "router" + }, + "strategy": { + "activeDeadlineSeconds": 21600, + "resources": {}, + "rollingParams": { + "intervalSeconds": 1, + "maxSurge": "50%", + "maxUnavailable": "50%", + "timeoutSeconds": 600, + "updatePeriodSeconds": 1 + }, + "type": "Rolling" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "router": "router" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "DEFAULT_CERTIFICATE_DIR", + "value": "/etc/pki/tls/private" + }, + { + "name": "DEFAULT_CERTIFICATE_PATH", + "value": "/etc/pki/tls/private/tls.crt" + }, + { + "name": "ROUTER_EXTERNAL_HOST_HOSTNAME" + }, + { + "name": "ROUTER_EXTERNAL_HOST_HTTPS_VSERVER" + }, + { + "name": "ROUTER_EXTERNAL_HOST_HTTP_VSERVER" + }, + { + "name": "ROUTER_EXTERNAL_HOST_INSECURE", + "value": "false" + }, + { + "name": "ROUTER_EXTERNAL_HOST_INTERNAL_ADDRESS" + }, + { + "name": "ROUTER_EXTERNAL_HOST_PARTITION_PATH" + }, + { + "name": "ROUTER_EXTERNAL_HOST_PASSWORD" + }, + { + "name": "ROUTER_EXTERNAL_HOST_PRIVKEY", + "value": "/etc/secret-volume/router.pem" + }, + { + "name": "ROUTER_EXTERNAL_HOST_USERNAME" + }, + { + "name": "ROUTER_EXTERNAL_HOST_VXLAN_GW_CIDR" + }, + { + "name": "ROUTER_SERVICE_HTTPS_PORT", + "value": "443" + }, + { + "name": "ROUTER_SERVICE_HTTP_PORT", + "value": "80" + }, + { + "name": "ROUTER_SERVICE_NAME", + "value": "router" + }, + { + "name": "ROUTER_SERVICE_NAMESPACE", + "value": "default" + }, + { + "name": "ROUTER_SUBDOMAIN" + }, + { + "name": "STATS_PASSWORD", + "value": "UEKR5GCWGI" + }, + { + "name": "STATS_PORT", + "value": "1936" + }, + { + "name": "STATS_USERNAME", + "value": "admin" + }, + { + "name": "EXTENDED_VALIDATION", + "value": "false" + }, + { + "name": "ROUTER_USE_PROXY_PROTOCOL", + "value": "true" + } + ], + "image": "openshift3/ose-haproxy-router:v3.5.0.17", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 3, + "httpGet": { + "host": "localhost", + "path": "/healthz", + "port": 1936, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "router", + "ports": [ + { + "containerPort": 80, + "hostPort": 80, + "protocol": "TCP" + }, + { + "containerPort": 443, + "hostPort": 443, + "protocol": "TCP" + }, + { + "containerPort": 5000, + "hostPort": 5000, + "protocol": "TCP" + }, + { + "containerPort": 1936, + "hostPort": 1936, + "name": "stats", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "host": "localhost", + "path": "/healthz", + "port": 1936, + "scheme": "HTTP" + }, + "initialDelaySeconds": 10, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "requests": { + "cpu": "100m", + "memory": "256Mi" + } + }, + "terminationMessagePath": "/dev/termination-log", + "volumeMounts": [ + { + "mountPath": "/etc/pki/tls/private", + "name": "server-certificate", + "readOnly": true + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "nodeSelector": { + "type": "infra" + }, + "restartPolicy": "Always", + "securityContext": {}, + "serviceAccount": "router", + "serviceAccountName": "router", + "terminationGracePeriodSeconds": 30, + "volumes": [ + { + "name": "server-certificate", + "secret": { + "defaultMode": 420, + "secretName": "router-certs" + } + } + ] + } + }, + "test": false, + "triggers": [ + { + "type": "ConfigChange" + } + ] + }, + "status": { + "availableReplicas": 2, + "conditions": [ + { + "lastTransitionTime": "2017-02-02T15:59:12Z", + "lastUpdateTime": null, + "message": "Deployment config has minimum availability.", + "status": "True", + "type": "Available" + }, + { + "lastTransitionTime": "2017-02-07T19:55:26Z", + "lastUpdateTime": "2017-02-07T19:55:26Z", + "message": "replication controller router-2 has failed progressing", + "reason": "ProgressDeadlineExceeded", + "status": "False", + "type": "Progressing" + } + ], + "details": { + "causes": [ + { + "type": "ConfigChange" + } + ], + "message": "config change" + }, + "latestVersion": 2, + "observedGeneration": 8, + "readyReplicas": 2, + "replicas": 2, + "unavailableReplicas": 0, + "updatedReplicas": 0 + } + }''' + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + (0, dc_results, ''), # First call to the mock + ] + + # Act + results = OCEnv.run_ansible(params, False) + + # Assert + self.assertFalse(results['changed']) + for env_var in results['results']: + if env_var == {'name': 'DEFAULT_CERTIFICATE_DIR', 'value': '/etc/pki/tls/private'}: + break + else: + self.fail('Did not find envionrment variables in results.') + self.assertEqual(results['state'], 'list') + + # Making sure our mocks were called as we expected + mock_cmd.assert_has_calls([ + mock.call(['oc', '-n', 'default', 'get', 'dc', 'router', '-o', 'json'], None), + ]) + +# @mock.patch('oc_serviceaccount_secret.Yedit._write') +# @mock.patch('oc_serviceaccount_secret.OCServiceAccountSecret._run') +# def test_removing_a_secret_to_a_serviceaccount(self, mock_cmd, mock_write): +# ''' Testing adding a secret to a service account ''' +# +# # Arrange +# +# # run_ansible input parameters +# params = { +# 'state': 'absent', +# 'namespace': 'default', +# 'secret': 'newsecret', +# 'service_account': 'builder', +# 'kubeconfig': '/etc/origin/master/admin.kubeconfig', +# 'debug': False, +# } +# +# oc_get_sa_before = '''{ +# "kind": "ServiceAccount", +# "apiVersion": "v1", +# "metadata": { +# "name": "builder", +# "namespace": "default", +# "selfLink": "/api/v1/namespaces/default/serviceaccounts/builder", +# "uid": "cf47bca7-ebc4-11e6-b041-0ed9df7abc38", +# "resourceVersion": "302879", +# "creationTimestamp": "2017-02-05T17:02:00Z" +# }, +# "secrets": [ +# { +# "name": "builder-dockercfg-rsrua" +# }, +# { +# "name": "builder-token-akqxi" +# }, +# { +# "name": "newsecret" +# } +# +# ], +# "imagePullSecrets": [ +# { +# "name": "builder-dockercfg-rsrua" +# } +# ] +# } +# ''' +# +# builder_yaml_file = '''\ +#secrets: +#- name: builder-dockercfg-rsrua +#- name: builder-token-akqxi +#kind: ServiceAccount +#imagePullSecrets: +#- name: builder-dockercfg-rsrua +#apiVersion: v1 +#metadata: +# name: builder +# namespace: default +# resourceVersion: '302879' +# creationTimestamp: '2017-02-05T17:02:00Z' +# selfLink: /api/v1/namespaces/default/serviceaccounts/builder +# uid: cf47bca7-ebc4-11e6-b041-0ed9df7abc38 +#''' +# +# # Return values of our mocked function call. These get returned once per call. +# mock_cmd.side_effect = [ +# (0, oc_get_sa_before, ''), # First call to the mock +# (0, oc_get_sa_before, ''), # Second call to the mock +# (0, 'serviceaccount "builder" replaced', ''), # Third call to the mock +# ] +# +# # Act +# results = OCServiceAccountSecret.run_ansible(params, False) +# +# # Assert +# self.assertTrue(results['changed']) +# self.assertEqual(results['results']['returncode'], 0) +# self.assertEqual(results['state'], 'absent') +# +# # Making sure our mocks were called as we expected +# mock_cmd.assert_has_calls([ +# mock.call(['oc', '-n', 'default', 'get', 'sa', 'builder', '-o', 'json'], None), +# mock.call(['oc', '-n', 'default', 'get', 'sa', 'builder', '-o', 'json'], None), +# mock.call(['oc', '-n', 'default', 'replace', '-f', '/tmp/builder'], None), +# ]) +# +# mock_write.assert_has_calls([ +# mock.call('/tmp/builder', builder_yaml_file) +# ]) + + def tearDown(self): + '''TearDown method''' + pass + + +if __name__ == "__main__": + unittest.main() -- cgit v1.2.3 From 7538002114965b4c4e6b202bf7216ec9c9a6d669 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 8 Feb 2017 16:45:33 -0500 Subject: Adding integration tests. --- roles/lib_openshift/src/class/oc_env.py | 6 +- .../lib_openshift/src/test/integration/oc_env.yml | 75 +++ roles/lib_openshift/src/test/unit/oc_env.py | 581 ++++++++++++--------- 3 files changed, 408 insertions(+), 254 deletions(-) create mode 100755 roles/lib_openshift/src/test/integration/oc_env.yml (limited to 'roles/lib_openshift/src') diff --git a/roles/lib_openshift/src/class/oc_env.py b/roles/lib_openshift/src/class/oc_env.py index a7ea0c9eb..10d44412a 100644 --- a/roles/lib_openshift/src/class/oc_env.py +++ b/roles/lib_openshift/src/class/oc_env.py @@ -107,7 +107,7 @@ class OCEnv(OpenShiftCLI): api_rval = ocenv.delete() - return {'changed': True, 'results': results, 'state': 'absent'} + return {'changed': True, 'state': 'absent'} return {'changed': False, 'state': 'absent'} @@ -134,9 +134,9 @@ class OCEnv(OpenShiftCLI): if api_rval['returncode'] != 0: return {'failed': True, 'msg': api_rval} - return {'changed': True, 'results': results, 'state': 'present'} + return {'changed': True, 'results': api_rval['results'], 'state': 'present'} - return {'changed': False, 'results': results, 'state': 'present'} + return {'changed': False, 'results': api_rval['results'], 'state': 'present'} return {'failed': True, diff --git a/roles/lib_openshift/src/test/integration/oc_env.yml b/roles/lib_openshift/src/test/integration/oc_env.yml new file mode 100755 index 000000000..97a7c8922 --- /dev/null +++ b/roles/lib_openshift/src/test/integration/oc_env.yml @@ -0,0 +1,75 @@ +#!/usr/bin/ansible-playbook --module-path=../../../library/ +# ./oc_env.yml -e "cli_master_test=$OPENSHIFT_MASTER +--- +- hosts: "{{ cli_master_test }}" + gather_facts: no + user: root + vars: + my_env_var: + SOMEKEY : SOMEVALUE + + check_env_var: + name: DEFAULT_CERTIFICATE_DIR + value: /etc/pki/tls/private + + tasks: + - name: list environment variables from router dc + oc_env: + state: list + name: router + namespace: default + kind: dc + register: envout + - debug: var=envout + + - assert: + that: + - "'{{ check_env_var.name }}' == '{{ envout.results[0].name }}'" + - "{{ envout.results|length }} > 0" + msg: "Did not find environment variables." + + - name: list environment variables from router dc + oc_env: + state: present + name: router + namespace: default + kind: dc + env_vars: "{{ my_env_var }}" + register: envout + - debug: var=envout + + - assert: + that: + - "'SOMEKEY' == '{{ envout.results[-1].name }}'" + - "'SOMEVALUE' == '{{ envout.results[-1].value }}'" + msg: "Did not find updated environment variables." + + - name: remove environment variables from router dc + oc_env: + state: absent + name: router + namespace: default + kind: dc + env_vars: "{{ my_env_var }}" + register: envout + - debug: var=envout + + - assert: + that: + - envout.changed == True + msg: "state: Absent failed." + + - name: list environment variables from router dc + oc_env: + state: list + name: router + namespace: default + kind: dc + register: envout + - debug: var=envout + + - assert: + that: + - "'SOMEKEY' != '{{ envout.results[-1].name }}'" + - "'SOMEVALUE' != '{{ envout.results[-1].value }}'" + msg: "Did find updated environment variables." diff --git a/roles/lib_openshift/src/test/unit/oc_env.py b/roles/lib_openshift/src/test/unit/oc_env.py index 5661065b9..eefd40b61 100755 --- a/roles/lib_openshift/src/test/unit/oc_env.py +++ b/roles/lib_openshift/src/test/unit/oc_env.py @@ -35,8 +35,9 @@ class OCEnvTest(unittest.TestCase): ''' setup method will create a file and set to known configuration ''' pass + @mock.patch('oc_env.Utils.create_tmpfile_copy') @mock.patch('oc_env.OCEnv._run') - def test_listing_all_env_vars(self, mock_cmd): + def test_listing_all_env_vars(self, mock_cmd, mock_tmpfile_copy): ''' Testing listing all environment variables from a dc''' # Arrange @@ -47,7 +48,6 @@ class OCEnvTest(unittest.TestCase): 'namespace': 'default', 'name': 'router', 'kind': 'dc', - 'list_all': False, 'env_vars': None, 'kubeconfig': '/etc/origin/master/admin.kubeconfig', 'debug': False, @@ -64,27 +64,13 @@ class OCEnvTest(unittest.TestCase): }, "name": "router", "namespace": "default", - "resourceVersion": "513678", - "selfLink": "/oapi/v1/namespaces/default/deploymentconfigs/router", - "uid": "7c705902-e960-11e6-b041-0ed9df7abc38" + "resourceVersion": "513678" }, "spec": { "replicas": 2, "selector": { "router": "router" }, - "strategy": { - "activeDeadlineSeconds": 21600, - "resources": {}, - "rollingParams": { - "intervalSeconds": 1, - "maxSurge": "50%", - "maxUnavailable": "50%", - "timeoutSeconds": 600, - "updatePeriodSeconds": 1 - }, - "type": "Rolling" - }, "template": { "metadata": { "creationTimestamp": null, @@ -116,151 +102,368 @@ class OCEnvTest(unittest.TestCase): { "name": "ROUTER_EXTERNAL_HOST_INSECURE", "value": "false" + } + ], + "name": "router" + } + ] + } + }, + "test": false, + "triggers": [ + { + "type": "ConfigChange" + } + ] + } + }''' + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + (0, dc_results, ''), # First call to the mock + ] + + mock_tmpfile_copy.side_effect = [ + '/tmp/mock_adminkubeconfig', + ] + + # Act + results = OCEnv.run_ansible(params, False) + + # Assert + self.assertFalse(results['changed']) + for env_var in results['results']: + if env_var == {'name': 'DEFAULT_CERTIFICATE_DIR', 'value': '/etc/pki/tls/private'}: + break + else: + self.fail('Did not find environment variables in results.') + self.assertEqual(results['state'], 'list') + + # Making sure our mocks were called as we expected + mock_cmd.assert_has_calls([ + mock.call(['oc', '-n', 'default', 'get', 'dc', 'router', '-o', 'json'], None), + ]) + + @mock.patch('oc_env.Utils.create_tmpfile_copy') + @mock.patch('oc_env.OCEnv._run') + def test_adding_env_vars(self, mock_cmd, mock_tmpfile_copy): + ''' Test add environment variables to a dc''' + + # Arrange + + # run_ansible input parameters + params = { + 'state': 'present', + 'namespace': 'default', + 'name': 'router', + 'kind': 'dc', + 'kubeconfig': '/etc/origin/master/admin.kubeconfig', + 'debug': False, + 'env_vars': {'SOMEKEY': 'SOMEVALUE'}, + } + + dc_results = '''{ + "apiVersion": "v1", + "kind": "DeploymentConfig", + "metadata": { + "creationTimestamp": "2017-02-02T15:58:49Z", + "generation": 8, + "labels": { + "router": "router" + }, + "name": "router", + "namespace": "default", + "resourceVersion": "513678" + }, + "spec": { + "replicas": 2, + "selector": { + "router": "router" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "router": "router" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "DEFAULT_CERTIFICATE_DIR", + "value": "/etc/pki/tls/private" }, { - "name": "ROUTER_EXTERNAL_HOST_INTERNAL_ADDRESS" + "name": "DEFAULT_CERTIFICATE_PATH", + "value": "/etc/pki/tls/private/tls.crt" }, { - "name": "ROUTER_EXTERNAL_HOST_PARTITION_PATH" + "name": "ROUTER_EXTERNAL_HOST_HOSTNAME" }, { - "name": "ROUTER_EXTERNAL_HOST_PASSWORD" + "name": "ROUTER_EXTERNAL_HOST_HTTPS_VSERVER" }, { - "name": "ROUTER_EXTERNAL_HOST_PRIVKEY", - "value": "/etc/secret-volume/router.pem" + "name": "ROUTER_EXTERNAL_HOST_HTTP_VSERVER" }, { - "name": "ROUTER_EXTERNAL_HOST_USERNAME" + "name": "ROUTER_EXTERNAL_HOST_INSECURE", + "value": "false" + } + ], + "name": "router" + } + ] + } + }, + "test": false, + "triggers": [ + { + "type": "ConfigChange" + } + ] + } + }''' + + dc_results_after = '''{ + "apiVersion": "v1", + "kind": "DeploymentConfig", + "metadata": { + "creationTimestamp": "2017-02-02T15:58:49Z", + "generation": 8, + "labels": { + "router": "router" + }, + "name": "router", + "namespace": "default", + "resourceVersion": "513678" + }, + "spec": { + "replicas": 2, + "selector": { + "router": "router" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "router": "router" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "DEFAULT_CERTIFICATE_DIR", + "value": "/etc/pki/tls/private" }, { - "name": "ROUTER_EXTERNAL_HOST_VXLAN_GW_CIDR" + "name": "DEFAULT_CERTIFICATE_PATH", + "value": "/etc/pki/tls/private/tls.crt" }, { - "name": "ROUTER_SERVICE_HTTPS_PORT", - "value": "443" + "name": "ROUTER_EXTERNAL_HOST_HOSTNAME" }, { - "name": "ROUTER_SERVICE_HTTP_PORT", - "value": "80" + "name": "ROUTER_EXTERNAL_HOST_HTTPS_VSERVER" }, { - "name": "ROUTER_SERVICE_NAME", - "value": "router" + "name": "ROUTER_EXTERNAL_HOST_HTTP_VSERVER" }, { - "name": "ROUTER_SERVICE_NAMESPACE", - "value": "default" + "name": "ROUTER_EXTERNAL_HOST_INSECURE", + "value": "false" }, { - "name": "ROUTER_SUBDOMAIN" + "name": "SOMEKEY", + "value": "SOMEVALUE" + } + ], + "name": "router" + } + ] + } + }, + "test": false, + "triggers": [ + { + "type": "ConfigChange" + } + ] + } + }''' + + # Return values of our mocked function call. These get returned once per call. + mock_cmd.side_effect = [ + (0, dc_results, ''), + (0, dc_results, ''), + (0, dc_results_after, ''), + (0, dc_results_after, ''), + ] + + mock_tmpfile_copy.side_effect = [ + '/tmp/mock_adminkubeconfig', + ] + + # Act + results = OCEnv.run_ansible(params, False) + + # Assert + self.assertTrue(results['changed']) + for env_var in results['results']: + if env_var == {'name': 'SOMEKEY', 'value': 'SOMEVALUE'}: + break + else: + self.fail('Did not find environment variables in results.') + self.assertEqual(results['state'], 'present') + + # Making sure our mocks were called as we expected + mock_cmd.assert_has_calls([ + mock.call(['oc', '-n', 'default', 'get', 'dc', 'router', '-o', 'json'], None), + ]) + + @mock.patch('oc_env.Utils.create_tmpfile_copy') + @mock.patch('oc_env.OCEnv._run') + def test_removing_env_vars(self, mock_cmd, mock_tmpfile_copy): + ''' Test add environment variables to a dc''' + + # Arrange + + # run_ansible input parameters + params = { + 'state': 'absent', + 'namespace': 'default', + 'name': 'router', + 'kind': 'dc', + 'kubeconfig': '/etc/origin/master/admin.kubeconfig', + 'debug': False, + 'env_vars': {'SOMEKEY': 'SOMEVALUE'}, + } + + dc_results_after = '''{ + "apiVersion": "v1", + "kind": "DeploymentConfig", + "metadata": { + "creationTimestamp": "2017-02-02T15:58:49Z", + "generation": 8, + "labels": { + "router": "router" + }, + "name": "router", + "namespace": "default", + "resourceVersion": "513678" + }, + "spec": { + "replicas": 2, + "selector": { + "router": "router" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "router": "router" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "DEFAULT_CERTIFICATE_DIR", + "value": "/etc/pki/tls/private" }, { - "name": "STATS_PASSWORD", - "value": "UEKR5GCWGI" + "name": "DEFAULT_CERTIFICATE_PATH", + "value": "/etc/pki/tls/private/tls.crt" }, { - "name": "STATS_PORT", - "value": "1936" + "name": "ROUTER_EXTERNAL_HOST_HOSTNAME" }, { - "name": "STATS_USERNAME", - "value": "admin" + "name": "ROUTER_EXTERNAL_HOST_HTTPS_VSERVER" }, { - "name": "EXTENDED_VALIDATION", - "value": "false" + "name": "ROUTER_EXTERNAL_HOST_HTTP_VSERVER" }, { - "name": "ROUTER_USE_PROXY_PROTOCOL", - "value": "true" + "name": "ROUTER_EXTERNAL_HOST_INSECURE", + "value": "false" } ], - "image": "openshift3/ose-haproxy-router:v3.5.0.17", - "imagePullPolicy": "IfNotPresent", - "livenessProbe": { - "failureThreshold": 3, - "httpGet": { - "host": "localhost", - "path": "/healthz", - "port": 1936, - "scheme": "HTTP" + "name": "router" + } + ] + } + }, + "test": false, + "triggers": [ + { + "type": "ConfigChange" + } + ] + } + }''' + + dc_results_before = '''{ + "apiVersion": "v1", + "kind": "DeploymentConfig", + "metadata": { + "creationTimestamp": "2017-02-02T15:58:49Z", + "generation": 8, + "labels": { + "router": "router" + }, + "name": "router", + "namespace": "default", + "resourceVersion": "513678" + }, + "spec": { + "replicas": 2, + "selector": { + "router": "router" + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "router": "router" + } + }, + "spec": { + "containers": [ + { + "env": [ + { + "name": "DEFAULT_CERTIFICATE_DIR", + "value": "/etc/pki/tls/private" + }, + { + "name": "DEFAULT_CERTIFICATE_PATH", + "value": "/etc/pki/tls/private/tls.crt" }, - "initialDelaySeconds": 10, - "periodSeconds": 10, - "successThreshold": 1, - "timeoutSeconds": 1 - }, - "name": "router", - "ports": [ - { - "containerPort": 80, - "hostPort": 80, - "protocol": "TCP" + { + "name": "ROUTER_EXTERNAL_HOST_HOSTNAME" }, { - "containerPort": 443, - "hostPort": 443, - "protocol": "TCP" + "name": "ROUTER_EXTERNAL_HOST_HTTPS_VSERVER" }, { - "containerPort": 5000, - "hostPort": 5000, - "protocol": "TCP" + "name": "ROUTER_EXTERNAL_HOST_HTTP_VSERVER" }, { - "containerPort": 1936, - "hostPort": 1936, - "name": "stats", - "protocol": "TCP" - } - ], - "readinessProbe": { - "failureThreshold": 3, - "httpGet": { - "host": "localhost", - "path": "/healthz", - "port": 1936, - "scheme": "HTTP" + "name": "ROUTER_EXTERNAL_HOST_INSECURE", + "value": "false" }, - "initialDelaySeconds": 10, - "periodSeconds": 10, - "successThreshold": 1, - "timeoutSeconds": 1 - }, - "resources": { - "requests": { - "cpu": "100m", - "memory": "256Mi" - } - }, - "terminationMessagePath": "/dev/termination-log", - "volumeMounts": [ { - "mountPath": "/etc/pki/tls/private", - "name": "server-certificate", - "readOnly": true + "name": "SOMEKEY", + "value": "SOMEVALUE" } - ] - } - ], - "dnsPolicy": "ClusterFirst", - "hostNetwork": true, - "nodeSelector": { - "type": "infra" - }, - "restartPolicy": "Always", - "securityContext": {}, - "serviceAccount": "router", - "serviceAccountName": "router", - "terminationGracePeriodSeconds": 30, - "volumes": [ - { - "name": "server-certificate", - "secret": { - "defaultMode": 420, - "secretName": "router-certs" - } + ], + "name": "router" } ] } @@ -271,156 +474,32 @@ class OCEnvTest(unittest.TestCase): "type": "ConfigChange" } ] - }, - "status": { - "availableReplicas": 2, - "conditions": [ - { - "lastTransitionTime": "2017-02-02T15:59:12Z", - "lastUpdateTime": null, - "message": "Deployment config has minimum availability.", - "status": "True", - "type": "Available" - }, - { - "lastTransitionTime": "2017-02-07T19:55:26Z", - "lastUpdateTime": "2017-02-07T19:55:26Z", - "message": "replication controller router-2 has failed progressing", - "reason": "ProgressDeadlineExceeded", - "status": "False", - "type": "Progressing" - } - ], - "details": { - "causes": [ - { - "type": "ConfigChange" - } - ], - "message": "config change" - }, - "latestVersion": 2, - "observedGeneration": 8, - "readyReplicas": 2, - "replicas": 2, - "unavailableReplicas": 0, - "updatedReplicas": 0 } }''' # Return values of our mocked function call. These get returned once per call. mock_cmd.side_effect = [ - (0, dc_results, ''), # First call to the mock + (0, dc_results_before, ''), + (0, dc_results_before, ''), + (0, '', ''), + ] + + mock_tmpfile_copy.side_effect = [ + '/tmp/mock_adminkubeconfig', ] # Act results = OCEnv.run_ansible(params, False) # Assert - self.assertFalse(results['changed']) - for env_var in results['results']: - if env_var == {'name': 'DEFAULT_CERTIFICATE_DIR', 'value': '/etc/pki/tls/private'}: - break - else: - self.fail('Did not find envionrment variables in results.') - self.assertEqual(results['state'], 'list') + self.assertTrue(results['changed']) + self.assertEqual(results['state'], 'absent') # Making sure our mocks were called as we expected mock_cmd.assert_has_calls([ mock.call(['oc', '-n', 'default', 'get', 'dc', 'router', '-o', 'json'], None), ]) -# @mock.patch('oc_serviceaccount_secret.Yedit._write') -# @mock.patch('oc_serviceaccount_secret.OCServiceAccountSecret._run') -# def test_removing_a_secret_to_a_serviceaccount(self, mock_cmd, mock_write): -# ''' Testing adding a secret to a service account ''' -# -# # Arrange -# -# # run_ansible input parameters -# params = { -# 'state': 'absent', -# 'namespace': 'default', -# 'secret': 'newsecret', -# 'service_account': 'builder', -# 'kubeconfig': '/etc/origin/master/admin.kubeconfig', -# 'debug': False, -# } -# -# oc_get_sa_before = '''{ -# "kind": "ServiceAccount", -# "apiVersion": "v1", -# "metadata": { -# "name": "builder", -# "namespace": "default", -# "selfLink": "/api/v1/namespaces/default/serviceaccounts/builder", -# "uid": "cf47bca7-ebc4-11e6-b041-0ed9df7abc38", -# "resourceVersion": "302879", -# "creationTimestamp": "2017-02-05T17:02:00Z" -# }, -# "secrets": [ -# { -# "name": "builder-dockercfg-rsrua" -# }, -# { -# "name": "builder-token-akqxi" -# }, -# { -# "name": "newsecret" -# } -# -# ], -# "imagePullSecrets": [ -# { -# "name": "builder-dockercfg-rsrua" -# } -# ] -# } -# ''' -# -# builder_yaml_file = '''\ -#secrets: -#- name: builder-dockercfg-rsrua -#- name: builder-token-akqxi -#kind: ServiceAccount -#imagePullSecrets: -#- name: builder-dockercfg-rsrua -#apiVersion: v1 -#metadata: -# name: builder -# namespace: default -# resourceVersion: '302879' -# creationTimestamp: '2017-02-05T17:02:00Z' -# selfLink: /api/v1/namespaces/default/serviceaccounts/builder -# uid: cf47bca7-ebc4-11e6-b041-0ed9df7abc38 -#''' -# -# # Return values of our mocked function call. These get returned once per call. -# mock_cmd.side_effect = [ -# (0, oc_get_sa_before, ''), # First call to the mock -# (0, oc_get_sa_before, ''), # Second call to the mock -# (0, 'serviceaccount "builder" replaced', ''), # Third call to the mock -# ] -# -# # Act -# results = OCServiceAccountSecret.run_ansible(params, False) -# -# # Assert -# self.assertTrue(results['changed']) -# self.assertEqual(results['results']['returncode'], 0) -# self.assertEqual(results['state'], 'absent') -# -# # Making sure our mocks were called as we expected -# mock_cmd.assert_has_calls([ -# mock.call(['oc', '-n', 'default', 'get', 'sa', 'builder', '-o', 'json'], None), -# mock.call(['oc', '-n', 'default', 'get', 'sa', 'builder', '-o', 'json'], None), -# mock.call(['oc', '-n', 'default', 'replace', '-f', '/tmp/builder'], None), -# ]) -# -# mock_write.assert_has_calls([ -# mock.call('/tmp/builder', builder_yaml_file) -# ]) - def tearDown(self): '''TearDown method''' pass -- cgit v1.2.3 From ffac7eac61666332d8d6c6484c5648b48dcaa648 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Wed, 8 Feb 2017 17:03:29 -0500 Subject: Pleasing the linting bot. --- roles/lib_openshift/src/ansible/oc_env.py | 1 + roles/lib_openshift/src/class/oc_env.py | 3 + .../lib_openshift/src/test/integration/oc_env.yml | 2 +- roles/lib_openshift/src/test/unit/oc_env.py | 65 ---------------------- 4 files changed, 5 insertions(+), 66 deletions(-) (limited to 'roles/lib_openshift/src') diff --git a/roles/lib_openshift/src/ansible/oc_env.py b/roles/lib_openshift/src/ansible/oc_env.py index 4a58f7ec1..e49295873 100644 --- a/roles/lib_openshift/src/ansible/oc_env.py +++ b/roles/lib_openshift/src/ansible/oc_env.py @@ -1,4 +1,5 @@ # pylint: skip-file +# flake8: noqa def main(): ''' diff --git a/roles/lib_openshift/src/class/oc_env.py b/roles/lib_openshift/src/class/oc_env.py index 10d44412a..b5e78bf90 100644 --- a/roles/lib_openshift/src/class/oc_env.py +++ b/roles/lib_openshift/src/class/oc_env.py @@ -1,4 +1,6 @@ # pylint: skip-file +# flake8: noqa + # pylint: disable=too-many-instance-attributes class OCEnv(OpenShiftCLI): @@ -73,6 +75,7 @@ class OCEnv(OpenShiftCLI): return self._replace_content(self.kind, self.name, self.resource.yaml_dict) + # pylint: disable=too-many-return-statements @staticmethod def run_ansible(params, check_mode): '''run the idempotent ansible code''' diff --git a/roles/lib_openshift/src/test/integration/oc_env.yml b/roles/lib_openshift/src/test/integration/oc_env.yml index 97a7c8922..cbb97ed46 100755 --- a/roles/lib_openshift/src/test/integration/oc_env.yml +++ b/roles/lib_openshift/src/test/integration/oc_env.yml @@ -6,7 +6,7 @@ user: root vars: my_env_var: - SOMEKEY : SOMEVALUE + SOMEKEY: SOMEVALUE check_env_var: name: DEFAULT_CERTIFICATE_DIR diff --git a/roles/lib_openshift/src/test/unit/oc_env.py b/roles/lib_openshift/src/test/unit/oc_env.py index eefd40b61..15bd7e464 100755 --- a/roles/lib_openshift/src/test/unit/oc_env.py +++ b/roles/lib_openshift/src/test/unit/oc_env.py @@ -343,71 +343,6 @@ class OCEnvTest(unittest.TestCase): 'env_vars': {'SOMEKEY': 'SOMEVALUE'}, } - dc_results_after = '''{ - "apiVersion": "v1", - "kind": "DeploymentConfig", - "metadata": { - "creationTimestamp": "2017-02-02T15:58:49Z", - "generation": 8, - "labels": { - "router": "router" - }, - "name": "router", - "namespace": "default", - "resourceVersion": "513678" - }, - "spec": { - "replicas": 2, - "selector": { - "router": "router" - }, - "template": { - "metadata": { - "creationTimestamp": null, - "labels": { - "router": "router" - } - }, - "spec": { - "containers": [ - { - "env": [ - { - "name": "DEFAULT_CERTIFICATE_DIR", - "value": "/etc/pki/tls/private" - }, - { - "name": "DEFAULT_CERTIFICATE_PATH", - "value": "/etc/pki/tls/private/tls.crt" - }, - { - "name": "ROUTER_EXTERNAL_HOST_HOSTNAME" - }, - { - "name": "ROUTER_EXTERNAL_HOST_HTTPS_VSERVER" - }, - { - "name": "ROUTER_EXTERNAL_HOST_HTTP_VSERVER" - }, - { - "name": "ROUTER_EXTERNAL_HOST_INSECURE", - "value": "false" - } - ], - "name": "router" - } - ] - } - }, - "test": false, - "triggers": [ - { - "type": "ConfigChange" - } - ] - } - }''' - dc_results_before = '''{ "apiVersion": "v1", "kind": "DeploymentConfig", -- cgit v1.2.3 From 45c57201d4601d24e6131bf80800cb7f49d21af7 Mon Sep 17 00:00:00 2001 From: Kenny Woodson Date: Fri, 10 Feb 2017 09:45:24 -0500 Subject: Fixing docs, linting, and comments. --- roles/lib_openshift/src/class/oc_env.py | 12 +++++------- roles/lib_openshift/src/doc/env | 7 +++++++ 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'roles/lib_openshift/src') diff --git a/roles/lib_openshift/src/class/oc_env.py b/roles/lib_openshift/src/class/oc_env.py index b5e78bf90..d34c8234e 100644 --- a/roles/lib_openshift/src/class/oc_env.py +++ b/roles/lib_openshift/src/class/oc_env.py @@ -42,16 +42,16 @@ class OCEnv(OpenShiftCLI): ''' setter function for resource var''' self._resource = data - def value_exists(self, key, value): + def key_value_exists(self, key, value): ''' return whether a key, value pair exists ''' return self.resource.exists_env_value(key, value) def key_exists(self, key): - ''' return whether a key, value pair exists ''' + ''' return whether a key exists ''' return self.resource.exists_env_key(key) def get(self): - '''return a environment variables ''' + '''return environment variables ''' result = self._get(self.kind, self.name) if result['returncode'] == 0: if self.kind == 'dc': @@ -60,14 +60,12 @@ class OCEnv(OpenShiftCLI): return result def delete(self): - '''return all pods ''' - #yed.put(OCEnv.container_path[self.kind], env_vars_array) + ''' delete environment variables ''' if self.resource.delete_env_var(self.env_vars.keys()): return self._replace_content(self.kind, self.name, self.resource.yaml_dict) return {'returncode': 0, 'changed': False} - # pylint: disable=too-many-function-args def put(self): '''place env vars into dc ''' for update_key, update_value in self.env_vars.items(): @@ -119,7 +117,7 @@ class OCEnv(OpenShiftCLI): # Create ######## for key, value in params.get('env_vars', {}).items(): - if not ocenv.value_exists(key, value): + if not ocenv.key_value_exists(key, value): if check_mode: return {'changed': False, diff --git a/roles/lib_openshift/src/doc/env b/roles/lib_openshift/src/doc/env index 0544014e6..36edcd211 100644 --- a/roles/lib_openshift/src/doc/env +++ b/roles/lib_openshift/src/doc/env @@ -52,6 +52,13 @@ options: - dc - pods aliases: [] + env_vars: + description: + - The environment variables to insert. The format is a dict of value pairs. + - e.g. {key1: value1, key2: value2}) + required: False + default: None + aliases: [] author: - "Kenny Woodson " extends_documentation_fragment: [] -- cgit v1.2.3