text: # Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  #
  # Licensed under the Apache License, Version 2.0 (the "License"). You
  # may not use this file except in compliance with the License. A copy of
  # the License is located at
  #
  # http://aws.amazon.com/apache2.0/
  #
  # or in the "license" file accompanying this file. This file is
  # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
  # ANY KIND, either express or implied. See the License for the specific
  # language governing permissions and limitations under the License.
  import os
  
  from botocore.compat import six
  
  from ebcli.containers.envvarcollector import EnvvarCollector
  
  
  AWSEB_LOGS = 'awseb-logs-'
  COMPOSE_CMD_KEY = 'command'
  COMPOSE_ENV_KEY = 'environment'
  COMPOSE_IMG_KEY = 'image'
  COMPOSE_LINKS_KEY = 'links'
  COMPOSE_PORTS_KEY = 'ports'
  COMPOSE_VOLUMES_KEY = 'volumes'
  CONTAINER_DEF_CMD_KEY = 'command'
  CONTAINER_DEF_CONTAINERPORT_KEY = 'containerPort'
  CONTAINER_DEF_ENV_KEY = 'environment'
  CONTAINER_DEF_ENV_NAME_KEY = 'name'
  CONTAINER_DEF_ENV_VALUE_KEY = 'value'
  CONTAINER_DEF_HOSTPORT_KEY = 'hostPort'
  CONTAINER_DEF_IMG_KEY = 'image'
  CONTAINER_DEF_KEY = 'containerDefinitions'
  CONTAINER_DEF_LINKS_KEY = 'links'
  CONTAINER_DEF_NAME_KEY = 'name'
  CONTAINER_DEF_PORT_MAPPINGS_KEY = 'portMappings'
  CONTAINER_PATH_KEY = 'containerPath'
  CONTAINER_DEF_PRIVILEGED_KEY = 'privileged'
  LOCAL_CONTAINER_DEF_KEY = 'localContainerDefinitions'
  MOUNT_POINTS = 'mountPoints'
  READ_ONLY_KEY = 'readOnly'
  READ_ONLY_VOLUME = ':ro'
  SOURCE_VOLUME_KEY = 'sourceVolume'
  VAR_APP_CURRENT = '/var/app/current/'
  VOLUMES_KEY = 'volumes'
  VOLUMES_NAME_KEY = 'name'
  VOLUMES_HOST_KEY = 'host'
  VOLUMES_SOURCE_PATH_KEY = 'sourcePath'
  
  
  iter_services = six.iterkeys
  
  
  def compose_dict(dockerrun, docker_proj_path, host_log, high_priority_env):
      """
      Return a docker-compose.yml representation as dict translated from the info
      provided in Dockerrun.aws.json.
      :param dockerrun: dict: dictionary representation of Dockerrun.aws.json
      :param docker_proj_path: str: path of the project directory
      :param host_log: str: path to the root host logs
      :param high_priority_env: EnvvarCollector: Contains environment variables to add and remove
      :return dict
      """
  
      # Service is to docker-compose.yml as container definition
      # is to Dockerrun.aws.json. We want to turn definition -> service
      services = {}
      definitions = (dockerrun.get(CONTAINER_DEF_KEY, []) +
                     dockerrun.get(LOCAL_CONTAINER_DEF_KEY, []))
  
      # Maps 'volume name' to local path
      # E.x.: proxy-static -> /workspace/eb-project/proxy/html
      volume_map = _get_volume_map(dockerrun.get(VOLUMES_KEY, []), docker_proj_path)
  
      for definition in definitions:
          _add_service(services, definition, volume_map, host_log, high_priority_env)
  
      return services
  
  
  def _add_service(services, definition, volume_map, host_log, high_priority_env):
      realname = definition[CONTAINER_DEF_NAME_KEY]
      img = definition[CONTAINER_DEF_IMG_KEY]
      links = definition.get(CONTAINER_DEF_LINKS_KEY, [])
      command = definition.get(CONTAINER_DEF_CMD_KEY, [])
      dockerrun_port_mappings = definition.get(CONTAINER_DEF_PORT_MAPPINGS_KEY, [])
      ports = _get_port_maps(dockerrun_port_mappings)
      remote_mountpoints = definition.get(MOUNT_POINTS, [])
      definition_env = EnvvarCollector(_get_definition_envvars(definition))
      merged_envvars = definition_env.merge(high_priority_env).filtered().map
      privileged = definition.get(CONTAINER_DEF_PRIVILEGED_KEY, None)
  
      service = {COMPOSE_IMG_KEY: img}
  
      if command:
          service[COMPOSE_CMD_KEY] = command
  
      if ports:
          service[COMPOSE_PORTS_KEY] = ports
  
      if links:
          service[COMPOSE_LINKS_KEY] = ['{}:{}'.format(_fakename(n), n)
                                        for n in links]
      if merged_envvars:
          service[COMPOSE_ENV_KEY] = merged_envvars
  
      if privileged is not None:
          service[CONTAINER_DEF_PRIVILEGED_KEY] = privileged
  
      volumes = []
      for mp in remote_mountpoints:
          src_vol = mp[SOURCE_VOLUME_KEY]
          container_path = mp[CONTAINER_PATH_KEY]
          read_only = mp.get(READ_ONLY_KEY)
  
          if src_vol in volume_map:
              src_path = volume_map[src_vol]
  
          elif src_vol.startswith(AWSEB_LOGS):
              dirname = src_vol[len(AWSEB_LOGS):]
              src_path = os.path.join(host_log, dirname)
  
              os.makedirs(src_path)
          else:
              continue
  
          volume = '{}:{}'.format(src_path, container_path)
          if read_only:
              volume += READ_ONLY_VOLUME
          volumes.append(volume)
  
      if volumes:
          service[COMPOSE_VOLUMES_KEY] = volumes
  
      # alias the container names because '-' character is not allowed for service
      # names in docker-compose.yml
      services[_fakename(realname)] = service
  
  
  def _get_port_maps(dockerrun_port_mappings):
      port_maps = []
  
      for m in dockerrun_port_mappings:
          hostport = m[CONTAINER_DEF_HOSTPORT_KEY]
          containerport = m[CONTAINER_DEF_CONTAINERPORT_KEY]
          port_map = '{}:{}'.format(hostport, containerport)
          port_maps.append(port_map)
  
      return port_maps
  
  
  def _get_volume_map(volumes, docker_proj_path):
      vmap = {}
  
      for volume in volumes:
          name = volume[VOLUMES_NAME_KEY]
          source_path = volume[VOLUMES_HOST_KEY][VOLUMES_SOURCE_PATH_KEY]
  
          if source_path.startswith(VAR_APP_CURRENT):
              local_relative_path = source_path[len(VAR_APP_CURRENT):]
              local_source_path = os.path.join(docker_proj_path, local_relative_path)
          else:
              local_source_path = source_path
  
          vmap[name] = local_source_path
      return vmap
  
  
  def _fakename(realname):
      # docker-compose service names must be alphanumeric
      return ''.join(c for c in realname if c.isalnum())
  
  
  def _get_definition_envvars(definition):
      return {e[CONTAINER_DEF_ENV_NAME_KEY]: e[CONTAINER_DEF_ENV_VALUE_KEY] for e
              in definition.get(CONTAINER_DEF_ENV_KEY, [])}
  