Skip to content

Commit

Permalink
Merge pull request #2 from tanishq-dubey/v0-2--basic-improvements
Browse files Browse the repository at this point in the history
V0 2  basic improvements
  • Loading branch information
tanishq-dubey authored Nov 16, 2019
2 parents ab64fe0 + c2cc0c9 commit 880ec22
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 38 deletions.
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include README.md
95 changes: 57 additions & 38 deletions harbormaster.py → harbormaster/harbormaster.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
#! /usr/bin/python3
#! /usr/bin/env python3

import sys
import os

import docker
import argparse
import logging

import subprocess
import time
import argparse

import docker


dockerTunnel = None
dRunning = {}

def createTunnel(port, user, host):
logging.info(f'Creating tunnel for port {port} to {user}@{host}')
Expand All @@ -25,50 +25,61 @@ def createTunnel(port, user, host):

def main(args, spath):
global dockerTunnel
global dRunning

# Not using createTunnel() here because this one off tunnel has slightly different syntax
dockerTunnel = subprocess.Popen([
'ssh', '-nNT',
'-L', f'localhost:{args.p}:/var/run/docker.sock',
f'{args.user}@{args.host}'
])
logging.info(f'Docker socket forwarding started to {args.user}@{args.host} on local port {args.p}')

# Get list of running containers
logging.debug('Waiting for SSH to stabilize')
time.sleep(5)
dClient = docker.DockerClient(base_url=f'tcp://localhost:{args.p}')
connected = False
while not connected:
try:
dClient = docker.DockerClient(base_url=f'tcp://localhost:{args.p}')
dClient.ping()
connected = True
except:
logging.info(f'Waiting for tunnel to come up...')
time.sleep(1)

logging.info(f'Remote docker engine connection established')

# Get list of running containers
cList = dClient.containers.list()
logging.debug(f'Found {len(cList)} running containers on connect')

dRunning = {}
"""
>>> x.attrs['NetworkSettings']['Ports']
{'3000/tcp': [{'HostIp': '0.0.0.0', 'HostPort': '3000'}]}
"""
while True:
cList = dClient.containers.list()
tRunning = {}
for c in cList:
if c.id not in dRunning:
logging.info(f'Found new container with ID {c.short_id} and name {c.name}')
cPortsRaw = c.attrs['NetworkSettings']['Ports']
for k,v in cPortsRaw.items():
if v:
for p in v:
port = p['HostPort']
proc = createTunnel(port, args.user, args.host)
dRunning[c.id] = proc
tRunning[c.id] = proc
else:
tRunning[c.id] = "still running"
dead = {k: dRunning[k] for k in dRunning if k not in tRunning}
for k in dead:
logging.info(f'Closing tunnel {k}')
dRunning[k].terminate()
del dRunning[k]
time.sleep(1)

for c in cList:
if c.id not in dRunning:
logging.info(f'Found existing container with ID {c.short_id} and name {c.name}')
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

# 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']]

def configfile(spath, port):
hmsShellPrepend = [
Expand Down Expand Up @@ -110,9 +121,15 @@ def cleanfile(spath, port):

def cleanup(spath, port):
global dockerTunnel
global dRunning

cleanfile(spath, port)

for k, v in dRunning.items():
logging.info(f'Closing tunnel {k}')
v.terminate()


logging.warning(f'Closing remote docker socket connection')
dockerTunnel.terminate()

Expand All @@ -132,12 +149,14 @@ def cleanup(spath, port):
else:
logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO)

s = os.path.abspath(os.path.expanduser('~/.zshrc'))
s = os.path.abspath(os.path.expanduser('~/.zshenv'))

configfile(s, a.p)

main(a, s)
except KeyboardInterrupt:
logging.warning('Got CTRL-C, cleaning up (CTRL-C again to force)')
cleanup(s, a.p)
except Exception:
cleanup(s, a.p)

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
docker==3.7.3
26 changes: 26 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from setuptools import setup

def readme():
with open('README.md') as f:
return f.read()

setup(name='harbormaster',
version='0.2',
description='automating docker remote host forwarding',
long_description=readme(),
url='https://github.com/tanishq-dubey/harbormaster',
author='Tanishq Dubey',
author_email='tanishq@dubey.dev',
license='MIT',
packages=['harbormaster'],
zip_safe=False,
scripts=['harbormaster/harbormaster.py'],
classifiers=[
'Development Status :: 4 - Beta',
'Intended Audience :: Developers',
'Topic :: Software Development :: Build Tools',
'Topic :: Utilities',
'Environment :: Console',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3',
])

0 comments on commit 880ec22

Please sign in to comment.