Browse Source

Adding oc_edit module to lib_openshift.

Kenny Woodson 8 years ago
parent
commit
ea33e223e3

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


File diff suppressed because it is too large
+ 824 - 819
roles/lib_openshift/library/oc_route.py


+ 48 - 0
roles/lib_openshift/src/ansible/oc_edit.py

@@ -0,0 +1,48 @@
+# pylint: skip-file
+# flake8: noqa
+
+
+def main():
+    '''
+    ansible oc module for editing objects
+    '''
+
+    module = AnsibleModule(
+        argument_spec=dict(
+            kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'),
+            state=dict(default='present', type='str',
+                       choices=['present']),
+            debug=dict(default=False, type='bool'),
+            namespace=dict(default='default', type='str'),
+            name=dict(default=None, required=True, type='str'),
+            kind=dict(required=True,
+                      type='str',
+                      choices=['dc', 'deploymentconfig',
+                               'rc', 'replicationcontroller',
+                               'svc', 'service',
+                               'scc', 'securitycontextconstraints',
+                               'ns', 'namespace', 'project', 'projects',
+                               'is', 'imagestream',
+                               'istag', 'imagestreamtag',
+                               'bc', 'buildconfig',
+                               'routes',
+                               'node',
+                               'secret',
+                               'pv', 'persistentvolume']),
+            file_name=dict(default=None, type='str'),
+            file_format=dict(default='yaml', type='str'),
+            content=dict(default=None, required=True, type='dict'),
+            force=dict(default=False, type='bool'),
+            separator=dict(default='.', type='str'),
+        ),
+        supports_check_mode=True,
+    )
+
+    rval = Edit.run_ansible(module.params, module.check_mode)
+    if 'failed' in rval:
+        module.fail_json(**rval)
+
+    module.exit_json(**rval)
+
+if __name__ == '__main__':
+    main()

+ 94 - 0
roles/lib_openshift/src/class/oc_edit.py

@@ -0,0 +1,94 @@
+# pylint: skip-file
+# flake8: noqa
+
+class Edit(OpenShiftCLI):
+    ''' Class to wrap the oc command line tools
+    '''
+    # pylint: disable=too-many-arguments
+    def __init__(self,
+                 kind,
+                 namespace,
+                 resource_name=None,
+                 kubeconfig='/etc/origin/master/admin.kubeconfig',
+                 separator='.',
+                 verbose=False):
+        ''' Constructor for OpenshiftOC '''
+        super(Edit, self).__init__(namespace, kubeconfig)
+        self.namespace = namespace
+        self.kind = kind
+        self.name = resource_name
+        self.kubeconfig = kubeconfig
+        self.separator = separator
+        self.verbose = verbose
+
+    def get(self):
+        '''return a secret by name '''
+        return self._get(self.kind, self.name)
+
+    def update(self, file_name, content, force=False, content_type='yaml'):
+        '''run update '''
+        if file_name:
+            if content_type == 'yaml':
+                data = yaml.load(open(file_name))
+            elif content_type == 'json':
+                data = json.loads(open(file_name).read())
+
+            changes = []
+            yed = Yedit(filename=file_name, content=data, separator=self.separator)
+            for key, value in content.items():
+                changes.append(yed.put(key, value))
+
+            if any([not change[0] for change in changes]):
+                return {'returncode': 0, 'updated': False}
+
+            yed.write()
+
+            atexit.register(Utils.cleanup, [file_name])
+
+            return self._replace(file_name, force=force)
+
+        return self._replace_content(self.kind, self.name, content, force=force, sep=self.separator)
+
+    @staticmethod
+    def run_ansible(params, check_mode):
+        '''run the ansible idempotent code'''
+
+        ocedit = Edit(params['kind'],
+                      params['namespace'],
+                      params['name'],
+                      kubeconfig=params['kubeconfig'],
+                      separator=params['separator'],
+                      verbose=params['debug'])
+
+        api_rval = ocedit.get()
+
+        ########
+        # Create
+        ########
+        if not Utils.exists(api_rval['results'], params['name']):
+            return {"failed": True, 'msg': api_rval}
+
+        ########
+        # Update
+        ########
+        if check_mode:
+            return {'changed': True, 'msg': 'CHECK_MODE: Would have performed edit'}
+
+        api_rval = ocedit.update(params['file_name'],
+                                 params['content'],
+                                 params['force'],
+                                 params['file_format'])
+
+        if api_rval['returncode'] != 0:
+            return {"failed": True, 'msg': api_rval}
+
+        if 'updated' in api_rval and not api_rval['updated']:
+            return {"changed": False, 'results': api_rval, 'state': 'present'}
+
+        # return the created object
+        api_rval = ocedit.get()
+
+        if api_rval['returncode'] != 0:
+            return {"failed": True, 'msg': api_rval}
+
+        return {"changed": True, 'results': api_rval, 'state': 'present'}

+ 1 - 0
roles/lib_openshift/src/class/oc_route.py

@@ -64,6 +64,7 @@ class OCRoute(OpenShiftCLI):
         skip = []
         return not Utils.check_def_equal(self.config.data, self.route.yaml_dict, skip_keys=skip, debug=True)
 
+    # pylint: disable=too-many-return-statements,too-many-branches
     @staticmethod
     def run_ansible(params, files, check_mode=False):
         ''' run the idempotent asnible code

+ 116 - 0
roles/lib_openshift/src/doc/edit

@@ -0,0 +1,116 @@
+# flake8: noqa
+# pylint: skip-file
+
+DOCUMENTATION = '''
+---
+module: oc_edit
+short_description: Modify, and idempotently manage openshift objects.
+description:
+  - Modify openshift objects programmatically.
+options:
+  state:
+    description:
+    - Currently present is only supported state.
+    required: true
+    default: present
+    choices: ["present"]
+    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: True
+    default: None
+    choices:
+    - bc
+    - buildconfig
+    - configmaps
+    - dc
+    - deploymentconfig
+    - imagestream
+    - imagestreamtag
+    - is
+    - istag
+    - namespace
+    - project
+    - projects
+    - node
+    - ns
+    - persistentvolume
+    - pv
+    - rc
+    - replicationcontroller
+    - routes
+    - scc
+    - secret
+    - securitycontextconstraints
+    - service
+    - svc
+    aliases: []
+  file_name:
+    description:
+    - The file name in which to edit
+    required: false
+    default: None
+    aliases: []
+  file_format:
+    description:
+    - The format of the file being edited.
+    required: false
+    default: yaml
+    aliases: []
+  content:
+    description:
+    - Content of the file
+    required: false
+    default: None
+    aliases: []
+  force:
+    description:
+    - Whether or not to force the operation
+    required: false
+    default: None
+    aliases: []
+  separator:
+    description:
+    - The separator format for the edit.
+    required: false
+    default: '.'
+    aliases: []
+author:
+- "Kenny Woodson <kwoodson@redhat.com>"
+extends_documentation_fragment: []
+'''
+
+EXAMPLES = '''
+oc_edit:
+  kind: rc
+  name: hawkular-cassandra-rc
+  namespace: openshift-infra
+  content:
+    spec.template.spec.containers[0].resources.limits.memory: 512
+    spec.template.spec.containers[0].resources.requests.memory: 256
+'''

+ 3 - 3
roles/lib_openshift/src/doc/route

@@ -3,10 +3,10 @@
 
 DOCUMENTATION = '''
 ---
-module: yedit
-short_description: Create, modify, and idempotently manage yaml files.
+module: oc_route
+short_description: Create, modify, and idempotently manage openshift routes.
 description:
-  - Modify yaml files programmatically.
+  - Manage openshift route objects programmatically.
 options:
   state:
     description:

+ 2 - 1
roles/lib_openshift/src/generate.py

@@ -9,6 +9,7 @@ import yaml
 # pylint: disable=anomalous-backslash-in-string
 GEN_STR = "#!/usr/bin/env python\n" + \
           "# pylint: disable=missing-docstring\n" + \
+          "# flake8: noqa: T001\n" + \
           "#     ___ ___ _  _ ___ ___    _ _____ ___ ___\n" + \
           "#    / __| __| \| | __| _ \  /_\_   _| __|   \\\n" + \
           "#   | (_ | _|| .` | _||   / / _ \| | | _|| |) |\n" + \
@@ -18,7 +19,7 @@ GEN_STR = "#!/usr/bin/env python\n" + \
           "#   |___/ \___/  |_|\_|\___/ |_|   |___|___/___| |_|\n"
 
 OPENSHIFT_ANSIBLE_PATH = os.path.dirname(os.path.realpath(__file__))
-OPENSHIFT_ANSIBLE_SOURCES_PATH = os.path.join(OPENSHIFT_ANSIBLE_PATH, 'generate_sources.yml')  # noqa: E501
+OPENSHIFT_ANSIBLE_SOURCES_PATH = os.path.join(OPENSHIFT_ANSIBLE_PATH, 'sources.yml')  # noqa: E501
 
 
 def main():

+ 32 - 34
roles/lib_openshift/src/lib/base.py

@@ -1,9 +1,7 @@
 # pylint: skip-file
 # flake8: noqa
-'''
-   OpenShiftCLI class that wraps the oc commands in a subprocess
-'''
 # pylint: disable=too-many-lines
+# noqa: E301,E302,E303,T001
 
 
 class OpenShiftCLIError(Exception):
@@ -213,7 +211,7 @@ class OpenShiftCLI(object):
         err = None
 
         if self.verbose:
-            print ' '.join(cmds)
+            print(' '.join(cmds))
 
         proc = subprocess.Popen(cmds,
                                 stdin=subprocess.PIPE,
@@ -232,14 +230,14 @@ class OpenShiftCLI(object):
                     try:
                         rval['results'] = json.loads(stdout)
                     except ValueError as err:
-                        if "No JSON object could be decoded" in err.message:
-                            err = err.message
+                        if "No JSON object could be decoded" in str(err):
+                            err = str(err)
                 elif output_type == 'raw':
                     rval['results'] = stdout
 
             if self.verbose:
-                print stdout
-                print stderr
+                print(stdout)
+                print(stderr)
 
             if err:
                 rval.update({"err": err,
@@ -350,50 +348,50 @@ class Utils(object):
             if isinstance(value, list):
                 if key not in user_def:
                     if debug:
-                        print 'User data does not have key [%s]' % key
-                        print 'User data: %s' % user_def
+                        print('User data does not have key [%s]' % key)
+                        print('User data: %s' % user_def)
                     return False
 
                 if not isinstance(user_def[key], list):
                     if debug:
-                        print 'user_def[key] is not a list key=[%s] user_def[key]=%s' % (key, user_def[key])
+                        print('user_def[key] is not a list key=[%s] user_def[key]=%s' % (key, user_def[key]))
                     return False
 
                 if len(user_def[key]) != len(value):
                     if debug:
-                        print "List lengths are not equal."
-                        print "key=[%s]: user_def[%s] != value[%s]" % (key, len(user_def[key]), len(value))
-                        print "user_def: %s" % user_def[key]
-                        print "value: %s" % value
+                        print("List lengths are not equal.")
+                        print("key=[%s]: user_def[%s] != value[%s]" % (key, len(user_def[key]), len(value)))
+                        print("user_def: %s" % user_def[key])
+                        print("value: %s" % value)
                     return False
 
                 for values in zip(user_def[key], value):
                     if isinstance(values[0], dict) and isinstance(values[1], dict):
                         if debug:
-                            print 'sending list - list'
-                            print type(values[0])
-                            print type(values[1])
+                            print('sending list - list')
+                            print(type(values[0]))
+                            print(type(values[1]))
                         result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug)
                         if not result:
-                            print 'list compare returned false'
+                            print('list compare returned false')
                             return False
 
                     elif value != user_def[key]:
                         if debug:
-                            print 'value should be identical'
-                            print value
-                            print user_def[key]
+                            print('value should be identical')
+                            print(value)
+                            print(user_def[key])
                         return False
 
             # recurse on a dictionary
             elif isinstance(value, dict):
                 if key not in user_def:
                     if debug:
-                        print "user_def does not have key [%s]" % key
+                        print("user_def does not have key [%s]" % key)
                     return False
                 if not isinstance(user_def[key], dict):
                     if debug:
-                        print "dict returned false: not instance of dict"
+                        print("dict returned false: not instance of dict")
                     return False
 
                 # before passing ensure keys match
@@ -401,31 +399,31 @@ class Utils(object):
                 user_values = set(user_def[key].keys()) - set(skip)
                 if api_values != user_values:
                     if debug:
-                        print "keys are not equal in dict"
-                        print api_values
-                        print user_values
+                        print("keys are not equal in dict")
+                        print(api_values)
+                        print(user_values)
                     return False
 
                 result = Utils.check_def_equal(user_def[key], value, skip_keys=skip_keys, debug=debug)
                 if not result:
                     if debug:
-                        print "dict returned false"
-                        print result
+                        print("dict returned false")
+                        print(result)
                     return False
 
             # Verify each key, value pair is the same
             else:
                 if key not in user_def or value != user_def[key]:
                     if debug:
-                        print "value not equal; user_def does not have key"
-                        print key
-                        print value
+                        print("value not equal; user_def does not have key")
+                        print(key)
+                        print(value)
                         if key in user_def:
-                            print user_def[key]
+                            print(user_def[key])
                     return False
 
         if debug:
-            print 'returning true'
+            print('returning true')
         return True
 
 

+ 3 - 2
roles/lib_openshift/src/lib/import.py

@@ -5,12 +5,13 @@
 '''
 # pylint: disable=too-many-lines
 
-
+from __future__ import print_function
 import atexit
 import json
 import os
 import re
-import ruamel.yaml as yaml
 import shutil
 import subprocess
+# pylint: disable=import-error
+import ruamel.yaml as yaml
 from ansible.module_utils.basic import AnsibleModule

+ 1 - 0
roles/lib_openshift/src/lib/route.py

@@ -1,5 +1,6 @@
 # pylint: skip-file
 # flake8: noqa
+# noqa: E302,E301
 
 
 # pylint: disable=too-many-instance-attributes

+ 9 - 1
roles/lib_openshift/src/generate_sources.yml

@@ -3,8 +3,16 @@ oc_route.py:
 - doc/license
 - lib/import.py
 - doc/route
-- lib/base.py
 - ../../lib_utils/src/class/yedit.py
+- lib/base.py
 - lib/route.py
 - class/oc_route.py
 - ansible/oc_route.py
+oc_edit.py:
+- doc/license
+- lib/import.py
+- doc/edit
+- ../../lib_utils/src/class/yedit.py
+- lib/base.py
+- class/oc_edit.py
+- ansible/oc_edit.py

+ 58 - 0
roles/lib_openshift/src/test/integration/route.yml

@@ -0,0 +1,58 @@
+#!/usr/bin/ansible-playbook
+# ./route.yml -M ../../../library -e "cli_master_test=$OPENSHIFT_MASTER
+---
+- hosts: "{{ cli_master_test }}"
+  gather_facts: no
+  user: root
+  tasks:
+  - name: create route
+    oc_route:
+      name: test
+      namespace: test
+      tls_termination: edge
+      cert_content: testing cert
+      cacert_content: testing cacert
+      service_name: test
+      host: test.example
+    register: routeout
+  - debug: var=routeout
+
+  - name: get route
+    oc_route:
+      state: list
+      name: test
+      namespace: default
+    register: routeout
+  - debug: var=routeout
+
+  - name: delete route
+    oc_route:
+      state: absent
+      name: test
+      namespace: default
+    register: routeout
+  - debug: var=routeout
+
+  - name: create route
+    oc_route:
+      name: test
+      namespace: test
+      tls_termination: edge
+      cert_content: testing cert
+      cacert_content: testing cacert
+      service_name: test
+      host: test.example
+    register: routeout
+  - debug: var=routeout
+
+  - name: create route noop
+    oc_route:
+      name: test
+      namespace: test
+      tls_termination: edge
+      cert_content: testing cert
+      cacert_content: testing cacert
+      service_name: test
+      host: test.example
+    register: routeout
+  - debug: var=routeout

+ 4 - 0
roles/lib_utils/library/yedit.py

@@ -162,12 +162,15 @@ EXAMPLES = '''
 #   b:
 #     c: d
 '''
+# noqa: E301,E302
+
 
 class YeditException(Exception):
     ''' Exception class for Yedit '''
     pass
 
 
+# pylint: disable=too-many-public-methods
 class Yedit(object):
     ''' Class to modify yaml files '''
     re_valid_key = r"(((\[-?\d+\])|([0-9a-zA-Z%s/_-]+)).?)+$"
@@ -724,6 +727,7 @@ class Yedit(object):
 
         return {'failed': True, 'msg': 'Unkown state passed'}
 
+
 # pylint: disable=too-many-branches
 def main():
     ''' ansible oc module for secrets '''

+ 1 - 0
roles/lib_utils/src/ansible/yedit.py

@@ -1,6 +1,7 @@
 # flake8: noqa
 # pylint: skip-file
 
+
 # pylint: disable=too-many-branches
 def main():
     ''' ansible oc module for secrets '''

+ 2 - 0
roles/lib_utils/src/class/yedit.py

@@ -1,5 +1,6 @@
 # flake8: noqa
 # pylint: skip-file
+# noqa: E301,E302
 
 
 class YeditException(Exception):
@@ -7,6 +8,7 @@ class YeditException(Exception):
     pass
 
 
+# pylint: disable=too-many-public-methods
 class Yedit(object):
     ''' Class to modify yaml files '''
     re_valid_key = r"(((\[-?\d+\])|([0-9a-zA-Z%s/_-]+)).?)+$"

+ 0 - 58
roles/lib_utils/src/test/integration/kube-manager-test.yaml

@@ -1,58 +0,0 @@
-apiVersion: v1
-kind: Pod
-metadata:
-  name: kube-controller-manager
-  namespace: kube-system
-spec:
-  hostNetwork: true
-  containers:
-  - name: kube-controller-manager
-    image: openshift/kube:v1.0.0
-    command:
-    - /hyperkube
-    - controller-manager
-    - --master=http://127.0.0.1:8080
-    - --leader-elect=true
-    - --service-account-private-key-file=/etc/kubernetes/ssl/apiserver-key.pem
-    - --root-ca-file=/etc/k8s/ssl/my.pem
-    - --my-new-parameter=openshift
-    livenessProbe:
-      httpGet:
-        host: 127.0.0.1
-        path: /healthz
-        port: 10252
-      initialDelaySeconds: 15
-      timeoutSeconds: 1
-    volumeMounts:
-    - mountPath: /etc/kubernetes/ssl
-      name: ssl-certs-kubernetes
-      readOnly: true
-    - mountPath: /etc/ssl/certs
-      name: ssl-certs-host
-      readOnly: 'true'
-  volumes:
-  - hostPath:
-      path: /etc/kubernetes/ssl
-    name: ssl-certs-kubernetes
-  - hostPath:
-      path: /usr/share/ca-certificates
-    name: ssl-certs-host
-yedittest: yedittest
-metadata-namespace: openshift-is-awesome
-nonexistingkey:
-- --my-new-parameter=openshift
-a:
-  b:
-    c: d
-e:
-  f:
-    g:
-      h:
-        i:
-          j: k
-z:
-  x:
-    y:
-    - 1
-    - 2
-    - 3