def _create_container(self, image_path, microservice_name, dict_ports, dict_environment, dict_volumes, dockyard_user, dockyard_password, resource_limits): ports = None port_bindings = None if dict_ports: ports = map(int, dict_ports.values()) port_bindings = dict((int(port_container), int(port_host)) for port_host, port_container in dict_ports.iteritems()) environment = dict_environment or None volumes = None volume_bindings = None if dict_volumes: volumes = dict_volumes.values() volume_bindings = dict( (path_host, {'bind': path_container, 'ro': False}) for path_host, path_container in dict_volumes.iteritems()) dockyard_address, image_name, image_tag = split_image_path(image_path) docker_api = self._get_docker_api(dockyard_address, dockyard_user, dockyard_password) self._pull_latest_image(docker_api, image_path) host_config = self._create_host_config(docker_api, resource_limits, volume_bindings, port_bindings) container_info = docker_api.create_container(image_path, ports=ports, environment=environment, volumes=volumes, host_config=host_config) long_container_id = container_info['Id'] return long_container_id
def _create_container(self, image_path, microservice_name, dict_ports, dict_environment, dict_volumes, dockyard_user, dockyard_password, resource_limits): ports = None port_bindings = None if dict_ports: ports = map(int, dict_ports.values()) port_bindings = dict((int(port_container), int(port_host)) for port_host, port_container in dict_ports.iteritems()) environment = dict_environment or None volumes = None volume_bindings = None if dict_volumes: volumes = dict_volumes.values() volume_bindings = dict( (path_host, {'bind': path_container, 'ro': False}) for path_host, path_container in dict_volumes.iteritems()) dockyard_address, image_name, image_tag = split_image_path(image_path) docker_api = self._get_docker_api(dockyard_address, dockyard_user, dockyard_password) self._pull_latest_image(docker_api, image_path) dev = environment.get('ARMADA_VAGRANT_DEV') if dev: self._tag_local_image(docker_api, image_path) image_path = '{}:{}'.format(image_name, image_tag) host_config = self._create_host_config(docker_api, resource_limits, volume_bindings, port_bindings) container_info = docker_api.create_container(image_path, ports=ports, environment=environment, volumes=volumes, host_config=host_config) long_container_id = container_info['Id'] return long_container_id
def _pull_latest_image(self, docker_api, image_path): dockyard_address, image_name, image_tag = split_image_path(image_path) if dockyard_address: try: docker_client.docker_pull(docker_api, dockyard_address, image_name, image_tag) except Exception as e: if "ping attempt failed" in str(e): raise RuntimeError(INSECURE_REGISTRY_ERROR_MSG.format(header="ERROR!", address=dockyard_address)) raise e
def _pull_latest_image(self, docker_api, image_path): dockyard_address, image_name, image_tag = split_image_path(image_path) if dockyard_address: try: docker_client.docker_pull(docker_api, dockyard_address, image_name, image_tag) except Exception as e: if "ping attempt failed" in str(e): raise RuntimeError(INSECURE_REGISTRY_ERROR_MSG.format(header="ERROR!", address=dockyard_address)) raise e
def _create_service(self, image_path=None, microservice_name=None, microservice_env=None, microservice_app_id=None, dockyard_user=None, dockyard_password=None, ports=None, environment=None, volumes=None, run_command=None, resource_limits=None, configs=None, **kwargs): # Check required fields in received JSON: if not image_path: raise ValueError('Field image_path cannot be empty.') if not run_command: raise ValueError('Field run_command cannot be empty.') if kwargs: get_logger().warning('JSON data sent to API contains unrecognized keys: {}'.format(list(kwargs.keys()))) # Set default values: environment = environment or {} ports = ports or {} volumes = volumes or {} resource_limits = resource_limits or {} configs = configs or [] image_name = split_image_path(image_path)[1] microservice_name = microservice_name or environment.get('MICROSERVICE_NAME') or image_name microservice_env = microservice_env or environment.get('MICROSERVICE_ENV') microservice_app_id = microservice_app_id or environment.get('MICROSERVICE_APP_ID') # Update environment variables with armada-specific values: restart_parameters = { 'image_path': image_path, 'microservice_name': microservice_name, 'microservice_env': microservice_env, 'microservice_app_id': microservice_app_id, 'dockyard_user': dockyard_user, 'dockyard_password': dockyard_password, 'ports': ports, 'environment': environment, 'volumes': volumes, 'run_command': run_command, 'resource_limits': resource_limits, 'configs': configs, } environment['RESTART_CONTAINER_PARAMETERS'] = base64.b64encode(json.dumps(restart_parameters, sort_keys=True)) environment['ARMADA_RUN_COMMAND'] = base64.b64encode(run_command) environment['MICROSERVICE_NAME'] = microservice_name if microservice_env: environment['MICROSERVICE_ENV'] = microservice_env if microservice_app_id: environment['MICROSERVICE_APP_ID'] = microservice_app_id config_path, hermes_volumes = process_hermes(microservice_name, image_name, microservice_env, microservice_app_id, configs) if config_path: environment['CONFIG_PATH'] = config_path volumes[docker_client.DOCKER_SOCKET_PATH] = docker_client.DOCKER_SOCKET_PATH volumes.update(hermes_volumes or {}) long_container_id = self._create_container( image_path, microservice_name, ports, environment, volumes, dockyard_user, dockyard_password, resource_limits) return long_container_id
def get_image_creation_time(self, image_path, tag='latest'): image_name = split_image_path(image_path)[1] url = '{}/v2/{}/manifests/{}'.format(self.url, image_name, tag) manifests = _http_get(url, auth=self.auth).json() if 'history' not in manifests: return None return max([ json.loads(history['v1Compatibility'])['created'] for history in manifests['history'] ])
def command_build(args): dockerfile_path = args.file if not os.path.exists(dockerfile_path): raise ArmadaCommandException( 'ERROR: {} not found.'.format(dockerfile_path)) source_base_image_paths = _get_base_image_paths(dockerfile_path) dockyard_alias = args.dockyard or get_default_alias() try: image = ArmadaImageFactory(args.microservice_name, dockyard_alias, os.environ.get('MICROSERVICE_NAME')) except InvalidImagePathException: raise ArmadaCommandException('No microservice name supplied.') notify_about_detected_dev_environment(image.image_name) for source_base_image_path in source_base_image_paths: source_dockyard_address = split_image_path(source_base_image_path)[0] if source_dockyard_address: base_image = ArmadaImageFactory(source_base_image_path, args.dockyard) else: print_warning( 'Using image name only as base image ("FROM {}") has been deprecated. ' 'Consider providing full dockyard/docker registry address, ' 'e.g.: "FROM dockyard.armada.sh/microservice".'.format( source_base_image_path)) base_image = ArmadaImageFactory(source_base_image_path, dockyard_alias) base_image_path = _pull_base_image(base_image, source_base_image_path, dockyard_alias) if base_image_path != source_base_image_path: if is_verbose(): print( 'Tagging "{base_image_path}" as "{source_base_image_path}"\n' .format(**locals())) tag_command = "docker tag {} {}".format(base_image_path, source_base_image_path) assert execute_local_command(tag_command, stream_output=True, retries=1)[0] == 0 build_command = _generate_build_command(args, dockerfile_path, image) assert execute_local_command(' '.join(build_command), stream_output=True)[0] == 0
def __new__(cls, image_path, dockyard_alias=None, fallback_service_name=None): dockyard_address, image_name, image_tag = split_image_path(image_path) image_name = image_name or fallback_service_name if not image_name: raise InvalidImagePathException if dockyard_alias == 'local': return LocalArmadaImage(dockyard_address, image_name, image_tag) if dockyard_alias and dockyard_address: raise ArmadaCommandException('Ambiguous dockyard. Please specify either -d/--dockyard ' 'or dockyard_hostname[:port]/image_name') return RemoteArmadaImage(dockyard_address, image_name, image_tag, dockyard_alias)
def __new__(cls, image_path, dockyard_alias=None, fallback_service_name=None): dockyard_address, image_name, image_tag = split_image_path(image_path) image_name = image_name or fallback_service_name if not image_name: raise InvalidImagePathException if not dockyard_address and not dockyard_alias and image_name.startswith('microservice'): dockyard_address = DOCKYARD_FALLBACK_ADDRESS if dockyard_alias == 'local': return LocalArmadaImage(dockyard_address, image_name, image_tag) if dockyard_alias and dockyard_address: dockyard_address = None return RemoteArmadaImage(dockyard_address, image_name, image_tag, dockyard_alias)
def __new__(cls, image_path, dockyard_alias=None, fallback_service_name=None): dockyard_address, image_name, image_tag = split_image_path(image_path) image_name = image_name or fallback_service_name if not image_name: raise InvalidImagePathException if dockyard_alias == 'local': return LocalArmadaImage(dockyard_address, image_name, image_tag) if dockyard_alias and dockyard_address: raise ArmadaCommandException( 'Ambiguous dockyard. Please specify either -d/--dockyard ' 'or dockyard_hostname[:port]/image_name') return RemoteArmadaImage(dockyard_address, image_name, image_tag, dockyard_alias)
def _tag_local_image(self, docker_api, image_path): dockyard_address, image_name, image_tag = split_image_path(image_path) if dockyard_address: docker_client.docker_tag(docker_api, dockyard_address, image_name, image_tag)
def _pull_latest_image(self, docker_api, image_path): dockyard_address, image_name, image_tag = split_image_path(image_path) if dockyard_address: docker_client.docker_pull(docker_api, dockyard_address, image_name, image_tag)
def _create_service(self, image_path=None, microservice_name=None, microservice_env=None, microservice_app_id=None, dockyard_user=None, dockyard_password=None, ports=None, environment=None, volumes=None, run_command=None, resource_limits=None, configs=None, **kwargs): # Check required fields in received JSON: if not image_path: raise ValueError('Field image_path cannot be empty.') if not run_command: raise ValueError('Field run_command cannot be empty.') if kwargs: get_logger().warning( 'JSON data sent to API contains unrecognized keys: %s', list(kwargs.keys())) # Set default values: environment = environment or {} ports = ports or {} volumes = volumes or {} resource_limits = resource_limits or {} configs = configs or [] image_name = split_image_path(image_path)[1] microservice_name = microservice_name or environment.get( 'MICROSERVICE_NAME') or image_name microservice_env = microservice_env or environment.get( 'MICROSERVICE_ENV') microservice_app_id = microservice_app_id or environment.get( 'MICROSERVICE_APP_ID') # Update environment variables with armada-specific values: restart_parameters = { 'image_path': image_path, 'microservice_name': microservice_name, 'microservice_env': microservice_env, 'microservice_app_id': microservice_app_id, 'dockyard_user': dockyard_user, 'dockyard_password': dockyard_password, 'ports': ports, 'environment': environment, 'volumes': volumes, 'run_command': run_command, 'resource_limits': resource_limits, 'configs': configs, } dev = environment.get('ARMADA_DEVELOP') if dev: restart_parameters['image_path'] = image_path.split('/', 1)[-1] environment['ARMADA_RUN_COMMAND'] = base64.b64encode( run_command.encode()) environment['IMAGE_NAME'] = image_name environment['MICROSERVICE_NAME'] = microservice_name environment['RESTART_CONTAINER_PARAMETERS'] = base64.b64encode( json.dumps(restart_parameters, sort_keys=True).encode()) if microservice_env: environment['MICROSERVICE_ENV'] = microservice_env if microservice_app_id: environment['MICROSERVICE_APP_ID'] = microservice_app_id config_path, hermes_volumes = process_hermes(microservice_name, image_name, microservice_env, microservice_app_id, configs) if config_path: environment['CONFIG_PATH'] = config_path volumes[docker_client. DOCKER_SOCKET_PATH] = docker_client.DOCKER_SOCKET_PATH volumes.update(hermes_volumes or {}) long_container_id = self._create_container(image_path, ports, environment, volumes, dockyard_user, dockyard_password, resource_limits) return long_container_id
def get_image_creation_time(self, image_path, tag='latest'): image_name = split_image_path(image_path)[1] long_image_id = self.__get_remote_long_image_id(image_name, tag) url = '{}/v1/images/{}/json'.format(self.url, long_image_id) image_dict = _http_get(url, auth=self.auth).json() return str(image_dict.get('created'))