summaryrefslogtreecommitdiffstats
path: root/roles/lib_openshift_api/library/oc_secret.py
diff options
context:
space:
mode:
Diffstat (limited to 'roles/lib_openshift_api/library/oc_secret.py')
-rw-r--r--roles/lib_openshift_api/library/oc_secret.py231
1 files changed, 208 insertions, 23 deletions
diff --git a/roles/lib_openshift_api/library/oc_secret.py b/roles/lib_openshift_api/library/oc_secret.py
index 96a0f1db1..985ff8bfa 100644
--- a/roles/lib_openshift_api/library/oc_secret.py
+++ b/roles/lib_openshift_api/library/oc_secret.py
@@ -1,7 +1,15 @@
-#!/usr/bin/env python
+#!usr/bin/env python
+# ___ ___ _ _ ___ ___ _ _____ ___ ___
+# / __| __| \| | __| _ \ /_\_ _| __| \
+# | (_ | _|| .` | _|| / / _ \| | | _|| |) |
+# \___|___|_|\_|___|_|_\/_/_\_\_|_|___|___/_ _____
+# | \ / _ \ | \| |/ _ \_ _| | __| \_ _|_ _|
+# | |) | (_) | | .` | (_) || | | _|| |) | | | |
+# |___/ \___/ |_|\_|\___/ |_| |___|___/___| |_|
'''
- OpenShiftCLI class that wraps the oc commands in a subprocess
+ OpenShiftCLI class that wraps the oc commands in a subprocess
'''
+
import atexit
import json
import os
@@ -9,6 +17,7 @@ import shutil
import subprocess
import yaml
+# pylint: disable=too-few-public-methods
class OpenShiftCLI(object):
''' Class to wrap the oc command line tools '''
def __init__(self,
@@ -20,22 +29,39 @@ class OpenShiftCLI(object):
self.verbose = verbose
self.kubeconfig = kubeconfig
- def replace(self, fname, force=False):
+ # 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])
+ for key, value in content.items():
+ yed.put(key, value)
+
+ atexit.register(Utils.cleanup, [fname])
+
+ return self._replace(fname, force)
+
+ def _replace(self, fname, force=False):
'''return all pods '''
- cmd = ['replace', '-f', fname]
+ cmd = ['-n', self.namespace, 'replace', '-f', fname]
if force:
- cmd = ['replace', '--force', '-f', fname]
+ cmd.append('--force')
return self.oc_cmd(cmd)
- def create(self, fname):
+ def _create(self, fname):
'''return all pods '''
return self.oc_cmd(['create', '-f', fname, '-n', self.namespace])
- def delete(self, resource, rname):
+ def _delete(self, resource, rname):
'''return all pods '''
return self.oc_cmd(['delete', resource, rname, '-n', self.namespace])
- def get(self, resource, rname=None):
+ def _get(self, resource, rname=None):
'''return a secret by name '''
cmd = ['get', resource, '-o', 'json', '-n', self.namespace]
if rname:
@@ -96,7 +122,7 @@ class Utils(object):
path = os.path.join('/tmp', rname)
with open(path, 'w') as fds:
if ftype == 'yaml':
- fds.write(yaml.dump(data, default_flow_style=False))
+ fds.write(yaml.safe_dump(data, default_flow_style=False))
elif ftype == 'json':
fds.write(json.dumps(data))
@@ -173,7 +199,7 @@ class Utils(object):
''' 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 = ['creationTimestamp', 'selfLink', 'resourceVersion', 'uid', 'namespace']
+ skip = ['metadata', 'status']
for key, value in result_def.items():
if key in skip:
@@ -222,6 +248,165 @@ class Utils(object):
return True
+class YeditException(Exception):
+ ''' Exception class for Yedit '''
+ pass
+
+class Yedit(object):
+ ''' Class to modify yaml files '''
+
+ def __init__(self, filename=None, content=None):
+ self.content = content
+ self.filename = filename
+ self.__yaml_dict = content
+ if self.filename and not self.content:
+ self.get()
+ elif self.filename and self.content:
+ self.write()
+
+ @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, keys):
+ ''' remove an item from a dictionary with key notation a.b.c
+ d = {'a': {'b': 'c'}}}
+ keys = a.b
+ item = c
+ '''
+ if "." in keys:
+ key, rest = keys.split(".", 1)
+ if key in data.keys():
+ Yedit.remove_entry(data[key], rest)
+ else:
+ del data[keys]
+
+ @staticmethod
+ def add_entry(data, keys, item):
+ ''' Add an item to a dictionary with key notation a.b.c
+ d = {'a': {'b': 'c'}}}
+ keys = a.b
+ item = c
+ '''
+ if "." in keys:
+ key, rest = keys.split(".", 1)
+ if key not in data:
+ data[key] = {}
+
+ if not isinstance(data, dict):
+ raise YeditException('Invalid add_entry called on a [%s] of type [%s].' % (data, type(data)))
+ else:
+ Yedit.add_entry(data[key], rest, item)
+
+ else:
+ data[keys] = item
+
+
+ @staticmethod
+ def get_entry(data, keys):
+ ''' Get an item from a dictionary with key notation a.b.c
+ d = {'a': {'b': 'c'}}}
+ keys = a.b
+ return c
+ '''
+ if keys and "." in keys:
+ key, rest = keys.split(".", 1)
+ if not isinstance(data[key], dict):
+ raise YeditException('Invalid get_entry called on a [%s] of type [%s].' % (data, type(data)))
+
+ else:
+ return Yedit.get_entry(data[key], rest)
+
+ else:
+ return data.get(keys, None)
+
+
+ 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 get(self):
+ ''' return yaml file '''
+ contents = self.read()
+
+ if not contents:
+ return None
+
+ # check if it is yaml
+ try:
+ self.yaml_dict = yaml.load(contents)
+ except yaml.YAMLError as _:
+ # Error loading yaml
+ return None
+
+ return self.yaml_dict
+
+ def delete(self, key):
+ ''' put key, value into a yaml file '''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, key)
+ except KeyError as _:
+ entry = None
+ if not entry:
+ return (False, self.yaml_dict)
+
+ Yedit.remove_entry(self.yaml_dict, key)
+ self.write()
+ return (True, self.get())
+
+ def put(self, key, value):
+ ''' put key, value into a yaml file '''
+ try:
+ entry = Yedit.get_entry(self.yaml_dict, key)
+ except KeyError as _:
+ entry = None
+
+ if entry == value:
+ return (False, self.yaml_dict)
+
+ Yedit.add_entry(self.yaml_dict, key, value)
+ self.write()
+ return (True, self.get())
+
+ def create(self, key, value):
+ ''' create the file '''
+ if not self.exists():
+ self.yaml_dict = {key: value}
+ self.write()
+ return (True, self.get())
+
+ return (False, self.get())
+
class Secret(OpenShiftCLI):
''' Class to wrap the oc command line tools
'''
@@ -237,16 +422,16 @@ class Secret(OpenShiftCLI):
self.kubeconfig = kubeconfig
self.verbose = verbose
- def get_secrets(self):
+ def get(self):
'''return a secret by name '''
- return self.get('secrets', self.name)
+ return self._get('secrets', self.name)
- def delete_secret(self):
- '''return all pods '''
- return self.delete('secrets', self.name)
+ def delete(self):
+ '''delete a secret by name'''
+ return self._delete('secrets', self.name)
- def secret_new(self, files=None, contents=None):
- '''Create a secret with all pods '''
+ def create(self, files=None, contents=None):
+ '''Create a secret '''
if not files:
files = Utils.create_files_from_contents(contents)
@@ -256,7 +441,7 @@ class Secret(OpenShiftCLI):
return self.oc_cmd(cmd)
- def update_secret(self, files, force=False):
+ def update(self, files, force=False):
'''run update secret
This receives a list of file names and converts it into a secret.
@@ -272,7 +457,7 @@ class Secret(OpenShiftCLI):
atexit.register(Utils.cleanup, [sfile_path])
- return self.replace(sfile_path, force=force)
+ return self._replace(sfile_path, force=force)
def prep_secret(self, files=None, contents=None):
''' return what the secret would look like if created
@@ -319,7 +504,7 @@ def main():
state = module.params['state']
- api_rval = occmd.get_secrets()
+ api_rval = occmd.get()
#####
# Get
@@ -339,7 +524,7 @@ def main():
if module.check_mode:
module.exit_json(change=False, msg='Would have performed a delete.')
- api_rval = occmd.delete_secret()
+ api_rval = occmd.delete()
module.exit_json(changed=True, results=api_rval, state="absent")
@@ -359,7 +544,7 @@ def main():
if module.check_mode:
module.exit_json(change=False, msg='Would have performed a create.')
- api_rval = occmd.secret_new(module.params['files'], module.params['contents'])
+ api_rval = occmd.create(module.params['files'], module.params['contents'])
# Remove files
if files and module.params['delete_after']:
@@ -386,7 +571,7 @@ def main():
if module.check_mode:
module.exit_json(change=False, msg='Would have performed an update.')
- api_rval = occmd.update_secret(files, force=module.params['force'])
+ api_rval = occmd.update(files, force=module.params['force'])
# Remove files
if secret and module.params['delete_after']: