Ejemplo n.º 1
0
    def _span_end(
        self,
        span_name: str,
        status: Optional["status.StatusCode"] = None,
    ) -> bool:
        # Check that the current context matches the lifecycle
        if context.get_value(self.lifecycle_key) != span_name:
            logger.warning(f"Requested span not active: {span_name}")
            return False

        span = trace.get_current_span()

        # Set span status
        if status is not None:
            span.set_status(status)

        # End current span
        span.end()

        # Pop context stack
        context_detach_token: Optional[str] = None
        try:
            context_detach_token = self.context_detach_tokens[-1]
        except IndexError:
            pass

        if context_detach_token:
            context.detach(context_detach_token)
            self.context_detach_tokens.pop()
        else:
            logger.warning(f"Context detach token missing: {span_name}")

        return True
Ejemplo n.º 2
0
    def _map_ci_variables(self) -> None:
        """
        Map CI variables to settings

        Strategy:
        1. If a value is set in the env, use it
        2. If a value is not set in the env and a CI value is set, use the CI value
        3. If a value is not set in the env and not in the CI, use the default value
        """
        if not self.active_ci:
            return None
        for name_from, name_to in self.active_ci.MAPPING.items():
            if name_to not in _VARIABLE_DEFINITIONS:
                logger.warning(
                    message=
                    f"CI variable mapping failed, no setting called {name_to}")

            has_set_value = name_to if name_to in os.environ else None
            if not has_set_value:
                has_set_value = (f"{self.PROJECT_NAME_SAFE}_{name_to}"
                                 if f"{self.PROJECT_NAME_SAFE}_{name_to}"
                                 in os.environ else None)

            if has_set_value:
                continue

            parser, default_value = _VARIABLE_DEFINITIONS[name_to]
            ci_value = parser(name_from, None)
            if not ci_value:
                continue
            setattr(self, name_to, ci_value)
Ejemplo n.º 3
0
    def _parse_file_secrets(
            self,
            filesecrets: Dict[str,
                              str]) -> Tuple[Dict[str, str], Dict[str, str]]:
        if settings.active_ci:
            valid_prefixes = settings.active_ci.VALID_FILE_SECRET_PATH_PREFIXES
        else:
            raise ImproperlyConfigured("An active CI is needed")

        filecontents = {}
        mapping = {}
        for name, filename in filesecrets.items():
            path = Path(filename)
            if not validate_file_secret_path(path, valid_prefixes):
                # TODO: This needs refactoring. Variable names do not match the contents.

                # If path-variable doesn't contain a valid path, we expect it to contain
                # the value for the secret file and we can use it directly.
                logger.warning(
                    f'Not a valid file path for a file "{name}". Using contents as a secret value.'
                )
                # Here we expect that filename-variable contains the secret
                filecontents[name] = b64encode(
                    filename.encode("UTF-8")).decode("UTF-8")
                mapping[name] = f"{settings.K8S_FILE_SECRET_MOUNTPATH}/{name}"
                continue
            try:
                filecontents[name] = self._b64_encode_file(path)
                mapping[name] = f"{settings.K8S_FILE_SECRET_MOUNTPATH}/{name}"
            except OSError as e:
                logger.error(f'Error while reading a file: "{path}"', error=e)

        return filecontents, mapping
Ejemplo n.º 4
0
    def delete_image(self, image: DockerImage) -> None:
        logger.warning(icon=f"{self.ICON}", message="Removing Docker image")
        for tag in image.tags:
            logger.info(message=f"\t {image.repository}:{tag}: ", end="")
            delete_command = ["docker", "rmi", f"{image.repository}:{tag}"]
            result = run_os_command(delete_command, shell=False)

            if result.return_code:
                logger.std(result, raise_exception=False)
            else:
                logger.success()
Ejemplo n.º 5
0
def _import_plugins(
    directory: Optional[Path] = None,
) -> Generator[Type[PluginBase], None, None]:
    if not directory:
        directory = Path(__file__).parent

    for init_file in directory.glob("*/__init__.py"):
        module_name = init_file.parent.name
        module = import_module(f".{module_name}", package=__package__)

        try:
            yield getattr(module, "Plugin")
        except AttributeError:
            logger.warning(f"Unable to load plugin: {module_name}")
Ejemplo n.º 6
0
    def map_variables(self,
                      fields: Dict[str, "ModelField"],
                      suppress_warnings: bool = False) -> Dict[str, Any]:
        """
        Map CI variables to settings

        If the source name starts with '=', get the value from mapper's
        attribute. Otwerwise read the value from environment.
        """
        values = {}

        for name_to, name_from in self.MAPPING.items():
            if name_to not in fields:
                if not suppress_warnings:
                    logger.warning(
                        message=
                        f"CI variable mapping failed, no setting called {name_to}"
                    )
                continue

            if name_from.startswith("="):
                name_from = name_from[1:]
                try:
                    value = getattr(self, name_from)
                except AttributeError:
                    if not suppress_warnings:
                        logger.warning(
                            message=
                            f"CI variable mapping failed, no mapper attribute called {name_from}"
                        )
                    continue
            elif name_from in os.environ:
                raw_value = os.environ.get(name_from)
                value, error = fields[name_to].validate(raw_value, {},
                                                        loc=name_from)
                if error:
                    raise ImproperlyConfigured(
                        f"Invalid valid value: {name_from}={raw_value}")
            else:
                value = None

            if value is not None:
                values[name_to] = value

        return values
Ejemplo n.º 7
0
    def _parse_file_secrets(
            self,
            filesecrets: Dict[str,
                              str]) -> Tuple[Dict[str, str], Dict[str, str]]:
        if settings.active_ci:
            valid_prefixes = settings.active_ci.VALID_FILE_SECRET_PATH_PREFIXES
        else:
            raise ImproperlyConfigured("An active CI is needed")

        filecontents = {}
        mapping = {}
        for name, filename in filesecrets.items():
            path = Path(filename)
            if not validate_file_secret_path(path, valid_prefixes):
                logger.warning(f'Not a valid file path: "{path}". Skipping.')
                continue
            try:
                filecontents[name] = self._b64_encode_file(path)
                mapping[name] = f"{settings.K8S_FILE_SECRET_MOUNTPATH}/{name}"
            except OSError as e:
                logger.error(f'Error while reading a file: "{path}"', error=e)

        return filecontents, mapping