-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add proposal for a binaries download page #190
base: master
Are you sure you want to change the base?
Conversation
81699a0
to
e78741b
Compare
|
||
## Drawbacks | ||
|
||
- Requires us to bake all the binaries into the hub image. Could inflate the size and add complexity to the build process. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the openshift-console page that inspired this idea they seem to take a mixed approach, and we could probably duplicate either.
They have a separate downloads
container that requests are redirected to, which contains all the oc binaries. This probably prevents having to complicate their console container build process, and likewise if we took a similar approach not complicate the hub container build process.
$ oc get po -n openshift-console
NAME READY STATUS RESTARTS AGE
console-588ff9dbb7-shrnk 1/1 Running 11 7d2h
downloads-8ccff8dfd-frpx9 1/1 Running 10 7d2h
# find /usr/share/openshift/ -name oc
/usr/share/openshift/linux_amd64/oc
/usr/share/openshift/linux_arm64/oc
/usr/share/openshift/linux_ppc64le/oc
/usr/share/openshift/linux_s390x/oc
/usr/share/openshift/mac/oc
/usr/share/openshift/mac_arm64/oc
They then launch a python script.
For helm and odo they just redirect to the downloads.
https://mirror.openshift.com/pub/openshift-v4/clients/helm/latest
https://developers.redhat.com/content-gateway/rest/mirror/pub/openshift-v4/clients/odo/latest
I think either approach would be easier / better than baking them into the hub container.
The download container python script:
Command:
/bin/sh
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', 'arm64', 'ppc64le', 's390x']:
os.mkdir(arch)
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'),
('arm64', 'mac', '/usr/share/openshift/mac_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.mkdir(os.path.join(arch, operating_system))
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="{3}.tar">tar</a> <a href="{3}.zip">zip</a>)'.format(
target_path, arch, operating_system, archive_path_root
)
)
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
Signed-off-by: Fabian von Feilitzsch <[email protected]>
e78741b
to
ec52eb5
Compare
No description provided.