Browse Source

Merge pull request #3249 from kwoodson/oc_label

Adding oc_label to lib_openshift.
Kenny Woodson 8 years ago
parent
commit
a965c28ab7

File diff suppressed because it is too large
+ 1569 - 0
roles/lib_openshift/library/oc_label.py


+ 32 - 0
roles/lib_openshift/src/ansible/oc_label.py

@@ -0,0 +1,32 @@
+# pylint: skip-file
+# flake8: noqa
+
+def main():
+    ''' ansible oc module for labels '''
+
+    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', 'add']),
+            debug=dict(default=False, type='bool'),
+            kind=dict(default='node', type='str', required=True,
+                      choices=['node', 'pod', 'namespace']),
+            name=dict(default=None, type='str'),
+            namespace=dict(default=None, type='str'),
+            labels=dict(default=None, type='list'),
+            selector=dict(default=None, type='str'),
+        ),
+        supports_check_mode=True,
+        mutually_exclusive=(['name', 'selector']),
+    )
+
+    results = OCLabel.run_ansible(module.params, module.check_mode)
+
+    if 'failed' in results:
+        module.fail_json(**results)
+
+    module.exit_json(**results)
+
+if __name__ == '__main__':
+    main()

+ 294 - 0
roles/lib_openshift/src/class/oc_label.py

@@ -0,0 +1,294 @@
+# pylint: skip-file
+# flake8: noqa
+
+
+# pylint: disable=too-many-instance-attributes
+class OCLabel(OpenShiftCLI):
+    ''' Class to wrap the oc command line tools '''
+
+    # pylint allows 5
+    # pylint: disable=too-many-arguments
+    def __init__(self,
+                 name,
+                 namespace,
+                 kind,
+                 kubeconfig,
+                 labels=None,
+                 selector=None,
+                 verbose=False):
+        ''' Constructor for OCLabel '''
+        super(OCLabel, self).__init__(namespace, kubeconfig)
+        self.name = name
+        self.namespace = namespace
+        self.kind = kind
+        self.kubeconfig = kubeconfig
+        self.labels = labels
+        self._curr_labels = None
+        self.selector = selector
+
+    @property
+    def current_labels(self):
+        '''property for the current labels'''
+        if self._curr_labels is None:
+            results = self.get()
+            self._curr_labels = results['labels']
+
+        return self._curr_labels
+
+    @current_labels.setter
+    def current_labels(self, data):
+        '''property setter for current labels'''
+        self._curr_labels = data
+
+    def compare_labels(self, host_labels):
+        ''' compare incoming labels against current labels'''
+
+        for label in self.labels:
+            if label['key'] not in host_labels or \
+               label['value'] != host_labels[label['key']]:
+                return False
+        return True
+
+    def all_user_labels_exist(self):
+        ''' return whether all the labels already exist '''
+
+        for current_host_labels in self.current_labels:
+            rbool = self.compare_labels(current_host_labels)
+            if not rbool:
+                return False
+        return True
+
+    def any_label_exists(self):
+        ''' return whether any single label already exists '''
+
+        for current_host_labels in self.current_labels:
+            for label in self.labels:
+                if label['key'] in current_host_labels:
+                    return True
+        return False
+
+    def get_user_keys(self):
+        ''' go through list of user key:values and return all keys '''
+
+        user_keys = []
+        for label in self.labels:
+            user_keys.append(label['key'])
+
+        return user_keys
+
+    def get_current_label_keys(self):
+        ''' collect all the current label keys '''
+
+        current_label_keys = []
+        for current_host_labels in self.current_labels:
+            for key in current_host_labels.keys():
+                current_label_keys.append(key)
+
+        return list(set(current_label_keys))
+
+    def get_extra_current_labels(self):
+        ''' return list of labels that are currently stored, but aren't
+            in user-provided list '''
+
+        extra_labels = []
+        user_label_keys = self.get_user_keys()
+        current_label_keys = self.get_current_label_keys()
+
+        for current_key in current_label_keys:
+            if current_key not in user_label_keys:
+                extra_labels.append(current_key)
+
+        return extra_labels
+
+    def extra_current_labels(self):
+        ''' return whether there are labels currently stored that user
+            hasn't directly provided '''
+        extra_labels = self.get_extra_current_labels()
+
+        if len(extra_labels) > 0:
+            return True
+
+        return False
+
+    def replace(self):
+        ''' replace currently stored labels with user provided labels '''
+        cmd = self.cmd_template()
+
+        # First delete any extra labels
+        extra_labels = self.get_extra_current_labels()
+        if len(extra_labels) > 0:
+            for label in extra_labels:
+                cmd.append("{}-".format(label))
+
+        # Now add/modify the user-provided label list
+        if len(self.labels) > 0:
+            for label in self.labels:
+                cmd.append("{}={}".format(label['key'], label['value']))
+
+        # --overwrite for the case where we are updating existing labels
+        cmd.append("--overwrite")
+        return self.openshift_cmd(cmd)
+
+    def get(self):
+        '''return label information '''
+
+        result_dict = {}
+        label_list = []
+
+        if self.name:
+            result = self._get(resource=self.kind, rname=self.name, selector=self.selector)
+
+            if 'labels' in result['results'][0]['metadata']:
+                label_list.append(result['results'][0]['metadata']['labels'])
+            else:
+                label_list.append({})
+
+        else:
+            result = self._get(resource=self.kind, selector=self.selector)
+
+            for item in result['results'][0]['items']:
+                if 'labels' in item['metadata']:
+                    label_list.append(item['metadata']['labels'])
+                else:
+                    label_list.append({})
+
+        self.current_labels = label_list
+        result_dict['labels'] = self.current_labels
+        result_dict['item_count'] = len(self.current_labels)
+        result['results'] = result_dict
+
+        return result
+
+    def cmd_template(self):
+        ''' boilerplate oc command for modifying lables on this object '''
+        # let's build the cmd with what we have passed in
+        cmd = ["label", self.kind]
+
+        if self.selector:
+            cmd.extend(["--selector", self.selector])
+        elif self.name:
+            cmd.extend([self.name])
+
+        return cmd
+
+    def add(self):
+        ''' add labels '''
+        cmd = self.cmd_template()
+
+        for label in self.labels:
+            cmd.append("{}={}".format(label['key'], label['value']))
+
+        cmd.append("--overwrite")
+
+        return self.openshift_cmd(cmd)
+
+    def delete(self):
+        '''delete the labels'''
+        cmd = self.cmd_template()
+        for label in self.labels:
+            cmd.append("{}-".format(label['key']))
+
+        return self.openshift_cmd(cmd)
+
+    # pylint: disable=too-many-branches,too-many-return-statements
+    @staticmethod
+    def run_ansible(params, check_mode=False):
+        ''' run the idempotent ansible code
+
+            prams comes from the ansible portion of this module
+            check_mode: does the module support check mode. (module.check_mode)
+        '''
+        oc_label = OCLabel(params['name'],
+                           params['namespace'],
+                           params['kind'],
+                           params['kubeconfig'],
+                           params['labels'],
+                           params['selector'],
+                           verbose=params['debug'])
+
+        state = params['state']
+        name = params['name']
+        selector = params['selector']
+
+        api_rval = oc_label.get()
+
+        #####
+        # Get
+        #####
+        if state == 'list':
+            return {'changed': False, 'results': api_rval['results'], 'state': "list"}
+
+        #######
+        # Add
+        #######
+        if state == 'add':
+            if not (name or selector):
+                return {'failed': True,
+                        'msg': "Param 'name' or 'selector' is required if state == 'add'"}
+            if not oc_label.all_user_labels_exist():
+                if check_mode:
+                    return {'changed': False, 'msg': 'Would have performed an addition.'}
+                api_rval = oc_label.add()
+
+                if api_rval['returncode'] != 0:
+                    return {'failed': True, 'msg': api_rval}
+
+                return {'changed': True, 'results': api_rval, 'state': "add"}
+
+            return {'changed': False, 'state': "add"}
+
+        ########
+        # Delete
+        ########
+        if state == 'absent':
+            if not (name or selector):
+                return {'failed': True,
+                        'msg': "Param 'name' or 'selector' is required if state == 'absent'"}
+
+            if oc_label.any_label_exists():
+                if check_mode:
+                    return {'changed': False, 'msg': 'Would have performed a delete.'}
+
+                api_rval = oc_label.delete()
+
+                if api_rval['returncode'] != 0:
+                    return {'failed': True, 'msg': api_rval}
+
+                return {'changed': True, 'results': api_rval, 'state': "absent"}
+
+            return {'changed': False, 'state': "absent"}
+
+        if state == 'present':
+            ########
+            # Update
+            ########
+            if not (name or selector):
+                return {'failed': True,
+                        'msg': "Param 'name' or 'selector' is required if state == 'present'"}
+            # if all the labels passed in don't already exist
+            # or if there are currently stored labels that haven't
+            # been passed in
+            if not oc_label.all_user_labels_exist() or \
+               oc_label.extra_current_labels():
+                if check_mode:
+                    return {'changed': False, 'msg': 'Would have made changes.'}
+
+                api_rval = oc_label.replace()
+
+                if api_rval['returncode'] != 0:
+                    return {'failed': True, 'msg': api_rval}
+
+                # return the created object
+                api_rval = oc_label.get()
+
+                if api_rval['returncode'] != 0:
+                    return {'failed': True, 'msg': api_rval}
+
+                return {'changed': True, 'results': api_rval, 'state': "present"}
+
+            return {'changed': False, 'results': api_rval, 'state': "present"}
+
+        return {'failed': True,
+                'changed': False,
+                'results': 'Unknown state passed. %s' % state,
+                'state': "unknown"}

+ 92 - 0
roles/lib_openshift/src/doc/label

@@ -0,0 +1,92 @@
+# flake8: noqa
+# pylint: skip-file
+
+DOCUMENTATION = '''
+---
+module: oc_label
+short_description: Create, modify, and idempotently manage openshift labels.
+description:
+  - Modify openshift labels programmatically.
+options:
+  state:
+    description:
+    - State controls the action that will be taken with resource
+    - 'present' will create or update and object to the desired state
+    - 'absent' will ensure certain labels are removed
+    - 'list' will read the labels
+    - 'add' will insert labels to the already existing labels
+    default: present
+    choices: ["present", "absent", "list", "add"]
+    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: []
+  kind:
+    description:
+    - The kind of object that can be managed.
+    default: node
+    choices:
+    - node
+    - pod
+    - namespace
+    aliases: []
+  labels:
+    description:
+    - A list of labels for the resource.
+    - Each list consists of a key and a value.
+    - eg, {'key': 'foo', 'value': 'bar'}
+    required: false
+    default: None
+    aliases: []
+  selector:
+    description:
+    - The selector to apply to the resource query
+    required: false
+    default: None
+    aliases: []
+author:
+- "Joel Diaz <jdiaz@redhat.com>"
+extends_documentation_fragment: []
+'''
+
+EXAMPLES = '''
+- name: Add a single label to a node's existing labels
+  oc_label:
+    name: ip-172-31-5-23.ec2.internal
+    state: add
+    kind: node
+    labels:
+      - key: logging-infra-fluentd
+        value: 'true'
+
+- name: remove a label from a node
+  oc_label:
+    name: ip-172-31-5-23.ec2.internal
+    state: absent
+    kind: node
+    labels:
+      - key: color
+        value: blue
+
+- name: Ensure node has these exact labels
+  oc_label:
+    name: ip-172-31-5-23.ec2.internal
+    state: present
+    kind: node
+    labels:
+      - key: color
+        value: green
+      - key: type
+        value: master
+      - key: environment
+        value: production
+'''

+ 10 - 0
roles/lib_openshift/src/sources.yml

@@ -19,6 +19,16 @@ oc_edit.py:
 - class/oc_edit.py
 - ansible/oc_edit.py
 
+oc_label.py:
+- doc/generated
+- doc/license
+- lib/import.py
+- doc/label
+- ../../lib_utils/src/class/yedit.py
+- lib/base.py
+- class/oc_label.py
+- ansible/oc_label.py
+
 oc_obj.py:
 - doc/generated
 - doc/license

+ 29 - 0
roles/lib_openshift/src/test/integration/filter_plugins/filters.py

@@ -0,0 +1,29 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+# vim: expandtab:tabstop=4:shiftwidth=4
+'''
+Custom filters for use in testing
+'''
+
+
+class FilterModule(object):
+    ''' Custom filters for use in integration testing '''
+
+    @staticmethod
+    def label_dict_to_key_value_list(label_dict):
+        ''' Given a dict of labels/values, return list of key: <key> value: <value> pairs
+
+            These are only used in integration testing.
+        '''
+
+        label_list = []
+        for key in label_dict:
+            label_list.append({'key': key, 'value': label_dict[key]})
+
+        return label_list
+
+    def filters(self):
+        ''' returns a mapping of filters to methods '''
+        return {
+            "label_dict_to_key_value_list": self.label_dict_to_key_value_list,
+        }

+ 323 - 0
roles/lib_openshift/src/test/integration/oc_label.yml

@@ -0,0 +1,323 @@
+#!/usr/bin/ansible-playbook --module-path=../../../library/
+# ./oc_label.yml -e "cli_master_test=$OPENSHIFT_MASTER -e "cli_node_test=ip-172-0-31-1.ec2"
+---
+- hosts: "{{ cli_master_test }}"
+  gather_facts: no
+  user: root
+
+  vars:
+  - def_namespace: default
+  - def_kind: node
+
+  pre_tasks:
+  - name: ensure needed vars are defined
+    fail:
+      msg: "{{ item }} not defined"
+    when: "{{ item }} is not defined"
+    with_items:
+    - cli_node_test  # openshift node to be used to add/remove labels to
+    - cli_master_test  # ansible inventory instance to run playbook against
+
+  tasks:
+  - name: delete test labels (start from known starting position)
+    oc_label:
+      state: absent
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+      - key: testlabel3
+
+  - name: list to check whether our test labels already exist
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: original_labels
+  - name: assert that testlabel2 and testlabel3 test labels don't exist
+    assert:
+      that: original_labels['results']['labels'][0]['testlabel2'] is not defined and
+            original_labels['results']['labels'][0]['testlabel3'] is not defined
+      msg: "{{ original_labels['results']['labels'] }}"
+
+  - name: add label
+    oc_label:
+      state: add
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+        value: "yes"
+    register: label_out
+  - name: assert adding label marked as changed
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: test if add label succeeded
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: label_out
+  - name: assert that testlabel2 label actually added
+    assert:
+      that: label_out['results']['labels'][0]['testlabel2'] is defined and
+            label_out['results']['labels'][0]['testlabel2'] == "yes"
+      msg: "{{ label_out }}"
+
+  - name: test that re-adding does nothing
+    oc_label:
+      state: add
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+        value: "yes"
+    register: label_out
+  - name: assert that re-adding made no changes
+    assert:
+      that: label_out['changed'] == False
+      msg: "{{ label_out }}"
+
+  - name: test that modifying existing label marked modified
+    oc_label:
+      state: add
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+        value: "different"
+    register: label_out
+  - name: assert that modifying existing label marked modified
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: test if modify label actually did modification
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: label_out
+  - name: assert that testlabel2 label actually modified
+    assert:
+      that: label_out['results']['labels'][0]['testlabel2'] is defined and
+            label_out['results']['labels'][0]['testlabel2'] == "different"
+      msg: "{{ label_out['results']['labels'] }}"
+
+  - name: delete non-existant label
+    oc_label:
+      state: absent
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabelnone
+    register: label_out
+  - name: assert that deleting non-existant label marked not changed
+    assert:
+      that: label_out['changed'] == False
+      msg: "{{ label_out }}"
+
+  - name: delete label
+    oc_label:
+      state: absent
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+    register: label_out
+  - name: assert that deleting existing label marked changed
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: re-delete label
+    oc_label:
+      state: absent
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+    register: label_out
+  - name: assert that re-deleting label marked not changed
+    assert:
+      that: label_out['changed'] == False
+      msg: "{{ label_out }}"
+
+  - name: check whether really deleted
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: label_out
+  - name: assert label actually deleted
+    assert:
+      that: label_out['results']['labels'][0]['testlabel2'] is not defined
+      msg: "{{ label_out }}"
+
+  - name: add two labels
+    oc_label:
+      state: add
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+        value: "yes"
+      - key: testlabel3
+        value: "yes"
+    register: label_out
+  - name: assert that adding two labels marked as changed
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: check whether both labels are there
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: label_out
+  - name: assert that both labels actually exist
+    assert:
+      that: label_out['results']['labels'][0]['testlabel2'] is defined and
+            label_out['results']['labels'][0]['testlabel2'] == 'yes' and
+            label_out['results']['labels'][0]['testlabel3'] is defined and
+            label_out['results']['labels'][0]['testlabel3'] == 'yes'
+      msg: "{{ label_out['results']['labels'] }}"
+
+  - name: check whether two deletes work
+    oc_label:
+      state: absent
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+      - key: testlabel3
+    register: label_out
+  - name: assert that change were made when delete both labels
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: check whether re-two deletes makes no changes
+    oc_label:
+      state: absent
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels:
+      - key: testlabel2
+      - key: testlabel3
+    register: label_out
+  - name: assert that change was not made when re-delete both labels
+    assert:
+      that: label_out['changed'] == False
+      msg: "{{ label_out }}"
+
+  - set_fact:
+      original_labels_as_key_value_list: "{{ original_labels['results']['labels'][0] | label_dict_to_key_value_list }}"
+
+  - name: check that present with original label list makes no changes
+    oc_label:
+      state: present
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels: "{{ original_labels_as_key_value_list }}"
+    register: label_out
+  - name: assert that no changes are made when current list matches existing list
+    assert:
+      that: label_out['changed'] == False
+      msg: "{{ label_out }}"
+
+  - name: check that present with extra item makes changes
+    oc_label:
+      state: present
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels: "{{ original_labels_as_key_value_list + [{'key': 'testlabel2', 'value': 'yes'}] }}"
+    register: label_out
+  - name: assert that changes were made
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: get current label list
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: label_out
+  - name: asssert that new label was actually added
+    assert:
+      that: label_out['results']['labels'][0]['testlabel2'] is defined and
+            label_out['results']['labels'][0]['testlabel2'] == 'yes'
+      msg: "{{ label_out['results']['labels'] }}"
+
+  - name: check that present with changed item makes changes
+    oc_label:
+      state: present
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels: "{{ original_labels_as_key_value_list + [{'key': 'testlabel2', 'value': 'different'}]}}"
+    register: label_out
+  - name: assert that changes were made when existing key's value is changed
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: get current label list
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: label_out
+  - name: asssert that changed label was actually changed
+    assert:
+      that: label_out['results']['labels'][0]['testlabel2'] is defined and
+            label_out['results']['labels'][0]['testlabel2'] == 'different'
+      msg: "{{ label_out['results']['labels'] }}"
+
+  - name: check that present with removed extra item makes changes
+    oc_label:
+      state: present
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+      labels: "{{ original_labels_as_key_value_list }}"
+    register: label_out
+  - name: assert that changes were made
+    assert:
+      that: label_out['changed'] == True
+      msg: "{{ label_out }}"
+
+  - name: get current label list
+    oc_label:
+      state: list
+      namespace: "{{ def_namespace }}"
+      kind: "{{ def_kind }}"
+      name: "{{ cli_node_test }}"
+    register: label_out
+  - name: asssert that present-removed actually removed
+    assert:
+      that: label_out['results']['labels'][0]['testlabel2'] is not defined
+      msg: "{{ label_out }}"

+ 186 - 0
roles/lib_openshift/src/test/unit/oc_label.py

@@ -0,0 +1,186 @@
+#!/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 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_label import OCLabel  # noqa: E402
+
+
+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.OCLabel._run')
+    def test_state_list(self, mock_cmd):
+        ''' Testing a label list '''
+        params = {'name': 'default',
+                  'namespace': 'default',
+                  'labels': None,
+                  'state': 'list',
+                  'kind': 'namespace',
+                  'selector': None,
+                  'kubeconfig': '/etc/origin/master/admin.kubeconfig',
+                  'debug': False}
+
+        ns = '''{
+            "kind": "Namespace",
+            "apiVersion": "v1",
+            "metadata": {
+                "name": "default",
+                "selfLink": "/api/v1/namespaces/default",
+                "uid": "c45b9547-e3d3-11e6-ba9c-0eece8f2ce22",
+                "resourceVersion": "403024",
+                "creationTimestamp": "2017-01-26T14:28:55Z",
+                "labels": {
+                    "storage_pv_quota": "False"
+                },
+                "annotations": {
+                    "openshift.io/node-selector": "",
+                    "openshift.io/sa.initialized-roles": "true",
+                    "openshift.io/sa.scc.mcs": "s0:c1,c0",
+                    "openshift.io/sa.scc.supplemental-groups": "1000000000/10000",
+                    "openshift.io/sa.scc.uid-range": "1000000000/10000"
+                }
+            },
+            "spec": {
+                "finalizers": [
+                    "kubernetes",
+                    "openshift.io/origin"
+                ]
+            },
+            "status": {
+                "phase": "Active"
+            }
+        }'''
+
+        mock_cmd.side_effect = [
+            (0, ns, ''),
+        ]
+
+        results = OCLabel.run_ansible(params, False)
+
+        self.assertFalse(results['changed'])
+        self.assertTrue(results['results']['labels'] == [{'storage_pv_quota': 'False'}])
+
+    @mock.patch('oc_label.OCLabel._run')
+    def test_state_present(self, mock_cmd):
+        ''' Testing a label list '''
+        params = {'name': 'default',
+                  'namespace': 'default',
+                  'labels': [
+                      {'key': 'awesomens', 'value': 'testinglabel'},
+                      {'key': 'storage_pv_quota', 'value': 'False'}
+                  ],
+                  'state': 'present',
+                  'kind': 'namespace',
+                  'selector': None,
+                  'kubeconfig': '/etc/origin/master/admin.kubeconfig',
+                  'debug': False}
+
+        ns = '''{
+            "kind": "Namespace",
+            "apiVersion": "v1",
+            "metadata": {
+                "name": "default",
+                "selfLink": "/api/v1/namespaces/default",
+                "uid": "c45b9547-e3d3-11e6-ba9c-0eece8f2ce22",
+                "resourceVersion": "403024",
+                "creationTimestamp": "2017-01-26T14:28:55Z",
+                "labels": {
+                    "storage_pv_quota": "False"
+                },
+                "annotations": {
+                    "openshift.io/node-selector": "",
+                    "openshift.io/sa.initialized-roles": "true",
+                    "openshift.io/sa.scc.mcs": "s0:c1,c0",
+                    "openshift.io/sa.scc.supplemental-groups": "1000000000/10000",
+                    "openshift.io/sa.scc.uid-range": "1000000000/10000"
+                }
+            },
+            "spec": {
+                "finalizers": [
+                    "kubernetes",
+                    "openshift.io/origin"
+                ]
+            },
+            "status": {
+                "phase": "Active"
+            }
+        }'''
+
+        ns1 = '''{
+            "kind": "Namespace",
+            "apiVersion": "v1",
+            "metadata": {
+                "name": "default",
+                "selfLink": "/api/v1/namespaces/default",
+                "uid": "c45b9547-e3d3-11e6-ba9c-0eece8f2ce22",
+                "resourceVersion": "403024",
+                "creationTimestamp": "2017-01-26T14:28:55Z",
+                "labels": {
+                    "storage_pv_quota": "False",
+                    "awesomens": "testinglabel"
+                },
+                "annotations": {
+                    "openshift.io/node-selector": "",
+                    "openshift.io/sa.initialized-roles": "true",
+                    "openshift.io/sa.scc.mcs": "s0:c1,c0",
+                    "openshift.io/sa.scc.supplemental-groups": "1000000000/10000",
+                    "openshift.io/sa.scc.uid-range": "1000000000/10000"
+                }
+            },
+            "spec": {
+                "finalizers": [
+                    "kubernetes",
+                    "openshift.io/origin"
+                ]
+            },
+            "status": {
+                "phase": "Active"
+            }
+        }'''
+
+        mock_cmd.side_effect = [
+            (0, ns, ''),
+            (0, '', ''),
+            (0, ns1, ''),
+        ]
+
+        results = OCLabel.run_ansible(params, False)
+
+        self.assertTrue(results['changed'])
+        self.assertTrue(results['results']['results']['labels'][0] ==
+                        {'storage_pv_quota': 'False', 'awesomens': 'testinglabel'})
+
+    def tearDown(self):
+        '''TearDown method'''
+        pass
+
+
+if __name__ == "__main__":
+    unittest.main()