apiVersion: apps/v1
kind: Deployment
metadata:
  name: downloads
  namespace: openshift-console
  labels:
    app: console
    component: downloads
  annotations: {}
spec:
  selector:
    matchLabels:
      app: console
      component: downloads
  strategy:
    type: RollingUpdate
  template:
    metadata:
      name: downloads
      labels:
        app: console
        component: downloads
      annotations:
        target.workload.openshift.io/management: '{"effect": "PreferredDuringScheduling"}'
    spec:
      nodeSelector:
        kubernetes.io/os: linux
      terminationGracePeriodSeconds: 0
      securityContext: {}
      containers:
        - resources:
            requests:
              cpu: 10m
              memory: 50Mi
          readinessProbe:
            httpGet:
              path: /
              port: 8080
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          name: download-server
          command:
            - /bin/sh
          livenessProbe:
            httpGet:
              path: /
              port: 8080
              scheme: HTTP
            timeoutSeconds: 1
            periodSeconds: 10
            successThreshold: 1
            failureThreshold: 3
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          imagePullPolicy: IfNotPresent
          terminationMessagePolicy: FallbackToLogsOnError
          image: ${IMAGE}
          args:
            - '-c'
            - |
              cat <<EOF >>/tmp/serve.py
              import errno, http.server, os, re, signal, socket, sys, tarfile, tempfile, threading, time, zipfile

              signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(0))

              def write_index(path, message):
                with open(path, 'wb') as f:
                  f.write('\n'.join([
                    '<!doctype html>',
                    '<html lang="en">',
                    '<head>',
                    '  <meta charset="utf-8">',
                    '</head>',
                    '<body>',
                    '  {}'.format(message),
                    '</body>',
                    '</html>',
                    '',
                  ]).encode('utf-8'))

              # 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):
                  server = http.server.SimpleHTTPRequestHandler
                  server.server_version = "OpenShift Downloads Server"
                  server.sys_version = ""
                  httpd = http.server.HTTPServer(addr, server, 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', 'mac', 'windows']:
                  os.mkdir(os.path.join(arch, operating_system))
              for arch in ['arm64', 'ppc64le', 's390x']:
                os.mkdir(arch)
                for operating_system in ['linux']:
                  os.mkdir(os.path.join(arch, operating_system))
              content = ['<a href="oc-license">license</a>']
              os.symlink('/usr/share/openshift/LICENSE', 'oc-license')

              for arch, operating_system, path in [
                  ('amd64', 'linux', '/usr/share/openshift/linux_amd64/oc'),
                  ('amd64', 'mac', '/usr/share/openshift/mac/oc'),
                  ('amd64', 'windows', '/usr/share/openshift/windows/oc.exe'),
                  ('arm64', 'linux', '/usr/share/openshift/linux_arm64/oc'),
                  ('ppc64le', 'linux', '/usr/share/openshift/linux_ppc64le/oc'),
                  ('s390x', 'linux', '/usr/share/openshift/linux_s390x/oc'),
                  ]:
                basename = os.path.basename(path)
                target_path = os.path.join(arch, operating_system, basename)
                os.symlink(path, target_path)
                base_root, _ = os.path.splitext(basename)
                archive_path_root = os.path.join(arch, operating_system, base_root)
                with tarfile.open('{}.tar'.format(archive_path_root), 'w') as tar:
                  tar.add(path, basename)
                with zipfile.ZipFile('{}.zip'.format(archive_path_root), 'w') as zip:
                  zip.write(path, basename)
                content.append('<a href="{0}">oc ({1} {2})</a> (<a href="{0}.tar">tar</a> <a href="{0}.zip">zip</a>)'.format(target_path, arch, operating_system))

              for root, directories, filenames in os.walk(temp_dir):
                root_link = os.path.relpath(temp_dir, os.path.join(root, 'child')).replace(os.path.sep, '/')
                for directory in directories:
                  write_index(
                    path=os.path.join(root, directory, 'index.html'),
                    message='<p>Directory listings are disabled.  See <a href="{}">here</a> for available content.</p>'.format(root_link),
                  )

              write_index(
                path=os.path.join(temp_dir, 'index.html'),
                message='\n'.join(
                  ['<ul>'] +
                  ['  <li>{}</li>'.format(entry) for entry in content] +
                  ['</ul>']
                ),
              )

              # Create socket
              # IPv6 should handle IPv4 passively so long as it is not bound to a
              # specific address or set to IPv6_ONLY
              # https://stackoverflow.com/questions/25817848/python-3-does-http-server-support-ipv6
              try:
                addr = ('::', 8080)
                sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
              except socket.error as err:
                # errno.EAFNOSUPPORT is "socket.error: [Errno 97] Address family not supported by protocol"
                # When IPv6 is disabled, socket will bind using IPv4.
                if err.errno == errno.EAFNOSUPPORT:
                  addr = ('', 8080)
                  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                else:
                  raise    
              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
              exec python3 /tmp/serve.py
      tolerations:
        - key: node-role.kubernetes.io/master
          operator: Exists
          effect: NoSchedule
        - key: node.kubernetes.io/unreachable
          operator: Exists
          effect: NoExecute
          tolerationSeconds: 120
        - key: node.kubernetes.io/not-reachable
          operator: Exists
          effect: NoExecute
          tolerationSeconds: 120
      priorityClassName: system-cluster-critical
