Add a new fig command for retrieving the locally bound port of a service.
Signed-off-by: Daniel Nephin <dnephin@gmail.com>
This commit is contained in:
parent
2827786886
commit
c48ee5caef
9 changed files with 164 additions and 51 deletions
|
|
@ -9,6 +9,8 @@ class UserError(Exception):
|
|||
def __unicode__(self):
|
||||
return self.msg
|
||||
|
||||
__str__ = __unicode__
|
||||
|
||||
|
||||
class DockerNotFoundMac(UserError):
|
||||
def __init__(self):
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ class TopLevelCommand(Command):
|
|||
help Get help on a command
|
||||
kill Kill containers
|
||||
logs View output from containers
|
||||
port Print the public port for a port binding
|
||||
ps List containers
|
||||
rm Remove stopped containers
|
||||
run Run a one-off command
|
||||
|
|
@ -148,6 +149,26 @@ class TopLevelCommand(Command):
|
|||
print("Attaching to", list_containers(containers))
|
||||
LogPrinter(containers, attach_params={'logs': True}, monochrome=monochrome).run()
|
||||
|
||||
def port(self, project, options):
|
||||
"""
|
||||
Print the public port for a port binding.
|
||||
|
||||
Usage: port [options] SERVICE PRIVATE_PORT
|
||||
|
||||
Options:
|
||||
--protocol=proto tcp or udp (defaults to tcp)
|
||||
--index=index index of the container if there are multiple
|
||||
instances of a service (defaults to 1)
|
||||
"""
|
||||
service = project.get_service(options['SERVICE'])
|
||||
try:
|
||||
container = service.get_container(number=options.get('--index') or 1)
|
||||
except ValueError as e:
|
||||
raise UserError(str(e))
|
||||
print(container.get_local_port(
|
||||
options['PRIVATE_PORT'],
|
||||
protocol=options.get('--protocol') or 'tcp') or '')
|
||||
|
||||
def ps(self, project, options):
|
||||
"""
|
||||
List containers.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
from __future__ import unicode_literals
|
||||
from __future__ import absolute_import
|
||||
|
||||
from fig.packages import six
|
||||
|
||||
|
||||
class Container(object):
|
||||
"""
|
||||
|
|
@ -63,17 +65,20 @@ class Container(object):
|
|||
return None
|
||||
|
||||
@property
|
||||
def human_readable_ports(self):
|
||||
def ports(self):
|
||||
self.inspect_if_not_inspected()
|
||||
if not self.dictionary['NetworkSettings']['Ports']:
|
||||
return ''
|
||||
ports = []
|
||||
for private, public in list(self.dictionary['NetworkSettings']['Ports'].items()):
|
||||
if public:
|
||||
ports.append('%s->%s' % (public[0]['HostPort'], private))
|
||||
else:
|
||||
ports.append(private)
|
||||
return ', '.join(ports)
|
||||
return self.dictionary['NetworkSettings']['Ports'] or {}
|
||||
|
||||
@property
|
||||
def human_readable_ports(self):
|
||||
def format_port(private, public):
|
||||
if not public:
|
||||
return private
|
||||
return '{HostIp}:{HostPort}->{private}'.format(
|
||||
private=private, **public[0])
|
||||
|
||||
return ', '.join(format_port(*item)
|
||||
for item in sorted(six.iteritems(self.ports)))
|
||||
|
||||
@property
|
||||
def human_readable_state(self):
|
||||
|
|
@ -105,6 +110,10 @@ class Container(object):
|
|||
self.inspect_if_not_inspected()
|
||||
return self.dictionary['State']['Running']
|
||||
|
||||
def get_local_port(self, port, protocol='tcp'):
|
||||
port = self.ports.get("%s/%s" % (port, protocol))
|
||||
return "{HostIp}:{HostPort}".format(**port[0]) if port else None
|
||||
|
||||
def start(self, **options):
|
||||
return self.client.start(self.id, **options)
|
||||
|
||||
|
|
|
|||
|
|
@ -78,9 +78,22 @@ class Service(object):
|
|||
name = get_container_name(container)
|
||||
if not name or not is_valid_name(name, one_off):
|
||||
return False
|
||||
project, name, number = parse_name(name)
|
||||
project, name, _number = parse_name(name)
|
||||
return project == self.project and name == self.name
|
||||
|
||||
def get_container(self, number=1):
|
||||
"""Return a :class:`fig.container.Container` for this service. The
|
||||
container must be active, and match `number`.
|
||||
"""
|
||||
for container in self.client.containers():
|
||||
if not self.has_container(container):
|
||||
continue
|
||||
_, _, container_number = parse_name(get_container_name(container))
|
||||
if container_number == number:
|
||||
return Container.from_ps(self.client, container)
|
||||
|
||||
raise ValueError("No container found for %s_%s" % (self.name, number))
|
||||
|
||||
def start(self, **options):
|
||||
for c in self.containers(stopped=True):
|
||||
self.start_container_if_stopped(c, **options)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue