<filename>ebcli/docker/container.py
# 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 abc
import hashlib

from . import commands
from . import dockerrun
from . import log
from ..objects.exceptions import CommandError


class Container(object):
    """
    Abstract class subclassed by PreconfiguredContainer and GenericContainer.
    Container holds all of the data and most of the functionality needed to
    run a Docker container locally.
    """

    __metaclass__ = abc.ABCMeta

    def __init__(self, fs_handler, soln_stk, container_cfg,
                 envvars_map=None, host_port=None):
        """
        Constructor for Container.
        :param fs_handler: ContainerFSHandler: manages container related files
        :param soln_stk: SolutionStack: environment's solution stack
        :param container_cfg: dict: container_config.json as dict
        :param envvars_map: dict: optional key-val map of environment variables
        :param host_port: str: optional host port. Same as container port by default
        """

        self.fs_handler = fs_handler
        self.soln_stk = soln_stk
        self.container_cfg = container_cfg
        self.envvars_map = envvars_map
        self.host_port = host_port


    def start(self):
        """
        Download S3 object storing .dockercfg if Authentication provided
        in Dockerrun.aws.json, containerize app by adding Dockerfile if user
        doesn't provide one, then pull, build, and run the container.
        :return None
        """

        if self.fs_handler.require_append_dockerignore():
            self.fs_handler.append_dockerignore()

        if self.fs_handler.require_new_dockerfile():
            self._containerize()

        if self._require_pull():
            self._pull()

        self._remove()
        img_id = self._build()
        self._run(img_id)

    def validate(self):
        """
        Validates the container is configured properly.
        :return None
        """
        pass

    def get_name(self, hash_obj=hashlib.sha1):
        """
        Return the name that is or will be assigned to this container.
        :return str
        """

        hash_key = self.fs_handler.docker_proj_path.encode('utf-8')
        return hash_obj(hash_key).hexdigest()

    def is_running(self):
        return commands.is_running(self.get_name())


    @abc.abstractmethod
    def _containerize(self, destination_dockerfile=None):
        """
        Make a Dockerfile to destiantion path used for when user doesn't
        provide a Dockerfile.
        :param destination_dockerfile: str: full path to destination Dockerfile
        :return None
        """
        pass

    def _get_full_docker_path(self):
        """
        Return the full path to the Dockerfile we will be using for pulling
        and building Docker images.
        :return str
        """

        if self.fs_handler.dockerfile_exists:
            return self.fs_handler.dockerfile_path
        else:  # Then we create one at .elasticbeanstalk/Dockerfile.local
            return self.fs_handler.new_dockerfile_path

    def _require_pull(self):
        return dockerrun.require_docker_pull(self.fs_handler.dockerrun)

    def _pull(self):
        return commands.pull_img(self._get_full_docker_path())

    def _build(self):
        return commands.build_img(self.fs_handler.docker_proj_path,
                                  self._get_full_docker_path())

    def _run(self, img_id):
        log_volume_map = self._get_log_volume_map()
        if log_volume_map:
            log.make_logdirs(self.fs_handler.logdir_path, log_volume_map)

        return commands.run_container(self._get_full_docker_path(),
                                      img_id,
                                      envvars_map=self.envvars_map,
                                      host_port=self.host_port,
                                      volume_map=log_volume_map,
                                      name=self.get_name())

    def _get_log_volume_map(self):
        return log.get_log_volume_map(self.fs_handler.logdir_path,
                                      self.fs_handler.dockerrun)

    def _remove(self):
        try:
            commands.rm_container(self.get_name(), force=True)
        except CommandError:
            pass

<filename>ebcli/docker/container.py
# 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 abc
import hashlib

from . import commands
from . import dockerrun
from . import log
from ..objects.exceptions import CommandError


class Container(object):
    """
    Abstract class subclassed by PreconfiguredContainer and GenericContainer.
    Container holds all of the data and most of the functionality needed to
    run a Docker container locally.
    """

    __metaclass__ = abc.ABCMeta

    def __init__(self, fs_handler, soln_stk, container_cfg,
                 envvars_map=None, host_port=None):
        """
        Constructor for Container.
        :param fs_handler: ContainerFSHandler: manages container related files
        :param soln_stk: SolutionStack: environment's solution stack
        :param container_cfg: dict: container_config.json as dict
        :param envvars_map: dict: optional key-val map of environment variables
        :param host_port: str: optional host port. Same as container port by default
        """

        self.fs_handler = fs_handler
        self.soln_stk = soln_stk
        self.container_cfg = container_cfg
        self.envvars_map = envvars_map
        self.host_port = host_port


    def start(self):
        """
        Download S3 object storing .dockercfg if Authentication provided
        in Dockerrun.aws.json, containerize app by adding Dockerfile if user
        doesn't provide one, then pull, build, and run the container.
        :return None
        """

        if self.fs_handler.require_append_dockerignore():
            self.fs_handler.append_dockerignore()

        if self.fs_handler.require_new_dockerfile():
            self._containerize()

        if self._require_pull():
            self._pull()

        self._remove()
        img_id = self._build()
        self._run(img_id)

    def validate(self):
        """
        Validates the container is configured properly.
        :return None
        """
        pass

    def get_name(self, hash_obj=hashlib.sha1):
        """
        Return the name that is or will be assigned to this container.
        :return str
        """

        hash_key = self.fs_handler.docker_proj_path.encode('utf-8')
        return hash_obj(hash_key).hexdigest()

    def is_running(self):
        return commands.is_running(self.get_name())


    @abc.abstractmethod
    def _containerize(self, destination_dockerfile=None):
        """
        Make a Dockerfile to destiantion path used for when user doesn't
        provide a Dockerfile.
        :param destination_dockerfile: str: full path to destination Dockerfile
        :return None
        """
        pass

    def _get_full_docker_path(self):
        """
        Return the full path to the Dockerfile we will be using for pulling
        and building Docker images.
        :return str
        """

        if self.fs_handler.dockerfile_exists:
            return self.fs_handler.dockerfile_path
        else:  # Then we create one at .elasticbeanstalk/Dockerfile.local
            return self.fs_handler.new_dockerfile_path

    def _require_pull(self):
        return dockerrun.require_docker_pull(self.fs_handler.dockerrun)

    def _pull(self):
        return commands.pull_img(self._get_full_docker_path())

    def _build(self):
        return commands.build_img(self.fs_handler.docker_proj_path,
                                  self._get_full_docker_path())

    def _run(self, img_id):
        log_volume_map = self._get_log_volume_map()
        if log_volume_map:
            log.make_logdirs(self.fs_handler.logdir_path, log_volume_map)

        return commands.run_container(self._get_full_docker_path(),
                                      img_id,
                                      envvars_map=self.envvars_map,
                                      host_port=self.host_port,
                                      volume_map=log_volume_map,
                                      name=self.get_name())

    def _get_log_volume_map(self):
        return log.get_log_volume_map(self.fs_handler.logdir_path,
                                      self.fs_handler.dockerrun)

    def _remove(self):
        try:
            commands.rm_container(self.get_name(), force=True)
        except CommandError:
            pass

# 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. Abstract class subclassed by PreconfiguredContainer and GenericContainer.     Container holds all of the data and most of the functionality needed to     run a Docker container locally. Constructor for Container.         :param fs_handler: ContainerFSHandler: manages container related files         :param soln_stk: SolutionStack: environment's solution stack         :param container_cfg: dict: container_config.json as dict         :param envvars_map: dict: optional key-val map of environment variables         :param host_port: str: optional host port. Same as container port by default Download S3 object storing .dockercfg if Authentication provided         in Dockerrun.aws.json, containerize app by adding Dockerfile if user         doesn't provide one, then pull, build, and run the container.         :return None Validates the container is configured properly.         :return None Return the name that is or will be assigned to this container.         :return str Make a Dockerfile to destiantion path used for when user doesn't         provide a Dockerfile.         :param destination_dockerfile: str: full path to destination Dockerfile         :return None Return the full path to the Dockerfile we will be using for pulling         and building Docker images.         :return str # Then we create one at .elasticbeanstalk/Dockerfile.local