From 3681ab5fb2a39ccb06024e6ad514ad50df21f9d2 Mon Sep 17 00:00:00 2001 From: Joel Diaz Date: Fri, 8 Apr 2016 13:48:13 -0400 Subject: cleanup roles after roles move to openshift-tools also removing inventory/multi_inventory* things left behind unchanged even though they were copied: playbooks/adhoc/* roles/dns roles/kube_nfs_volumes roles/os_update_latest --- roles/lib_openshift_api/build/ansible/edit.py | 84 --- roles/lib_openshift_api/build/ansible/obj.py | 139 ---- roles/lib_openshift_api/build/ansible/router.py | 142 ---- roles/lib_openshift_api/build/ansible/secret.py | 121 --- roles/lib_openshift_api/build/generate.py | 64 -- roles/lib_openshift_api/build/src/base.py | 300 -------- roles/lib_openshift_api/build/src/edit.py | 49 -- roles/lib_openshift_api/build/src/obj.py | 78 -- roles/lib_openshift_api/build/src/router.py | 152 ---- roles/lib_openshift_api/build/src/secret.py | 68 -- roles/lib_openshift_api/build/test/README | 5 - .../build/test/deploymentconfig.yml | 120 --- roles/lib_openshift_api/build/test/edit.yml | 53 -- .../lib_openshift_api/build/test/files/config.yml | 1 - .../lib_openshift_api/build/test/files/dc-mod.yml | 124 ---- roles/lib_openshift_api/build/test/files/dc.yml | 120 --- .../build/test/files/passwords.yml | 4 - .../build/test/files/router-mod.json | 30 - .../lib_openshift_api/build/test/files/router.json | 29 - roles/lib_openshift_api/build/test/roles | 1 - roles/lib_openshift_api/build/test/router.yml | 79 -- roles/lib_openshift_api/build/test/secrets.yml | 81 --- roles/lib_openshift_api/build/test/services.yml | 133 ---- roles/lib_openshift_api/library/oadm_router.py | 807 --------------------- roles/lib_openshift_api/library/oc_edit.py | 646 ----------------- roles/lib_openshift_api/library/oc_obj.py | 730 ------------------- roles/lib_openshift_api/library/oc_secret.py | 702 ------------------ 27 files changed, 4862 deletions(-) delete mode 100644 roles/lib_openshift_api/build/ansible/edit.py delete mode 100644 roles/lib_openshift_api/build/ansible/obj.py delete mode 100644 roles/lib_openshift_api/build/ansible/router.py delete mode 100644 roles/lib_openshift_api/build/ansible/secret.py delete mode 100755 roles/lib_openshift_api/build/generate.py delete mode 100644 roles/lib_openshift_api/build/src/base.py delete mode 100644 roles/lib_openshift_api/build/src/edit.py delete mode 100644 roles/lib_openshift_api/build/src/obj.py delete mode 100644 roles/lib_openshift_api/build/src/router.py delete mode 100644 roles/lib_openshift_api/build/src/secret.py delete mode 100644 roles/lib_openshift_api/build/test/README delete mode 100755 roles/lib_openshift_api/build/test/deploymentconfig.yml delete mode 100755 roles/lib_openshift_api/build/test/edit.yml delete mode 100644 roles/lib_openshift_api/build/test/files/config.yml delete mode 100644 roles/lib_openshift_api/build/test/files/dc-mod.yml delete mode 100644 roles/lib_openshift_api/build/test/files/dc.yml delete mode 100644 roles/lib_openshift_api/build/test/files/passwords.yml delete mode 100644 roles/lib_openshift_api/build/test/files/router-mod.json delete mode 100644 roles/lib_openshift_api/build/test/files/router.json delete mode 120000 roles/lib_openshift_api/build/test/roles delete mode 100755 roles/lib_openshift_api/build/test/router.yml delete mode 100755 roles/lib_openshift_api/build/test/secrets.yml delete mode 100755 roles/lib_openshift_api/build/test/services.yml delete mode 100644 roles/lib_openshift_api/library/oadm_router.py delete mode 100644 roles/lib_openshift_api/library/oc_edit.py delete mode 100644 roles/lib_openshift_api/library/oc_obj.py delete mode 100644 roles/lib_openshift_api/library/oc_secret.py (limited to 'roles/lib_openshift_api') diff --git a/roles/lib_openshift_api/build/ansible/edit.py b/roles/lib_openshift_api/build/ansible/edit.py deleted file mode 100644 index 943fa47a6..000000000 --- a/roles/lib_openshift_api/build/ansible/edit.py +++ /dev/null @@ -1,84 +0,0 @@ -# pylint: skip-file - -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']), - 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', - 'svc', 'service', - 'scc', 'securitycontextconstraints', - 'ns', 'namespace', 'project', 'projects', - 'is', 'imagestream', - 'istag', 'imagestreamtag', - 'bc', 'buildconfig', - 'routes', - 'node', - 'secret', - ]), - 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'), - ), - supports_check_mode=True, - ) - ocedit = Edit(module.params['kind'], - module.params['namespace'], - module.params['name'], - kubeconfig=module.params['kubeconfig'], - verbose=module.params['debug']) - - state = module.params['state'] - - api_rval = ocedit.get() - - ######## - # Create - ######## - if not Utils.exists(api_rval['results'], module.params['name']): - module.fail_json(msg=api_rval) - - ######## - # Update - ######## - api_rval = ocedit.update(module.params['file_name'], - module.params['content'], - module.params['force'], - module.params['file_format']) - - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - if api_rval.has_key('updated') and not api_rval['updated']: - module.exit_json(changed=False, results=api_rval, state="present") - - # return the created object - api_rval = ocedit.get() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * - -main() diff --git a/roles/lib_openshift_api/build/ansible/obj.py b/roles/lib_openshift_api/build/ansible/obj.py deleted file mode 100644 index a14ac0e43..000000000 --- a/roles/lib_openshift_api/build/ansible/obj.py +++ /dev/null @@ -1,139 +0,0 @@ -# pylint: skip-file - -# 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'), - name=dict(default=None, type='str'), - files=dict(default=None, type='list'), - kind=dict(required=True, - type='str', - choices=['dc', 'deploymentconfig', - 'svc', 'service', - 'scc', 'securitycontextconstraints', - 'ns', 'namespace', 'project', 'projects', - 'is', 'imagestream', - 'istag', 'imagestreamtag', - 'bc', 'buildconfig', - 'routes', - 'node', - 'secret', - ]), - delete_after=dict(default=False, type='bool'), - content=dict(default=None, type='dict'), - force=dict(default=False, type='bool'), - ), - mutually_exclusive=[["content", "files"]], - - supports_check_mode=True, - ) - ocobj = OCObject(module.params['kind'], - module.params['namespace'], - module.params['name'], - kubeconfig=module.params['kubeconfig'], - verbose=module.params['debug']) - - state = module.params['state'] - - api_rval = ocobj.get() - - ##### - # Get - ##### - if state == 'list': - module.exit_json(changed=False, results=api_rval['results'], state="list") - - if not module.params['name']: - module.fail_json(msg='Please specify a name when state is absent|present.') - ######## - # Delete - ######## - if state == 'absent': - if not Utils.exists(api_rval['results'], module.params['name']): - module.exit_json(changed=False, state="absent") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a delete.') - - api_rval = ocobj.delete() - module.exit_json(changed=True, results=api_rval, state="absent") - - if state == 'present': - ######## - # Create - ######## - if not Utils.exists(api_rval['results'], module.params['name']): - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a create.') - - # Create it here - api_rval = ocobj.create(module.params['files'], module.params['content']) - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - # return the created object - api_rval = ocobj.get() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - # Remove files - if module.params['files'] and module.params['delete_after']: - Utils.cleanup(module.params['files']) - - module.exit_json(changed=True, results=api_rval, state="present") - - ######## - # Update - ######## - # if a file path is passed, use it. - update = ocobj.needs_update(module.params['files'], module.params['content']) - if not isinstance(update, bool): - module.fail_json(msg=update) - - # No changes - if not update: - if module.params['files'] and module.params['delete_after']: - Utils.cleanup(module.params['files']) - - module.exit_json(changed=False, results=api_rval['results'][0], state="present") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed an update.') - - api_rval = ocobj.update(module.params['files'], - module.params['content'], - module.params['force']) - - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - # return the created object - api_rval = ocobj.get() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * - -main() diff --git a/roles/lib_openshift_api/build/ansible/router.py b/roles/lib_openshift_api/build/ansible/router.py deleted file mode 100644 index 3b24c7b5e..000000000 --- a/roles/lib_openshift_api/build/ansible/router.py +++ /dev/null @@ -1,142 +0,0 @@ -# pylint: skip-file - -def main(): - ''' - ansible oc module for secrets - ''' - - module = AnsibleModule( - argument_spec=dict( - state=dict(default='present', type='str', - choices=['present', 'absent']), - debug=dict(default=False, type='bool'), - namespace=dict(default='default', type='str'), - name=dict(default='router', type='str'), - - kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'), - credentials=dict(default='/etc/origin/master/openshift-router.kubeconfig', type='str'), - cert_file=dict(default=None, type='str'), - key_file=dict(default=None, type='str'), - image=dict(default=None, type='str'), #'openshift3/ose-${component}:${version}' - latest_image=dict(default=False, type='bool'), - labels=dict(default=None, type='list'), - ports=dict(default=['80:80', '443:443'], type='list'), - replicas=dict(default=1, type='int'), - selector=dict(default=None, type='str'), - service_account=dict(default='router', type='str'), - router_type=dict(default='haproxy-router', type='str'), - host_network=dict(default=True, type='bool'), - # external host options - external_host=dict(default=None, type='str'), - external_host_vserver=dict(default=None, type='str'), - external_host_insecure=dict(default=False, type='bool'), - external_host_partition_path=dict(default=None, type='str'), - external_host_username=dict(default=None, type='str'), - external_host_password=dict(default=None, type='str'), - external_host_private_key=dict(default=None, type='str'), - # Metrics - expose_metrics=dict(default=False, type='bool'), - metrics_image=dict(default=None, type='str'), - # Stats - stats_user=dict(default=None, type='str'), - stats_password=dict(default=None, type='str'), - stats_port=dict(default=1936, type='int'), - - ), - mutually_exclusive=[["router_type", "images"]], - - supports_check_mode=True, - ) - - rconfig = RouterConfig(module.params['name'], - module.params['kubeconfig'], - {'credentials': {'value': module.params['credentials'], 'include': True}, - 'default_cert': {'value': None, 'include': True}, - 'cert_file': {'value': module.params['cert_file'], 'include': False}, - 'key_file': {'value': module.params['key_file'], 'include': False}, - 'image': {'value': module.params['image'], 'include': True}, - 'latest_image': {'value': module.params['latest_image'], 'include': True}, - 'labels': {'value': module.params['labels'], 'include': True}, - 'ports': {'value': ','.join(module.params['ports']), 'include': True}, - 'replicas': {'value': module.params['replicas'], 'include': True}, - 'selector': {'value': module.params['selector'], 'include': True}, - 'service_account': {'value': module.params['service_account'], 'include': True}, - 'router_type': {'value': module.params['router_type'], 'include': False}, - 'host_network': {'value': module.params['host_network'], 'include': True}, - 'external_host': {'value': module.params['external_host'], 'include': True}, - 'external_host_vserver': {'value': module.params['external_host_vserver'], - 'include': True}, - 'external_host_insecure': {'value': module.params['external_host_insecure'], - 'include': True}, - 'external_host_partition_path': {'value': module.params['external_host_partition_path'], - 'include': True}, - 'external_host_username': {'value': module.params['external_host_username'], - 'include': True}, - 'external_host_password': {'value': module.params['external_host_password'], - 'include': True}, - 'external_host_private_key': {'value': module.params['external_host_private_key'], - 'include': True}, - 'expose_metrics': {'value': module.params['expose_metrics'], 'include': True}, - 'metrics_image': {'value': module.params['metrics_image'], 'include': True}, - 'stats_user': {'value': module.params['stats_user'], 'include': True}, - 'stats_password': {'value': module.params['stats_password'], 'include': True}, - 'stats_port': {'value': module.params['stats_port'], 'include': True}, - }) - - - ocrouter = Router(rconfig) - - state = module.params['state'] - - ######## - # Delete - ######## - if state == 'absent': - if not ocrouter.exists(): - module.exit_json(changed=False, state="absent") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a delete.') - - api_rval = ocrouter.delete() - module.exit_json(changed=True, results=api_rval, state="absent") - - - if state == 'present': - ######## - # Create - ######## - if not ocrouter.exists(): - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a create.') - - api_rval = ocrouter.create() - - module.exit_json(changed=True, results=api_rval, state="present") - - ######## - # Update - ######## - if not ocrouter.needs_update(): - module.exit_json(changed=False, state="present") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed an update.') - - api_rval = ocrouter.update() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * -main() diff --git a/roles/lib_openshift_api/build/ansible/secret.py b/roles/lib_openshift_api/build/ansible/secret.py deleted file mode 100644 index 8df7bbc64..000000000 --- a/roles/lib_openshift_api/build/ansible/secret.py +++ /dev/null @@ -1,121 +0,0 @@ -# pylint: skip-file - -# pylint: disable=too-many-branches -def main(): - ''' - ansible oc module for secrets - ''' - - 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'), - name=dict(default=None, type='str'), - files=dict(default=None, type='list'), - delete_after=dict(default=False, type='bool'), - contents=dict(default=None, type='list'), - force=dict(default=False, type='bool'), - ), - mutually_exclusive=[["contents", "files"]], - - supports_check_mode=True, - ) - occmd = Secret(module.params['namespace'], - module.params['name'], - kubeconfig=module.params['kubeconfig'], - verbose=module.params['debug']) - - state = module.params['state'] - - api_rval = occmd.get() - - ##### - # Get - ##### - if state == 'list': - module.exit_json(changed=False, results=api_rval['results'], state="list") - - if not module.params['name']: - module.fail_json(msg='Please specify a name when state is absent|present.') - ######## - # Delete - ######## - if state == 'absent': - if not Utils.exists(api_rval['results'], module.params['name']): - module.exit_json(changed=False, state="absent") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a delete.') - - api_rval = occmd.delete() - module.exit_json(changed=True, results=api_rval, state="absent") - - - if state == 'present': - if module.params['files']: - files = module.params['files'] - elif module.params['contents']: - files = Utils.create_files_from_contents(module.params['contents']) - else: - module.fail_json(msg='Either specify files or contents.') - - ######## - # Create - ######## - if not Utils.exists(api_rval['results'], module.params['name']): - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a create.') - - api_rval = occmd.create(module.params['files'], module.params['contents']) - - # Remove files - if files and module.params['delete_after']: - Utils.cleanup(files) - - module.exit_json(changed=True, results=api_rval, state="present") - - ######## - # Update - ######## - secret = occmd.prep_secret(module.params['files'], module.params['contents']) - - if secret['returncode'] != 0: - module.fail_json(msg=secret) - - if Utils.check_def_equal(secret['results'], api_rval['results'][0]): - - # Remove files - if files and module.params['delete_after']: - Utils.cleanup(files) - - module.exit_json(changed=False, results=secret['results'], state="present") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed an update.') - - api_rval = occmd.update(files, force=module.params['force']) - - # Remove files - if secret and module.params['delete_after']: - Utils.cleanup(files) - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * - -main() diff --git a/roles/lib_openshift_api/build/generate.py b/roles/lib_openshift_api/build/generate.py deleted file mode 100755 index 9fc1986f1..000000000 --- a/roles/lib_openshift_api/build/generate.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -''' - Generate the openshift-ansible/roles/lib_openshift_cli/library/ modules. -''' - -import os - -# pylint: disable=anomalous-backslash-in-string -GEN_STR = "#!/usr/bin/env python\n" + \ - "# ___ ___ _ _ ___ ___ _ _____ ___ ___\n" + \ - "# / __| __| \| | __| _ \ /_\_ _| __| \\\n" + \ - "# | (_ | _|| .` | _|| / / _ \| | | _|| |) |\n" + \ - "# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____\n" + \ - "# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _|\n" + \ - "# | |) | (_) | | .` | (_) || | | _|| |) | | | |\n" + \ - "# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_|\n" - -OPENSHIFT_ANSIBLE_PATH = os.path.dirname(os.path.realpath(__file__)) - - -FILES = {'oc_obj.py': ['src/base.py', - '../../lib_yaml_editor/build/src/yedit.py', - 'src/obj.py', - 'ansible/obj.py', - ], - 'oc_secret.py': ['src/base.py', - '../../lib_yaml_editor/build/src/yedit.py', - 'src/secret.py', - 'ansible/secret.py', - ], - 'oc_edit.py': ['src/base.py', - '../../lib_yaml_editor/build/src/yedit.py', - 'src/edit.py', - 'ansible/edit.py', - ], - 'oadm_router.py': ['src/base.py', - '../../lib_yaml_editor/build/src/yedit.py', - 'src/router.py', - 'ansible/router.py', - ], - } - - -def main(): - ''' combine the necessary files to create the ansible module ''' - library = os.path.join(OPENSHIFT_ANSIBLE_PATH, '..', 'library/') - for fname, parts in FILES.items(): - with open(os.path.join(library, fname), 'w') as afd: - afd.seek(0) - afd.write(GEN_STR) - for fpart in parts: - with open(os.path.join(OPENSHIFT_ANSIBLE_PATH, fpart)) as pfd: - # first line is pylint disable so skip it - for idx, line in enumerate(pfd): - if idx == 0 and 'skip-file' in line: - continue - - afd.write(line) - - -if __name__ == '__main__': - main() - - diff --git a/roles/lib_openshift_api/build/src/base.py b/roles/lib_openshift_api/build/src/base.py deleted file mode 100644 index 257379d92..000000000 --- a/roles/lib_openshift_api/build/src/base.py +++ /dev/null @@ -1,300 +0,0 @@ -# pylint: skip-file -''' - OpenShiftCLI class that wraps the oc commands in a subprocess -''' - -import atexit -import json -import os -import shutil -import subprocess -import re - -import yaml -# This is here because of a bug that causes yaml -# to incorrectly handle timezone info on timestamps -def timestamp_constructor(_, node): - '''return timestamps as strings''' - return str(node.value) -yaml.add_constructor(u'tag:yaml.org,2002:timestamp', timestamp_constructor) - -# pylint: disable=too-few-public-methods -class OpenShiftCLI(object): - ''' Class to wrap the command line tools ''' - def __init__(self, - namespace, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftCLI ''' - self.namespace = namespace - self.verbose = verbose - self.kubeconfig = kubeconfig - - # Pylint allows only 5 arguments to be passed. - # pylint: disable=too-many-arguments - def _replace_content(self, resource, rname, content, force=False): - ''' replace the current object with the content ''' - res = self._get(resource, rname) - if not res['results']: - return res - - fname = '/tmp/%s' % rname - yed = Yedit(fname, res['results'][0]) - changes = [] - 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, [fname]) - - return self._replace(fname, force) - - def _replace(self, fname, force=False): - '''return all pods ''' - cmd = ['-n', self.namespace, 'replace', '-f', fname] - if force: - cmd.append('--force') - return self.openshift_cmd(cmd) - - def _create(self, fname): - '''return all pods ''' - return self.openshift_cmd(['create', '-f', fname, '-n', self.namespace]) - - def _delete(self, resource, rname): - '''return all pods ''' - return self.openshift_cmd(['delete', resource, rname, '-n', self.namespace]) - - def _get(self, resource, rname=None): - '''return a secret by name ''' - cmd = ['get', resource, '-o', 'json', '-n', self.namespace] - if rname: - cmd.append(rname) - - rval = self.openshift_cmd(cmd, output=True) - - # Ensure results are retuned in an array - if rval.has_key('items'): - rval['results'] = rval['items'] - elif not isinstance(rval['results'], list): - rval['results'] = [rval['results']] - - return rval - - def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json'): - '''Base command for oc ''' - #cmds = ['/usr/bin/oc', '--config', self.kubeconfig] - cmds = [] - if oadm: - cmds = ['/usr/bin/oadm'] - else: - cmds = ['/usr/bin/oc'] - - cmds.extend(cmd) - - rval = {} - results = '' - err = None - - if self.verbose: - print ' '.join(cmds) - - proc = subprocess.Popen(cmds, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env={'KUBECONFIG': self.kubeconfig}) - - proc.wait() - stdout = proc.stdout.read() - stderr = proc.stderr.read() - rval = {"returncode": proc.returncode, - "results": results, - "cmd": ' '.join(cmds), - } - - if proc.returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as err: - if "No JSON object could be decoded" in err.message: - err = err.message - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print stdout - print stderr - print - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds - }) - - else: - rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}, - }) - - return rval - -class Utils(object): - ''' utilities for openshiftcli modules ''' - @staticmethod - def create_file(rname, data, ftype=None): - ''' create a file in tmp with name and contents''' - path = os.path.join('/tmp', rname) - with open(path, 'w') as fds: - if ftype == 'yaml': - fds.write(yaml.safe_dump(data, default_flow_style=False)) - - elif ftype == 'json': - fds.write(json.dumps(data)) - else: - fds.write(data) - - # Register cleanup when module is done - atexit.register(Utils.cleanup, [path]) - return path - - @staticmethod - def create_files_from_contents(data): - '''Turn an array of dict: filename, content into a files array''' - files = [] - - for sfile in data: - path = Utils.create_file(sfile['path'], sfile['content']) - files.append(path) - - return files - - @staticmethod - def cleanup(files): - '''Clean up on exit ''' - for sfile in files: - if os.path.exists(sfile): - if os.path.isdir(sfile): - shutil.rmtree(sfile) - elif os.path.isfile(sfile): - os.remove(sfile) - - - @staticmethod - def exists(results, _name): - ''' Check to see if the results include the name ''' - if not results: - return False - - - if Utils.find_result(results, _name): - return True - - return False - - @staticmethod - def find_result(results, _name): - ''' Find the specified result by name''' - rval = None - for result in results: - if result.has_key('metadata') and result['metadata']['name'] == _name: - rval = result - break - - return rval - - @staticmethod - def get_resource_file(sfile, sfile_type='yaml'): - ''' return the service file ''' - contents = None - with open(sfile) as sfd: - contents = sfd.read() - - if sfile_type == 'yaml': - contents = yaml.safe_load(contents) - elif sfile_type == 'json': - contents = json.loads(contents) - - return contents - - # Disabling too-many-branches. This is a yaml dictionary comparison function - # pylint: disable=too-many-branches,too-many-return-statements - @staticmethod - def check_def_equal(user_def, result_def, skip_keys=None, debug=False): - ''' Given a user defined definition, compare it with the results given back by our query. ''' - - # Currently these values are autogenerated and we do not need to check them - skip = ['metadata', 'status'] - if skip_keys: - skip.extend(skip_keys) - - for key, value in result_def.items(): - if key in skip: - continue - - # Both are lists - if isinstance(value, list): - if not isinstance(user_def[key], list): - if debug: - print 'user_def[key] is not a list' - 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]) - result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug) - if not result: - 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] - return False - - # recurse on a dictionary - elif isinstance(value, dict): - if not isinstance(user_def[key], dict): - if debug: - print "dict returned false not instance of dict" - return False - - # before passing ensure keys match - api_values = set(value.keys()) - set(skip) - user_values = set(user_def[key].keys()) - set(skip) - if api_values != user_values: - if debug: - print api_values - print user_values - print "keys are not equal in dict" - 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 - return False - - # Verify each key, value pair is the same - else: - if not user_def.has_key(key) or value != user_def[key]: - if debug: - print "value not equal; user_def does not have key" - print value - print user_def[key] - return False - - return True diff --git a/roles/lib_openshift_api/build/src/edit.py b/roles/lib_openshift_api/build/src/edit.py deleted file mode 100644 index 7020ace47..000000000 --- a/roles/lib_openshift_api/build/src/edit.py +++ /dev/null @@ -1,49 +0,0 @@ -# pylint: skip-file - -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', - 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.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(file_name, data) - 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) - - diff --git a/roles/lib_openshift_api/build/src/obj.py b/roles/lib_openshift_api/build/src/obj.py deleted file mode 100644 index 13aeba8e1..000000000 --- a/roles/lib_openshift_api/build/src/obj.py +++ /dev/null @@ -1,78 +0,0 @@ -# pylint: skip-file - -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, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftOC ''' - super(OCObject, self).__init__(namespace, kubeconfig) - self.kind = kind - self.namespace = namespace - self.name = rname - self.kubeconfig = kubeconfig - self.verbose = verbose - - def get(self): - '''return a deploymentconfig by name ''' - return self._get(self.kind, rname=self.name) - - def delete(self): - '''return all pods ''' - return self._delete(self.kind, self.name) - - def create(self, files=None, content=None): - '''Create a deploymentconfig ''' - if files: - return self._create(files[0]) - - return self._create(Utils.create_files_from_contents(content)) - - - # pylint: disable=too-many-function-args - def update(self, files=None, content=None, force=False): - '''run update dc - - This receives a list of file names and takes the first filename and calls replace. - ''' - if files: - return self._replace(files[0], force) - - return self.update_content(content, force) - - def update_content(self, content, force=False): - '''update the dc with the content''' - 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) - - # 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) - else: - data = content - - for key, value in data.items(): - if key == 'metadata': - continue - if not objects['results'][0].has_key(key): - return True - if value != objects['results'][0][key]: - return True - - return False - diff --git a/roles/lib_openshift_api/build/src/router.py b/roles/lib_openshift_api/build/src/router.py deleted file mode 100644 index 69454d594..000000000 --- a/roles/lib_openshift_api/build/src/router.py +++ /dev/null @@ -1,152 +0,0 @@ -# pylint: skip-file - -import time - -class RouterConfig(object): - ''' RouterConfig is a DTO for the router. ''' - def __init__(self, rname, kubeconfig, router_options): - self.name = rname - self.kubeconfig = kubeconfig - self._router_options = router_options - - @property - def router_options(self): - ''' return router options ''' - return self._router_options - - def to_option_list(self): - ''' return all options as a string''' - return RouterConfig.stringify(self.router_options) - - @staticmethod - def stringify(options): - ''' return hash as list of key value pairs ''' - rval = [] - for key, data in options.items(): - if data['include'] and data['value']: - rval.append('--%s=%s' % (key.replace('_', '-'), data['value'])) - - return rval - -class Router(OpenShiftCLI): - ''' Class to wrap the oc command line tools ''' - def __init__(self, - router_config, - verbose=False): - ''' Constructor for OpenshiftOC - - a router consists of 3 or more parts - - dc/router - - svc/router - - endpoint/router - ''' - super(Router, self).__init__('default', router_config.kubeconfig, verbose) - self.rconfig = router_config - self.verbose = verbose - self.router_parts = [{'kind': 'dc', 'name': self.rconfig.name}, - {'kind': 'svc', 'name': self.rconfig.name}, - #{'kind': 'endpoints', 'name': self.rconfig.name}, - ] - def get(self, filter_kind=None): - ''' return the self.router_parts ''' - rparts = self.router_parts - parts = [] - if filter_kind: - rparts = [part for part in self.router_parts if filter_kind == part['kind']] - - for part in rparts: - parts.append(self._get(part['kind'], rname=part['name'])) - - return parts - - def exists(self): - '''return a deploymentconfig by name ''' - parts = self.get() - for part in parts: - if part['returncode'] != 0: - return False - - return True - - def delete(self): - '''return all pods ''' - parts = [] - for part in self.router_parts: - parts.append(self._delete(part['kind'], part['name'])) - - return parts - - def create(self, dryrun=False, output=False, output_type='json'): - '''Create a deploymentconfig ''' - # We need to create the pem file - router_pem = '/tmp/router.pem' - with open(router_pem, 'w') as rfd: - rfd.write(open(self.rconfig.router_options['cert_file']['value']).read()) - rfd.write(open(self.rconfig.router_options['key_file']['value']).read()) - - atexit.register(Utils.cleanup, [router_pem]) - self.rconfig.router_options['default_cert']['value'] = router_pem - - options = self.rconfig.to_option_list() - - cmd = ['router'] - cmd.extend(options) - if dryrun: - cmd.extend(['--dry-run=True', '-o', 'json']) - - results = self.openshift_cmd(cmd, oadm=True, output=output, output_type=output_type) - - return results - - def update(self): - '''run update for the router. This performs a delete and then create ''' - parts = self.delete() - if any([part['returncode'] != 0 for part in parts]): - return parts - - # Ugly built in sleep here. - time.sleep(15) - - return self.create() - - def needs_update(self, verbose=False): - ''' check to see if we need to update ''' - dc_inmem = self.get(filter_kind='dc')[0] - if dc_inmem['returncode'] != 0: - return dc_inmem - - user_dc = self.create(dryrun=True, output=True, output_type='raw') - if user_dc['returncode'] != 0: - return user_dc - - # Since the output from oadm_router is returned as raw - # we need to parse it. The first line is the stats_password - user_dc_results = user_dc['results'].split('\n') - # stats_password = user_dc_results[0] - - # Load the string back into json and get the newly created dc - user_dc = json.loads('\n'.join(user_dc_results[1:]))['items'][0] - - # Router needs some exceptions. - # We do not want to check the autogenerated password for stats admin - if not self.rconfig.router_options['stats_password']['value']: - for idx, env_var in enumerate(user_dc['spec']['template']['spec']['containers'][0]['env']): - if env_var['name'] == 'STATS_PASSWORD': - env_var['value'] = \ - dc_inmem['results'][0]['spec']['template']['spec']['containers'][0]['env'][idx]['value'] - - # dry-run doesn't add the protocol to the ports section. We will manually do that. - for idx, port in enumerate(user_dc['spec']['template']['spec']['containers'][0]['ports']): - if not port.has_key('protocol'): - port['protocol'] = 'TCP' - - # These are different when generating - skip = ['dnsPolicy', - 'terminationGracePeriodSeconds', - 'restartPolicy', 'timeoutSeconds', - 'livenessProbe', 'readinessProbe', - 'terminationMessagePath', - 'rollingParams', - ] - - return not Utils.check_def_equal(user_dc, dc_inmem['results'][0], skip_keys=skip, debug=verbose) diff --git a/roles/lib_openshift_api/build/src/secret.py b/roles/lib_openshift_api/build/src/secret.py deleted file mode 100644 index 154716828..000000000 --- a/roles/lib_openshift_api/build/src/secret.py +++ /dev/null @@ -1,68 +0,0 @@ -# pylint: skip-file - -class Secret(OpenShiftCLI): - ''' Class to wrap the oc command line tools - ''' - def __init__(self, - namespace, - secret_name=None, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftOC ''' - super(Secret, self).__init__(namespace, kubeconfig) - self.namespace = namespace - self.name = secret_name - self.kubeconfig = kubeconfig - self.verbose = verbose - - def get(self): - '''return a secret by name ''' - return self._get('secrets', self.name) - - def delete(self): - '''delete a secret by name''' - return self._delete('secrets', self.name) - - def create(self, files=None, contents=None): - '''Create a secret ''' - if not files: - files = Utils.create_files_from_contents(contents) - - secrets = ["%s=%s" % (os.path.basename(sfile), sfile) for sfile in files] - cmd = ['-n%s' % self.namespace, 'secrets', 'new', self.name] - cmd.extend(secrets) - - return self.openshift_cmd(cmd) - - def update(self, files, force=False): - '''run update secret - - This receives a list of file names and converts it into a secret. - The secret is then written to disk and passed into the `oc replace` command. - ''' - secret = self.prep_secret(files) - if secret['returncode'] != 0: - return secret - - sfile_path = '/tmp/%s' % self.name - with open(sfile_path, 'w') as sfd: - sfd.write(json.dumps(secret['results'])) - - atexit.register(Utils.cleanup, [sfile_path]) - - return self._replace(sfile_path, force=force) - - def prep_secret(self, files=None, contents=None): - ''' return what the secret would look like if created - This is accomplished by passing -ojson. This will most likely change in the future - ''' - if not files: - files = Utils.create_files_from_contents(contents) - - secrets = ["%s=%s" % (os.path.basename(sfile), sfile) for sfile in files] - cmd = ['-ojson', '-n%s' % self.namespace, 'secrets', 'new', self.name] - cmd.extend(secrets) - - return self.openshift_cmd(cmd, output=True) - - diff --git a/roles/lib_openshift_api/build/test/README b/roles/lib_openshift_api/build/test/README deleted file mode 100644 index af9f05b3d..000000000 --- a/roles/lib_openshift_api/build/test/README +++ /dev/null @@ -1,5 +0,0 @@ -After generate.py has run, the ansible modules will be placed under ../../../openshift-ansible/roles/lib_openshift_api/library. - - -To run the tests you need to run them like this: -./services.yml -M ../../library diff --git a/roles/lib_openshift_api/build/test/deploymentconfig.yml b/roles/lib_openshift_api/build/test/deploymentconfig.yml deleted file mode 100755 index d041ab22a..000000000 --- a/roles/lib_openshift_api/build/test/deploymentconfig.yml +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/ansible-playbook ---- -- hosts: "oo_clusterid_mwoodson:&oo_version_3:&oo_master_primary" - gather_facts: no - user: root - - post_tasks: - - copy: - dest: "/tmp/{{ item }}" - src: "files/{{ item }}" - with_items: - - dc.yml - - - name: list dc - oc_obj: - kind: dc - state: list - namespace: default - name: router - register: dcout - - - debug: - var: dcout - - - name: absent dc - oc_obj: - kind: dc - state: absent - namespace: default - name: router - register: dcout - - - debug: - var: dcout - - - name: present dc - oc_obj: - kind: dc - state: present - namespace: default - name: router - files: - - /tmp/dc.yml - register: dcout - - - debug: - var: dcout - - - name: dump router - oc_obj: - kind: dc - state: list - name: router - register: routerout - - - name: write router file - copy: - dest: /tmp/dc-mod.json - content: "{{ routerout.results[0] }}" - - - command: cat /tmp/dc-mod.json - register: catout - - - debug: - msg: "{{ catout }}" - - - command: "sed -i 's/: 80/: 81/g' /tmp/dc-mod.json" - register: catout - - - name: present dc update - oc_obj: - kind: dc - state: present - namespace: default - name: router - files: - - /tmp/dc-mod.json - delete_after: True - register: dcout - - - debug: - var: dcout - - - include_vars: "files/dc-mod.yml" - - - name: absent dc - oc_obj: - kind: dc - state: absent - namespace: default - name: router - register: dcout - - - debug: - var: dcout - - - name: present dc - oc_obj: - kind: dc - state: present - namespace: default - name: router - files: - - /tmp/dc.yml - delete_after: True - register: dcout - - - name: present dc - oc_obj: - kind: dc - state: present - namespace: default - name: router - content: "{{ dc }}" - delete_after: True - register: dcout - - - debug: - var: dcout - diff --git a/roles/lib_openshift_api/build/test/edit.yml b/roles/lib_openshift_api/build/test/edit.yml deleted file mode 100755 index 9aa01303a..000000000 --- a/roles/lib_openshift_api/build/test/edit.yml +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/ansible-playbook ---- -- hosts: "oo_clusterid_mwoodson:&oo_version_3:&oo_master_primary" - gather_facts: no - user: root - - post_tasks: - - copy: - dest: "/tmp/{{ item }}" - src: "files/{{ item }}" - with_items: - - dc.yml - - - name: present dc - oc_edit: - kind: dc - namespace: default - name: router - content: - spec.template.spec.containers[0].ports[0].containerPort: 80 - spec.template.spec.containers[0].ports[0].hostPort: 80 - register: dcout - - - debug: - var: dcout - - - name: present dc - oc_edit: - kind: dc - namespace: default - name: router - content: - spec.template.spec.containers[0].ports[0].containerPort: 81 - spec.template.spec.containers[0].ports[0].hostPort: 81 - file_format: yaml - register: dcout - - - debug: - var: dcout - - - name: present dc - oc_edit: - kind: dc - namespace: default - name: router - content: - spec.template.spec.containers[0].ports[0].containerPort: 80 - spec.template.spec.containers[0].ports[0].hostPort: 80 - file_format: yaml - register: dcout - - - debug: - var: dcout diff --git a/roles/lib_openshift_api/build/test/files/config.yml b/roles/lib_openshift_api/build/test/files/config.yml deleted file mode 100644 index c544c6fd4..000000000 --- a/roles/lib_openshift_api/build/test/files/config.yml +++ /dev/null @@ -1 +0,0 @@ -value: True diff --git a/roles/lib_openshift_api/build/test/files/dc-mod.yml b/roles/lib_openshift_api/build/test/files/dc-mod.yml deleted file mode 100644 index 6c700d6c7..000000000 --- a/roles/lib_openshift_api/build/test/files/dc-mod.yml +++ /dev/null @@ -1,124 +0,0 @@ -dc: - path: - dc-mod.yml - content: - apiVersion: v1 - kind: DeploymentConfig - metadata: - labels: - router: router - name: router - namespace: default - resourceVersion: "84016" - selfLink: /oapi/v1/namespaces/default/deploymentconfigs/router - uid: 48f8b9d9-ed42-11e5-9903-0a9a9d4e7f2b - spec: - replicas: 2 - selector: - router: router - strategy: - resources: {} - rollingParams: - intervalSeconds: 1 - maxSurge: 0 - maxUnavailable: 25% - timeoutSeconds: 600 - updatePercent: -25 - updatePeriodSeconds: 1 - type: Rolling - template: - metadata: - creationTimestamp: null - labels: - router: router - spec: - containers: - - env: - - name: DEFAULT_CERTIFICATE - - name: OPENSHIFT_CA_DATA - value: | - -----BEGIN CERTIFICATE----- - MIIC5jCCAdCgAwIBAgIBATALBgkqhkiG9w0BAQswJjEkMCIGA1UEAwwbb3BlbnNo - -----END CERTIFICATE----- - - name: OPENSHIFT_CERT_DATA - value: | - -----BEGIN CERTIFICATE----- - MIIDDTCCAfegAwIBAgIBCDALBgkqhkiG9w0BAQswJjEkMCIGA1UEAwwbb3BlbnNo - -----END CERTIFICATE----- - - name: OPENSHIFT_INSECURE - value: "false" - - name: OPENSHIFT_KEY_DATA - value: | - -----BEGIN RSA PRIVATE KEY----- - MIIEogIBAAKCAQEA2lf49DrPHfCdCORcnIbmDVrx8yos7trjWdBvuledijyslRVR - -----END RSA PRIVATE KEY----- - - name: OPENSHIFT_MASTER - value: https://internal.api.mwoodson.openshift.com - - name: ROUTER_EXTERNAL_HOST_HOSTNAME - - name: ROUTER_EXTERNAL_HOST_HTTPS_VSERVER - - name: ROUTER_EXTERNAL_HOST_HTTP_VSERVER - - name: ROUTER_EXTERNAL_HOST_INSECURE - value: "false" - - name: ROUTER_EXTERNAL_HOST_PARTITION_PATH - - name: ROUTER_EXTERNAL_HOST_PASSWORD - - name: ROUTER_EXTERNAL_HOST_PRIVKEY - value: /etc/secret-volume/router.pem - - name: ROUTER_EXTERNAL_HOST_USERNAME - - name: ROUTER_SERVICE_NAME - value: router - - name: ROUTER_SERVICE_NAMESPACE - value: default - - name: STATS_PASSWORD - value: ugCk6YBm4q - - name: STATS_PORT - value: "1936" - - name: STATS_USERNAME - value: admin - image: openshift3/ose-haproxy-router:v3.1.1.6 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - host: localhost - path: /healthz - port: 1936 - scheme: HTTP - initialDelaySeconds: 10 - timeoutSeconds: 1 - name: router - ports: - - containerPort: 81 - hostPort: 81 - protocol: TCP - - containerPort: 443 - hostPort: 443 - protocol: TCP - - containerPort: 1936 - hostPort: 1936 - name: stats - protocol: TCP - readinessProbe: - httpGet: - host: localhost - path: /healthz - port: 1937 - scheme: HTTP - timeoutSeconds: 1 - resources: {} - terminationMessagePath: /dev/termination-log - dnsPolicy: ClusterFirst - hostNetwork: true - nodeSelector: - type: infra - restartPolicy: Always - securityContext: {} - serviceAccount: router - serviceAccountName: router - terminationGracePeriodSeconds: 30 - triggers: - - type: ConfigChange - status: - details: - causes: - - type: ConfigChange - latestVersion: 1 - diff --git a/roles/lib_openshift_api/build/test/files/dc.yml b/roles/lib_openshift_api/build/test/files/dc.yml deleted file mode 100644 index 24f690ef4..000000000 --- a/roles/lib_openshift_api/build/test/files/dc.yml +++ /dev/null @@ -1,120 +0,0 @@ -apiVersion: v1 -kind: DeploymentConfig -metadata: - creationTimestamp: 2016-04-01T15:23:29Z - labels: - router: router - name: router - namespace: default - resourceVersion: "1338477" - selfLink: /oapi/v1/namespaces/default/deploymentconfigs/router - uid: b00c7eba-f81d-11e5-809b-0a581f893e3f -spec: - replicas: 2 - selector: - router: router - strategy: - resources: {} - rollingParams: - intervalSeconds: 1 - maxSurge: 0 - maxUnavailable: 25% - timeoutSeconds: 600 - updatePercent: -25 - updatePeriodSeconds: 1 - type: Rolling - template: - metadata: - creationTimestamp: null - labels: - router: router - spec: - containers: - - env: - - name: DEFAULT_CERTIFICATE - - name: OPENSHIFT_CA_DATA - value: | - -----BEGIN CERTIFICATE----- - MIIC5jCCAdCgAwIBAgIBATALBgkqhkiG9w0BAQswJjEkMCIGA1UEAwwbb3BlbnNo - -----END CERTIFICATE----- - - name: OPENSHIFT_CERT_DATA - value: | - -----BEGIN CERTIFICATE----- - MIIDDTCCAfegAwIBAgIBCDALBgkqhkiG9w0BAQswJjEkMCIGA1UEAwwbb3BlbnNo - -----END CERTIFICATE----- - - name: OPENSHIFT_INSECURE - value: "false" - - name: OPENSHIFT_KEY_DATA - value: | - -----BEGIN RSA PRIVATE KEY----- - MIIEogIBAAKCAQEA2lf49DrPHfCdCORcnIbmDVrx8yos7trjWdBvuledijyslRVR - -----END RSA PRIVATE KEY----- - - name: OPENSHIFT_MASTER - value: https://internal.api.mwoodson.openshift.com - - name: ROUTER_EXTERNAL_HOST_HOSTNAME - - name: ROUTER_EXTERNAL_HOST_HTTPS_VSERVER - - name: ROUTER_EXTERNAL_HOST_HTTP_VSERVER - - name: ROUTER_EXTERNAL_HOST_INSECURE - value: "false" - - name: ROUTER_EXTERNAL_HOST_PARTITION_PATH - - name: ROUTER_EXTERNAL_HOST_PASSWORD - - name: ROUTER_EXTERNAL_HOST_PRIVKEY - value: /etc/secret-volume/router.pem - - name: ROUTER_EXTERNAL_HOST_USERNAME - - name: ROUTER_SERVICE_NAME - value: router - - name: ROUTER_SERVICE_NAMESPACE - value: default - - name: STATS_PASSWORD - value: ugCk6YBm4q - - name: STATS_PORT - value: "1936" - - name: STATS_USERNAME - value: admin - image: openshift3/ose-haproxy-router:v3.1.1.6 - imagePullPolicy: IfNotPresent - livenessProbe: - httpGet: - host: localhost - path: /healthz - port: 1936 - scheme: HTTP - initialDelaySeconds: 10 - timeoutSeconds: 1 - name: router - ports: - - containerPort: 80 - hostPort: 80 - protocol: TCP - - containerPort: 443 - hostPort: 443 - protocol: TCP - - containerPort: 1936 - hostPort: 1936 - name: stats - protocol: TCP - readinessProbe: - httpGet: - host: localhost - path: /healthz - port: 1936 - scheme: HTTP - timeoutSeconds: 1 - resources: {} - terminationMessagePath: /dev/termination-log - dnsPolicy: ClusterFirst - hostNetwork: true - nodeSelector: - type: infra - restartPolicy: Always - securityContext: {} - serviceAccount: router - serviceAccountName: router - terminationGracePeriodSeconds: 30 - triggers: - - type: ConfigChange -status: - details: - causes: - - type: ConfigChange - latestVersion: 12 diff --git a/roles/lib_openshift_api/build/test/files/passwords.yml b/roles/lib_openshift_api/build/test/files/passwords.yml deleted file mode 100644 index fadbf1d85..000000000 --- a/roles/lib_openshift_api/build/test/files/passwords.yml +++ /dev/null @@ -1,4 +0,0 @@ -test1 -test2 -test3 -test4 diff --git a/roles/lib_openshift_api/build/test/files/router-mod.json b/roles/lib_openshift_api/build/test/files/router-mod.json deleted file mode 100644 index 45e2e7c8d..000000000 --- a/roles/lib_openshift_api/build/test/files/router-mod.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "kind": "Service", - "apiVersion": "v1", - "metadata": { - "name": "router", - "namespace": "default", - "labels": { - "router": "router" - } - }, - "spec": { - "ports": [ - { - "name": "81-tcp", - "protocol": "TCP", - "port": 81, - "targetPort": 81 - } - ], - "selector": { - "router": "router" - }, - "type": "ClusterIP", - "sessionAffinity": "None" - }, - "status": { - "loadBalancer": {} - } -} - diff --git a/roles/lib_openshift_api/build/test/files/router.json b/roles/lib_openshift_api/build/test/files/router.json deleted file mode 100644 index cad3c6f53..000000000 --- a/roles/lib_openshift_api/build/test/files/router.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "apiVersion": "v1", - "kind": "Service", - "metadata": { - "labels": { - "router": "router" - }, - "name": "router", - "namespace": "default" - }, - "spec": { - "ports": [ - { - "name": "80-tcp", - "port": 80, - "protocol": "TCP", - "targetPort": 80 - } - ], - "selector": { - "router": "router" - }, - "sessionAffinity": "None", - "type": "ClusterIP" - }, - "status": { - "loadBalancer": {} - } -} diff --git a/roles/lib_openshift_api/build/test/roles b/roles/lib_openshift_api/build/test/roles deleted file mode 120000 index ae82aa9bb..000000000 --- a/roles/lib_openshift_api/build/test/roles +++ /dev/null @@ -1 +0,0 @@ -../../../../roles/ \ No newline at end of file diff --git a/roles/lib_openshift_api/build/test/router.yml b/roles/lib_openshift_api/build/test/router.yml deleted file mode 100755 index 7ab192b97..000000000 --- a/roles/lib_openshift_api/build/test/router.yml +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/ansible-playbook ---- -- hosts: "oo_clusterid_mwoodson:&oo_master_primary" - gather_facts: no - user: root - - tasks: - - oadm_router: - state: absent - credentials: /etc/origin/master/openshift-router.kubeconfig - service_account: router - replicas: 2 - namespace: default - selector: type=infra - cert_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.crt - key_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.key - register: routerout - - - debug: var=routerout - - - pause: - seconds: 10 - - - oadm_router: - credentials: /etc/origin/master/openshift-router.kubeconfig - service_account: router - replicas: 2 - namespace: default - selector: type=infra - cert_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.crt - key_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.key - register: routerout - - - debug: var=routerout - - - pause: - seconds: 10 - - - oadm_router: - credentials: /etc/origin/master/openshift-router.kubeconfig - service_account: router - replicas: 2 - namespace: default - selector: type=infra - cert_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.crt - key_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.key - register: routerout - - - debug: var=routerout - - - pause: - seconds: 10 - - - oadm_router: - credentials: /etc/origin/master/openshift-router.kubeconfig - service_account: router - replicas: 3 - namespace: default - selector: type=test - cert_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.crt - key_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.key - register: routerout - - - debug: var=routerout - - - pause: - seconds: 10 - - - oadm_router: - credentials: /etc/origin/master/openshift-router.kubeconfig - service_account: router - replicas: 2 - namespace: default - selector: type=infra - cert_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.crt - key_file: /etc/origin/master/named_certificates/12ab.mwoodson.openshiftapps.com.key - register: routerout - - - debug: var=routerout diff --git a/roles/lib_openshift_api/build/test/secrets.yml b/roles/lib_openshift_api/build/test/secrets.yml deleted file mode 100755 index dddc05c4d..000000000 --- a/roles/lib_openshift_api/build/test/secrets.yml +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/ansible-playbook ---- -- hosts: "oo_clusterid_mwoodson:&oo_version_3:&oo_master_primary" - gather_facts: no - user: root - - post_tasks: - - copy: - dest: "/tmp/{{ item }}" - src: "files/{{ item }}" - with_items: - - config.yml - - passwords.yml - - - name: list secrets - oc_secret: - state: list - namespace: default - name: kenny - register: secret_out - - - debug: - var: secret_out - - - name: absent secrets - oc_secret: - state: absent - namespace: default - name: kenny - register: secret_out - - - debug: - var: secret_out - - - name: present secrets - oc_secret: - state: present - namespace: default - name: kenny - files: - - /tmp/config.yml - - /tmp/passwords.yml - delete_after: True - register: secret_out - - - debug: - var: secret_out - - - name: present secrets - oc_secret: - state: present - namespace: default - name: kenny - contents: - - path: config.yml - content: "value: True\n" - - path: passwords.yml - content: "test1\ntest2\ntest3\ntest4\n" - delete_after: True - register: secret_out - - - debug: - var: secret_out - - - name: present secrets update - oc_secret: - state: present - namespace: default - name: kenny - contents: - - path: config.yml - content: "value: True\n" - - path: passwords.yml - content: "test1\ntest2\ntest3\ntest4\ntest5\n" - delete_after: True - force: True - register: secret_out - - - debug: - var: secret_out - diff --git a/roles/lib_openshift_api/build/test/services.yml b/roles/lib_openshift_api/build/test/services.yml deleted file mode 100755 index a32e8d012..000000000 --- a/roles/lib_openshift_api/build/test/services.yml +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/ansible-playbook ---- -- hosts: "oo_clusterid_mwoodson:&oo_master_primary" - gather_facts: no - user: root - - roles: - - roles/lib_yaml_editor - - tasks: - - copy: - dest: "/tmp/{{ item }}" - src: "files/{{ item }}" - with_items: - - router.json - - router-mod.json - - - name: list services - oc_obj: - kind: service - state: list - namespace: default - name: router - register: service_out - - - debug: - var: service_out.results - - - name: absent service - oc_obj: - kind: service - state: absent - namespace: default - name: router - register: service_out - - - debug: - var: service_out - - - name: present service create - oc_obj: - kind: service - state: present - namespace: default - name: router - files: - - /tmp/router.json - delete_after: True - register: service_out - - - debug: - var: service_out - - - name: dump router - oc_obj: - kind: service - state: list - name: router - namespace: default - register: routerout - - - name: write router file - copy: - dest: /tmp/router-mod.json - content: "{{ routerout.results[0] }}" - - - command: cat /tmp/router-mod.json - register: catout - - - debug: - msg: "{{ catout }}" - - - command: "sed -i 's/80-tcp/81-tcp/g' /tmp/router-mod.json" - register: catout - - - name: present service replace - oc_obj: - kind: service - state: present - namespace: default - name: router - files: - - /tmp/router-mod.json - #delete_after: True - register: service_out - - - debug: - var: service_out - - - name: list services - oc_obj: - kind: service - state: list - namespace: default - name: router - register: service_out - - - debug: - var: service_out.results - - - set_fact: - new_service: "{{ service_out.results[0] }}" - - - yedit: - src: /tmp/routeryedit - content: "{{ new_service }}" - key: spec.ports - value: - - name: 80-tcp - port: 80 - protocol: TCP - targetPort: 80 - - - yedit: - src: /tmp/routeryedit - state: list - register: yeditout - - - debug: - var: yeditout - - - name: present service replace - oc_obj: - kind: service - state: present - namespace: default - name: router - content: "{{ yeditout.results }}" - delete_after: True - register: service_out - - - debug: - var: service_out diff --git a/roles/lib_openshift_api/library/oadm_router.py b/roles/lib_openshift_api/library/oadm_router.py deleted file mode 100644 index c6b45c14e..000000000 --- a/roles/lib_openshift_api/library/oadm_router.py +++ /dev/null @@ -1,807 +0,0 @@ -#!/usr/bin/env python -# ___ ___ _ _ ___ ___ _ _____ ___ ___ -# / __| __| \| | __| _ \ /_\_ _| __| \ -# | (_ | _|| .` | _|| / / _ \| | | _|| |) | -# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____ -# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _| -# | |) | (_) | | .` | (_) || | | _|| |) | | | | -# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_| -''' - OpenShiftCLI class that wraps the oc commands in a subprocess -''' - -import atexit -import json -import os -import shutil -import subprocess -import re - -import yaml -# This is here because of a bug that causes yaml -# to incorrectly handle timezone info on timestamps -def timestamp_constructor(_, node): - '''return timestamps as strings''' - return str(node.value) -yaml.add_constructor(u'tag:yaml.org,2002:timestamp', timestamp_constructor) - -# pylint: disable=too-few-public-methods -class OpenShiftCLI(object): - ''' Class to wrap the command line tools ''' - def __init__(self, - namespace, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftCLI ''' - self.namespace = namespace - self.verbose = verbose - self.kubeconfig = kubeconfig - - # Pylint allows only 5 arguments to be passed. - # pylint: disable=too-many-arguments - def _replace_content(self, resource, rname, content, force=False): - ''' replace the current object with the content ''' - res = self._get(resource, rname) - if not res['results']: - return res - - fname = '/tmp/%s' % rname - yed = Yedit(fname, res['results'][0]) - changes = [] - 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, [fname]) - - return self._replace(fname, force) - - def _replace(self, fname, force=False): - '''return all pods ''' - cmd = ['-n', self.namespace, 'replace', '-f', fname] - if force: - cmd.append('--force') - return self.openshift_cmd(cmd) - - def _create(self, fname): - '''return all pods ''' - return self.openshift_cmd(['create', '-f', fname, '-n', self.namespace]) - - def _delete(self, resource, rname): - '''return all pods ''' - return self.openshift_cmd(['delete', resource, rname, '-n', self.namespace]) - - def _get(self, resource, rname=None): - '''return a secret by name ''' - cmd = ['get', resource, '-o', 'json', '-n', self.namespace] - if rname: - cmd.append(rname) - - rval = self.openshift_cmd(cmd, output=True) - - # Ensure results are retuned in an array - if rval.has_key('items'): - rval['results'] = rval['items'] - elif not isinstance(rval['results'], list): - rval['results'] = [rval['results']] - - return rval - - def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json'): - '''Base command for oc ''' - #cmds = ['/usr/bin/oc', '--config', self.kubeconfig] - cmds = [] - if oadm: - cmds = ['/usr/bin/oadm'] - else: - cmds = ['/usr/bin/oc'] - - cmds.extend(cmd) - - rval = {} - results = '' - err = None - - if self.verbose: - print ' '.join(cmds) - - proc = subprocess.Popen(cmds, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env={'KUBECONFIG': self.kubeconfig}) - - proc.wait() - stdout = proc.stdout.read() - stderr = proc.stderr.read() - rval = {"returncode": proc.returncode, - "results": results, - "cmd": ' '.join(cmds), - } - - if proc.returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as err: - if "No JSON object could be decoded" in err.message: - err = err.message - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print stdout - print stderr - print - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds - }) - - else: - rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}, - }) - - return rval - -class Utils(object): - ''' utilities for openshiftcli modules ''' - @staticmethod - def create_file(rname, data, ftype=None): - ''' create a file in tmp with name and contents''' - path = os.path.join('/tmp', rname) - with open(path, 'w') as fds: - if ftype == 'yaml': - fds.write(yaml.safe_dump(data, default_flow_style=False)) - - elif ftype == 'json': - fds.write(json.dumps(data)) - else: - fds.write(data) - - # Register cleanup when module is done - atexit.register(Utils.cleanup, [path]) - return path - - @staticmethod - def create_files_from_contents(data): - '''Turn an array of dict: filename, content into a files array''' - files = [] - - for sfile in data: - path = Utils.create_file(sfile['path'], sfile['content']) - files.append(path) - - return files - - @staticmethod - def cleanup(files): - '''Clean up on exit ''' - for sfile in files: - if os.path.exists(sfile): - if os.path.isdir(sfile): - shutil.rmtree(sfile) - elif os.path.isfile(sfile): - os.remove(sfile) - - - @staticmethod - def exists(results, _name): - ''' Check to see if the results include the name ''' - if not results: - return False - - - if Utils.find_result(results, _name): - return True - - return False - - @staticmethod - def find_result(results, _name): - ''' Find the specified result by name''' - rval = None - for result in results: - if result.has_key('metadata') and result['metadata']['name'] == _name: - rval = result - break - - return rval - - @staticmethod - def get_resource_file(sfile, sfile_type='yaml'): - ''' return the service file ''' - contents = None - with open(sfile) as sfd: - contents = sfd.read() - - if sfile_type == 'yaml': - contents = yaml.safe_load(contents) - elif sfile_type == 'json': - contents = json.loads(contents) - - return contents - - # Disabling too-many-branches. This is a yaml dictionary comparison function - # pylint: disable=too-many-branches,too-many-return-statements - @staticmethod - def check_def_equal(user_def, result_def, skip_keys=None, debug=False): - ''' Given a user defined definition, compare it with the results given back by our query. ''' - - # Currently these values are autogenerated and we do not need to check them - skip = ['metadata', 'status'] - if skip_keys: - skip.extend(skip_keys) - - for key, value in result_def.items(): - if key in skip: - continue - - # Both are lists - if isinstance(value, list): - if not isinstance(user_def[key], list): - if debug: - print 'user_def[key] is not a list' - 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]) - result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug) - if not result: - 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] - return False - - # recurse on a dictionary - elif isinstance(value, dict): - if not isinstance(user_def[key], dict): - if debug: - print "dict returned false not instance of dict" - return False - - # before passing ensure keys match - api_values = set(value.keys()) - set(skip) - user_values = set(user_def[key].keys()) - set(skip) - if api_values != user_values: - if debug: - print api_values - print user_values - print "keys are not equal in dict" - 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 - return False - - # Verify each key, value pair is the same - else: - if not user_def.has_key(key) or value != user_def[key]: - if debug: - print "value not equal; user_def does not have key" - print value - print user_def[key] - return False - - return True - -class YeditException(Exception): - ''' Exception class for Yedit ''' - pass - -class Yedit(object): - ''' Class to modify yaml files ''' - re_valid_key = r"(((\[-?\d+\])|([a-zA-Z-./]+)).?)+$" - re_key = r"(?:\[(-?\d+)\])|([a-zA-Z-./]+)" - - def __init__(self, filename=None, content=None, content_type='yaml'): - self.content = content - self.filename = filename - self.__yaml_dict = content - self.content_type = content_type - if self.filename and not self.content: - self.load(content_type=self.content_type) - - @property - def yaml_dict(self): - ''' getter method for yaml_dict ''' - return self.__yaml_dict - - @yaml_dict.setter - def yaml_dict(self, value): - ''' setter method for yaml_dict ''' - self.__yaml_dict = value - - @staticmethod - def remove_entry(data, key): - ''' remove data at location key ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for remove - # expected list entry - if key_indexes[-1][0]: - if isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - del data[int(key_indexes[-1][0])] - return True - - # expected dict entry - elif key_indexes[-1][1]: - if isinstance(data, dict): - del data[key_indexes[-1][1]] - return True - - @staticmethod - def add_entry(data, key, item=None): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - curr_data = data - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key: - if isinstance(data, dict) and data.has_key(dict_key): - data = data[dict_key] - continue - - data[dict_key] = {} - data = data[dict_key] - - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for add - # expected list entry - if key_indexes[-1][0] and isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - data[int(key_indexes[-1][0])] = item - - # expected dict entry - elif key_indexes[-1][1] and isinstance(data, dict): - data[key_indexes[-1][1]] = item - - return curr_data - - @staticmethod - def get_entry(data, key): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - return data - - def write(self): - ''' write to file ''' - if not self.filename: - raise YeditException('Please specify a filename.') - - with open(self.filename, 'w') as yfd: - yfd.write(yaml.safe_dump(self.yaml_dict, default_flow_style=False)) - - def read(self): - ''' write to file ''' - # check if it exists - if not self.exists(): - return None - - contents = None - with open(self.filename) as yfd: - contents = yfd.read() - - return contents - - def exists(self): - ''' return whether file exists ''' - if os.path.exists(self.filename): - return True - - return False - - def load(self, content_type='yaml'): - ''' return yaml file ''' - contents = self.read() - - if not contents: - return None - - # check if it is yaml - try: - if content_type == 'yaml': - self.yaml_dict = yaml.load(contents) - elif content_type == 'json': - self.yaml_dict = json.loads(contents) - except yaml.YAMLError as _: - # Error loading yaml or json - return None - - return self.yaml_dict - - def get(self, key): - ''' get a specified key''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - return entry - - def delete(self, key): - ''' remove key from a dict''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - if not entry: - return (False, self.yaml_dict) - - result = Yedit.remove_entry(self.yaml_dict, key) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def put(self, key, value): - ''' put key, value into a dict ''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - if entry == value: - return (False, self.yaml_dict) - - result = Yedit.add_entry(self.yaml_dict, key, value) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def create(self, key, value): - ''' create a yaml file ''' - if not self.exists(): - self.yaml_dict = {key: value} - return (True, self.yaml_dict) - - return (False, self.yaml_dict) - -import time - -class RouterConfig(object): - ''' RouterConfig is a DTO for the router. ''' - def __init__(self, rname, kubeconfig, router_options): - self.name = rname - self.kubeconfig = kubeconfig - self._router_options = router_options - - @property - def router_options(self): - ''' return router options ''' - return self._router_options - - def to_option_list(self): - ''' return all options as a string''' - return RouterConfig.stringify(self.router_options) - - @staticmethod - def stringify(options): - ''' return hash as list of key value pairs ''' - rval = [] - for key, data in options.items(): - if data['include'] and data['value']: - rval.append('--%s=%s' % (key.replace('_', '-'), data['value'])) - - return rval - -class Router(OpenShiftCLI): - ''' Class to wrap the oc command line tools ''' - def __init__(self, - router_config, - verbose=False): - ''' Constructor for OpenshiftOC - - a router consists of 3 or more parts - - dc/router - - svc/router - - endpoint/router - ''' - super(Router, self).__init__('default', router_config.kubeconfig, verbose) - self.rconfig = router_config - self.verbose = verbose - self.router_parts = [{'kind': 'dc', 'name': self.rconfig.name}, - {'kind': 'svc', 'name': self.rconfig.name}, - #{'kind': 'endpoints', 'name': self.rconfig.name}, - ] - def get(self, filter_kind=None): - ''' return the self.router_parts ''' - rparts = self.router_parts - parts = [] - if filter_kind: - rparts = [part for part in self.router_parts if filter_kind == part['kind']] - - for part in rparts: - parts.append(self._get(part['kind'], rname=part['name'])) - - return parts - - def exists(self): - '''return a deploymentconfig by name ''' - parts = self.get() - for part in parts: - if part['returncode'] != 0: - return False - - return True - - def delete(self): - '''return all pods ''' - parts = [] - for part in self.router_parts: - parts.append(self._delete(part['kind'], part['name'])) - - return parts - - def create(self, dryrun=False, output=False, output_type='json'): - '''Create a deploymentconfig ''' - # We need to create the pem file - router_pem = '/tmp/router.pem' - with open(router_pem, 'w') as rfd: - rfd.write(open(self.rconfig.router_options['cert_file']['value']).read()) - rfd.write(open(self.rconfig.router_options['key_file']['value']).read()) - - atexit.register(Utils.cleanup, [router_pem]) - self.rconfig.router_options['default_cert']['value'] = router_pem - - options = self.rconfig.to_option_list() - - cmd = ['router'] - cmd.extend(options) - if dryrun: - cmd.extend(['--dry-run=True', '-o', 'json']) - - results = self.openshift_cmd(cmd, oadm=True, output=output, output_type=output_type) - - return results - - def update(self): - '''run update for the router. This performs a delete and then create ''' - parts = self.delete() - if any([part['returncode'] != 0 for part in parts]): - return parts - - # Ugly built in sleep here. - time.sleep(15) - - return self.create() - - def needs_update(self, verbose=False): - ''' check to see if we need to update ''' - dc_inmem = self.get(filter_kind='dc')[0] - if dc_inmem['returncode'] != 0: - return dc_inmem - - user_dc = self.create(dryrun=True, output=True, output_type='raw') - if user_dc['returncode'] != 0: - return user_dc - - # Since the output from oadm_router is returned as raw - # we need to parse it. The first line is the stats_password - user_dc_results = user_dc['results'].split('\n') - # stats_password = user_dc_results[0] - - # Load the string back into json and get the newly created dc - user_dc = json.loads('\n'.join(user_dc_results[1:]))['items'][0] - - # Router needs some exceptions. - # We do not want to check the autogenerated password for stats admin - if not self.rconfig.router_options['stats_password']['value']: - for idx, env_var in enumerate(user_dc['spec']['template']['spec']['containers'][0]['env']): - if env_var['name'] == 'STATS_PASSWORD': - env_var['value'] = \ - dc_inmem['results'][0]['spec']['template']['spec']['containers'][0]['env'][idx]['value'] - - # dry-run doesn't add the protocol to the ports section. We will manually do that. - for idx, port in enumerate(user_dc['spec']['template']['spec']['containers'][0]['ports']): - if not port.has_key('protocol'): - port['protocol'] = 'TCP' - - # These are different when generating - skip = ['dnsPolicy', - 'terminationGracePeriodSeconds', - 'restartPolicy', 'timeoutSeconds', - 'livenessProbe', 'readinessProbe', - 'terminationMessagePath', - 'rollingParams', - ] - - return not Utils.check_def_equal(user_dc, dc_inmem['results'][0], skip_keys=skip, debug=verbose) - -def main(): - ''' - ansible oc module for secrets - ''' - - module = AnsibleModule( - argument_spec=dict( - state=dict(default='present', type='str', - choices=['present', 'absent']), - debug=dict(default=False, type='bool'), - namespace=dict(default='default', type='str'), - name=dict(default='router', type='str'), - - kubeconfig=dict(default='/etc/origin/master/admin.kubeconfig', type='str'), - credentials=dict(default='/etc/origin/master/openshift-router.kubeconfig', type='str'), - cert_file=dict(default=None, type='str'), - key_file=dict(default=None, type='str'), - image=dict(default=None, type='str'), #'openshift3/ose-${component}:${version}' - latest_image=dict(default=False, type='bool'), - labels=dict(default=None, type='list'), - ports=dict(default=['80:80', '443:443'], type='list'), - replicas=dict(default=1, type='int'), - selector=dict(default=None, type='str'), - service_account=dict(default='router', type='str'), - router_type=dict(default='haproxy-router', type='str'), - host_network=dict(default=True, type='bool'), - # external host options - external_host=dict(default=None, type='str'), - external_host_vserver=dict(default=None, type='str'), - external_host_insecure=dict(default=False, type='bool'), - external_host_partition_path=dict(default=None, type='str'), - external_host_username=dict(default=None, type='str'), - external_host_password=dict(default=None, type='str'), - external_host_private_key=dict(default=None, type='str'), - # Metrics - expose_metrics=dict(default=False, type='bool'), - metrics_image=dict(default=None, type='str'), - # Stats - stats_user=dict(default=None, type='str'), - stats_password=dict(default=None, type='str'), - stats_port=dict(default=1936, type='int'), - - ), - mutually_exclusive=[["router_type", "images"]], - - supports_check_mode=True, - ) - - rconfig = RouterConfig(module.params['name'], - module.params['kubeconfig'], - {'credentials': {'value': module.params['credentials'], 'include': True}, - 'default_cert': {'value': None, 'include': True}, - 'cert_file': {'value': module.params['cert_file'], 'include': False}, - 'key_file': {'value': module.params['key_file'], 'include': False}, - 'image': {'value': module.params['image'], 'include': True}, - 'latest_image': {'value': module.params['latest_image'], 'include': True}, - 'labels': {'value': module.params['labels'], 'include': True}, - 'ports': {'value': ','.join(module.params['ports']), 'include': True}, - 'replicas': {'value': module.params['replicas'], 'include': True}, - 'selector': {'value': module.params['selector'], 'include': True}, - 'service_account': {'value': module.params['service_account'], 'include': True}, - 'router_type': {'value': module.params['router_type'], 'include': False}, - 'host_network': {'value': module.params['host_network'], 'include': True}, - 'external_host': {'value': module.params['external_host'], 'include': True}, - 'external_host_vserver': {'value': module.params['external_host_vserver'], - 'include': True}, - 'external_host_insecure': {'value': module.params['external_host_insecure'], - 'include': True}, - 'external_host_partition_path': {'value': module.params['external_host_partition_path'], - 'include': True}, - 'external_host_username': {'value': module.params['external_host_username'], - 'include': True}, - 'external_host_password': {'value': module.params['external_host_password'], - 'include': True}, - 'external_host_private_key': {'value': module.params['external_host_private_key'], - 'include': True}, - 'expose_metrics': {'value': module.params['expose_metrics'], 'include': True}, - 'metrics_image': {'value': module.params['metrics_image'], 'include': True}, - 'stats_user': {'value': module.params['stats_user'], 'include': True}, - 'stats_password': {'value': module.params['stats_password'], 'include': True}, - 'stats_port': {'value': module.params['stats_port'], 'include': True}, - }) - - - ocrouter = Router(rconfig) - - state = module.params['state'] - - ######## - # Delete - ######## - if state == 'absent': - if not ocrouter.exists(): - module.exit_json(changed=False, state="absent") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a delete.') - - api_rval = ocrouter.delete() - module.exit_json(changed=True, results=api_rval, state="absent") - - - if state == 'present': - ######## - # Create - ######## - if not ocrouter.exists(): - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a create.') - - api_rval = ocrouter.create() - - module.exit_json(changed=True, results=api_rval, state="present") - - ######## - # Update - ######## - if not ocrouter.needs_update(): - module.exit_json(changed=False, state="present") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed an update.') - - api_rval = ocrouter.update() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * -main() diff --git a/roles/lib_openshift_api/library/oc_edit.py b/roles/lib_openshift_api/library/oc_edit.py deleted file mode 100644 index e43b6175a..000000000 --- a/roles/lib_openshift_api/library/oc_edit.py +++ /dev/null @@ -1,646 +0,0 @@ -#!/usr/bin/env python -# ___ ___ _ _ ___ ___ _ _____ ___ ___ -# / __| __| \| | __| _ \ /_\_ _| __| \ -# | (_ | _|| .` | _|| / / _ \| | | _|| |) | -# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____ -# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _| -# | |) | (_) | | .` | (_) || | | _|| |) | | | | -# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_| -''' - OpenShiftCLI class that wraps the oc commands in a subprocess -''' - -import atexit -import json -import os -import shutil -import subprocess -import re - -import yaml -# This is here because of a bug that causes yaml -# to incorrectly handle timezone info on timestamps -def timestamp_constructor(_, node): - '''return timestamps as strings''' - return str(node.value) -yaml.add_constructor(u'tag:yaml.org,2002:timestamp', timestamp_constructor) - -# pylint: disable=too-few-public-methods -class OpenShiftCLI(object): - ''' Class to wrap the command line tools ''' - def __init__(self, - namespace, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftCLI ''' - self.namespace = namespace - self.verbose = verbose - self.kubeconfig = kubeconfig - - # Pylint allows only 5 arguments to be passed. - # pylint: disable=too-many-arguments - def _replace_content(self, resource, rname, content, force=False): - ''' replace the current object with the content ''' - res = self._get(resource, rname) - if not res['results']: - return res - - fname = '/tmp/%s' % rname - yed = Yedit(fname, res['results'][0]) - changes = [] - 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, [fname]) - - return self._replace(fname, force) - - def _replace(self, fname, force=False): - '''return all pods ''' - cmd = ['-n', self.namespace, 'replace', '-f', fname] - if force: - cmd.append('--force') - return self.openshift_cmd(cmd) - - def _create(self, fname): - '''return all pods ''' - return self.openshift_cmd(['create', '-f', fname, '-n', self.namespace]) - - def _delete(self, resource, rname): - '''return all pods ''' - return self.openshift_cmd(['delete', resource, rname, '-n', self.namespace]) - - def _get(self, resource, rname=None): - '''return a secret by name ''' - cmd = ['get', resource, '-o', 'json', '-n', self.namespace] - if rname: - cmd.append(rname) - - rval = self.openshift_cmd(cmd, output=True) - - # Ensure results are retuned in an array - if rval.has_key('items'): - rval['results'] = rval['items'] - elif not isinstance(rval['results'], list): - rval['results'] = [rval['results']] - - return rval - - def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json'): - '''Base command for oc ''' - #cmds = ['/usr/bin/oc', '--config', self.kubeconfig] - cmds = [] - if oadm: - cmds = ['/usr/bin/oadm'] - else: - cmds = ['/usr/bin/oc'] - - cmds.extend(cmd) - - rval = {} - results = '' - err = None - - if self.verbose: - print ' '.join(cmds) - - proc = subprocess.Popen(cmds, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env={'KUBECONFIG': self.kubeconfig}) - - proc.wait() - stdout = proc.stdout.read() - stderr = proc.stderr.read() - rval = {"returncode": proc.returncode, - "results": results, - "cmd": ' '.join(cmds), - } - - if proc.returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as err: - if "No JSON object could be decoded" in err.message: - err = err.message - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print stdout - print stderr - print - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds - }) - - else: - rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}, - }) - - return rval - -class Utils(object): - ''' utilities for openshiftcli modules ''' - @staticmethod - def create_file(rname, data, ftype=None): - ''' create a file in tmp with name and contents''' - path = os.path.join('/tmp', rname) - with open(path, 'w') as fds: - if ftype == 'yaml': - fds.write(yaml.safe_dump(data, default_flow_style=False)) - - elif ftype == 'json': - fds.write(json.dumps(data)) - else: - fds.write(data) - - # Register cleanup when module is done - atexit.register(Utils.cleanup, [path]) - return path - - @staticmethod - def create_files_from_contents(data): - '''Turn an array of dict: filename, content into a files array''' - files = [] - - for sfile in data: - path = Utils.create_file(sfile['path'], sfile['content']) - files.append(path) - - return files - - @staticmethod - def cleanup(files): - '''Clean up on exit ''' - for sfile in files: - if os.path.exists(sfile): - if os.path.isdir(sfile): - shutil.rmtree(sfile) - elif os.path.isfile(sfile): - os.remove(sfile) - - - @staticmethod - def exists(results, _name): - ''' Check to see if the results include the name ''' - if not results: - return False - - - if Utils.find_result(results, _name): - return True - - return False - - @staticmethod - def find_result(results, _name): - ''' Find the specified result by name''' - rval = None - for result in results: - if result.has_key('metadata') and result['metadata']['name'] == _name: - rval = result - break - - return rval - - @staticmethod - def get_resource_file(sfile, sfile_type='yaml'): - ''' return the service file ''' - contents = None - with open(sfile) as sfd: - contents = sfd.read() - - if sfile_type == 'yaml': - contents = yaml.safe_load(contents) - elif sfile_type == 'json': - contents = json.loads(contents) - - return contents - - # Disabling too-many-branches. This is a yaml dictionary comparison function - # pylint: disable=too-many-branches,too-many-return-statements - @staticmethod - def check_def_equal(user_def, result_def, skip_keys=None, debug=False): - ''' Given a user defined definition, compare it with the results given back by our query. ''' - - # Currently these values are autogenerated and we do not need to check them - skip = ['metadata', 'status'] - if skip_keys: - skip.extend(skip_keys) - - for key, value in result_def.items(): - if key in skip: - continue - - # Both are lists - if isinstance(value, list): - if not isinstance(user_def[key], list): - if debug: - print 'user_def[key] is not a list' - 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]) - result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug) - if not result: - 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] - return False - - # recurse on a dictionary - elif isinstance(value, dict): - if not isinstance(user_def[key], dict): - if debug: - print "dict returned false not instance of dict" - return False - - # before passing ensure keys match - api_values = set(value.keys()) - set(skip) - user_values = set(user_def[key].keys()) - set(skip) - if api_values != user_values: - if debug: - print api_values - print user_values - print "keys are not equal in dict" - 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 - return False - - # Verify each key, value pair is the same - else: - if not user_def.has_key(key) or value != user_def[key]: - if debug: - print "value not equal; user_def does not have key" - print value - print user_def[key] - return False - - return True - -class YeditException(Exception): - ''' Exception class for Yedit ''' - pass - -class Yedit(object): - ''' Class to modify yaml files ''' - re_valid_key = r"(((\[-?\d+\])|([a-zA-Z-./]+)).?)+$" - re_key = r"(?:\[(-?\d+)\])|([a-zA-Z-./]+)" - - def __init__(self, filename=None, content=None, content_type='yaml'): - self.content = content - self.filename = filename - self.__yaml_dict = content - self.content_type = content_type - if self.filename and not self.content: - self.load(content_type=self.content_type) - - @property - def yaml_dict(self): - ''' getter method for yaml_dict ''' - return self.__yaml_dict - - @yaml_dict.setter - def yaml_dict(self, value): - ''' setter method for yaml_dict ''' - self.__yaml_dict = value - - @staticmethod - def remove_entry(data, key): - ''' remove data at location key ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for remove - # expected list entry - if key_indexes[-1][0]: - if isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - del data[int(key_indexes[-1][0])] - return True - - # expected dict entry - elif key_indexes[-1][1]: - if isinstance(data, dict): - del data[key_indexes[-1][1]] - return True - - @staticmethod - def add_entry(data, key, item=None): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - curr_data = data - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key: - if isinstance(data, dict) and data.has_key(dict_key): - data = data[dict_key] - continue - - data[dict_key] = {} - data = data[dict_key] - - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for add - # expected list entry - if key_indexes[-1][0] and isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - data[int(key_indexes[-1][0])] = item - - # expected dict entry - elif key_indexes[-1][1] and isinstance(data, dict): - data[key_indexes[-1][1]] = item - - return curr_data - - @staticmethod - def get_entry(data, key): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - return data - - def write(self): - ''' write to file ''' - if not self.filename: - raise YeditException('Please specify a filename.') - - with open(self.filename, 'w') as yfd: - yfd.write(yaml.safe_dump(self.yaml_dict, default_flow_style=False)) - - def read(self): - ''' write to file ''' - # check if it exists - if not self.exists(): - return None - - contents = None - with open(self.filename) as yfd: - contents = yfd.read() - - return contents - - def exists(self): - ''' return whether file exists ''' - if os.path.exists(self.filename): - return True - - return False - - def load(self, content_type='yaml'): - ''' return yaml file ''' - contents = self.read() - - if not contents: - return None - - # check if it is yaml - try: - if content_type == 'yaml': - self.yaml_dict = yaml.load(contents) - elif content_type == 'json': - self.yaml_dict = json.loads(contents) - except yaml.YAMLError as _: - # Error loading yaml or json - return None - - return self.yaml_dict - - def get(self, key): - ''' get a specified key''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - return entry - - def delete(self, key): - ''' remove key from a dict''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - if not entry: - return (False, self.yaml_dict) - - result = Yedit.remove_entry(self.yaml_dict, key) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def put(self, key, value): - ''' put key, value into a dict ''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - if entry == value: - return (False, self.yaml_dict) - - result = Yedit.add_entry(self.yaml_dict, key, value) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def create(self, key, value): - ''' create a yaml file ''' - if not self.exists(): - self.yaml_dict = {key: value} - return (True, self.yaml_dict) - - return (False, self.yaml_dict) - -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', - 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.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(file_name, data) - 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) - - - -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']), - 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', - 'svc', 'service', - 'scc', 'securitycontextconstraints', - 'ns', 'namespace', 'project', 'projects', - 'is', 'imagestream', - 'istag', 'imagestreamtag', - 'bc', 'buildconfig', - 'routes', - 'node', - 'secret', - ]), - 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'), - ), - supports_check_mode=True, - ) - ocedit = Edit(module.params['kind'], - module.params['namespace'], - module.params['name'], - kubeconfig=module.params['kubeconfig'], - verbose=module.params['debug']) - - state = module.params['state'] - - api_rval = ocedit.get() - - ######## - # Create - ######## - if not Utils.exists(api_rval['results'], module.params['name']): - module.fail_json(msg=api_rval) - - ######## - # Update - ######## - api_rval = ocedit.update(module.params['file_name'], - module.params['content'], - module.params['force'], - module.params['file_format']) - - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - if api_rval.has_key('updated') and not api_rval['updated']: - module.exit_json(changed=False, results=api_rval, state="present") - - # return the created object - api_rval = ocedit.get() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * - -main() diff --git a/roles/lib_openshift_api/library/oc_obj.py b/roles/lib_openshift_api/library/oc_obj.py deleted file mode 100644 index f0ea66aee..000000000 --- a/roles/lib_openshift_api/library/oc_obj.py +++ /dev/null @@ -1,730 +0,0 @@ -#!/usr/bin/env python -# ___ ___ _ _ ___ ___ _ _____ ___ ___ -# / __| __| \| | __| _ \ /_\_ _| __| \ -# | (_ | _|| .` | _|| / / _ \| | | _|| |) | -# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____ -# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _| -# | |) | (_) | | .` | (_) || | | _|| |) | | | | -# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_| -''' - OpenShiftCLI class that wraps the oc commands in a subprocess -''' - -import atexit -import json -import os -import shutil -import subprocess -import re - -import yaml -# This is here because of a bug that causes yaml -# to incorrectly handle timezone info on timestamps -def timestamp_constructor(_, node): - '''return timestamps as strings''' - return str(node.value) -yaml.add_constructor(u'tag:yaml.org,2002:timestamp', timestamp_constructor) - -# pylint: disable=too-few-public-methods -class OpenShiftCLI(object): - ''' Class to wrap the command line tools ''' - def __init__(self, - namespace, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftCLI ''' - self.namespace = namespace - self.verbose = verbose - self.kubeconfig = kubeconfig - - # Pylint allows only 5 arguments to be passed. - # pylint: disable=too-many-arguments - def _replace_content(self, resource, rname, content, force=False): - ''' replace the current object with the content ''' - res = self._get(resource, rname) - if not res['results']: - return res - - fname = '/tmp/%s' % rname - yed = Yedit(fname, res['results'][0]) - changes = [] - 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, [fname]) - - return self._replace(fname, force) - - def _replace(self, fname, force=False): - '''return all pods ''' - cmd = ['-n', self.namespace, 'replace', '-f', fname] - if force: - cmd.append('--force') - return self.openshift_cmd(cmd) - - def _create(self, fname): - '''return all pods ''' - return self.openshift_cmd(['create', '-f', fname, '-n', self.namespace]) - - def _delete(self, resource, rname): - '''return all pods ''' - return self.openshift_cmd(['delete', resource, rname, '-n', self.namespace]) - - def _get(self, resource, rname=None): - '''return a secret by name ''' - cmd = ['get', resource, '-o', 'json', '-n', self.namespace] - if rname: - cmd.append(rname) - - rval = self.openshift_cmd(cmd, output=True) - - # Ensure results are retuned in an array - if rval.has_key('items'): - rval['results'] = rval['items'] - elif not isinstance(rval['results'], list): - rval['results'] = [rval['results']] - - return rval - - def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json'): - '''Base command for oc ''' - #cmds = ['/usr/bin/oc', '--config', self.kubeconfig] - cmds = [] - if oadm: - cmds = ['/usr/bin/oadm'] - else: - cmds = ['/usr/bin/oc'] - - cmds.extend(cmd) - - rval = {} - results = '' - err = None - - if self.verbose: - print ' '.join(cmds) - - proc = subprocess.Popen(cmds, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env={'KUBECONFIG': self.kubeconfig}) - - proc.wait() - stdout = proc.stdout.read() - stderr = proc.stderr.read() - rval = {"returncode": proc.returncode, - "results": results, - "cmd": ' '.join(cmds), - } - - if proc.returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as err: - if "No JSON object could be decoded" in err.message: - err = err.message - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print stdout - print stderr - print - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds - }) - - else: - rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}, - }) - - return rval - -class Utils(object): - ''' utilities for openshiftcli modules ''' - @staticmethod - def create_file(rname, data, ftype=None): - ''' create a file in tmp with name and contents''' - path = os.path.join('/tmp', rname) - with open(path, 'w') as fds: - if ftype == 'yaml': - fds.write(yaml.safe_dump(data, default_flow_style=False)) - - elif ftype == 'json': - fds.write(json.dumps(data)) - else: - fds.write(data) - - # Register cleanup when module is done - atexit.register(Utils.cleanup, [path]) - return path - - @staticmethod - def create_files_from_contents(data): - '''Turn an array of dict: filename, content into a files array''' - files = [] - - for sfile in data: - path = Utils.create_file(sfile['path'], sfile['content']) - files.append(path) - - return files - - @staticmethod - def cleanup(files): - '''Clean up on exit ''' - for sfile in files: - if os.path.exists(sfile): - if os.path.isdir(sfile): - shutil.rmtree(sfile) - elif os.path.isfile(sfile): - os.remove(sfile) - - - @staticmethod - def exists(results, _name): - ''' Check to see if the results include the name ''' - if not results: - return False - - - if Utils.find_result(results, _name): - return True - - return False - - @staticmethod - def find_result(results, _name): - ''' Find the specified result by name''' - rval = None - for result in results: - if result.has_key('metadata') and result['metadata']['name'] == _name: - rval = result - break - - return rval - - @staticmethod - def get_resource_file(sfile, sfile_type='yaml'): - ''' return the service file ''' - contents = None - with open(sfile) as sfd: - contents = sfd.read() - - if sfile_type == 'yaml': - contents = yaml.safe_load(contents) - elif sfile_type == 'json': - contents = json.loads(contents) - - return contents - - # Disabling too-many-branches. This is a yaml dictionary comparison function - # pylint: disable=too-many-branches,too-many-return-statements - @staticmethod - def check_def_equal(user_def, result_def, skip_keys=None, debug=False): - ''' Given a user defined definition, compare it with the results given back by our query. ''' - - # Currently these values are autogenerated and we do not need to check them - skip = ['metadata', 'status'] - if skip_keys: - skip.extend(skip_keys) - - for key, value in result_def.items(): - if key in skip: - continue - - # Both are lists - if isinstance(value, list): - if not isinstance(user_def[key], list): - if debug: - print 'user_def[key] is not a list' - 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]) - result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug) - if not result: - 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] - return False - - # recurse on a dictionary - elif isinstance(value, dict): - if not isinstance(user_def[key], dict): - if debug: - print "dict returned false not instance of dict" - return False - - # before passing ensure keys match - api_values = set(value.keys()) - set(skip) - user_values = set(user_def[key].keys()) - set(skip) - if api_values != user_values: - if debug: - print api_values - print user_values - print "keys are not equal in dict" - 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 - return False - - # Verify each key, value pair is the same - else: - if not user_def.has_key(key) or value != user_def[key]: - if debug: - print "value not equal; user_def does not have key" - print value - print user_def[key] - return False - - return True - -class YeditException(Exception): - ''' Exception class for Yedit ''' - pass - -class Yedit(object): - ''' Class to modify yaml files ''' - re_valid_key = r"(((\[-?\d+\])|([a-zA-Z-./]+)).?)+$" - re_key = r"(?:\[(-?\d+)\])|([a-zA-Z-./]+)" - - def __init__(self, filename=None, content=None, content_type='yaml'): - self.content = content - self.filename = filename - self.__yaml_dict = content - self.content_type = content_type - if self.filename and not self.content: - self.load(content_type=self.content_type) - - @property - def yaml_dict(self): - ''' getter method for yaml_dict ''' - return self.__yaml_dict - - @yaml_dict.setter - def yaml_dict(self, value): - ''' setter method for yaml_dict ''' - self.__yaml_dict = value - - @staticmethod - def remove_entry(data, key): - ''' remove data at location key ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for remove - # expected list entry - if key_indexes[-1][0]: - if isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - del data[int(key_indexes[-1][0])] - return True - - # expected dict entry - elif key_indexes[-1][1]: - if isinstance(data, dict): - del data[key_indexes[-1][1]] - return True - - @staticmethod - def add_entry(data, key, item=None): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - curr_data = data - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key: - if isinstance(data, dict) and data.has_key(dict_key): - data = data[dict_key] - continue - - data[dict_key] = {} - data = data[dict_key] - - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for add - # expected list entry - if key_indexes[-1][0] and isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - data[int(key_indexes[-1][0])] = item - - # expected dict entry - elif key_indexes[-1][1] and isinstance(data, dict): - data[key_indexes[-1][1]] = item - - return curr_data - - @staticmethod - def get_entry(data, key): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - return data - - def write(self): - ''' write to file ''' - if not self.filename: - raise YeditException('Please specify a filename.') - - with open(self.filename, 'w') as yfd: - yfd.write(yaml.safe_dump(self.yaml_dict, default_flow_style=False)) - - def read(self): - ''' write to file ''' - # check if it exists - if not self.exists(): - return None - - contents = None - with open(self.filename) as yfd: - contents = yfd.read() - - return contents - - def exists(self): - ''' return whether file exists ''' - if os.path.exists(self.filename): - return True - - return False - - def load(self, content_type='yaml'): - ''' return yaml file ''' - contents = self.read() - - if not contents: - return None - - # check if it is yaml - try: - if content_type == 'yaml': - self.yaml_dict = yaml.load(contents) - elif content_type == 'json': - self.yaml_dict = json.loads(contents) - except yaml.YAMLError as _: - # Error loading yaml or json - return None - - return self.yaml_dict - - def get(self, key): - ''' get a specified key''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - return entry - - def delete(self, key): - ''' remove key from a dict''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - if not entry: - return (False, self.yaml_dict) - - result = Yedit.remove_entry(self.yaml_dict, key) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def put(self, key, value): - ''' put key, value into a dict ''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - if entry == value: - return (False, self.yaml_dict) - - result = Yedit.add_entry(self.yaml_dict, key, value) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def create(self, key, value): - ''' create a yaml file ''' - if not self.exists(): - self.yaml_dict = {key: value} - return (True, self.yaml_dict) - - return (False, self.yaml_dict) - -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, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftOC ''' - super(OCObject, self).__init__(namespace, kubeconfig) - self.kind = kind - self.namespace = namespace - self.name = rname - self.kubeconfig = kubeconfig - self.verbose = verbose - - def get(self): - '''return a deploymentconfig by name ''' - return self._get(self.kind, rname=self.name) - - def delete(self): - '''return all pods ''' - return self._delete(self.kind, self.name) - - def create(self, files=None, content=None): - '''Create a deploymentconfig ''' - if files: - return self._create(files[0]) - - return self._create(Utils.create_files_from_contents(content)) - - - # pylint: disable=too-many-function-args - def update(self, files=None, content=None, force=False): - '''run update dc - - This receives a list of file names and takes the first filename and calls replace. - ''' - if files: - return self._replace(files[0], force) - - return self.update_content(content, force) - - def update_content(self, content, force=False): - '''update the dc with the content''' - 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) - - # 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) - else: - data = content - - for key, value in data.items(): - if key == 'metadata': - continue - if not objects['results'][0].has_key(key): - return True - if value != objects['results'][0][key]: - return True - - return False - - -# 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'), - name=dict(default=None, type='str'), - files=dict(default=None, type='list'), - kind=dict(required=True, - type='str', - choices=['dc', 'deploymentconfig', - 'svc', 'service', - 'scc', 'securitycontextconstraints', - 'ns', 'namespace', 'project', 'projects', - 'is', 'imagestream', - 'istag', 'imagestreamtag', - 'bc', 'buildconfig', - 'routes', - 'node', - 'secret', - ]), - delete_after=dict(default=False, type='bool'), - content=dict(default=None, type='dict'), - force=dict(default=False, type='bool'), - ), - mutually_exclusive=[["content", "files"]], - - supports_check_mode=True, - ) - ocobj = OCObject(module.params['kind'], - module.params['namespace'], - module.params['name'], - kubeconfig=module.params['kubeconfig'], - verbose=module.params['debug']) - - state = module.params['state'] - - api_rval = ocobj.get() - - ##### - # Get - ##### - if state == 'list': - module.exit_json(changed=False, results=api_rval['results'], state="list") - - if not module.params['name']: - module.fail_json(msg='Please specify a name when state is absent|present.') - ######## - # Delete - ######## - if state == 'absent': - if not Utils.exists(api_rval['results'], module.params['name']): - module.exit_json(changed=False, state="absent") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a delete.') - - api_rval = ocobj.delete() - module.exit_json(changed=True, results=api_rval, state="absent") - - if state == 'present': - ######## - # Create - ######## - if not Utils.exists(api_rval['results'], module.params['name']): - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a create.') - - # Create it here - api_rval = ocobj.create(module.params['files'], module.params['content']) - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - # return the created object - api_rval = ocobj.get() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - # Remove files - if module.params['files'] and module.params['delete_after']: - Utils.cleanup(module.params['files']) - - module.exit_json(changed=True, results=api_rval, state="present") - - ######## - # Update - ######## - # if a file path is passed, use it. - update = ocobj.needs_update(module.params['files'], module.params['content']) - if not isinstance(update, bool): - module.fail_json(msg=update) - - # No changes - if not update: - if module.params['files'] and module.params['delete_after']: - Utils.cleanup(module.params['files']) - - module.exit_json(changed=False, results=api_rval['results'][0], state="present") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed an update.') - - api_rval = ocobj.update(module.params['files'], - module.params['content'], - module.params['force']) - - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - # return the created object - api_rval = ocobj.get() - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * - -main() diff --git a/roles/lib_openshift_api/library/oc_secret.py b/roles/lib_openshift_api/library/oc_secret.py deleted file mode 100644 index ca58d7139..000000000 --- a/roles/lib_openshift_api/library/oc_secret.py +++ /dev/null @@ -1,702 +0,0 @@ -#!/usr/bin/env python -# ___ ___ _ _ ___ ___ _ _____ ___ ___ -# / __| __| \| | __| _ \ /_\_ _| __| \ -# | (_ | _|| .` | _|| / / _ \| | | _|| |) | -# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____ -# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _| -# | |) | (_) | | .` | (_) || | | _|| |) | | | | -# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_| -''' - OpenShiftCLI class that wraps the oc commands in a subprocess -''' - -import atexit -import json -import os -import shutil -import subprocess -import re - -import yaml -# This is here because of a bug that causes yaml -# to incorrectly handle timezone info on timestamps -def timestamp_constructor(_, node): - '''return timestamps as strings''' - return str(node.value) -yaml.add_constructor(u'tag:yaml.org,2002:timestamp', timestamp_constructor) - -# pylint: disable=too-few-public-methods -class OpenShiftCLI(object): - ''' Class to wrap the command line tools ''' - def __init__(self, - namespace, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftCLI ''' - self.namespace = namespace - self.verbose = verbose - self.kubeconfig = kubeconfig - - # Pylint allows only 5 arguments to be passed. - # pylint: disable=too-many-arguments - def _replace_content(self, resource, rname, content, force=False): - ''' replace the current object with the content ''' - res = self._get(resource, rname) - if not res['results']: - return res - - fname = '/tmp/%s' % rname - yed = Yedit(fname, res['results'][0]) - changes = [] - 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, [fname]) - - return self._replace(fname, force) - - def _replace(self, fname, force=False): - '''return all pods ''' - cmd = ['-n', self.namespace, 'replace', '-f', fname] - if force: - cmd.append('--force') - return self.openshift_cmd(cmd) - - def _create(self, fname): - '''return all pods ''' - return self.openshift_cmd(['create', '-f', fname, '-n', self.namespace]) - - def _delete(self, resource, rname): - '''return all pods ''' - return self.openshift_cmd(['delete', resource, rname, '-n', self.namespace]) - - def _get(self, resource, rname=None): - '''return a secret by name ''' - cmd = ['get', resource, '-o', 'json', '-n', self.namespace] - if rname: - cmd.append(rname) - - rval = self.openshift_cmd(cmd, output=True) - - # Ensure results are retuned in an array - if rval.has_key('items'): - rval['results'] = rval['items'] - elif not isinstance(rval['results'], list): - rval['results'] = [rval['results']] - - return rval - - def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json'): - '''Base command for oc ''' - #cmds = ['/usr/bin/oc', '--config', self.kubeconfig] - cmds = [] - if oadm: - cmds = ['/usr/bin/oadm'] - else: - cmds = ['/usr/bin/oc'] - - cmds.extend(cmd) - - rval = {} - results = '' - err = None - - if self.verbose: - print ' '.join(cmds) - - proc = subprocess.Popen(cmds, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env={'KUBECONFIG': self.kubeconfig}) - - proc.wait() - stdout = proc.stdout.read() - stderr = proc.stderr.read() - rval = {"returncode": proc.returncode, - "results": results, - "cmd": ' '.join(cmds), - } - - if proc.returncode == 0: - if output: - if output_type == 'json': - try: - rval['results'] = json.loads(stdout) - except ValueError as err: - if "No JSON object could be decoded" in err.message: - err = err.message - elif output_type == 'raw': - rval['results'] = stdout - - if self.verbose: - print stdout - print stderr - print - - if err: - rval.update({"err": err, - "stderr": stderr, - "stdout": stdout, - "cmd": cmds - }) - - else: - rval.update({"stderr": stderr, - "stdout": stdout, - "results": {}, - }) - - return rval - -class Utils(object): - ''' utilities for openshiftcli modules ''' - @staticmethod - def create_file(rname, data, ftype=None): - ''' create a file in tmp with name and contents''' - path = os.path.join('/tmp', rname) - with open(path, 'w') as fds: - if ftype == 'yaml': - fds.write(yaml.safe_dump(data, default_flow_style=False)) - - elif ftype == 'json': - fds.write(json.dumps(data)) - else: - fds.write(data) - - # Register cleanup when module is done - atexit.register(Utils.cleanup, [path]) - return path - - @staticmethod - def create_files_from_contents(data): - '''Turn an array of dict: filename, content into a files array''' - files = [] - - for sfile in data: - path = Utils.create_file(sfile['path'], sfile['content']) - files.append(path) - - return files - - @staticmethod - def cleanup(files): - '''Clean up on exit ''' - for sfile in files: - if os.path.exists(sfile): - if os.path.isdir(sfile): - shutil.rmtree(sfile) - elif os.path.isfile(sfile): - os.remove(sfile) - - - @staticmethod - def exists(results, _name): - ''' Check to see if the results include the name ''' - if not results: - return False - - - if Utils.find_result(results, _name): - return True - - return False - - @staticmethod - def find_result(results, _name): - ''' Find the specified result by name''' - rval = None - for result in results: - if result.has_key('metadata') and result['metadata']['name'] == _name: - rval = result - break - - return rval - - @staticmethod - def get_resource_file(sfile, sfile_type='yaml'): - ''' return the service file ''' - contents = None - with open(sfile) as sfd: - contents = sfd.read() - - if sfile_type == 'yaml': - contents = yaml.safe_load(contents) - elif sfile_type == 'json': - contents = json.loads(contents) - - return contents - - # Disabling too-many-branches. This is a yaml dictionary comparison function - # pylint: disable=too-many-branches,too-many-return-statements - @staticmethod - def check_def_equal(user_def, result_def, skip_keys=None, debug=False): - ''' Given a user defined definition, compare it with the results given back by our query. ''' - - # Currently these values are autogenerated and we do not need to check them - skip = ['metadata', 'status'] - if skip_keys: - skip.extend(skip_keys) - - for key, value in result_def.items(): - if key in skip: - continue - - # Both are lists - if isinstance(value, list): - if not isinstance(user_def[key], list): - if debug: - print 'user_def[key] is not a list' - 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]) - result = Utils.check_def_equal(values[0], values[1], skip_keys=skip_keys, debug=debug) - if not result: - 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] - return False - - # recurse on a dictionary - elif isinstance(value, dict): - if not isinstance(user_def[key], dict): - if debug: - print "dict returned false not instance of dict" - return False - - # before passing ensure keys match - api_values = set(value.keys()) - set(skip) - user_values = set(user_def[key].keys()) - set(skip) - if api_values != user_values: - if debug: - print api_values - print user_values - print "keys are not equal in dict" - 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 - return False - - # Verify each key, value pair is the same - else: - if not user_def.has_key(key) or value != user_def[key]: - if debug: - print "value not equal; user_def does not have key" - print value - print user_def[key] - return False - - return True - -class YeditException(Exception): - ''' Exception class for Yedit ''' - pass - -class Yedit(object): - ''' Class to modify yaml files ''' - re_valid_key = r"(((\[-?\d+\])|([a-zA-Z-./]+)).?)+$" - re_key = r"(?:\[(-?\d+)\])|([a-zA-Z-./]+)" - - def __init__(self, filename=None, content=None, content_type='yaml'): - self.content = content - self.filename = filename - self.__yaml_dict = content - self.content_type = content_type - if self.filename and not self.content: - self.load(content_type=self.content_type) - - @property - def yaml_dict(self): - ''' getter method for yaml_dict ''' - return self.__yaml_dict - - @yaml_dict.setter - def yaml_dict(self, value): - ''' setter method for yaml_dict ''' - self.__yaml_dict = value - - @staticmethod - def remove_entry(data, key): - ''' remove data at location key ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for remove - # expected list entry - if key_indexes[-1][0]: - if isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - del data[int(key_indexes[-1][0])] - return True - - # expected dict entry - elif key_indexes[-1][1]: - if isinstance(data, dict): - del data[key_indexes[-1][1]] - return True - - @staticmethod - def add_entry(data, key, item=None): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - curr_data = data - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes[:-1]: - if dict_key: - if isinstance(data, dict) and data.has_key(dict_key): - data = data[dict_key] - continue - - data[dict_key] = {} - data = data[dict_key] - - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - # process last index for add - # expected list entry - if key_indexes[-1][0] and isinstance(data, list) and int(key_indexes[-1][0]) <= len(data) - 1: - data[int(key_indexes[-1][0])] = item - - # expected dict entry - elif key_indexes[-1][1] and isinstance(data, dict): - data[key_indexes[-1][1]] = item - - return curr_data - - @staticmethod - def get_entry(data, key): - ''' Get an item from a dictionary with key notation a.b.c - d = {'a': {'b': 'c'}}} - key = a.b - return c - ''' - if not (key and re.match(Yedit.re_valid_key, key) and isinstance(data, (list, dict))): - return None - - key_indexes = re.findall(Yedit.re_key, key) - for arr_ind, dict_key in key_indexes: - if dict_key and isinstance(data, dict): - data = data.get(dict_key, None) - elif arr_ind and isinstance(data, list) and int(arr_ind) <= len(data) - 1: - data = data[int(arr_ind)] - else: - return None - - return data - - def write(self): - ''' write to file ''' - if not self.filename: - raise YeditException('Please specify a filename.') - - with open(self.filename, 'w') as yfd: - yfd.write(yaml.safe_dump(self.yaml_dict, default_flow_style=False)) - - def read(self): - ''' write to file ''' - # check if it exists - if not self.exists(): - return None - - contents = None - with open(self.filename) as yfd: - contents = yfd.read() - - return contents - - def exists(self): - ''' return whether file exists ''' - if os.path.exists(self.filename): - return True - - return False - - def load(self, content_type='yaml'): - ''' return yaml file ''' - contents = self.read() - - if not contents: - return None - - # check if it is yaml - try: - if content_type == 'yaml': - self.yaml_dict = yaml.load(contents) - elif content_type == 'json': - self.yaml_dict = json.loads(contents) - except yaml.YAMLError as _: - # Error loading yaml or json - return None - - return self.yaml_dict - - def get(self, key): - ''' get a specified key''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - return entry - - def delete(self, key): - ''' remove key from a dict''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - if not entry: - return (False, self.yaml_dict) - - result = Yedit.remove_entry(self.yaml_dict, key) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def put(self, key, value): - ''' put key, value into a dict ''' - try: - entry = Yedit.get_entry(self.yaml_dict, key) - except KeyError as _: - entry = None - - if entry == value: - return (False, self.yaml_dict) - - result = Yedit.add_entry(self.yaml_dict, key, value) - if not result: - return (False, self.yaml_dict) - - return (True, self.yaml_dict) - - def create(self, key, value): - ''' create a yaml file ''' - if not self.exists(): - self.yaml_dict = {key: value} - return (True, self.yaml_dict) - - return (False, self.yaml_dict) - -class Secret(OpenShiftCLI): - ''' Class to wrap the oc command line tools - ''' - def __init__(self, - namespace, - secret_name=None, - kubeconfig='/etc/origin/master/admin.kubeconfig', - verbose=False): - ''' Constructor for OpenshiftOC ''' - super(Secret, self).__init__(namespace, kubeconfig) - self.namespace = namespace - self.name = secret_name - self.kubeconfig = kubeconfig - self.verbose = verbose - - def get(self): - '''return a secret by name ''' - return self._get('secrets', self.name) - - def delete(self): - '''delete a secret by name''' - return self._delete('secrets', self.name) - - def create(self, files=None, contents=None): - '''Create a secret ''' - if not files: - files = Utils.create_files_from_contents(contents) - - secrets = ["%s=%s" % (os.path.basename(sfile), sfile) for sfile in files] - cmd = ['-n%s' % self.namespace, 'secrets', 'new', self.name] - cmd.extend(secrets) - - return self.openshift_cmd(cmd) - - def update(self, files, force=False): - '''run update secret - - This receives a list of file names and converts it into a secret. - The secret is then written to disk and passed into the `oc replace` command. - ''' - secret = self.prep_secret(files) - if secret['returncode'] != 0: - return secret - - sfile_path = '/tmp/%s' % self.name - with open(sfile_path, 'w') as sfd: - sfd.write(json.dumps(secret['results'])) - - atexit.register(Utils.cleanup, [sfile_path]) - - return self._replace(sfile_path, force=force) - - def prep_secret(self, files=None, contents=None): - ''' return what the secret would look like if created - This is accomplished by passing -ojson. This will most likely change in the future - ''' - if not files: - files = Utils.create_files_from_contents(contents) - - secrets = ["%s=%s" % (os.path.basename(sfile), sfile) for sfile in files] - cmd = ['-ojson', '-n%s' % self.namespace, 'secrets', 'new', self.name] - cmd.extend(secrets) - - return self.openshift_cmd(cmd, output=True) - - - -# pylint: disable=too-many-branches -def main(): - ''' - ansible oc module for secrets - ''' - - 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'), - name=dict(default=None, type='str'), - files=dict(default=None, type='list'), - delete_after=dict(default=False, type='bool'), - contents=dict(default=None, type='list'), - force=dict(default=False, type='bool'), - ), - mutually_exclusive=[["contents", "files"]], - - supports_check_mode=True, - ) - occmd = Secret(module.params['namespace'], - module.params['name'], - kubeconfig=module.params['kubeconfig'], - verbose=module.params['debug']) - - state = module.params['state'] - - api_rval = occmd.get() - - ##### - # Get - ##### - if state == 'list': - module.exit_json(changed=False, results=api_rval['results'], state="list") - - if not module.params['name']: - module.fail_json(msg='Please specify a name when state is absent|present.') - ######## - # Delete - ######## - if state == 'absent': - if not Utils.exists(api_rval['results'], module.params['name']): - module.exit_json(changed=False, state="absent") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a delete.') - - api_rval = occmd.delete() - module.exit_json(changed=True, results=api_rval, state="absent") - - - if state == 'present': - if module.params['files']: - files = module.params['files'] - elif module.params['contents']: - files = Utils.create_files_from_contents(module.params['contents']) - else: - module.fail_json(msg='Either specify files or contents.') - - ######## - # Create - ######## - if not Utils.exists(api_rval['results'], module.params['name']): - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed a create.') - - api_rval = occmd.create(module.params['files'], module.params['contents']) - - # Remove files - if files and module.params['delete_after']: - Utils.cleanup(files) - - module.exit_json(changed=True, results=api_rval, state="present") - - ######## - # Update - ######## - secret = occmd.prep_secret(module.params['files'], module.params['contents']) - - if secret['returncode'] != 0: - module.fail_json(msg=secret) - - if Utils.check_def_equal(secret['results'], api_rval['results'][0]): - - # Remove files - if files and module.params['delete_after']: - Utils.cleanup(files) - - module.exit_json(changed=False, results=secret['results'], state="present") - - if module.check_mode: - module.exit_json(change=False, msg='Would have performed an update.') - - api_rval = occmd.update(files, force=module.params['force']) - - # Remove files - if secret and module.params['delete_after']: - Utils.cleanup(files) - - if api_rval['returncode'] != 0: - module.fail_json(msg=api_rval) - - - module.exit_json(changed=True, results=api_rval, state="present") - - module.exit_json(failed=True, - changed=False, - results='Unknown state passed. %s' % state, - state="unknown") - -# pylint: disable=redefined-builtin, unused-wildcard-import, wildcard-import, locally-disabled -# import module snippets. This are required -from ansible.module_utils.basic import * - -main() -- cgit v1.2.3