summaryrefslogtreecommitdiffstats
path: root/roles/lib_openshift_api/build
diff options
context:
space:
mode:
Diffstat (limited to 'roles/lib_openshift_api/build')
-rw-r--r--roles/lib_openshift_api/build/ansible/router.py142
-rwxr-xr-xroles/lib_openshift_api/build/generate.py5
-rw-r--r--roles/lib_openshift_api/build/src/base.py65
-rw-r--r--roles/lib_openshift_api/build/src/obj.py2
-rw-r--r--roles/lib_openshift_api/build/src/router.py152
-rw-r--r--roles/lib_openshift_api/build/src/secret.py4
-rwxr-xr-xroles/lib_openshift_api/build/test/router.yml79
7 files changed, 427 insertions, 22 deletions
diff --git a/roles/lib_openshift_api/build/ansible/router.py b/roles/lib_openshift_api/build/ansible/router.py
new file mode 100644
index 000000000..3b24c7b5e
--- /dev/null
+++ b/roles/lib_openshift_api/build/ansible/router.py
@@ -0,0 +1,142 @@
+# 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/generate.py b/roles/lib_openshift_api/build/generate.py
index cf3f61d2c..9fc1986f1 100755
--- a/roles/lib_openshift_api/build/generate.py
+++ b/roles/lib_openshift_api/build/generate.py
@@ -33,6 +33,11 @@ FILES = {'oc_obj.py': ['src/base.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',
+ ],
}
diff --git a/roles/lib_openshift_api/build/src/base.py b/roles/lib_openshift_api/build/src/base.py
index 66831c4e2..257379d92 100644
--- a/roles/lib_openshift_api/build/src/base.py
+++ b/roles/lib_openshift_api/build/src/base.py
@@ -20,12 +20,12 @@ yaml.add_constructor(u'tag:yaml.org,2002:timestamp', timestamp_constructor)
# pylint: disable=too-few-public-methods
class OpenShiftCLI(object):
- ''' Class to wrap the oc command line tools '''
+ ''' Class to wrap the command line tools '''
def __init__(self,
namespace,
kubeconfig='/etc/origin/master/admin.kubeconfig',
verbose=False):
- ''' Constructor for OpenshiftOC '''
+ ''' Constructor for OpenshiftCLI '''
self.namespace = namespace
self.verbose = verbose
self.kubeconfig = kubeconfig
@@ -58,15 +58,15 @@ class OpenShiftCLI(object):
cmd = ['-n', self.namespace, 'replace', '-f', fname]
if force:
cmd.append('--force')
- return self.oc_cmd(cmd)
+ return self.openshift_cmd(cmd)
def _create(self, fname):
'''return all pods '''
- return self.oc_cmd(['create', '-f', fname, '-n', self.namespace])
+ return self.openshift_cmd(['create', '-f', fname, '-n', self.namespace])
def _delete(self, resource, rname):
'''return all pods '''
- return self.oc_cmd(['delete', resource, rname, '-n', self.namespace])
+ return self.openshift_cmd(['delete', resource, rname, '-n', self.namespace])
def _get(self, resource, rname=None):
'''return a secret by name '''
@@ -74,7 +74,7 @@ class OpenShiftCLI(object):
if rname:
cmd.append(rname)
- rval = self.oc_cmd(cmd, output=True)
+ rval = self.openshift_cmd(cmd, output=True)
# Ensure results are retuned in an array
if rval.has_key('items'):
@@ -84,10 +84,15 @@ class OpenShiftCLI(object):
return rval
- def oc_cmd(self, cmd, output=False):
+ def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json'):
'''Base command for oc '''
#cmds = ['/usr/bin/oc', '--config', self.kubeconfig]
- cmds = ['/usr/bin/oc']
+ cmds = []
+ if oadm:
+ cmds = ['/usr/bin/oadm']
+ else:
+ cmds = ['/usr/bin/oc']
+
cmds.extend(cmd)
rval = {}
@@ -105,18 +110,21 @@ class OpenShiftCLI(object):
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:
- try:
- rval['results'] = json.loads(stdout)
- except ValueError as err:
- if "No JSON object could be decoded" in err.message:
- err = err.message
+ 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
@@ -219,11 +227,13 @@ class Utils(object):
# 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, debug=False):
+ 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:
@@ -232,11 +242,27 @@ class Utils(object):
# 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
- # lists should be identical
- if value != user_def[key]:
- 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):
@@ -255,10 +281,11 @@ class Utils(object):
print "keys are not equal in dict"
return False
- result = Utils.check_def_equal(user_def[key], value, debug=debug)
+ 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
diff --git a/roles/lib_openshift_api/build/src/obj.py b/roles/lib_openshift_api/build/src/obj.py
index a3ad4b3c4..13aeba8e1 100644
--- a/roles/lib_openshift_api/build/src/obj.py
+++ b/roles/lib_openshift_api/build/src/obj.py
@@ -62,7 +62,7 @@ class OCObject(OpenShiftCLI):
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], True)
+ return not Utils.check_def_equal(data, objects['results'][0], skip_keys=None, debug=False)
else:
data = content
diff --git a/roles/lib_openshift_api/build/src/router.py b/roles/lib_openshift_api/build/src/router.py
new file mode 100644
index 000000000..69454d594
--- /dev/null
+++ b/roles/lib_openshift_api/build/src/router.py
@@ -0,0 +1,152 @@
+# 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
index af61dfa01..154716828 100644
--- a/roles/lib_openshift_api/build/src/secret.py
+++ b/roles/lib_openshift_api/build/src/secret.py
@@ -32,7 +32,7 @@ class Secret(OpenShiftCLI):
cmd = ['-n%s' % self.namespace, 'secrets', 'new', self.name]
cmd.extend(secrets)
- return self.oc_cmd(cmd)
+ return self.openshift_cmd(cmd)
def update(self, files, force=False):
'''run update secret
@@ -63,6 +63,6 @@ class Secret(OpenShiftCLI):
cmd = ['-ojson', '-n%s' % self.namespace, 'secrets', 'new', self.name]
cmd.extend(secrets)
- return self.oc_cmd(cmd, output=True)
+ return self.openshift_cmd(cmd, output=True)
diff --git a/roles/lib_openshift_api/build/test/router.yml b/roles/lib_openshift_api/build/test/router.yml
new file mode 100755
index 000000000..7ab192b97
--- /dev/null
+++ b/roles/lib_openshift_api/build/test/router.yml
@@ -0,0 +1,79 @@
+#!/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