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
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