diff --git a/cloud/docker/docker_service.py b/cloud/docker/docker_service.py index 3e7d4335813..369854626c6 100644 --- a/cloud/docker/docker_service.py +++ b/cloud/docker/docker_service.py @@ -464,7 +464,7 @@ try: from compose import __version__ as compose_version from compose.cli.command import project_from_options - from compose.service import ConvergenceStrategy + from compose.service import ConvergenceStrategy, NoSuchImageError from compose.cli.main import convergence_strategy_from_opts, build_action_from_opts, image_type_from_opt from compose.const import DEFAULT_TIMEOUT except ImportError as exc: @@ -484,7 +484,7 @@ u'tls_verify': u'--tlsverify' } - + class ContainerManager(DockerBaseClass): def __init__(self, client): @@ -598,11 +598,11 @@ def _get_auth_options(self): return options def cmd_up(self): - + start_deps = self.dependencies service_names = self.services detached = True - result = dict(changed=False, actions=dict(), ansible_facts=dict()) + result = dict(changed=False, actions=[], ansible_facts=dict()) up_options = { u'--no-recreate': False, @@ -624,26 +624,29 @@ def cmd_up(self): self.log("convergence strategy: %s" % converge) if self.pull: - result.update(self.cmd_pull()) + pull_output = self.cmd_pull() + result['changed'] = pull_output['changed'] + result['actions'] += pull_output['actions'] if self.build: - result.update(self.cmd_build()) + build_output = self.cmd_build() + result['changed'] = build_output['changed'] + result['actions'] += build_output['actions'] for service in self.project.services: if not service_names or service.name in service_names: plan = service.convergence_plan(strategy=converge) if plan.action != 'noop': result['changed'] = True - if self.debug or self.check_mode: - if not result['actions'].get(service.name): - result['actions'][service.name] = dict() - result['actions'][service.name][plan.action] = [] + result_action = dict(service=service.name) + result_action[plan.action] = [] for container in plan.containers: - result['actions'][service.name][plan.action].append(dict( + result_action[plan.action].append(dict( id=container.id, name=container.name, short_id=container.short_id, )) + result['actions'].append(result_action) if not self.check_mode and result['changed']: try: @@ -661,13 +664,19 @@ def cmd_up(self): self.client.fail("Error starting project - %s" % str(exc)) if self.stopped: - result.update(self.cmd_stop(service_names)) + stop_output = self.cmd_stop(service_names) + result['changed'] = stop_output['changed'] + result['actions'] += stop_output['actions'] if self.restarted: - result.update(self.cmd_restart(service_names)) + restart_output = self.cmd_restart(service_names) + result['changed'] = restart_output['changed'] + result['actions'] += restart_output['actions'] if self.scale: - result.update(self.cmd_scale()) + scale_output = self.cmd_scale() + result['changed'] = scale_output['changed'] + result['actions'] += scale_output['actions'] for service in self.project.services: result['ansible_facts'][service.name] = dict() @@ -729,105 +738,131 @@ def cmd_up(self): def cmd_pull(self): result = dict( changed=False, - actions=dict(), + actions=[], ) if not self.check_mode: for service in self.project.get_services(self.services, include_deps=False): + if 'image' not in service.options: + continue + self.log('Pulling image for service %s' % service.name) # store the existing image ID - image = service.image() - old_image_id = None - if image and image.get('Id'): - old_image_id = image['Id'] + old_image_id = '' + try: + image = service.image() + if image and image.get('Id'): + old_image_id = image['Id'] + except NoSuchImageError: + pass + except Exception as exc: + self.client.fail("Error: service image lookup failed - %s" % str(exc)) # pull the image - service.pull(ignore_pull_failures=False) + try: + service.pull(ignore_pull_failures=False) + except Exception as exc: + self.client.fail("Error: pull failed with %s" % str(exc)) # store the new image ID - image = service.image() - new_image_id = None - if image and image.get('Id'): - new_image_id = image['Id'] + new_image_id = '' + try: + image = service.image() + if image and image.get('Id'): + new_image_id = image['Id'] + except NoSuchImageError as exc: + self.client.fail("Error: service image lookup failed after pull - %s" % str(exc)) if new_image_id != old_image_id: # if a new image was pulled result['changed'] = True - result['actions'][service.name] = dict() - result['actions'][service.name]['pulled_image'] = dict( - name=service.image_name, - id=service.image()['Id'] - ) + result['actions'].append(dict( + service=service.name, + pulled_image=dict( + name=service.image_name, + id=new_image_id + ) + )) return result def cmd_build(self): result = dict( changed=False, - actions=dict(), + actions=[] ) if not self.check_mode: for service in self.project.get_services(self.services, include_deps=False): - self.log('Building image for service %s' % service.name) if service.can_be_built(): + self.log('Building image for service %s' % service.name) # store the existing image ID - image = service.image() - old_image_id = None - if image and image.get('Id'): - old_image_id = image['Id'] + old_image_id = '' + try: + image = service.image() + if image and image.get('Id'): + old_image_id = image['Id'] + except NoSuchImageError: + pass + except Exception as exc: + self.client.fail("Error: service image lookup failed - %s" % str(exc)) # build the image - new_image_id = service.build(pull=True, no_cache=self.nocache) + try: + new_image_id = service.build(pull=True, no_cache=self.nocache) + except Exception as exc: + self.client.fail("Error: build failed with %s" % str(exc)) if new_image_id not in old_image_id: # if a new image was built result['changed'] = True - result['actions'][service.name] = dict() - result['actions'][service.name]['built_image'] = dict( - name=service.image_name, - id=service.image()['Id'] - ) + result['actions'].append(dict( + service=service.name, + built_image=dict( + name=service.image_name, + id=new_image_id + ) + )) return result def cmd_down(self): result = dict( changed=False, - actions=dict(), + actions=[] ) - for service in self.project.services: containers = service.containers(stopped=True) if len(containers): result['changed'] = True - if self.debug or self.check_mode: - result['actions'][service.name] = dict() - result['actions'][service.name]['deleted'] = [container.name for container in containers] - + result['actions'].append(dict( + service=service.name, + deleted=[container.name for container in containers] + )) if not self.check_mode and result['changed']: image_type = image_type_from_opt('--rmi', self.remove_images) try: self.project.down(image_type, self.remove_volumes, self.remove_orphans) except Exception as exc: self.client.fail("Error stopping project - %s" % str(exc)) - return result def cmd_stop(self, service_names): result = dict( changed=False, - actions=dict() + actions=[] ) for service in self.project.services: if not service_names or service.name in service_names: - result['actions'][service.name] = dict() - result['actions'][service.name]['stop'] = [] + service_res = dict( + service=service.name, + stop=[] + ) for container in service.containers(stopped=False): result['changed'] = True - if self.debug: - result['actions'][service.name]['stop'].append(dict( - id=container.id, - name=container.name, - short_id=container.short_id, - )) + service_res['stop'].append(dict( + id=container.id, + name=container.name, + short_id=container.short_id + )) + result['actions'].append(service_res) if not self.check_mode and result['changed']: try: @@ -840,22 +875,24 @@ def cmd_stop(self, service_names): def cmd_restart(self, service_names): result = dict( changed=False, - actions=dict() + actions=[] ) for service in self.project.services: if not service_names or service.name in service_names: - result['actions'][service.name] = dict() - result['actions'][service.name]['restart'] = [] + service_res = dict( + service=service.name, + restart=[] + ) for container in service.containers(stopped=True): result['changed'] = True - if self.debug or self.check_mode: - result['actions'][service.name]['restart'].append(dict( - id=container.id, - name=container.name, - short_id=container.short_id, - )) - + service_res['restart'].append(dict( + id=container.id, + name=container.name, + short_id=container.short_id + )) + result['actions'].append(service_res) + if not self.check_mode and result['changed']: try: self.project.restart(service_names=service_names, timeout=self.timeout) @@ -867,22 +904,25 @@ def cmd_restart(self, service_names): def cmd_scale(self): result = dict( changed=False, - actions=dict() + actions=[] ) for service in self.project.services: if service.name in self.scale: - result['actions'][service.name] = dict() + service_res = dict( + service=service.name, + scale=0 + ) containers = service.containers(stopped=True) if len(containers) != self.scale[service.name]: result['changed'] = True - if self.debug or self.check_mode: - result['actions'][service.name]['scale'] = self.scale[service.name] - len(containers) + service_res['scale'] = self.scale[service.name] - len(containers) if not self.check_mode: try: service.scale(int(self.scale[service.name])) except Exception as exc: self.client.fail("Error scaling %s - %s" % (service.name, str(exc))) + result['actions'].append(service_res) return result