def test_get_python_version_from_image(image: str, output: bytes,
                                       expected: float, mocker):
    from demisto_sdk.commands.lint import helpers
    mocker.patch.object(helpers, 'init_global_docker_client')
    helpers.init_global_docker_client().containers.run(
    ).logs.return_value = output
    assert expected == helpers.get_python_version_from_image(image)
def test_cache_of_get_python_version_from_image():
    """
    Given -
        docker image that should be alrady cached

    When -
        Try to get python version from am docker image

    Then -
        Validate the value returned from the cache
    """
    from demisto_sdk.commands.lint import helpers
    image = 'demisto/python3:3.9.8.12345'

    cache_info_before = helpers.get_python_version_from_image.cache_info()
    helpers.get_python_version_from_image(image)
    cache_info = helpers.get_python_version_from_image.cache_info()
    assert cache_info.hits == cache_info_before.hits

    helpers.get_python_version_from_image(image)
    cache_info = helpers.get_python_version_from_image.cache_info()
    assert cache_info.hits == cache_info_before.hits + 1
Beispiel #3
0
    def _gather_facts(self, modules: dict) -> bool:
        """ Gathering facts about the package - python version, docker images, valid docker image, yml parsing
        Args:
            modules(dict): Test mandatory modules to be ignore in lint check

        Returns:
            bool: Indicating if to continue further or not, if False exit Thread, Else continue.
        """
        # Looking for pkg yaml
        yml_file: Optional[Path] = self._pack_abs_dir.glob(
            [r'*.yaml', r'*.yml', r'!*unified*.yml'], flags=NEGATE)

        if not yml_file:
            logger.info(
                f"{self._pack_abs_dir} - Skipping no yaml file found {yml_file}"
            )
            self._pkg_lint_status["errors"].append(
                'Unable to find yml file in package')
            return True
        else:
            try:
                yml_file = next(yml_file)
            except StopIteration:
                return True
        # Get pack name
        self._pack_name = yml_file.stem
        log_prompt = f"{self._pack_name} - Facts"
        self._pkg_lint_status["pkg"] = yml_file.stem
        logger.info(f"{log_prompt} - Using yaml file {yml_file}")
        # Parsing pack yaml - in order to verify if check needed
        try:

            script_obj: Dict = {}
            yml_obj: Dict = YAML().load(yml_file)
            if isinstance(yml_obj, dict):
                script_obj = yml_obj.get('script', {}) if isinstance(
                    yml_obj.get('script'), dict) else yml_obj

            self._pkg_lint_status["pack_type"] = script_obj.get('type')
        except (FileNotFoundError, IOError, KeyError):
            self._pkg_lint_status["errors"].append(
                'Unable to parse package yml')
            return True
        # return no check needed if not python pack
        if self._pkg_lint_status["pack_type"] not in (TYPE_PYTHON, TYPE_PWSH):
            logger.info(
                f"{log_prompt} - Skipping due to not Python, Powershell package - Pack is"
                f" {self._pkg_lint_status['pack_type']}")
            return True
        # Docker images
        if self._facts["docker_engine"]:
            logger.info(
                f"{log_prompt} - Pulling docker images, can take up to 1-2 minutes if not exists locally "
            )
            self._facts["images"] = [[
                image, -1
            ] for image in get_all_docker_images(script_obj=script_obj)]
            # Gather environment variables for docker execution
            self._facts["env_vars"] = {
                "CI":
                os.getenv("CI", False),
                "DEMISTO_LINT_UPDATE_CERTS":
                os.getenv('DEMISTO_LINT_UPDATE_CERTS', "yes")
            }
        lint_files = set()
        # Facts for python pack
        if self._pkg_lint_status["pack_type"] == TYPE_PYTHON:
            if self._facts["docker_engine"]:
                # Getting python version from docker image - verifying if not valid docker image configured
                for image in self._facts["images"]:
                    py_num: float = get_python_version_from_image(
                        image=image[0])
                    image[1] = py_num
                    logger.info(
                        f"{self._pack_name} - Facts - {image[0]} - Python {py_num}"
                    )
                    if not self._facts["python_version"]:
                        self._facts["python_version"] = py_num
                # Checking whatever *test* exists in package
                self._facts["test"] = True if next(
                    self._pack_abs_dir.glob([r'test_*.py', r'*_test.py']),
                    None) else False
                if self._facts["test"]:
                    logger.info(f"{log_prompt} - Tests found")
                else:
                    logger.info(f"{log_prompt} - Tests not found")
                # Gather package requirements embedded test-requirements.py file
                test_requirements = self._pack_abs_dir / 'test-requirements.txt'
                if test_requirements.exists():
                    try:
                        additional_req = test_requirements.read_text(
                            encoding='utf-8').strip().split('\n')
                        self._facts["additional_requirements"].extend(
                            additional_req)
                        logger.info(
                            f"{log_prompt} - Additional package Pypi packages found - {additional_req}"
                        )
                    except (FileNotFoundError, IOError):
                        self._pkg_lint_status["errors"].append(
                            'Unable to parse test-requirements.txt in package')
            # Get lint files
            lint_files = set(
                self._pack_abs_dir.glob(["*.py", "!__init__.py", "!*.tmp"],
                                        flags=NEGATE))
        # Facts for Powershell pack
        elif self._pkg_lint_status["pack_type"] == TYPE_PWSH:
            # Get lint files
            lint_files = set(
                self._pack_abs_dir.glob([
                    "*.ps1", "!*Tests.ps1", "CommonServerPowerShell.ps1",
                    "demistomock.ps1'"
                ],
                                        flags=NEGATE))

        # Add CommonServer to the lint checks
        if 'commonserver' in self._pack_abs_dir.name.lower():
            # Powershell
            if self._pkg_lint_status["pack_type"] == TYPE_PWSH:
                self._facts["lint_files"] = [
                    Path(self._pack_abs_dir / 'CommonServerPowerShell.ps1')
                ]
            # Python
            elif self._pkg_lint_status["pack_type"] == TYPE_PYTHON:
                self._facts["lint_files"] = [
                    Path(self._pack_abs_dir / 'CommonServerPython.py')
                ]
        else:
            test_modules = {
                self._pack_abs_dir / module.name
                for module in modules.keys()
            }
            lint_files = lint_files.difference(test_modules)
            self._facts["lint_files"] = list(lint_files)
        if self._facts["lint_files"]:
            for lint_file in self._facts["lint_files"]:
                logger.info(f"{log_prompt} - Lint file {lint_file}")
        else:
            logger.info(f"{log_prompt} - Lint files not found")

        self._split_lint_files()
        return False