diff options
| author | Kenny Woodson <kwoodson@redhat.com> | 2017-01-26 14:16:23 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-01-26 14:16:23 -0500 | 
| commit | 8f2b3f132bc6cd03640c31c0c33cffb01f80138c (patch) | |
| tree | 6ec0b8b4caed6279c45d14f2979390468b7772bc /roles/lib_openshift/src | |
| parent | a44270f3dfd2c4707138891cfc485e0a82e7dd7c (diff) | |
| parent | b05c1e3bb7f1cd66a326bb7784ec166c4db4395a (diff) | |
| download | openshift-8f2b3f132bc6cd03640c31c0c33cffb01f80138c.tar.gz openshift-8f2b3f132bc6cd03640c31c0c33cffb01f80138c.tar.bz2 openshift-8f2b3f132bc6cd03640c31c0c33cffb01f80138c.tar.xz openshift-8f2b3f132bc6cd03640c31c0c33cffb01f80138c.zip | |
Merge pull request #3183 from kwoodson/oc_scale
Adding oc_scale to lib_openshift.
Diffstat (limited to 'roles/lib_openshift/src')
| -rw-r--r-- | roles/lib_openshift/src/ansible/oc_scale.py | 29 | ||||
| -rw-r--r-- | roles/lib_openshift/src/class/oc_scale.py | 109 | ||||
| -rw-r--r-- | roles/lib_openshift/src/doc/scale | 70 | ||||
| -rw-r--r-- | roles/lib_openshift/src/lib/base.py | 5 | ||||
| -rw-r--r-- | roles/lib_openshift/src/lib/deploymentconfig.py | 339 | ||||
| -rw-r--r-- | roles/lib_openshift/src/lib/replicationcontroller.py | 16 | ||||
| -rw-r--r-- | roles/lib_openshift/src/sources.yml | 29 | ||||
| -rwxr-xr-x | roles/lib_openshift/src/test/integration/oc_scale.yml | 92 | ||||
| -rwxr-xr-x | roles/lib_openshift/src/test/unit/oc_scale.py | 128 | ||||
| -rwxr-xr-x | roles/lib_openshift/src/test/unit/oc_version.py | 50 | 
10 files changed, 829 insertions, 38 deletions
| diff --git a/roles/lib_openshift/src/ansible/oc_scale.py b/roles/lib_openshift/src/ansible/oc_scale.py new file mode 100644 index 000000000..57f9902d6 --- /dev/null +++ b/roles/lib_openshift/src/ansible/oc_scale.py @@ -0,0 +1,29 @@ +# pylint: skip-file +# flake8: noqa + +def main(): +    ''' +    ansible oc module for scaling +    ''' + +    module = AnsibleModule( +        argument_spec=dict( +            kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'), +            state=dict(default='present', type='str', choices=['present', 'list']), +            debug=dict(default=False, type='bool'), +            kind=dict(default='dc', choices=['dc', 'rc'], type='str'), +            namespace=dict(default='default', type='str'), +            replicas=dict(default=None, type='int'), +            name=dict(default=None, type='str'), +        ), +        supports_check_mode=True, +    ) +    rval = OCScale.run_ansible(module.params, module.check_mode) +    if 'failed' in rval: +        module.fail_json(**rval) + +    module.exit_json(**rval) + + +if __name__ == '__main__': +    main() diff --git a/roles/lib_openshift/src/class/oc_scale.py b/roles/lib_openshift/src/class/oc_scale.py new file mode 100644 index 000000000..19fba3af5 --- /dev/null +++ b/roles/lib_openshift/src/class/oc_scale.py @@ -0,0 +1,109 @@ +# pylint: skip-file +# flake8: noqa + +# pylint: disable=too-many-instance-attributes +class OCScale(OpenShiftCLI): +    ''' Class to wrap the oc command line tools ''' + +    # pylint allows 5 +    # pylint: disable=too-many-arguments +    def __init__(self, +                 resource_name, +                 namespace, +                 replicas, +                 kind, +                 kubeconfig='/etc/origin/master/admin.kubeconfig', +                 verbose=False): +        ''' Constructor for OCScale ''' +        super(OCScale, self).__init__(namespace, kubeconfig) +        self.kind = kind +        self.replicas = replicas +        self.name = resource_name +        self.namespace = namespace +        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 get(self): +        '''return replicas information ''' +        vol = self._get(self.kind, self.name) +        if vol['returncode'] == 0: +            if self.kind == 'dc': +                # The resource returned from a query could be an rc or dc. +                # pylint: disable=redefined-variable-type +                self.resource = DeploymentConfig(content=vol['results'][0]) +                vol['results'] = [self.resource.get_replicas()] +            if self.kind == 'rc': +                # The resource returned from a query could be an rc or dc. +                # pylint: disable=redefined-variable-type +                self.resource = ReplicationController(content=vol['results'][0]) +                vol['results'] = [self.resource.get_replicas()] + +        return vol + +    def put(self): +        '''update replicas into dc ''' +        self.resource.update_replicas(self.replicas) +        return self._replace_content(self.kind, self.name, self.resource.yaml_dict) + +    def needs_update(self): +        ''' verify whether an update is needed ''' +        return self.resource.needs_update_replicas(self.replicas) + +    # pylint: disable=too-many-return-statements +    @staticmethod +    def run_ansible(params, check_mode): +        '''perform the idempotent ansible logic''' + +        oc_scale = OCScale(params['name'], +                           params['namespace'], +                           params['replicas'], +                           params['kind'], +                           params['kubeconfig'], +                           verbose=params['debug']) + +        state = params['state'] + +        api_rval = oc_scale.get() + +        ##### +        # Get +        ##### +        if state == 'list': +            return {'changed': False, 'result': api_rval['results'], 'state': 'list'}  # noqa: E501 + +        elif state == 'present': +            ######## +            # Update +            ######## +            if oc_scale.needs_update(): +                if check_mode: +                    return {'changed': True, 'result': 'CHECK_MODE: Would have updated.'}  # noqa: E501 +                api_rval = oc_scale.put() + +                if api_rval['returncode'] != 0: +                    return {'failed': True, 'msg': api_rval} + +                # return the created object +                api_rval = oc_scale.get() + +                if api_rval['returncode'] != 0: +                    return {'failed': True, 'msg': api_rval} + +                return {'changed': True, 'result': api_rval['results'], 'state': 'present'}  # noqa: E501 + +            return {'changed': False, 'result': api_rval['results'], 'state': 'present'}  # noqa: E501 + +        return {'failed': True, 'msg': 'Unknown state passed. [{}]'.format(state)} diff --git a/roles/lib_openshift/src/doc/scale b/roles/lib_openshift/src/doc/scale new file mode 100644 index 000000000..e98730911 --- /dev/null +++ b/roles/lib_openshift/src/doc/scale @@ -0,0 +1,70 @@ +# flake8: noqa +# pylint: skip-file + +DOCUMENTATION = ''' +--- +module: oc_scale +short_description: Manage openshift services through the scale parameters +description: +  - Manage openshift services through scaling them. +options: +  state: +    description: +    - State represents whether to scale or list the current replicas +    required: true +    default: present +    choices: ["present", "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: default +    aliases: [] +  kind: +    description: +    - The kind of object to scale. +    required: false +    default: None +    choices: +    - rc +    - dc +    aliases: [] +author: +- "Kenny Woodson <kwoodson@redhat.com>" +extends_documentation_fragment: [] +''' + +EXAMPLES = ''' +- name: scale down a rc to 0 +  oc_scale: +    name: my-replication-controller +    kind: rc +    namespace: openshift-infra +    replicas: 0 + +- name: scale up a deploymentconfig to 2 +  oc_scale: +    name: php +    kind: dc +    namespace: my-php-app +    replicas: 2 +''' diff --git a/roles/lib_openshift/src/lib/base.py b/roles/lib_openshift/src/lib/base.py index db5f4e890..8b5491d6b 100644 --- a/roles/lib_openshift/src/lib/base.py +++ b/roles/lib_openshift/src/lib/base.py @@ -111,12 +111,11 @@ class OpenShiftCLI(object):          cmd = ['get', resource]          if selector:              cmd.append('--selector=%s' % selector) +        elif rname: +            cmd.append(rname)          cmd.extend(['-o', 'json']) -        if rname: -            cmd.append(rname) -          rval = self.openshift_cmd(cmd, output=True)          # Ensure results are retuned in an array diff --git a/roles/lib_openshift/src/lib/deploymentconfig.py b/roles/lib_openshift/src/lib/deploymentconfig.py new file mode 100644 index 000000000..e060d3707 --- /dev/null +++ b/roles/lib_openshift/src/lib/deploymentconfig.py @@ -0,0 +1,339 @@ +# pylint: skip-file +# flake8: noqa + + +# pylint: disable=too-many-public-methods +class DeploymentConfig(Yedit): +    ''' Class to wrap the oc command line tools ''' +    default_deployment_config = ''' +apiVersion: v1 +kind: DeploymentConfig +metadata: +  name: default_dc +  namespace: default +spec: +  replicas: 0 +  selector: +    default_dc: default_dc +  strategy: +    resources: {} +    rollingParams: +      intervalSeconds: 1 +      maxSurge: 0 +      maxUnavailable: 25% +      timeoutSeconds: 600 +      updatePercent: -25 +      updatePeriodSeconds: 1 +    type: Rolling +  template: +    metadata: +    spec: +      containers: +      - env: +        - name: default +          value: default +        image: default +        imagePullPolicy: IfNotPresent +        name: default_dc +        ports: +        - containerPort: 8000 +          hostPort: 8000 +          protocol: TCP +          name: default_port +        resources: {} +        terminationMessagePath: /dev/termination-log +      dnsPolicy: ClusterFirst +      hostNetwork: true +      nodeSelector: +        type: compute +      restartPolicy: Always +      securityContext: {} +      serviceAccount: default +      serviceAccountName: default +      terminationGracePeriodSeconds: 30 +  triggers: +  - type: ConfigChange +''' + +    replicas_path = "spec.replicas" +    env_path = "spec.template.spec.containers[0].env" +    volumes_path = "spec.template.spec.volumes" +    container_path = "spec.template.spec.containers" +    volume_mounts_path = "spec.template.spec.containers[0].volumeMounts" + +    def __init__(self, content=None): +        ''' Constructor for deploymentconfig ''' +        if not content: +            content = DeploymentConfig.default_deployment_config + +        super(DeploymentConfig, self).__init__(content=content) + +    # pylint: disable=no-member +    def add_env_value(self, key, value): +        ''' add key, value pair to env array ''' +        rval = False +        env = self.get_env_vars() +        if env: +            env.append({'name': key, 'value': value}) +            rval = True +        else: +            result = self.put(DeploymentConfig.env_path, {'name': key, 'value': value}) +            rval = result[0] + +        return rval + +    def exists_env_value(self, key, value): +        ''' return whether a key, value  pair exists ''' +        results = self.get_env_vars() +        if not results: +            return False + +        for result in results: +            if result['name'] == key and result['value'] == value: +                return True + +        return False + +    def exists_env_key(self, key): +        ''' return whether a key, value  pair exists ''' +        results = self.get_env_vars() +        if not results: +            return False + +        for result in results: +            if result['name'] == key: +                return True + +        return False + +    def get_env_vars(self): +        '''return a environment variables ''' +        return self.get(DeploymentConfig.env_path) or [] + +    def delete_env_var(self, keys): +        '''delete a list of keys ''' +        if not isinstance(keys, list): +            keys = [keys] + +        env_vars_array = self.get_env_vars() +        modified = False +        idx = None +        for key in keys: +            for env_idx, env_var in enumerate(env_vars_array): +                if env_var['name'] == key: +                    idx = env_idx +                    break + +            if idx: +                modified = True +                del env_vars_array[idx] + +        if modified: +            return True + +        return False + +    def update_env_var(self, key, value): +        '''place an env in the env var list''' + +        env_vars_array = self.get_env_vars() +        idx = None +        for env_idx, env_var in enumerate(env_vars_array): +            if env_var['name'] == key: +                idx = env_idx +                break + +        if idx: +            env_vars_array[idx]['value'] = value +        else: +            self.add_env_value(key, value) + +        return True + +    def exists_volume_mount(self, volume_mount): +        ''' return whether a volume mount exists ''' +        exist_volume_mounts = self.get_volume_mounts() + +        if not exist_volume_mounts: +            return False + +        volume_mount_found = False +        for exist_volume_mount in exist_volume_mounts: +            if exist_volume_mount['name'] == volume_mount['name']: +                volume_mount_found = True +                break + +        return volume_mount_found + +    def exists_volume(self, volume): +        ''' return whether a volume exists ''' +        exist_volumes = self.get_volumes() + +        volume_found = False +        for exist_volume in exist_volumes: +            if exist_volume['name'] == volume['name']: +                volume_found = True +                break + +        return volume_found + +    def find_volume_by_name(self, volume, mounts=False): +        ''' return the index of a volume ''' +        volumes = [] +        if mounts: +            volumes = self.get_volume_mounts() +        else: +            volumes = self.get_volumes() +        for exist_volume in volumes: +            if exist_volume['name'] == volume['name']: +                return exist_volume + +        return None + +    def get_replicas(self): +        ''' return replicas setting ''' +        return self.get(DeploymentConfig.replicas_path) + +    def get_volume_mounts(self): +        '''return volume mount information ''' +        return self.get_volumes(mounts=True) + +    def get_volumes(self, mounts=False): +        '''return volume mount information ''' +        if mounts: +            return self.get(DeploymentConfig.volume_mounts_path) or [] + +        return self.get(DeploymentConfig.volumes_path) or [] + +    def delete_volume_by_name(self, volume): +        '''delete a volume ''' +        modified = False +        exist_volume_mounts = self.get_volume_mounts() +        exist_volumes = self.get_volumes() +        del_idx = None +        for idx, exist_volume in enumerate(exist_volumes): +            if 'name' in exist_volume and exist_volume['name'] == volume['name']: +                del_idx = idx +                break + +        if del_idx != None: +            del exist_volumes[del_idx] +            modified = True + +        del_idx = None +        for idx, exist_volume_mount in enumerate(exist_volume_mounts): +            if 'name' in exist_volume_mount and exist_volume_mount['name'] == volume['name']: +                del_idx = idx +                break + +        if del_idx != None: +            del exist_volume_mounts[idx] +            modified = True + +        return modified + +    def add_volume_mount(self, volume_mount): +        ''' add a volume or volume mount to the proper location ''' +        exist_volume_mounts = self.get_volume_mounts() + +        if not exist_volume_mounts and volume_mount: +            self.put(DeploymentConfig.volume_mounts_path, [volume_mount]) +        else: +            exist_volume_mounts.append(volume_mount) + +    def add_volume(self, volume): +        ''' add a volume or volume mount to the proper location ''' +        exist_volumes = self.get_volumes() +        if not volume: +            return + +        if not exist_volumes: +            self.put(DeploymentConfig.volumes_path, [volume]) +        else: +            exist_volumes.append(volume) + +    def update_replicas(self, replicas): +        ''' update replicas value ''' +        self.put(DeploymentConfig.replicas_path, replicas) + +    def update_volume(self, volume): +        '''place an env in the env var list''' +        exist_volumes = self.get_volumes() + +        if not volume: +            return False + +        # update the volume +        update_idx = None +        for idx, exist_vol in enumerate(exist_volumes): +            if exist_vol['name'] == volume['name']: +                update_idx = idx +                break + +        if update_idx != None: +            exist_volumes[update_idx] = volume +        else: +            self.add_volume(volume) + +        return True + +    def update_volume_mount(self, volume_mount): +        '''place an env in the env var list''' +        modified = False + +        exist_volume_mounts = self.get_volume_mounts() + +        if not volume_mount: +            return False + +        # update the volume mount +        for exist_vol_mount in exist_volume_mounts: +            if exist_vol_mount['name'] == volume_mount['name']: +                if 'mountPath' in exist_vol_mount and \ +                   str(exist_vol_mount['mountPath']) != str(volume_mount['mountPath']): +                    exist_vol_mount['mountPath'] = volume_mount['mountPath'] +                    modified = True +                break + +        if not modified: +            self.add_volume_mount(volume_mount) +            modified = True + +        return modified + +    def needs_update_volume(self, volume, volume_mount): +        ''' verify a volume update is needed ''' +        exist_volume = self.find_volume_by_name(volume) +        exist_volume_mount = self.find_volume_by_name(volume, mounts=True) +        results = [] +        results.append(exist_volume['name'] == volume['name']) + +        if 'secret' in volume: +            results.append('secret' in exist_volume) +            results.append(exist_volume['secret']['secretName'] == volume['secret']['secretName']) +            results.append(exist_volume_mount['name'] == volume_mount['name']) +            results.append(exist_volume_mount['mountPath'] == volume_mount['mountPath']) + +        elif 'emptyDir' in volume: +            results.append(exist_volume_mount['name'] == volume['name']) +            results.append(exist_volume_mount['mountPath'] == volume_mount['mountPath']) + +        elif 'persistentVolumeClaim' in volume: +            pvc = 'persistentVolumeClaim' +            results.append(pvc in exist_volume) +            if results[-1]: +                results.append(exist_volume[pvc]['claimName'] == volume[pvc]['claimName']) + +                if 'claimSize' in volume[pvc]: +                    results.append(exist_volume[pvc]['claimSize'] == volume[pvc]['claimSize']) + +        elif 'hostpath' in volume: +            results.append('hostPath' in exist_volume) +            results.append(exist_volume['hostPath']['path'] == volume_mount['mountPath']) + +        return not all(results) + +    def needs_update_replicas(self, replicas): +        ''' verify whether a replica update is needed ''' +        current_reps = self.get(DeploymentConfig.replicas_path) +        return not current_reps == replicas diff --git a/roles/lib_openshift/src/lib/replicationcontroller.py b/roles/lib_openshift/src/lib/replicationcontroller.py new file mode 100644 index 000000000..ae585a986 --- /dev/null +++ b/roles/lib_openshift/src/lib/replicationcontroller.py @@ -0,0 +1,16 @@ +# pylint: skip-file +# flake8: noqa + + +# pylint: disable=too-many-public-methods +class ReplicationController(DeploymentConfig): +    ''' Class to wrap the oc command line tools ''' +    replicas_path = "spec.replicas" +    env_path = "spec.template.spec.containers[0].env" +    volumes_path = "spec.template.spec.volumes" +    container_path = "spec.template.spec.containers" +    volume_mounts_path = "spec.template.spec.containers[0].volumeMounts" + +    def __init__(self, content): +        ''' Constructor for ReplicationController ''' +        super(ReplicationController, self).__init__(content=content) diff --git a/roles/lib_openshift/src/sources.yml b/roles/lib_openshift/src/sources.yml index 3c20b614d..5afcdc55d 100644 --- a/roles/lib_openshift/src/sources.yml +++ b/roles/lib_openshift/src/sources.yml @@ -27,15 +27,6 @@ oc_route.py:  - lib/route.py  - class/oc_route.py  - ansible/oc_route.py -oc_version.py: -- doc/generated -- doc/license -- lib/import.py -- doc/version -- ../../lib_utils/src/class/yedit.py -- lib/base.py -- class/oc_version.py -- ansible/oc_version.py  oc_secret.py:  - doc/generated  - doc/license @@ -46,3 +37,23 @@ oc_secret.py:  - lib/secret.py  - class/oc_secret.py  - ansible/oc_secret.py +oc_scale.py: +- doc/generated +- doc/license +- lib/import.py +- doc/scale +- ../../lib_utils/src/class/yedit.py +- lib/base.py +- lib/deploymentconfig.py +- lib/replicationcontroller.py +- class/oc_scale.py +- ansible/oc_scale.py +oc_version.py: +- doc/generated +- doc/license +- lib/import.py +- doc/version +- ../../lib_utils/src/class/yedit.py +- lib/base.py +- class/oc_version.py +- ansible/oc_version.py diff --git a/roles/lib_openshift/src/test/integration/oc_scale.yml b/roles/lib_openshift/src/test/integration/oc_scale.yml new file mode 100755 index 000000000..e96e16820 --- /dev/null +++ b/roles/lib_openshift/src/test/integration/oc_scale.yml @@ -0,0 +1,92 @@ +#!/usr/bin/ansible-playbook --module-path=../../../library/ +# ./oc_scale.yml -e "cli_master_test=$OPENSHIFT_MASTER +--- +- hosts: "{{ cli_master_test }}" +  gather_facts: no +  user: root +  tasks: +  - name: list oc scale for default router dc +    oc_scale: +      state: list +      name: router +      namespace: default +      kind: dc +    register: scaleout +  - debug: var=scaleout + +  - assert: +      that: +      - "'result' in scaleout" +      - scaleout.result > 0 +      msg: "Did not find 'result' in returned value or result not > 0." + +  - name: get the rc for router +    oc_obj: +      state: list +      kind: dc +      namespace: default +      selector: router=router +    register: rcout +  - debug: +      msg: "{{ rcout.results.results[0]['items'][-1]['metadata']['name'] }}" + +  - name: scale dc to 1 +    oc_scale: +      name: router +      namespace: default +      kind: dc +      replicas: 1 +    register: scaleout +  - debug: var=scaleout + +  # The preferred method here would be to let the module +  # detect when its finished and time out +  - name: let the scale happen +    pause: +      seconds: 10 +    when: scaleout.changed + +  - name: fetch the current router pods +    oc_obj: +      selector: router=router +      namespace: default +      kind: pod +      state: list +    register: pods +  - debug: var=pods + +  - assert: +      that: +      - "'results' in pods and 'results' in pods.results" +      - "{{ pods.results.results[0]['items']|length }} == 1" +      msg: "Did not find 1 replica in scale results." + +  - name: scale dc to 2 +    oc_scale: +      name: router +      namespace: default +      kind: dc +      replicas: 2 +    register: scaleout +  - debug: var=scaleout + +  # The preferred method here would be to let the module +  # detect when its finished and time out +  - name: let the scale happen +    pause: +      seconds: 30 + +  - name: fetch the current router pods +    oc_obj: +      selector: router=router +      namespace: default +      kind: pod +      state: list +    register: pods +  - debug: var=pods + +  - assert: +      that: +      - "'results' in pods and 'results' in pods.results" +      - "{{ pods.results.results[0]['items']|length }} == 2" +      msg: "Did not find 1 replica in scale results." diff --git a/roles/lib_openshift/src/test/unit/oc_scale.py b/roles/lib_openshift/src/test/unit/oc_scale.py new file mode 100755 index 000000000..c523592de --- /dev/null +++ b/roles/lib_openshift/src/test/unit/oc_scale.py @@ -0,0 +1,128 @@ +#!/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 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_scale import OCScale  # noqa: E402 + + +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.OCScale.openshift_cmd') +    def test_state_list(self, mock_openshift_cmd): +        ''' Testing a get ''' +        params = {'name': 'router', +                  'namespace': 'default', +                  'replicas': 2, +                  'state': 'list', +                  'kind': 'dc', +                  'kubeconfig': '/etc/origin/master/admin.kubeconfig', +                  'debug': False} + +        dc = '''{"kind": "DeploymentConfig", +               "apiVersion": "v1", +               "metadata": { +                   "name": "router", +                   "namespace": "default", +                   "selfLink": "/oapi/v1/namespaces/default/deploymentconfigs/router", +                   "uid": "a441eedc-e1ae-11e6-a2d5-0e6967f34d42", +                   "resourceVersion": "6558", +                   "generation": 8, +                   "creationTimestamp": "2017-01-23T20:58:07Z", +                   "labels": { +                       "router": "router" +                   } +               }, +               "spec": { +                   "replicas": 2, +               } +           }''' + +        mock_openshift_cmd.side_effect = [ +            {"cmd": '/usr/bin/oc get dc router -n default', +             'results': dc, +             'returncode': 0}] + +        results = OCScale.run_ansible(params, False) + +        self.assertFalse(results['changed']) +        self.assertEqual(results['result'][0], 2) + +    @mock.patch('oc_scale.OCScale.openshift_cmd') +    def test_scale(self, mock_openshift_cmd): +        ''' Testing a get ''' +        params = {'name': 'router', +                  'namespace': 'default', +                  'replicas': 3, +                  'state': 'list', +                  'kind': 'dc', +                  'kubeconfig': '/etc/origin/master/admin.kubeconfig', +                  'debug': False} + +        dc = '''{"kind": "DeploymentConfig", +               "apiVersion": "v1", +               "metadata": { +                   "name": "router", +                   "namespace": "default", +                   "selfLink": "/oapi/v1/namespaces/default/deploymentconfigs/router", +                   "uid": "a441eedc-e1ae-11e6-a2d5-0e6967f34d42", +                   "resourceVersion": "6558", +                   "generation": 8, +                   "creationTimestamp": "2017-01-23T20:58:07Z", +                   "labels": { +                       "router": "router" +                   } +               }, +               "spec": { +                   "replicas": 3, +               } +           }''' + +        mock_openshift_cmd.side_effect = [ +            {"cmd": '/usr/bin/oc get dc router -n default', +             'results': dc, +             'returncode': 0}, +            {"cmd": '/usr/bin/oc create -f /tmp/router -n default', +             'results': '', +             'returncode': 0} +        ] + +        results = OCScale.run_ansible(params, False) + +        self.assertFalse(results['changed']) +        self.assertEqual(results['result'][0], 3) + +    def tearDown(self): +        '''TearDown method''' +        pass + + +if __name__ == "__main__": +    unittest.main() diff --git a/roles/lib_openshift/src/test/unit/oc_version.py b/roles/lib_openshift/src/test/unit/oc_version.py index 8d9128187..f927948be 100755 --- a/roles/lib_openshift/src/test/unit/oc_version.py +++ b/roles/lib_openshift/src/test/unit/oc_version.py @@ -13,6 +13,7 @@  import os  import sys  import unittest +import mock  # Removing invalid variable names for tests so that I can  # keep them brief @@ -25,25 +26,6 @@ sys.path.insert(0, module_path)  from oc_version import OCVersion  # noqa: E402 -# pylint: disable=unused-argument -def oc_cmd_mock(cmd, oadm=False, output=False, output_type='json', input_data=None): -    '''mock command for openshift_cmd''' -    version = '''oc v3.4.0.39 -kubernetes v1.4.0+776c994 -features: Basic-Auth GSSAPI Kerberos SPNEGO - -Server https://internal.api.opstest.openshift.com -openshift v3.4.0.39 -kubernetes v1.4.0+776c994 -''' -    if 'version' in cmd: -        return {'stderr': None, -                'stdout': version, -                'returncode': 0, -                'results': version, -                'cmd': cmd} - -  class OCVersionTest(unittest.TestCase):      '''       Test class for OCVersion @@ -51,15 +33,31 @@ class OCVersionTest(unittest.TestCase):      def setUp(self):          ''' setup method will create a file and set to known configuration ''' -        self.oc_ver = OCVersion(None, False) -        self.oc_ver.openshift_cmd = oc_cmd_mock +        pass -    def test_get(self): +    @mock.patch('oc_version.OCVersion.openshift_cmd') +    def test_get(self, mock_openshift_cmd):          ''' Testing a get ''' -        results = self.oc_ver.get() -        self.assertEqual(results['oc_short'], '3.4') -        self.assertEqual(results['oc_numeric'], '3.4.0.39') -        self.assertEqual(results['kubernetes_numeric'], '1.4.0') +        params = {'kubeconfig': '/etc/origin/master/admin.kubeconfig', +                  'state': 'list', +                  'debug': False} + +        mock_openshift_cmd.side_effect = [ +            {"cmd": "oc version", +             "results": "oc v3.4.0.39\nkubernetes v1.4.0+776c994\n" + +                        "features: Basic-Auth GSSAPI Kerberos SPNEGO\n\n" + +                        "Server https://internal.api.opstest.openshift.com" + +                        "openshift v3.4.0.39\n" + +                        "kubernetes v1.4.0+776c994\n", +             "returncode": 0} +        ] + +        results = OCVersion.run_ansible(params) + +        self.assertFalse(results['changed']) +        self.assertEqual(results['results']['oc_short'], '3.4') +        self.assertEqual(results['results']['oc_numeric'], '3.4.0.39') +        self.assertEqual(results['results']['kubernetes_numeric'], '1.4.0')      def tearDown(self):          '''TearDown method''' | 
