summaryrefslogtreecommitdiffstats
path: root/roles/openshift_cli
diff options
context:
space:
mode:
authorDevan Goodwin <dgoodwin@redhat.com>2016-07-18 12:45:35 -0300
committerDevan Goodwin <dgoodwin@redhat.com>2016-07-21 12:06:33 -0300
commitca7767eab6674737a117a09f7f456b7918cffecf (patch)
treea61dd4214796431eff590a93a7e6211b515c7fe1 /roles/openshift_cli
parent3a71ccde5c1a0324648516f761515c09bc461be3 (diff)
downloadopenshift-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/openshift_cli')
-rw-r--r--roles/openshift_cli/library/openshift_container_binary_sync.py131
-rw-r--r--roles/openshift_cli/tasks/main.yml20
-rw-r--r--roles/openshift_cli/templates/openshift.j228
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} "${@}"