Пример #1
0
def test_copy_dir_to_container(mocker, archive_response: bool, expected_count: int, expected_exception: bool):
    from demisto_sdk.commands.lint import helpers
    mocker.patch.object(helpers, 'docker')
    mocker.patch.object(helpers, 'tarfile')
    mocker.patch.object(helpers, 'os')
    mock_container = mocker.MagicMock()
    mock_container_path = mocker.MagicMock()
    mock_host_path = mocker.MagicMock()
    mock_container.put_archive.side_effect = archive_response
    if expected_exception:
        with pytest.raises(Exception):
            helpers.copy_dir_to_container(mock_container, mock_container_path, mock_host_path)
    else:
        helpers.copy_dir_to_container(mock_container, mock_container_path, mock_host_path)

    assert mock_container.put_archive.call_count == expected_count
Пример #2
0
    def _docker_image_create(self, docker_base_image: str) -> str:
        """ Create docker image:
            1. Installing 'build base' if required in alpine images version - https://wiki.alpinelinux.org/wiki/GCC
            2. Installing pypi packs - if only pylint required - only pylint installed otherwise all pytest and pylint
               installed, packages which being install can be found in path demisto_sdk/commands/lint/dev_envs
            3. The docker image build done by Dockerfile template located in
                demisto_sdk/commands/lint/templates/dockerfile.jinja2

        Args:
            docker_base_image(str): docker image to use as base for installing dev deps..

        Returns:
            string. image name to use
        """
        log_prompt = f"{self._pack_name} - Image create"
        test_image_id = ""
        # Get requirements file for image
        requirements = []
        if 2 < docker_base_image[1] < 3:
            requirements = self._req_2
        elif docker_base_image[1] > 3:
            requirements = self._req_3
        # Using DockerFile template
        file_loader = FileSystemLoader(Path(__file__).parent / 'templates')
        env = Environment(loader=file_loader, lstrip_blocks=True, trim_blocks=True)
        template = env.get_template('dockerfile.jinja2')
        try:
            dockerfile = template.render(image=docker_base_image[0],
                                         pypi_packs=requirements + self._facts["additional_requirements"],
                                         pack_type=self._pkg_lint_status["pack_type"])
        except exceptions.TemplateError as e:
            logger.debug(f"{log_prompt} - Error when build image - {e.message()}")
            return test_image_id, str(e)
        # Trying to pull image based on dockerfile hash, will check if something changed
        errors = ""
        test_image_name = f'devtest{docker_base_image[0]}-{hashlib.md5(dockerfile.encode("utf-8")).hexdigest()}'
        test_image = None
        try:
            logger.info(f"{log_prompt} - Trying to pull existing image {test_image_name}")
            test_image = self._docker_client.images.pull(test_image_name)
        except (docker.errors.APIError, docker.errors.ImageNotFound):
            logger.info(f"{log_prompt} - Unable to find image {test_image_name}")
        # Creatng new image if existing image isn't found
        if not test_image:
            logger.info(
                f"{log_prompt} - Creating image based on {docker_base_image[0]} - Could take 2-3 minutes at first "
                f"time")
            try:
                with io.BytesIO() as f:
                    f.write(dockerfile.encode('utf-8'))
                    f.seek(0)
                    self._docker_client.images.build(fileobj=f,
                                                     tag=test_image_name,
                                                     forcerm=True)

                    if self._docker_hub_login:
                        for trial in range(2):
                            try:
                                self._docker_client.images.push(test_image_name)
                                logger.info(f"{log_prompt} - Image {test_image_name} pushed to repository")
                                break
                            except (requests.exceptions.ConnectionError, urllib3.exceptions.ReadTimeoutError):
                                logger.info(f"{log_prompt} - Unable to push image {test_image_name} to repository")

            except (docker.errors.BuildError, docker.errors.APIError, Exception) as e:
                logger.critical(f"{log_prompt} - Build errors occured {e}")
                errors = str(e)
        else:
            logger.info(f"{log_prompt} - Found existing image {test_image_name}")

        for trial in range(2):
            try:
                logger.info(f"{log_prompt} - Copy pack dir to image {test_image_name}")
                container_obj = self._docker_client.containers.create(image=test_image_name,
                                                                      command="update-ca-certificates")
                copy_dir_to_container(container_obj=container_obj,
                                      host_path=self._pack_abs_dir,
                                      container_path=Path('/devwork'))
                if self._facts["env_vars"]["DEMISTO_LINT_UPDATE_CERTS"] == "yes" and \
                        self._pkg_lint_status["pack_type"] == TYPE_PWSH:
                    copy_dir_to_container(container_obj=container_obj,
                                          host_path=Path(__file__).parent / 'resources' / 'certificates',
                                          container_path=Path('/usr/local/share/ca-certificates/'))
                    container_obj.start()
                    container_obj.wait()
                test_image_id = container_obj.commit().short_id
                container_obj.remove()
                break
            except (docker.errors.ImageNotFound, docker.errors.APIError, urllib3.exceptions.ReadTimeoutError) as e:
                logger.info(f"{log_prompt} - errors occured when copy pack dir {e}")
                if trial == 2:
                    errors = str(e)
        if test_image_id:
            logger.info(f"{log_prompt} - Image {test_image_id} created succefully")

        return test_image_id, errors