From 38f1ede8a5648f412bb5be59284d4375d887580d Mon Sep 17 00:00:00 2001 From: John Sloboda Date: Mon, 18 Nov 2019 17:41:03 -0500 Subject: [PATCH 1/4] Add symlink for executable, with unsuffixed name --- bin/harbormaster | 1 + 1 file changed, 1 insertion(+) create mode 120000 bin/harbormaster diff --git a/bin/harbormaster b/bin/harbormaster new file mode 120000 index 0000000..568fd7b --- /dev/null +++ b/bin/harbormaster @@ -0,0 +1 @@ +../harbormaster/harbormaster.py \ No newline at end of file From eb88d560400a9a79a64c998915fc23565eeb3a8e Mon Sep 17 00:00:00 2001 From: John Sloboda Date: Mon, 18 Nov 2019 17:42:39 -0500 Subject: [PATCH 2/4] Specify docker dependency --- setup.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6079068..ee560e8 100644 --- a/setup.py +++ b/setup.py @@ -14,8 +14,11 @@ def readme(): author_email='tanishq@dubey.dev', license='MIT', packages=['harbormaster'], + install_requires=[ + 'docker', + ], zip_safe=False, - scripts=['harbormaster/harbormaster.py'], + scripts=['bin/harbormaster'], classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', From 8746242c75c72f08cfc7339d6ee2a0ef33aa7a14 Mon Sep 17 00:00:00 2001 From: John Sloboda Date: Mon, 18 Nov 2019 17:43:46 -0500 Subject: [PATCH 3/4] Add event loop around main connector opening and closing, check process exists before terminating, and stop swallowing exceptions --- harbormaster/harbormaster.py | 39 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/harbormaster/harbormaster.py b/harbormaster/harbormaster.py index 5cf10f9..32fcce8 100755 --- a/harbormaster/harbormaster.py +++ b/harbormaster/harbormaster.py @@ -63,23 +63,25 @@ def main(args, spath): dRunning[c.id] = proc # Main Loop - for event in dClient.events(decode=True): - if event['Type'] == 'container' and event['status'] == 'start': - c = dClient.containers.get(event['id']) - logging.info(f'Got container start event for {c.name} ({c.short_id})') - cPortsRaw = c.attrs['NetworkSettings']['Ports'] - for _,v in cPortsRaw.items(): - if v: - for p in v: - port = p['HostPort'] - proc = createTunnel(port, args.user, args.host) - dRunning[c.id] = proc - if event['Type'] == 'container' and event['status'] == 'die': - c = dClient.containers.get(event['id']) - logging.info(f'Got container die event for {c.name} ({c.short_id})') - logging.info(f'Closing tunnel {event["id"]}') - dRunning[event['id']].terminate() - del dRunning[event['id']] + while True: + for event in dClient.events(decode=True): + if event['Type'] == 'container' and event['status'] == 'start': + c = dClient.containers.get(event['id']) + logging.info(f'Got container start event for {c.name} ({c.short_id})') + cPortsRaw = c.attrs['NetworkSettings']['Ports'] + for _,v in cPortsRaw.items(): + if v: + for p in v: + port = p['HostPort'] + proc = createTunnel(port, args.user, args.host) + dRunning[c.id] = proc + if event['Type'] == 'container' and event['status'] == 'die': + c = dClient.containers.get(event['id']) + logging.info(f'Got container die event for {c.name} ({c.short_id})') + logging.info(f'Closing tunnel {event["id"]}') + if c.id in dRunning: + dRunning[c.id].terminate() + del dRunning[c.id] def configfile(spath, port): hmsShellPrepend = [ @@ -156,7 +158,6 @@ def cleanup(spath, port): main(a, s) except KeyboardInterrupt: logging.warning('Got CTRL-C, cleaning up (CTRL-C again to force)') - cleanup(s, a.p) - except Exception: + finally: cleanup(s, a.p) From ddb175dc8166543c17d72af8329876af6f605376 Mon Sep 17 00:00:00 2001 From: Tanishq Dubey Date: Tue, 19 Nov 2019 00:12:41 -0500 Subject: [PATCH 4/4] should fix most bugs, need to merge with jsloboda --- harbormaster/harbormaster.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/harbormaster/harbormaster.py b/harbormaster/harbormaster.py index 5cf10f9..5c684b5 100755 --- a/harbormaster/harbormaster.py +++ b/harbormaster/harbormaster.py @@ -60,7 +60,10 @@ def main(args, spath): for p in v: port = p['HostPort'] proc = createTunnel(port, args.user, args.host) - dRunning[c.id] = proc + if c.id in dRunning: + dRunning[c.id].append(proc) + else: + dRunning[c.id] = [proc] # Main Loop for event in dClient.events(decode=True): @@ -73,13 +76,20 @@ def main(args, spath): for p in v: port = p['HostPort'] proc = createTunnel(port, args.user, args.host) - dRunning[c.id] = proc + if c.id in dRunning: + dRunning[c.id].append(proc) + else: + dRunning[c.id] = [proc] if event['Type'] == 'container' and event['status'] == 'die': c = dClient.containers.get(event['id']) logging.info(f'Got container die event for {c.name} ({c.short_id})') - logging.info(f'Closing tunnel {event["id"]}') - dRunning[event['id']].terminate() - del dRunning[event['id']] + if c.id in dRunning: + logging.info(f'Closing tunnel(s) {event["id"]}') + for p in dRunning[event['id']]: + p.terminate() + del dRunning[event['id']] + else: + logging.info(f'Harbormaster is no longer managing {c.name} ({event["id"]})') def configfile(spath, port): hmsShellPrepend = [ @@ -88,8 +98,12 @@ def configfile(spath, port): '#<<<$< END HARBOR MASTER >$>>>\n' ] logging.debug(f'Opening shell config at {spath}') - with open(spath, 'r') as f: - dat = f.readlines() + try: + with open(spath, 'r') as f: + dat = f.readlines() + except Exception as e: + logging.error(f'There was an error opeing your .zshenv file: {e}') + sys.exit(-1) dat.extend(hmsShellPrepend) @@ -126,8 +140,9 @@ def cleanup(spath, port): cleanfile(spath, port) for k, v in dRunning.items(): - logging.info(f'Closing tunnel {k}') - v.terminate() + logging.info(f'Closing tunnel(s) for {k}') + for p in v: + p.terminate() logging.warning(f'Closing remote docker socket connection') @@ -157,6 +172,7 @@ def cleanup(spath, port): except KeyboardInterrupt: logging.warning('Got CTRL-C, cleaning up (CTRL-C again to force)') cleanup(s, a.p) - except Exception: + except Exception as e: + logging.error(f'There was an error: {e}') cleanup(s, a.p)