From 77e4ad6a555795b914b3e7b432f6de0c06b66e71 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Fri, 15 Mar 2019 21:59:01 -0700 Subject: [PATCH] manifests: Serve oc from within the cluster We need to support the ability to download clients (oc) from the cluster when an install is successful. With this commit, I'm adding a new Deployment for serving the binary from the cli image referenced from the release image. That way, the provided oc is the appropriate version for the current cluster version. I've set 'replicas' to two to support continued availability during rolling updates. The Python here-document approach is based on openshift/ci-operator@95a41a39 (Use a multithreaded python server to serve RPMs, 2018-06-25, openshift/ci-operator#35). The script creates a scratch directory to serve from, and populates it with the oc binary (via a symlink). It also creates zip and tar versions, so users can do things like: $ wget https://downloads-openshift-console.apps.wking.devcluster.openshift.com/amd64/linux/oc.zip $ unzip oc.zip instead of: $ wget https://downloads-openshift-console.apps.wking.devcluster.openshift.com/amd64/linux/oc $ chmod +x oc if they prefer. We don't have to clean up the scratch directory in the script, because it will be reaped as part of container cleanup. Moving forward, we'll want to replace the cli image with a cli-downloads image that includes builds for other platforms and architectures, but I'm punting on that for now. [1]: https://github.com/openshift/ci-operator/commit/95a41a395fa778680b3dc93c845407eb8a1a0ae1 --- manifests/07-downloads-deployment.yaml | 84 ++++++++++++++++++++++++++ manifests/08-downloads-service.yaml | 14 +++++ manifests/09-downloads-route.yaml | 14 +++++ manifests/image-references | 5 +- 4 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 manifests/07-downloads-deployment.yaml create mode 100644 manifests/08-downloads-service.yaml create mode 100644 manifests/09-downloads-route.yaml diff --git a/manifests/07-downloads-deployment.yaml b/manifests/07-downloads-deployment.yaml new file mode 100644 index 000000000..a56d73d5a --- /dev/null +++ b/manifests/07-downloads-deployment.yaml @@ -0,0 +1,84 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + namespace: openshift-console + name: downloads +spec: + replicas: 2 + selector: + matchLabels: + app: console + component: downloads + template: + metadata: + name: downloads + labels: + app: console + component: downloads + spec: + tolerations: + - operator: Exists + containers: + - name: download-server + image: docker.io/openshift/origin-cli:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8080 + name: http + protocol: TCP + command: ["/bin/sh"] + args: + - '-c' + - | + cat <>/tmp/serve.py + import BaseHTTPServer, os, re, SimpleHTTPServer, socket, tarfile, tempfile, threading, time, zipfile + + # Launch multiple listeners as threads + class Thread(threading.Thread): + def __init__(self, i, socket): + threading.Thread.__init__(self) + self.i = i + self.socket = socket + self.daemon = True + self.start() + + def run(self): + httpd = BaseHTTPServer.HTTPServer(addr, SimpleHTTPServer.SimpleHTTPRequestHandler, False) + + # Prevent the HTTP server from re-binding every handler. + # https://stackoverflow.com/questions/46210672/ + httpd.socket = self.socket + httpd.server_bind = self.server_close = lambda self: None + + httpd.serve_forever() + + temp_dir = tempfile.mkdtemp() + print('serving from {}'.format(temp_dir)) + os.chdir(temp_dir) + for arch in ['amd64']: + os.mkdir(arch) + for operating_system in ['linux']: + os.mkdir(os.path.join(arch, operating_system)) + + for path in [ # TODO: get binaries for other platforms + '/usr/bin/oc', + ]: + basename = os.path.basename(path) + target_path = os.path.join('amd64', 'linux', basename) + os.symlink(path, target_path) + with tarfile.open('{}.tar'.format(target_path), 'w') as tar: + tar.add(path, basename) + with zipfile.ZipFile('{}.zip'.format(target_path), 'w') as zip: + zip.write(path, basename) + + # Create socket + addr = ('', 8080) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind(addr) + sock.listen(5) + + [Thread(i, socket=sock) for i in range(100)] + time.sleep(9e9) + EOF + python2 /tmp/serve.py # the cli image only has Python 2.7 diff --git a/manifests/08-downloads-service.yaml b/manifests/08-downloads-service.yaml new file mode 100644 index 000000000..59c84593d --- /dev/null +++ b/manifests/08-downloads-service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + namespace: openshift-console + name: downloads +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 8080 + selector: + app: console + component: downloads diff --git a/manifests/09-downloads-route.yaml b/manifests/09-downloads-route.yaml new file mode 100644 index 000000000..d5bafc2b6 --- /dev/null +++ b/manifests/09-downloads-route.yaml @@ -0,0 +1,14 @@ +apiVersion: route.openshift.io/v1 +kind: Route +metadata: + namespace: openshift-console + name: downloads +spec: + tls: + termination: edge + port: + targetPort: http + to: + kind: Service + name: downloads + wildcardPolicy: None diff --git a/manifests/image-references b/manifests/image-references index d5c9b3098..973c8870f 100644 --- a/manifests/image-references +++ b/manifests/image-references @@ -10,4 +10,7 @@ spec: from: kind: DockerImage name: docker.io/openshift/origin-console:latest - + - name: cli + from: + kind: DockerImage + name: docker.io/openshift/origin-cli:latest