From 3a71ccde5c1a0324648516f761515c09bc461be3 Mon Sep 17 00:00:00 2001
From: Devan Goodwin <dgoodwin@redhat.com>
Date: Mon, 18 Jul 2016 15:53:31 -0300
Subject: Stop reporting changes when docker pull is already up to date.

---
 roles/etcd/tasks/main.yml             | 2 ++
 roles/openshift_cli/tasks/main.yml    | 2 ++
 roles/openshift_master/tasks/main.yml | 2 ++
 roles/openshift_node/tasks/main.yml   | 8 ++++++--
 4 files changed, 12 insertions(+), 2 deletions(-)

(limited to 'roles')

diff --git a/roles/etcd/tasks/main.yml b/roles/etcd/tasks/main.yml
index 71735dc25..75d40216d 100644
--- a/roles/etcd/tasks/main.yml
+++ b/roles/etcd/tasks/main.yml
@@ -12,6 +12,8 @@
 
 - name: Pull etcd container
   command: docker pull {{ openshift.etcd.etcd_image }}
+  register: pull_result
+  changed_when: "'Downloaded newer image' in pull_result.stdout"
   when: etcd_is_containerized | bool
 
 - name: Install etcd container service file
diff --git a/roles/openshift_cli/tasks/main.yml b/roles/openshift_cli/tasks/main.yml
index 4d6219b94..509b8bc8a 100644
--- a/roles/openshift_cli/tasks/main.yml
+++ b/roles/openshift_cli/tasks/main.yml
@@ -6,6 +6,8 @@
 - name: Pull CLI Image
   command: >
     docker pull {{ openshift.common.cli_image }}:{{ openshift_image_tag }}
+  register: pull_result
+  changed_when: "'Downloaded newer image' in pull_result.stdout"
   when: openshift.common.is_containerized | bool
 
 - name: Create /usr/local/bin/openshift cli wrapper
diff --git a/roles/openshift_master/tasks/main.yml b/roles/openshift_master/tasks/main.yml
index 7a80ed8e3..5c6c64018 100644
--- a/roles/openshift_master/tasks/main.yml
+++ b/roles/openshift_master/tasks/main.yml
@@ -30,6 +30,8 @@
 - name: Pull master image
   command: >
     docker pull {{ openshift.master.master_image }}:{{ openshift_image_tag }}
+  register: pull_result
+  changed_when: "'Downloaded newer image' in pull_result.stdout"
   when: openshift.common.is_containerized | bool
 
 - name: Create openshift.common.data_dir
diff --git a/roles/openshift_node/tasks/main.yml b/roles/openshift_node/tasks/main.yml
index 97a21544d..889541e25 100644
--- a/roles/openshift_node/tasks/main.yml
+++ b/roles/openshift_node/tasks/main.yml
@@ -41,11 +41,15 @@
 - name: Pull node image
   command: >
     docker pull {{ openshift.node.node_image }}:{{ openshift_image_tag }}
+  register: pull_result
+  changed_when: "'Downloaded newer image' in pull_result.stdout"
   when: openshift.common.is_containerized | bool
 
 - name: Pull OpenVSwitch image
   command: >
     docker pull {{ openshift.node.ovs_image }}:{{ openshift_image_tag }}
+  register: pull_result
+  changed_when: "'Downloaded newer image' in pull_result.stdout"
   when: openshift.common.is_containerized | bool and openshift.common.use_openshift_sdn | bool
 
 - name: Install the systemd units
@@ -129,12 +133,12 @@
   service: name={{ openshift.common.service_type }}-node enabled=yes state=started
   register: node_start_result
   ignore_errors: yes
-  
+
 - name: Wait 30 seconds for docker initialization whenever node has failed
   pause:
     seconds: 30
   when: node_start_result | failed
-  
+
 - name: Start and enable node again
   service: name={{ openshift.common.service_type }}-node enabled=yes state=started
   register: node_start_result
-- 
cgit v1.2.3


From ca7767eab6674737a117a09f7f456b7918cffecf Mon Sep 17 00:00:00 2001
From: Devan Goodwin <dgoodwin@redhat.com>
Date: Mon, 18 Jul 2016 12:45:35 -0300
Subject: 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.
---
 .../library/openshift_container_binary_sync.py     | 131 +++++++++++++++++++++
 roles/openshift_cli/tasks/main.yml                 |  20 +---
 roles/openshift_cli/templates/openshift.j2         |  28 -----
 3 files changed, 135 insertions(+), 44 deletions(-)
 create mode 100644 roles/openshift_cli/library/openshift_container_binary_sync.py
 delete mode 100644 roles/openshift_cli/templates/openshift.j2

(limited to 'roles')

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} "${@}"
-- 
cgit v1.2.3