diff options
author | Devan Goodwin <dgoodwin@redhat.com> | 2016-07-18 12:45:35 -0300 |
---|---|---|
committer | Devan Goodwin <dgoodwin@redhat.com> | 2016-07-21 12:06:33 -0300 |
commit | ca7767eab6674737a117a09f7f456b7918cffecf (patch) | |
tree | a61dd4214796431eff590a93a7e6211b515c7fe1 /roles | |
parent | 3a71ccde5c1a0324648516f761515c09bc461be3 (diff) | |
download | openshift-ca7767eab6674737a117a09f7f456b7918cffecf.tar.gz openshift-ca7767eab6674737a117a09f7f456b7918cffecf.tar.bz2 openshift-ca7767eab6674737a117a09f7f456b7918cffecf.tar.xz openshift-ca7767eab6674737a117a09f7f456b7918cffecf.zip |
Copy openshift binaries instead of using wrapper script.
For containerized masters, we previously create a wrapper script to run
the docker CLI image and clean up afterward, but this approach is much
slower than having the binary on the native system.
Instead we now use an ansible module to handle the logic of syncing the
various OpenShift binaries and symlinks for client tools out onto the
host. The module will correctly report changed if modifications were
needed.
Substantial speed improvement for containerized installs which requires
many openshift/oc commands.
Diffstat (limited to 'roles')
-rw-r--r-- | roles/openshift_cli/library/openshift_container_binary_sync.py | 131 | ||||
-rw-r--r-- | roles/openshift_cli/tasks/main.yml | 20 | ||||
-rw-r--r-- | roles/openshift_cli/templates/openshift.j2 | 28 |
3 files changed, 135 insertions, 44 deletions
diff --git a/roles/openshift_cli/library/openshift_container_binary_sync.py b/roles/openshift_cli/library/openshift_container_binary_sync.py new file mode 100644 index 000000000..fd290c6fc --- /dev/null +++ b/roles/openshift_cli/library/openshift_container_binary_sync.py @@ -0,0 +1,131 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# vim: expandtab:tabstop=4:shiftwidth=4 +# pylint: disable=missing-docstring,invalid-name +# + +import random +import tempfile +import shutil +import os.path + +# pylint: disable=redefined-builtin,wildcard-import,unused-wildcard-import +from ansible.module_utils.basic import * + + +DOCUMENTATION = ''' +--- +module: openshift_container_binary_sync +short_description: Copies OpenShift binaries out of the given image tag to host system. +''' + + +class BinarySyncError(Exception): + def __init__(self, msg): + super(BinarySyncError, self).__init__(msg) + self.msg = msg + + +# pylint: disable=too-few-public-methods +class BinarySyncer(object): + """ + Syncs the openshift, oc, oadm, and kubectl binaries/symlinks out of + a container onto the host system. + """ + + def __init__(self, module, image, tag): + self.module = module + self.changed = False + self.output = [] + self.bin_dir = '/usr/local/bin' + self.image = image + self.tag = tag + self.temp_dir = None # TBD + + def sync(self): + container_name = "openshift-cli-%s" % random.randint(1, 100000) + rc, stdout, stderr = self.module.run_command(['docker', 'create', '--name', + container_name, '%s:%s' % (self.image, self.tag)]) + if rc: + raise BinarySyncError("Error creating temporary docker container. stdout=%s, stderr=%s" % + (stdout, stderr)) + self.output.append(stdout) + try: + self.temp_dir = tempfile.mkdtemp() + self.output.append("Using temp dir: %s" % self.temp_dir) + + rc, stdout, stderr = self.module.run_command(['docker', 'cp', "%s:/usr/bin/openshift" % container_name, + self.temp_dir]) + if rc: + raise BinarySyncError("Error copying file from docker container: stdout=%s, stderr=%s" % + (stdout, stderr)) + + rc, stdout, stderr = self.module.run_command(['docker', 'cp', "%s:/usr/bin/oc" % container_name, + self.temp_dir]) + if rc: + raise BinarySyncError("Error copying file from docker container: stdout=%s, stderr=%s" % + (stdout, stderr)) + + self._sync_binary('openshift') + + # In older versions, oc was a symlink to openshift: + if os.path.islink(os.path.join(self.temp_dir, 'oc')): + self._sync_symlink('oc', 'openshift') + else: + self._sync_binary('oc') + + # Ensure correct symlinks created: + self._sync_symlink('kubectl', 'openshift') + self._sync_symlink('oadm', 'openshift') + finally: + shutil.rmtree(self.temp_dir) + self.module.run_command(['docker', 'rm', container_name]) + + def _sync_symlink(self, binary_name, link_to): + """ Ensure the given binary name exists and links to the expected binary. """ + link_path = os.path.join(self.bin_dir, binary_name) + link_dest = os.path.join(self.bin_dir, binary_name) + if not os.path.exists(link_path) or \ + not os.path.islink(link_path) or \ + os.path.realpath(link_path) != os.path.realpath(link_dest): + if os.path.exists(link_path): + os.remove(link_path) + os.symlink(link_to, os.path.join(self.bin_dir, binary_name)) + self.output.append("Symlinked %s to %s." % (link_path, link_dest)) + self.changed = True + + def _sync_binary(self, binary_name): + src_path = os.path.join(self.temp_dir, binary_name) + dest_path = os.path.join(self.bin_dir, binary_name) + incoming_checksum = self.module.run_command(['sha256sum', src_path])[1] + if not os.path.exists(dest_path) or self.module.run_command(['sha256sum', dest_path])[1] != incoming_checksum: + shutil.move(src_path, dest_path) + self.output.append("Moved %s to %s." % (src_path, dest_path)) + self.changed = True + + +def main(): + module = AnsibleModule( + argument_spec=dict( + image=dict(required=True), + tag=dict(required=True), + ), + supports_check_mode=True + ) + + image = module.params['image'] + tag = module.params['tag'] + + binary_syncer = BinarySyncer(module, image, tag) + + try: + binary_syncer.sync() + except BinarySyncError as ex: + module.fail_json(msg=ex.msg) + + return module.exit_json(changed=binary_syncer.changed, + output=binary_syncer.output) + + +if __name__ == '__main__': + main() diff --git a/roles/openshift_cli/tasks/main.yml b/roles/openshift_cli/tasks/main.yml index 509b8bc8a..11c73b25c 100644 --- a/roles/openshift_cli/tasks/main.yml +++ b/roles/openshift_cli/tasks/main.yml @@ -10,22 +10,10 @@ changed_when: "'Downloaded newer image' in pull_result.stdout" when: openshift.common.is_containerized | bool -- name: Create /usr/local/bin/openshift cli wrapper - template: - src: openshift.j2 - dest: /usr/local/bin/openshift - mode: 0755 - when: openshift.common.is_containerized | bool - -- name: Create client symlinks - file: - path: "{{ item }}" - state: link - src: /usr/local/bin/openshift - with_items: - - /usr/local/bin/oadm - - /usr/local/bin/oc - - /usr/local/bin/kubectl +- name: Copy client binaries/symlinks out of CLI image for use on the host + openshift_container_binary_sync: + image: "{{ openshift.common.cli_image }}" + tag: "{{ openshift_image_tag }}" when: openshift.common.is_containerized | bool - name: Reload facts to pick up installed OpenShift version diff --git a/roles/openshift_cli/templates/openshift.j2 b/roles/openshift_cli/templates/openshift.j2 deleted file mode 100644 index 7786acead..000000000 --- a/roles/openshift_cli/templates/openshift.j2 +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash -if [ ! -d ~/.kube ]; then - mkdir -m 0700 ~/.kube -fi -cmd=`basename $0` -user=`id -u` -group=`id -g` -image_tag="{{ openshift_image_tag }}" - ->&2 echo """ -================================================================================ -ATTENTION: You are running ${cmd} via a wrapper around 'docker run {{ openshift.common.cli_image }}:${image_tag}'. -This wrapper is intended only to be used to bootstrap an environment. Please -install client tools on another host once you have granted cluster-admin -privileges to a user. -{% if openshift.common.deployment_type in ['openshift-enterprise','atomic-enterprise'] %} -See https://docs.openshift.com/enterprise/latest/cli_reference/get_started_cli.html -{% else %} -See https://docs.openshift.org/latest/cli_reference/get_started_cli.html -{% endif %} -================================================================================= -""" - -if [ -n "$image_tag" ]; then - image_tag=":$image_tag" -fi - -docker run -i --privileged --net=host --user=${user}:${group} -v ~/.kube:/root/.kube -v /tmp:/tmp -v {{ openshift.common.config_base}}:{{ openshift.common.config_base }} -e KUBECONFIG=/root/.kube/config --entrypoint ${cmd} --rm {{ openshift.common.cli_image }}${image_tag} "${@}" |