Merge pull request #562 from tjrivera/insecure-registry

Allow dependent image pull from insecure registry
This commit is contained in:
Ben Firshman 2014-10-22 18:45:03 +01:00
commit 9813a8d5be
4 changed files with 54 additions and 22 deletions

View File

@ -264,17 +264,21 @@ class TopLevelCommand(Command):
Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...] Usage: run [options] [-e KEY=VAL...] SERVICE [COMMAND] [ARGS...]
Options: Options:
-d Detached mode: Run container in the background, print --allow-insecure-ssl Allow insecure connections to the docker
new container name. registry
--entrypoint CMD Override the entrypoint of the image. -d Detached mode: Run container in the background, print
-e KEY=VAL Set an environment variable (can be used multiple times) new container name.
--no-deps Don't start linked services. --entrypoint CMD Override the entrypoint of the image.
--rm Remove container after run. Ignored in detached mode. -e KEY=VAL Set an environment variable (can be used multiple times)
-T Disable pseudo-tty allocation. By default `fig run` --no-deps Don't start linked services.
allocates a TTY. --rm Remove container after run. Ignored in detached mode.
-T Disable pseudo-tty allocation. By default `fig run`
allocates a TTY.
""" """
service = project.get_service(options['SERVICE']) service = project.get_service(options['SERVICE'])
insecure_registry = options['--allow-insecure-ssl']
if not options['--no-deps']: if not options['--no-deps']:
deps = service.get_linked_names() deps = service.get_linked_names()
@ -309,8 +313,11 @@ class TopLevelCommand(Command):
if options['--entrypoint']: if options['--entrypoint']:
container_options['entrypoint'] = options.get('--entrypoint') container_options['entrypoint'] = options.get('--entrypoint')
container = service.create_container(
container = service.create_container(one_off=True, **container_options) one_off=True,
insecure_registry=insecure_registry,
**container_options
)
if options['-d']: if options['-d']:
service.start_container(container, ports=None, one_off=True) service.start_container(container, ports=None, one_off=True)
print(container.name) print(container.name)
@ -396,12 +403,15 @@ class TopLevelCommand(Command):
Usage: up [options] [SERVICE...] Usage: up [options] [SERVICE...]
Options: Options:
-d Detached mode: Run containers in the background, --allow-insecure-ssl Allow insecure connections to the docker
print new container names. registry
--no-color Produce monochrome output. -d Detached mode: Run containers in the background,
--no-deps Don't start linked services. print new container names.
--no-recreate If containers already exist, don't recreate them. --no-color Produce monochrome output.
--no-deps Don't start linked services.
--no-recreate If containers already exist, don't recreate them.
""" """
insecure_registry = options['--allow-insecure-ssl']
detached = options['-d'] detached = options['-d']
monochrome = options['--no-color'] monochrome = options['--no-color']
@ -413,7 +423,8 @@ class TopLevelCommand(Command):
project.up( project.up(
service_names=service_names, service_names=service_names,
start_links=start_links, start_links=start_links,
recreate=recreate recreate=recreate,
insecure_registry=insecure_registry,
) )
to_attach = [c for s in project.get_services(service_names) for c in s.containers()] to_attach = [c for s in project.get_services(service_names) for c in s.containers()]

View File

@ -167,7 +167,7 @@ class Project(object):
else: else:
log.info('%s uses an image, skipping' % service.name) log.info('%s uses an image, skipping' % service.name)
def up(self, service_names=None, start_links=True, recreate=True): def up(self, service_names=None, start_links=True, recreate=True, insecure_registry=False):
running_containers = [] running_containers = []
for service in self.get_services(service_names, include_links=start_links): for service in self.get_services(service_names, include_links=start_links):
@ -175,7 +175,7 @@ class Project(object):
for (_, container) in service.recreate_containers(): for (_, container) in service.recreate_containers():
running_containers.append(container) running_containers.append(container)
else: else:
for container in service.start_or_create_containers(): for container in service.start_or_create_containers(insecure_registry=insecure_registry):
running_containers.append(container) running_containers.append(container)
return running_containers return running_containers

View File

@ -168,7 +168,7 @@ class Service(object):
log.info("Removing %s..." % c.name) log.info("Removing %s..." % c.name)
c.remove(**options) c.remove(**options)
def create_container(self, one_off=False, **override_options): def create_container(self, one_off=False, insecure_registry=False, **override_options):
""" """
Create a container for this service. If the image doesn't exist, attempt to pull Create a container for this service. If the image doesn't exist, attempt to pull
it. it.
@ -179,7 +179,11 @@ class Service(object):
except APIError as e: except APIError as e:
if e.response.status_code == 404 and e.explanation and 'No such image' in str(e.explanation): if e.response.status_code == 404 and e.explanation and 'No such image' in str(e.explanation):
log.info('Pulling image %s...' % container_options['image']) log.info('Pulling image %s...' % container_options['image'])
output = self.client.pull(container_options['image'], stream=True) output = self.client.pull(
container_options['image'],
stream=True,
insecure_registry=insecure_registry
)
stream_output(output, sys.stdout) stream_output(output, sys.stdout)
return Container.create(self.client, **container_options) return Container.create(self.client, **container_options)
raise raise
@ -270,12 +274,12 @@ class Service(object):
) )
return container return container
def start_or_create_containers(self): def start_or_create_containers(self, insecure_registry=False):
containers = self.containers(stopped=True) containers = self.containers(stopped=True)
if not containers: if not containers:
log.info("Creating %s..." % self._next_container_name(containers)) log.info("Creating %s..." % self._next_container_name(containers))
new_container = self.create_container() new_container = self.create_container(insecure_registry=insecure_registry)
return [self.start_container(new_container)] return [self.start_container(new_container)]
else: else:
return [self.start_container_if_stopped(c) for c in containers] return [self.start_container_if_stopped(c) for c in containers]

View File

@ -6,6 +6,7 @@ from .. import unittest
import mock import mock
import docker import docker
from requests import Response
from fig import Service from fig import Service
from fig.container import Container from fig.container import Container
@ -14,6 +15,7 @@ from fig.service import (
split_port, split_port,
parse_volume_spec, parse_volume_spec,
build_volume_binding, build_volume_binding,
APIError,
) )
@ -174,6 +176,21 @@ class ServiceTest(unittest.TestCase):
self.mock_client.pull.assert_called_once_with('someimage:sometag', insecure_registry=True) self.mock_client.pull.assert_called_once_with('someimage:sometag', insecure_registry=True)
mock_log.info.assert_called_once_with('Pulling foo (someimage:sometag)...') mock_log.info.assert_called_once_with('Pulling foo (someimage:sometag)...')
@mock.patch('fig.service.log', autospec=True)
def test_create_container_from_insecure_registry(self, mock_log):
service = Service('foo', client=self.mock_client, image='someimage:sometag')
mock_response = mock.Mock(Response)
mock_response.status_code = 404
mock_response.reason = "Not Found"
Container.create = mock.Mock()
Container.create.side_effect = APIError('Mock error', mock_response, "No such image")
try:
service.create_container(insecure_registry=True)
except APIError: # We expect the APIError because our service requires a non-existent image.
pass
self.mock_client.pull.assert_called_once_with('someimage:sometag', insecure_registry=True, stream=True)
mock_log.info.assert_called_once_with('Pulling image someimage:sometag...')
class ServiceVolumesTest(unittest.TestCase): class ServiceVolumesTest(unittest.TestCase):