diff options
-rw-r--r-- | roles/lib_openshift/library/oc_process.py | 102 | ||||
-rw-r--r-- | roles/lib_openshift/src/doc/process | 12 | ||||
-rwxr-xr-x | roles/lib_openshift/src/test/unit/oc_process.py | 14 | ||||
-rw-r--r-- | roles/lib_openshift/tasks/main.yml | 9 |
4 files changed, 100 insertions, 37 deletions
diff --git a/roles/lib_openshift/library/oc_process.py b/roles/lib_openshift/library/oc_process.py index 60eeb283b..702cb02d4 100644 --- a/roles/lib_openshift/library/oc_process.py +++ b/roles/lib_openshift/library/oc_process.py @@ -38,6 +38,7 @@ import os import re import shutil import subprocess +import tempfile # pylint: disable=import-error import ruamel.yaml as yaml from ansible.module_utils.basic import AnsibleModule @@ -55,7 +56,11 @@ description: options: state: description: - - Currently present is only supported state. + - State has a few different meanings when it comes to process. + - state: present - This state runs an `oc process <template>`. When used in + - conjunction with 'create: True' the process will be piped to | oc create -f + - state: absent - will remove a template + - state: list - will perform an `oc get template <template_name>` default: present choices: ["present", "absent", "list"] aliases: [] @@ -97,9 +102,9 @@ options: aliases: [] create: description: - - Whether or not to create the template after being processed. e.q oc process | oc create -f - - required: false - default: None + - Whether or not to create the template after being processed. e.g. oc process | oc create -f - + required: False + default: False aliases: [] reconcile: description: @@ -302,6 +307,17 @@ class Yedit(object): return data + @staticmethod + def _write(filename, contents): + ''' Actually write the file contents to disk. This helps with mocking. ''' + + tmp_filename = filename + '.yedit' + + with open(tmp_filename, 'w') as yfd: + yfd.write(contents) + + os.rename(tmp_filename, filename) + def write(self): ''' write to file ''' if not self.filename: @@ -310,15 +326,11 @@ class Yedit(object): if self.backup and self.file_exists(): shutil.copy(self.filename, self.filename + '.orig') - tmp_filename = self.filename + '.yedit' - with open(tmp_filename, 'w') as yfd: - # pylint: disable=no-member - if hasattr(self.yaml_dict, 'fa'): - self.yaml_dict.fa.set_block_style() - - yfd.write(yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) + # pylint: disable=no-member + if hasattr(self.yaml_dict, 'fa'): + self.yaml_dict.fa.set_block_style() - os.rename(tmp_filename, self.filename) + Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper)) return (True, self.yaml_dict) @@ -715,7 +727,7 @@ class OpenShiftCLI(object): ''' Constructor for OpenshiftCLI ''' self.namespace = namespace self.verbose = verbose - self.kubeconfig = kubeconfig + self.kubeconfig = Utils.create_tmpfile_copy(kubeconfig) self.all_namespaces = all_namespaces # Pylint allows only 5 arguments to be passed. @@ -726,7 +738,8 @@ class OpenShiftCLI(object): if not res['results']: return res - fname = '/tmp/%s' % rname + fname = Utils.create_tmpfile(rname + '-') + yed = Yedit(fname, res['results'][0], separator=sep) changes = [] for key, value in content.items(): @@ -750,7 +763,7 @@ class OpenShiftCLI(object): def _create_from_content(self, rname, content): '''create a temporary file and then call oc create on it''' - fname = '/tmp/%s' % rname + fname = Utils.create_tmpfile(rname + '-') yed = Yedit(fname, content=content) yed.write() @@ -793,7 +806,7 @@ class OpenShiftCLI(object): if results['returncode'] != 0 or not create: return results - fname = '/tmp/%s' % template_name + fname = Utils.create_tmpfile(template_name + '-') yed = Yedit(fname, results['results']) yed.write() @@ -974,32 +987,61 @@ class OpenShiftCLI(object): class Utils(object): ''' utilities for openshiftcli modules ''' + + @staticmethod + def _write(filename, contents): + ''' Actually write the file contents to disk. This helps with mocking. ''' + + with open(filename, 'w') as sfd: + sfd.write(contents) + @staticmethod - def create_file(rname, data, ftype='yaml'): + def create_tmp_file_from_contents(rname, data, ftype='yaml'): ''' 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.dump(data, Dumper=yaml.RoundTripDumper)) - elif ftype == 'json': - fds.write(json.dumps(data)) - else: - fds.write(data) + tmp = Utils.create_tmpfile(prefix=rname) + + if ftype == 'yaml': + Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper)) + elif ftype == 'json': + Utils._write(tmp, json.dumps(data)) + else: + Utils._write(tmp, data) # Register cleanup when module is done - atexit.register(Utils.cleanup, [path]) - return path + atexit.register(Utils.cleanup, [tmp]) + return tmp + + @staticmethod + def create_tmpfile_copy(inc_file): + '''create a temporary copy of a file''' + tmpfile = Utils.create_tmpfile('lib_openshift-') + Utils._write(tmpfile, open(inc_file).read()) + + # Cleanup the tmpfile + atexit.register(Utils.cleanup, [tmpfile]) + + return tmpfile + + @staticmethod + def create_tmpfile(prefix='tmp'): + ''' Generates and returns a temporary file name ''' + + with tempfile.NamedTemporaryFile(prefix=prefix, delete=False) as tmp: + return tmp.name @staticmethod - def create_files_from_contents(content, content_type=None): + def create_tmp_files_from_contents(content, content_type=None): '''Turn an array of dict: filename, content into a files array''' if not isinstance(content, list): content = [content] files = [] for item in content: - path = Utils.create_file(item['path'], item['data'], ftype=content_type) - files.append({'name': os.path.basename(path), 'path': path}) + path = Utils.create_tmp_file_from_contents(item['path'] + '-', + item['data'], + ftype=content_type) + files.append({'name': os.path.basename(item['path']), + 'path': path}) return files @staticmethod diff --git a/roles/lib_openshift/src/doc/process b/roles/lib_openshift/src/doc/process index 2322bf49c..86a854c07 100644 --- a/roles/lib_openshift/src/doc/process +++ b/roles/lib_openshift/src/doc/process @@ -10,7 +10,11 @@ description: options: state: description: - - Currently present is only supported state. + - State has a few different meanings when it comes to process. + - state: present - This state runs an `oc process <template>`. When used in + - conjunction with 'create: True' the process will be piped to | oc create -f + - state: absent - will remove a template + - state: list - will perform an `oc get template <template_name>` default: present choices: ["present", "absent", "list"] aliases: [] @@ -52,9 +56,9 @@ options: aliases: [] create: description: - - Whether or not to create the template after being processed. e.q oc process | oc create -f - - required: false - default: None + - Whether or not to create the template after being processed. e.g. oc process | oc create -f - + required: False + default: False aliases: [] reconcile: description: diff --git a/roles/lib_openshift/src/test/unit/oc_process.py b/roles/lib_openshift/src/test/unit/oc_process.py index c0cf625cc..450ff7071 100755 --- a/roles/lib_openshift/src/test/unit/oc_process.py +++ b/roles/lib_openshift/src/test/unit/oc_process.py @@ -257,8 +257,9 @@ class OCProcessTest(unittest.TestCase): ''' setup method will set to known configuration ''' pass + @mock.patch('oc_process.Utils.create_tmpfile_copy') @mock.patch('oc_process.OCProcess._run') - def test_state_list(self, mock_cmd): + def test_state_list(self, mock_cmd, mock_tmpfile_copy): ''' Testing a get ''' params = {'template_name': 'mysql-ephermeral', 'namespace': 'test', @@ -274,13 +275,18 @@ class OCProcessTest(unittest.TestCase): (0, OCProcessTest.mysql, '') ] + mock_tmpfile_copy.side_effect = [ + '/tmp/mock_kubeconfig', + ] + results = OCProcess.run_ansible(params, False) self.assertFalse(results['changed']) self.assertEqual(results['results']['results'][0]['metadata']['name'], 'mysql-ephemeral') + @mock.patch('oc_process.Utils.create_tmpfile_copy') @mock.patch('oc_process.OCProcess._run') - def test_process_no_create(self, mock_cmd): + def test_process_no_create(self, mock_cmd, mock_tmpfile_copy): ''' Testing a process with no create ''' params = {'template_name': 'mysql-ephermeral', 'namespace': 'test', @@ -459,6 +465,10 @@ class OCProcessTest(unittest.TestCase): (0, mysqlproc, ''), ] + mock_tmpfile_copy.side_effect = [ + '/tmp/mock_kubeconfig', + ] + results = OCProcess.run_ansible(params, False) self.assertFalse(results['changed']) diff --git a/roles/lib_openshift/tasks/main.yml b/roles/lib_openshift/tasks/main.yml index 2980c8a8d..157cf8f7f 100644 --- a/roles/lib_openshift/tasks/main.yml +++ b/roles/lib_openshift/tasks/main.yml @@ -1,5 +1,12 @@ --- - name: lib_openshift ensure python-ruamel-yaml package is on target package: - name: python-ruamel-yaml + name: "{{ item }}" state: present + with_items: + - ruamel.yaml + - ruamel.yaml + - ruamel.yaml + - ruamel.yaml + - ruamel.yaml + - ruamel.yaml |