diff options
Diffstat (limited to 'roles/lib_openshift/src')
| -rw-r--r-- | roles/lib_openshift/src/ansible/oc_obj.py | 37 | ||||
| -rw-r--r-- | roles/lib_openshift/src/class/oc_obj.py | 193 | ||||
| -rw-r--r-- | roles/lib_openshift/src/doc/obj | 95 | ||||
| -rw-r--r-- | roles/lib_openshift/src/lib/base.py | 24 | ||||
| -rw-r--r-- | roles/lib_openshift/src/sources.yml | 27 | 
5 files changed, 361 insertions, 15 deletions
| diff --git a/roles/lib_openshift/src/ansible/oc_obj.py b/roles/lib_openshift/src/ansible/oc_obj.py new file mode 100644 index 000000000..701740e4f --- /dev/null +++ b/roles/lib_openshift/src/ansible/oc_obj.py @@ -0,0 +1,37 @@ +# pylint: skip-file +# flake8: noqa + +# pylint: disable=too-many-branches +def main(): +    ''' +    ansible oc module for services +    ''' + +    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'), +            namespace=dict(default='default', type='str'), +            all_namespaces=dict(defaul=False, type='bool'), +            name=dict(default=None, type='str'), +            files=dict(default=None, type='list'), +            kind=dict(required=True, type='str'), +            delete_after=dict(default=False, type='bool'), +            content=dict(default=None, type='dict'), +            force=dict(default=False, type='bool'), +            selector=dict(default=None, type='str'), +        ), +        mutually_exclusive=[["content", "files"]], + +        supports_check_mode=True, +    ) +    rval = OCObject.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_obj.py b/roles/lib_openshift/src/class/oc_obj.py new file mode 100644 index 000000000..9d0b8e45b --- /dev/null +++ b/roles/lib_openshift/src/class/oc_obj.py @@ -0,0 +1,193 @@ +# pylint: skip-file +# flake8: noqa + +# pylint: disable=too-many-instance-attributes +class OCObject(OpenShiftCLI): +    ''' Class to wrap the oc command line tools ''' + +    # pylint allows 5. we need 6 +    # pylint: disable=too-many-arguments +    def __init__(self, +                 kind, +                 namespace, +                 rname=None, +                 selector=None, +                 kubeconfig='/etc/origin/master/admin.kubeconfig', +                 verbose=False, +                 all_namespaces=False): +        ''' Constructor for OpenshiftOC ''' +        super(OCObject, self).__init__(namespace, kubeconfig, +                                       all_namespaces=all_namespaces) +        self.kind = kind +        self.namespace = namespace +        self.name = rname +        self.selector = selector +        self.kubeconfig = kubeconfig +        self.verbose = verbose + +    def get(self): +        '''return a kind by name ''' +        results = self._get(self.kind, rname=self.name, selector=self.selector) +        if results['returncode'] != 0 and 'stderr' in results and \ +           '\"%s\" not found' % self.name in results['stderr']: +            results['returncode'] = 0 + +        return results + +    def delete(self): +        '''return all pods ''' +        return self._delete(self.kind, self.name) + +    def create(self, files=None, content=None): +        ''' +           Create a config + +           NOTE: This creates the first file OR the first conent. +           TODO: Handle all files and content passed in +        ''' +        if files: +            return self._create(files[0]) + +        content['data'] = yaml.dump(content['data']) +        content_file = Utils.create_files_from_contents(content)[0] + +        return self._create(content_file['path']) + +    # pylint: disable=too-many-function-args +    def update(self, files=None, content=None, force=False): +        '''update a current openshift object + +           This receives a list of file names or content +           and takes the first and calls replace. + +           TODO: take an entire list +        ''' +        if files: +            return self._replace(files[0], force) + +        if content and 'data' in content: +            content = content['data'] + +        return self.update_content(content, force) + +    def update_content(self, content, force=False): +        '''update an object through using the content param''' +        return self._replace_content(self.kind, self.name, content, force=force) + +    def needs_update(self, files=None, content=None, content_type='yaml'): +        ''' check to see if we need to update ''' +        objects = self.get() +        if objects['returncode'] != 0: +            return objects + +        # pylint: disable=no-member +        data = None +        if files: +            data = Utils.get_resource_file(files[0], content_type) +        elif content and 'data' in content: +            data = content['data'] +        else: +            data = content + +            # if equal then no need.  So not equal is True +        return not Utils.check_def_equal(data, objects['results'][0], skip_keys=None, debug=False) + +    # pylint: disable=too-many-return-statements,too-many-branches +    @staticmethod +    def run_ansible(params, check_mode=False): +        '''perform the ansible idempotent code''' + +        ocobj = OCObject(params['kind'], +                         params['namespace'], +                         params['name'], +                         params['selector'], +                         kubeconfig=params['kubeconfig'], +                         verbose=params['debug'], +                         all_namespaces=params['all_namespaces']) + +        state = params['state'] + +        api_rval = ocobj.get() + +        ##### +        # Get +        ##### +        if state == 'list': +            return {'changed': False, 'results': api_rval, 'state': 'list'} + +        if not params['name']: +            return {'failed': True, 'msg': 'Please specify a name when state is absent|present.'}  # noqa: E501 + +        ######## +        # Delete +        ######## +        if state == 'absent': +            if not Utils.exists(api_rval['results'], params['name']): +                return {'changed': False, 'state': 'absent'} + +            if check_mode: +                return {'changed': True, 'msg': 'CHECK_MODE: Would have performed a delete'} + +            api_rval = ocobj.delete() + +            return {'changed': True, 'results': api_rval, 'state': 'absent'} + +        if state == 'present': +            ######## +            # Create +            ######## +            if not Utils.exists(api_rval['results'], params['name']): + +                if check_mode: +                    return {'changed': True, 'msg': 'CHECK_MODE: Would have performed a create'} + +                # Create it here +                api_rval = ocobj.create(params['files'], params['content']) +                if api_rval['returncode'] != 0: +                    return {'failed': True, 'msg': api_rval} + +                # return the created object +                api_rval = ocobj.get() + +                if api_rval['returncode'] != 0: +                    return {'failed': True, 'msg': api_rval} + +                # Remove files +                if params['files'] and params['delete_after']: +                    Utils.cleanup(params['files']) + +                return {'changed': True, 'results': api_rval, 'state': "present"} + +            ######## +            # Update +            ######## +            # if a file path is passed, use it. +            update = ocobj.needs_update(params['files'], params['content']) +            if not isinstance(update, bool): +                return {'failed': True, 'msg': update} + +            # No changes +            if not update: +                if params['files'] and params['delete_after']: +                    Utils.cleanup(params['files']) + +                return {'changed': False, 'results': api_rval['results'][0], 'state': "present"} + +            if check_mode: +                return {'changed': True, 'msg': 'CHECK_MODE: Would have performed an update.'} + +            api_rval = ocobj.update(params['files'], +                                    params['content'], +                                    params['force']) + + +            if api_rval['returncode'] != 0: +                return {'failed': True, 'msg': api_rval} + +            # return the created object +            api_rval = ocobj.get() + +            if api_rval['returncode'] != 0: +                return {'failed': True, 'msg': api_rval} + +            return {'changed': True, 'results': api_rval, 'state': "present"} diff --git a/roles/lib_openshift/src/doc/obj b/roles/lib_openshift/src/doc/obj new file mode 100644 index 000000000..e44843eb3 --- /dev/null +++ b/roles/lib_openshift/src/doc/obj @@ -0,0 +1,95 @@ +# flake8: noqa +# pylint: skip-file + +DOCUMENTATION = ''' +--- +module: oc_obj +short_description: Generic interface to openshift objects +description: +  - Manage openshift objects programmatically. +options: +  state: +    description: +    - Currently present is only supported state. +    required: true +    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: [] +  all_namespace: +    description: +    - The namespace where the object lives. +    required: false +    default: false +    aliases: [] +  kind: +    description: +    - The kind attribute of the object. e.g. dc, bc, svc, route +    required: True +    default: None +    aliases: [] +  files: +    description: +    - A list of files provided for object +    required: false +    default: None +    aliases: [] +  delete_after: +    description: +    - Whether or not to delete the files after processing them. +    required: false +    default: false +    aliases: [] +  content: +    description: +    - Content of the object being managed. +    required: false +    default: None +    aliases: [] +  force: +    description: +    - Whether or not to force the operation +    required: false +    default: None +    aliases: [] +  selector: +    description: +    - Selector that gets added to the query. +    required: false +    default: None +    aliases: [] +author: +- "Kenny Woodson <kwoodson@redhat.com>" +extends_documentation_fragment: [] +''' + +EXAMPLES = ''' +oc_obj: +  kind: dc +  name: router +  namespace: default +register: router_output +''' diff --git a/roles/lib_openshift/src/lib/base.py b/roles/lib_openshift/src/lib/base.py index 915a7caca..cf2f1b14d 100644 --- a/roles/lib_openshift/src/lib/base.py +++ b/roles/lib_openshift/src/lib/base.py @@ -47,14 +47,14 @@ class OpenShiftCLI(object):          return {'returncode': 0, 'updated': False}      def _replace(self, fname, force=False): -        '''return all pods ''' +        '''replace the current object with oc replace'''          cmd = ['-n', self.namespace, 'replace', '-f', fname]          if force:              cmd.append('--force')          return self.openshift_cmd(cmd)      def _create_from_content(self, rname, content): -        '''return all pods ''' +        '''create a temporary file and then call oc create on it'''          fname = '/tmp/%s' % rname          yed = Yedit(fname, content=content)          yed.write() @@ -64,11 +64,11 @@ class OpenShiftCLI(object):          return self._create(fname)      def _create(self, fname): -        '''return all pods ''' +        '''call oc create on a filename'''          return self.openshift_cmd(['create', '-f', fname, '-n', self.namespace])      def _delete(self, resource, rname, selector=None): -        '''return all pods ''' +        '''call oc delete on a resource'''          cmd = ['delete', resource, rname, '-n', self.namespace]          if selector:              cmd.append('--selector=%s' % selector) @@ -76,7 +76,14 @@ class OpenShiftCLI(object):          return self.openshift_cmd(cmd)      def _process(self, template_name, create=False, params=None, template_data=None):  # noqa: E501 -        '''return all pods ''' +        '''process a template + +           template_name: the name of the template to process +           create: whether to send to oc create after processing +           params: the parameters for the template +           template_data: the incoming template's data; instead of a file +        ''' +          cmd = ['process', '-n', self.namespace]          if template_data:              cmd.extend(['-f', '-']) @@ -138,7 +145,12 @@ class OpenShiftCLI(object):          return self.openshift_cmd(cmd, oadm=True, output=True, output_type='raw')  # noqa: E501      def _list_pods(self, node=None, selector=None, pod_selector=None): -        ''' perform oadm manage-node evacuate ''' +        ''' perform oadm list pods + +            node: the node in which to list pods +            selector: the label selector filter if provided +            pod_selector: the pod selector filter if provided +        '''          cmd = ['manage-node']          if node:              cmd.extend(node) diff --git a/roles/lib_openshift/src/sources.yml b/roles/lib_openshift/src/sources.yml index 08fbbc201..50d70d1e5 100644 --- a/roles/lib_openshift/src/sources.yml +++ b/roles/lib_openshift/src/sources.yml @@ -1,20 +1,29 @@  --- -oc_route.py: +oc_edit.py:  - doc/generated  - doc/license  - lib/import.py -- doc/route +- doc/edit  - ../../lib_utils/src/class/yedit.py  - lib/base.py -- lib/route.py -- class/oc_route.py -- ansible/oc_route.py -oc_edit.py: +- class/oc_edit.py +- ansible/oc_edit.py +oc_obj.py:  - doc/generated  - doc/license  - lib/import.py -- doc/edit +- doc/obj  - ../../lib_utils/src/class/yedit.py  - lib/base.py -- class/oc_edit.py -- ansible/oc_edit.py +- class/oc_obj.py +- ansible/oc_obj.py +oc_route.py: +- doc/generated +- doc/license +- lib/import.py +- doc/route +- ../../lib_utils/src/class/yedit.py +- lib/base.py +- lib/route.py +- class/oc_route.py +- ansible/oc_route.py | 
