From e6aebfb6a0c34203ea026060e856cbcd841f1cc8 Mon Sep 17 00:00:00 2001 From: Alessandro De Maria Date: Sun, 8 Sep 2024 19:33:28 +0100 Subject: [PATCH] Adds validation for Inventory with Pydantic (#1234) Fixes # ## Proposed Changes * Adds inventory validation using Pydantic ## Docs and Tests * [X] Tests added --- .../compiled/jsonnet-env/jsonnet-env/env.yml | 12 +- kapitan/dependency_manager/base.py | 45 +- kapitan/errors.py | 26 -- kapitan/inputs/base.py | 17 +- kapitan/inputs/external.py | 1 - kapitan/inputs/helm.py | 18 +- kapitan/inputs/jinja2.py | 12 +- kapitan/inputs/jsonnet.py | 2 +- kapitan/inputs/kadet.py | 1 - kapitan/inventory/__init__.py | 9 +- .../inventory/inv_omegaconf/inv_omegaconf.py | 26 +- kapitan/inventory/inv_reclass_rs.py | 1 - kapitan/inventory/inventory.py | 17 +- kapitan/inventory/model/__init__.py | 42 ++ kapitan/inventory/model/dependencies.py | 44 ++ kapitan/inventory/model/input_types.py | 101 +++++ kapitan/inventory/model/references.py | 42 ++ kapitan/refs/__init__.py | 14 + kapitan/refs/base.py | 26 +- kapitan/refs/base64.py | 6 +- kapitan/refs/cmd_parser.py | 67 +-- kapitan/refs/env.py | 8 +- kapitan/refs/secrets/awskms.py | 5 +- kapitan/refs/secrets/azkms.py | 8 +- kapitan/refs/secrets/gkms.py | 7 +- kapitan/refs/secrets/gpg.py | 11 +- kapitan/refs/secrets/vaultkv.py | 5 +- kapitan/refs/secrets/vaulttransit.py | 5 +- kapitan/refs/vault_resources.py | 2 - kapitan/resources.py | 9 +- kapitan/targets.py | 72 ++-- kapitan/utils.py | 5 + poetry.lock | 398 +++++++++--------- pyproject.toml | 1 + tests/test_azure.py | 4 +- tests/test_compile.py | 4 + tests/test_compose_node_name.py | 2 - tests/test_dependency_manager.py | 84 ++-- tests/test_external_input.py | 1 - tests/test_from_dot_kapitan.py | 1 - tests/test_helm_input.py | 19 +- .../jsonnet-env/jsonnet-env/env.yml | 12 +- tests/test_omegaconf.py | 13 +- tests/test_remove.py | 2 - tests/vault_server.py | 2 - 45 files changed, 719 insertions(+), 490 deletions(-) create mode 100644 kapitan/inventory/model/__init__.py create mode 100644 kapitan/inventory/model/dependencies.py create mode 100644 kapitan/inventory/model/input_types.py create mode 100644 kapitan/inventory/model/references.py diff --git a/examples/kubernetes/compiled/jsonnet-env/jsonnet-env/env.yml b/examples/kubernetes/compiled/jsonnet-env/jsonnet-env/env.yml index 653c00bab..fd8c664c4 100644 --- a/examples/kubernetes/compiled/jsonnet-env/jsonnet-env/env.yml +++ b/examples/kubernetes/compiled/jsonnet-env/jsonnet-env/env.yml @@ -19,22 +19,32 @@ parameters: c: ccccc kapitan: compile: - - input_params: {} + - continue_on_compile_error: false + ignore_missing: false + input_params: {} input_paths: - components/jsonnet-env/env.jsonnet input_type: jsonnet + name: null output_path: jsonnet-env output_type: yml + prune: false + dependencies: [] + labels: {} secrets: awskms: key: alias/nameOfKey + azkms: null gkms: key: projects//locations//keyRings//cryptoKeys/ gpg: recipients: - fingerprint: D9234C61F58BEB3ED8552A57E28DC07A3CBFAE7C name: example@kapitan.dev + vaultkv: null + vaulttransit: null target_full_path: jsonnet-env + validate: [] vars: managed_by: kapitan namespace: jsonnet-env diff --git a/kapitan/dependency_manager/base.py b/kapitan/dependency_manager/base.py index d19678c91..a99063560 100644 --- a/kapitan/dependency_manager/base.py +++ b/kapitan/dependency_manager/base.py @@ -15,6 +15,7 @@ from kapitan.errors import GitFetchingError, GitSubdirNotFoundError, HelmFetchingError from kapitan.helm_cli import helm_cli +from kapitan.inventory.model.dependencies import KapitanDependencyTypes from kapitan.utils import ( copy_tree, make_request, @@ -46,16 +47,16 @@ def fetch_dependencies(output_path, target_objs, save_dir, force, pool): deps_output_paths = defaultdict(set) for target_obj in target_objs: try: - dependencies = target_obj["dependencies"] + dependencies = target_obj.dependencies for item in dependencies: - dependency_type = item["type"] - source_uri = item["source"] + dependency_type = item.type + source_uri = item.source # The target key "output_path" is relative to the compile output path set by the user # point to the full output path - full_output_path = normalise_join_path(output_path, item["output_path"]) - logger.debug("Updated output_path from %s to %s", item["output_path"], output_path) - item["output_path"] = full_output_path + full_output_path = normalise_join_path(output_path, item.output_path) + logger.debug("Updated output_path from %s to %s", item.output_path, output_path) + item.output_path = full_output_path if full_output_path in deps_output_paths[source_uri]: # if the output_path is duplicated for the same source_uri @@ -64,15 +65,13 @@ def fetch_dependencies(output_path, target_objs, save_dir, force, pool): else: deps_output_paths[source_uri].add(full_output_path) - if dependency_type == "git": + if dependency_type == KapitanDependencyTypes.GIT: git_deps[source_uri].append(item) - elif dependency_type in ("http", "https"): + elif dependency_type in (KapitanDependencyTypes.HTTP, KapitanDependencyTypes.HTTPS): http_deps[source_uri].append(item) - elif dependency_type == "helm": - version = item.get("version", "") - helm_deps[ - HelmSource(source_uri, item["chart_name"], version, item.get("helm_path")) - ].append(item) + elif dependency_type == KapitanDependencyTypes.HELM: + version = item.version + helm_deps[HelmSource(source_uri, item.chart_name, version, item.helm_path)].append(item) else: logger.warning("%s is not a valid source type", dependency_type) @@ -106,21 +105,17 @@ def fetch_git_dependency(dep_mapping, save_dir, force, item_type="Dependency"): logger.debug("Using cached %s %s", item_type, cached_repo_path) for dep in deps: repo = Repo(cached_repo_path) - output_path = dep["output_path"] + output_path = dep.output_path copy_src_path = cached_repo_path - if "ref" in dep: - ref = dep["ref"] - repo.git.checkout(ref) - else: - repo.git.checkout("master") # default ref + repo.git.checkout(dep.ref) # initialising submodules - if "submodules" not in dep or dep["submodules"]: + if dep.submodules: for submodule in repo.submodules: submodule.update(init=True) - if "subdir" in dep: - sub_dir = dep["subdir"] + if dep.subdir: + sub_dir = dep.subdir full_subdir = os.path.join(cached_repo_path, sub_dir) if os.path.isdir(full_subdir): copy_src_path = full_subdir @@ -169,8 +164,8 @@ def fetch_http_dependency(dep_mapping, save_dir, force, item_type="Dependency"): logger.debug("Using cached %s %s", item_type, cached_source_path) content_type = MimeTypes().guess_type(cached_source_path)[0] for dep in deps: - output_path = dep["output_path"] - if dep.get("unpack", False): + output_path = dep.output_path + if dep.unpack: # ensure that the directory we are extracting to exists os.makedirs(output_path, exist_ok=True) if force: @@ -236,7 +231,7 @@ def fetch_helm_chart(dep_mapping, save_dir, force): ) for dep in deps: - output_path = dep["output_path"] + output_path = dep.output_path if not os.path.exists(output_path) or force: if not exists_in_cache(cached_repo_path): diff --git a/kapitan/errors.py b/kapitan/errors.py index a83076f43..066db41e4 100644 --- a/kapitan/errors.py +++ b/kapitan/errors.py @@ -9,56 +9,38 @@ class KapitanError(Exception): """generic kapitan error""" - pass - class CompileError(KapitanError): """compile error""" - pass - class InventoryError(KapitanError): """inventory error""" - pass - class SecretError(KapitanError): """secrets error""" - pass - class RefError(KapitanError): """ref error""" - pass - class RefBackendError(KapitanError): """ref backend error""" - pass - class RefFromFuncError(KapitanError): """ref from func error""" - pass - class RefHashMismatchError(KapitanError): """ref has mismatch error""" - pass - class HelmBindingUnavailableError(KapitanError): """helm input is used when the binding is not available""" - pass - class HelmFetchingError(KapitanError): pass @@ -71,22 +53,14 @@ class HelmTemplateError(KapitanError): class GitSubdirNotFoundError(KapitanError): """git dependency subdir not found error""" - pass - class GitFetchingError(KapitanError): """repo not found and/or permission error""" - pass - class RequestUnsuccessfulError(KapitanError): """request error""" - pass - class KubernetesManifestValidationError(KapitanError): """kubernetes manifest schema validation error""" - - pass diff --git a/kapitan/inputs/base.py b/kapitan/inputs/base.py index a38a72783..3984c5f86 100644 --- a/kapitan/inputs/base.py +++ b/kapitan/inputs/base.py @@ -36,17 +36,17 @@ def compile_obj(self, comp_obj, ext_vars, **kwargs): and run compile_input_path() for each resolved input_path. kwargs are passed into compile_input_path() """ - input_type = comp_obj["input_type"] + input_type = comp_obj.input_type assert input_type == self.type_name # expand any globbed paths, taking into account provided search paths input_paths = [] - for input_path in comp_obj["input_paths"]: + for input_path in comp_obj.input_paths: globbed_paths = [glob.glob(os.path.join(path, input_path)) for path in self.search_paths] inputs = list(itertools.chain.from_iterable(globbed_paths)) # remove duplicate inputs inputs = set(inputs) - ignore_missing = comp_obj.get("ignore_missing", False) + ignore_missing = comp_obj.ignore_missing if len(inputs) == 0 and not ignore_missing: raise CompileError( "Compile error: {} for target: {} not found in " @@ -62,10 +62,11 @@ def compile_input_path(self, input_path, comp_obj, ext_vars, **kwargs): Compile validated input_path in comp_obj kwargs are passed into compile_file() """ - target_name = ext_vars["target"] - output_path = comp_obj["output_path"] - output_type = comp_obj.get("output_type", self.default_output_type()) - prune_output = comp_obj.get("prune", kwargs.get("prune", False)) + target_name = ext_vars.target + output_path = comp_obj.output_path + output_type = comp_obj.output_type + prune_output = comp_obj.prune + ext_vars_dict = ext_vars.model_dump(by_alias=True) logger.debug("Compiling %s", input_path) try: @@ -76,7 +77,7 @@ def compile_input_path(self, input_path, comp_obj, ext_vars, **kwargs): self.compile_file( input_path, _compile_path, - ext_vars, + ext_vars_dict, output=output_type, target_name=target_name, prune_output=prune_output, diff --git a/kapitan/inputs/external.py b/kapitan/inputs/external.py index ec0a55260..8f378766a 100644 --- a/kapitan/inputs/external.py +++ b/kapitan/inputs/external.py @@ -8,7 +8,6 @@ import logging import os import re -import shutil import subprocess from kapitan.inputs.base import InputType diff --git a/kapitan/inputs/helm.py b/kapitan/inputs/helm.py index 9168513ad..3863fbecd 100644 --- a/kapitan/inputs/helm.py +++ b/kapitan/inputs/helm.py @@ -15,6 +15,7 @@ from kapitan.helm_cli import helm_cli from kapitan.inputs.base import CompiledFile, InputType from kapitan.inputs.kadet import BaseModel, BaseObj, Dict +from kapitan.inventory.model.input_types import KapitanInputTypeHelmConfig logger = logging.getLogger(__name__) @@ -30,22 +31,19 @@ class Helm(InputType): - def __init__(self, compile_path, search_paths, ref_controller, args): + def __init__(self, compile_path, search_paths, ref_controller, args: KapitanInputTypeHelmConfig): super().__init__("helm", compile_path, search_paths, ref_controller) - self.helm_values_files = args.get("helm_values_files") - self.helm_params = args.get("helm_params") or {} - self.helm_path = args.get("helm_path") + self.helm_values_files = args.helm_values_files + self.helm_params = args.helm_params + self.helm_path = args.helm_path self.file_path = None self.helm_values_file = None - if "helm_values" in args: - self.helm_values_file = write_helm_values_file(args["helm_values"]) + if args.helm_values: + self.helm_values_file = write_helm_values_file(args.helm_values) - self.kube_version = None - if "kube_version" in args: - logger.warning("passing kube_version is deprecated. Use api_versions helm flag instead.") - self.kube_version = args["kube_version"] + self.kube_version = args.kube_version def compile_file(self, file_path, compile_path, ext_vars, **kwargs): """ diff --git a/kapitan/inputs/jinja2.py b/kapitan/inputs/jinja2.py index ba083e483..352ce9f57 100644 --- a/kapitan/inputs/jinja2.py +++ b/kapitan/inputs/jinja2.py @@ -19,11 +19,11 @@ class Jinja2(InputType): def __init__(self, compile_path, search_paths, ref_controller, args): super().__init__("jinja2", compile_path, search_paths, ref_controller) - self.strip_postfix = args.get("suffix_remove", False) - self.stripped_postfix = args.get("suffix_stripped", ".j2") - self.input_params = args.get("input_params", {}) + self.strip_postfix = args.suffix_remove + self.stripped_postfix = args.suffix_stripped + self.input_params = args.input_params - def compile_file(self, file_path, compile_path, ext_vars, **kwargs): + def compile_file(self, file_path, compile_path, ext_vars={}, **kwargs): """ Write items in path as jinja2 rendered files to compile_path. path can be either a file or directory. @@ -43,8 +43,8 @@ def compile_file(self, file_path, compile_path, ext_vars, **kwargs): # set ext_vars and inventory for jinja2 context context = ext_vars.copy() - context["inventory_global"] = cached.inv.inventory - context["inventory"] = cached.inv.inventory[target_name] + context["inventory_global"] = cached.global_inv + context["inventory"] = cached.global_inv[target_name] context["input_params"] = input_params jinja2_filters = kwargs.get("jinja2_filters") diff --git a/kapitan/inputs/jsonnet.py b/kapitan/inputs/jsonnet.py index 229cb1d3a..63838fde9 100644 --- a/kapitan/inputs/jsonnet.py +++ b/kapitan/inputs/jsonnet.py @@ -10,7 +10,6 @@ import os import sys -from kapitan import cached from kapitan.errors import CompileError from kapitan.inputs.base import CompiledFile, InputType from kapitan.resources import resource_callbacks, search_imports @@ -81,6 +80,7 @@ def _search_imports(cwd, imp): return search_imports(cwd, imp, self.search_paths) json_output = None + if self.use_go: json_output = go_jsonnet_file( file_path, diff --git a/kapitan/inputs/kadet.py b/kapitan/inputs/kadet.py index 30c95f927..8934343eb 100644 --- a/kapitan/inputs/kadet.py +++ b/kapitan/inputs/kadet.py @@ -10,7 +10,6 @@ import logging import os import sys -import time from functools import lru_cache from importlib.util import module_from_spec, spec_from_file_location diff --git a/kapitan/inventory/__init__.py b/kapitan/inventory/__init__.py index b61057664..a15a5953b 100644 --- a/kapitan/inventory/__init__.py +++ b/kapitan/inventory/__init__.py @@ -1,11 +1,8 @@ -from .inventory import Inventory +from typing import Type -try: - from enum import StrEnum -except ImportError: - from strenum import StrEnum +from kapitan.utils import StrEnum -from typing import Type +from .inventory import Inventory class InventoryBackends(StrEnum): diff --git a/kapitan/inventory/inv_omegaconf/inv_omegaconf.py b/kapitan/inventory/inv_omegaconf/inv_omegaconf.py index f7c4a1bb7..7f65dec88 100644 --- a/kapitan/inventory/inv_omegaconf/inv_omegaconf.py +++ b/kapitan/inventory/inv_omegaconf/inv_omegaconf.py @@ -14,12 +14,13 @@ import yaml from cachetools import LRUCache, cached from kadet import Dict -from omegaconf import DictConfig, ListMergeMode, OmegaConf -from pydantic import ConfigDict +from omegaconf import ListMergeMode, OmegaConf + +from kapitan.inventory.model import KapitanInventoryMetadata, KapitanInventoryParameters from ..inventory import Inventory, InventoryError, InventoryTarget from .migrate import migrate -from .resolvers import register_resolvers, register_user_resolvers +from .resolvers import register_resolvers logger = logging.getLogger(__name__) @@ -47,16 +48,15 @@ def __init__(self, *args, **kwargs): self.__add_metadata() def __add_metadata(self): - metadata = { - "name": { - "short": self.name.split(".")[-1], - "full": self.name, - "path": os.path.splitext(self.path)[0], - "parts": self.name.split("."), - } + name_metadata = { + "short": self.name.split(".")[-1], + "full": self.name, + "path": os.path.splitext(self.path)[0], + "parts": self.name.split("."), } - self.parameters["_kapitan_"] = metadata - self.parameters["_reclass_"] = metadata + kapitan_metadata = KapitanInventoryMetadata(name=name_metadata) + + self.parameters = KapitanInventoryParameters(_kapitan_=kapitan_metadata, _reclass_=kapitan_metadata) class OmegaConfInventory(Inventory): @@ -181,7 +181,7 @@ def load_target(self, target: OmegaConfTarget): full_target_path = os.path.join(self.targets_path, target.path) start = time.perf_counter() - parameters = OmegaConf.create(keys_to_strings(target.parameters)) + parameters = OmegaConf.create(keys_to_strings(target.parameters.model_dump(by_alias=True))) p, c, a, e = self.load_parameters_from_file(full_target_path, parameters=parameters) load_parameters = time.perf_counter() - start target.parameters = OmegaConf.to_container(p, resolve=True) diff --git a/kapitan/inventory/inv_reclass_rs.py b/kapitan/inventory/inv_reclass_rs.py index ac3c99336..322df562b 100644 --- a/kapitan/inventory/inv_reclass_rs.py +++ b/kapitan/inventory/inv_reclass_rs.py @@ -1,5 +1,4 @@ import logging -import os from datetime import datetime import reclass_rs diff --git a/kapitan/inventory/inventory.py b/kapitan/inventory/inventory.py index be81bce1b..574504db8 100644 --- a/kapitan/inventory/inventory.py +++ b/kapitan/inventory/inventory.py @@ -11,20 +11,22 @@ from abc import ABC, abstractmethod from typing import Dict -from pydantic import BaseModel, Field +from pydantic import BaseModel, ConfigDict, Field from kapitan.errors import KapitanError +from kapitan.inventory.model import KapitanInventoryParameters logger = logging.getLogger(__name__) class InventoryTarget(BaseModel): + model_config = ConfigDict(extra="forbid", validate_assignment=True) name: str = Field(exclude=True) path: str = Field(exclude=True) - parameters: Dict = {} + parameters: KapitanInventoryParameters = KapitanInventoryParameters() classes: list = list() applications: list = list() - exports: Dict = {} + exports: dict = {} class Inventory(ABC): @@ -54,7 +56,7 @@ def inventory(self) -> dict: get all targets from inventory """ - return {target.name: target.model_dump() for target in self.targets.values()} + return {target.name: target.model_dump(by_alias=True) for target in self.targets.values()} def __initialise(self, ignore_class_not_found) -> bool: """ @@ -136,7 +138,6 @@ def migrate(self): """ migrate the inventory, e.g. change interpolation syntax to new syntax """ - pass def __getitem__(self, key): return self.inventory[key] @@ -145,16 +146,10 @@ def __getitem__(self, key): class InventoryError(KapitanError): """inventory error""" - pass - class InventoryValidationError(InventoryError): """inventory validation error""" - pass - class InvalidTargetError(InventoryError): """inventory validation error""" - - pass diff --git a/kapitan/inventory/model/__init__.py b/kapitan/inventory/model/__init__.py new file mode 100644 index 000000000..fd53f0442 --- /dev/null +++ b/kapitan/inventory/model/__init__.py @@ -0,0 +1,42 @@ +from typing import List, Optional + +from pydantic import BaseModel, ConfigDict, Field + +from kapitan.inventory.model.dependencies import DependencyTypeConfig +from kapitan.inventory.model.input_types import CompileInputTypeConfig +from kapitan.inventory.model.references import KapitanReferenceConfig + + +class KapitanEssentialVars(BaseModel): + model_config = ConfigDict(extra="allow") + target: Optional[str] = None + + +class KapitanInventorySettings(BaseModel): + compile: List[CompileInputTypeConfig] = [] + vars: KapitanEssentialVars = KapitanEssentialVars() + labels: dict[str, str] = {} + dependencies: Optional[List[DependencyTypeConfig]] = [] + target_full_path: str = "" + secrets: Optional[KapitanReferenceConfig] = None + validate_: list[dict] = Field(alias="validate", default=[]) + + +class KapitanMetadataName(BaseModel): + short: str + full: str + path: str + parts: List[str] + + +class KapitanInventoryMetadata(BaseModel): + model_config = ConfigDict(extra="allow", validate_assignment=True) + name: Optional[KapitanMetadataName] = None + + +class KapitanInventoryParameters(BaseModel): + model_config = ConfigDict(extra="allow") + + kapitan: Optional[KapitanInventorySettings] = KapitanInventorySettings() + kapitan_metadata: Optional[KapitanInventoryMetadata] = Field(alias="_kapitan_", default=None) + reclass_metadata: Optional[KapitanInventoryMetadata] = Field(alias="_reclass_", default=None) diff --git a/kapitan/inventory/model/dependencies.py b/kapitan/inventory/model/dependencies.py new file mode 100644 index 000000000..86d9a8383 --- /dev/null +++ b/kapitan/inventory/model/dependencies.py @@ -0,0 +1,44 @@ +from typing import Literal, Optional, Union + +from pydantic import BaseModel, ConfigDict + +from kapitan.utils import StrEnum + + +class KapitanDependencyTypes(StrEnum): + HELM = "helm" + HTTP = "http" + HTTPS = "https" + GIT = "git" + + +class KapitanDependencyBaseConfig(BaseModel): + model_config = ConfigDict(extra="forbid") + type: KapitanDependencyTypes + source: str + output_path: str + + +class KapitanDependencyHelmConfig(KapitanDependencyBaseConfig): + type: Literal[KapitanDependencyTypes.HELM] = KapitanDependencyTypes.HELM + chart_name: str + version: Optional[str] = None + helm_path: Optional[str] = None + force_fetch: Optional[bool] = False + + +class KapitanDependencyGitConfig(KapitanDependencyBaseConfig): + type: Literal[KapitanDependencyTypes.GIT] = KapitanDependencyTypes.GIT + ref: Optional[str] = "master" + subdir: Optional[str] = None + submodules: Optional[bool] = False + + +class KapitanDependencyHttpsConfig(KapitanDependencyBaseConfig): + type: Literal[KapitanDependencyTypes.HTTPS, KapitanDependencyTypes.HTTP] + unpack: bool = False + + +DependencyTypeConfig = Union[ + KapitanDependencyHelmConfig, KapitanDependencyHttpsConfig, KapitanDependencyGitConfig +] diff --git a/kapitan/inventory/model/input_types.py b/kapitan/inventory/model/input_types.py new file mode 100644 index 000000000..9fd6f1728 --- /dev/null +++ b/kapitan/inventory/model/input_types.py @@ -0,0 +1,101 @@ +from typing import Annotated, List, Literal, Optional, Union + +from pydantic import BaseModel, ConfigDict, Field + +from kapitan.utils import StrEnum + + +class InputTypes(StrEnum): + JSONNET = "jsonnet" + JINJA2 = "jinja2" + HELM = "helm" + KADET = "kadet" + COPY = "copy" + REMOVE = "remove" + EXTERNAL = "external" + + +class OutputType(StrEnum): + JSON = "json" + YAML = "yaml" + YML = "yml" + PLAIN = "plain" + TOML = "toml" + + +class KapitanInputTypeBaseConfig(BaseModel): + model_config = ConfigDict(extra="forbid") + name: Optional[str] = Field(default=None) + input_type: InputTypes + output_path: str + input_params: dict = {} + continue_on_compile_error: Optional[bool] = False + + output_type: OutputType = OutputType.YAML + ignore_missing: Optional[bool] = False + prune: Optional[bool] = True + + +class KapitanInputTypeJsonnetConfig(KapitanInputTypeBaseConfig): + input_type: Literal[InputTypes.JSONNET] = InputTypes.JSONNET + output_type: OutputType = OutputType.JSON + input_paths: List[str] + prune: bool = False + + +class KapitanInputTypeExternalConfig(KapitanInputTypeBaseConfig): + input_type: Literal[InputTypes.EXTERNAL] = InputTypes.EXTERNAL + env_vars: dict[str, str] = {} + args: List[str] = [] + input_paths: List[str] + + +class KapitanInputTypeCopyConfig(KapitanInputTypeBaseConfig): + input_type: Literal[InputTypes.COPY] = InputTypes.COPY + input_paths: List[str] + ignore_missing: bool = False + + +class KapitanInputTypeJinja2Config(KapitanInputTypeBaseConfig): + input_type: Literal[InputTypes.JINJA2] = InputTypes.JINJA2 + input_paths: List[str] + output_type: Optional[OutputType] = OutputType.PLAIN + ignore_missing: Optional[bool] = True + suffix_remove: Optional[bool] = False + suffix_stripped: Optional[str] = ".j2" + + +class KapitanInputTypeHelmConfig(KapitanInputTypeBaseConfig): + input_type: Literal[InputTypes.HELM] = InputTypes.HELM + helm_params: dict = {} + helm_values: Optional[dict] = {} + helm_values_files: Optional[List[str]] = [] + helm_path: Optional[str] = None + input_paths: List[str] + kube_version: Optional[str] = None + + +class KapitanInputTypeKadetConfig(KapitanInputTypeBaseConfig): + input_type: Literal[InputTypes.KADET] = InputTypes.KADET + output_type: OutputType = OutputType.YAML + input_paths: List[str] + input_value: Optional[dict] = None + + +class KapitanInputTypeRemoveConfig(KapitanInputTypeBaseConfig): + input_type: Literal[InputTypes.REMOVE] + input_paths: List[str] + + +CompileInputTypeConfig = Annotated[ + Union[ + KapitanInputTypeJinja2Config, + KapitanInputTypeExternalConfig, + KapitanInputTypeCopyConfig, + KapitanInputTypeKadetConfig, + KapitanInputTypeJsonnetConfig, + KapitanInputTypeHelmConfig, + KapitanInputTypeRemoveConfig, + ], + Field(discriminator="input_type"), +] diff --git a/kapitan/inventory/model/references.py b/kapitan/inventory/model/references.py new file mode 100644 index 000000000..af7c74389 --- /dev/null +++ b/kapitan/inventory/model/references.py @@ -0,0 +1,42 @@ +from typing import List, Optional + +from pydantic import BaseModel, ConfigDict + + +class KapitanReferenceBaseConfig(BaseModel): + model_config = ConfigDict(extra="forbid") + + +class KapitanReferenceGPGConfig(KapitanReferenceBaseConfig): + recipients: List[dict[str, str]] = [] + + +class KapitanReferenceVaultKVConfig(KapitanReferenceBaseConfig): + auth: str + + +class KapitanReferenceVaultTransitConfig(KapitanReferenceBaseConfig): + key: str + auth: str + + +class KapitanReferenceAWKMSConfig(KapitanReferenceBaseConfig): + key: str + + +class KapitanReferenceGKMSConfig(KapitanReferenceBaseConfig): + key: str + + +class KapitanReferenceAZKMSConfig(KapitanReferenceBaseConfig): + key: str + + +class KapitanReferenceConfig(BaseModel): + model_config = ConfigDict(extra="forbid") + gpg: Optional[KapitanReferenceGPGConfig] = None + awskms: Optional[KapitanReferenceAWKMSConfig] = None + vaultkv: Optional[KapitanReferenceVaultKVConfig] = None + gkms: Optional[KapitanReferenceGKMSConfig] = None + vaulttransit: Optional[KapitanReferenceVaultTransitConfig] = None + azkms: Optional[KapitanReferenceAZKMSConfig] = None diff --git a/kapitan/refs/__init__.py b/kapitan/refs/__init__.py index d3195b502..5ff121fb6 100644 --- a/kapitan/refs/__init__.py +++ b/kapitan/refs/__init__.py @@ -1,3 +1,17 @@ # SPDX-FileCopyrightText: 2020 The Kapitan Authors # # SPDX-License-Identifier: Apache-2.0 + +from kapitan.utils import StrEnum + + +class KapitanReferencesTypes(StrEnum): + GPG = "gpg" + VAULTKV = "vaultkv" + VAULTTRANSIT = "vaulttransit" + AWSKMS = "awskms" + GKMS = "gkms" + AZKMS = "azkms" + BASE64 = "base64" + PLAIN = "plain" + ENV = "env" diff --git a/kapitan/refs/base.py b/kapitan/refs/base.py index 81dc36dd0..accded744 100644 --- a/kapitan/refs/base.py +++ b/kapitan/refs/base.py @@ -24,6 +24,7 @@ RefFromFuncError, RefHashMismatchError, ) +from kapitan.refs import KapitanReferencesTypes from kapitan.refs.functions import eval_func, get_func_lookup from kapitan.utils import PrettyDumper, list_all_paths @@ -45,7 +46,7 @@ def __init__(self, data, **kwargs): """ writes plain data """ - self.type_name = "plain" + self.type_name = KapitanReferencesTypes.PLAIN self.encoding = kwargs.get("encoding", "original") self.embedded_subvar_path = kwargs.get("embedded_subvar_path", None) self.data = data @@ -462,43 +463,48 @@ def _get_backend(self, type_name): return self.backends[type_name] except KeyError: ref_kwargs = {"embed_refs": self.embed_refs} - if type_name == "plain": + logger.error( + "RefController: registering backend for type %s for %s", + type_name, + KapitanReferencesTypes.PLAIN, + ) + if type_name == KapitanReferencesTypes.PLAIN: from kapitan.refs.base import PlainRefBackend # XXX embed_refs in plain backend does nothing self.register_backend(PlainRefBackend(self.path, **ref_kwargs)) - elif type_name == "env": + elif type_name == KapitanReferencesTypes.ENV: from kapitan.refs.env import EnvRefBackend # embed_refs in env backend also does nothing self.register_backend(EnvRefBackend(self.path, **ref_kwargs)) - elif type_name == "base64": + elif type_name == KapitanReferencesTypes.BASE64: from kapitan.refs.base64 import Base64RefBackend self.register_backend(Base64RefBackend(self.path, **ref_kwargs)) - elif type_name == "gpg": + elif type_name == KapitanReferencesTypes.GPG: from kapitan.refs.secrets.gpg import GPGBackend self.register_backend(GPGBackend(self.path, **ref_kwargs)) - elif type_name == "gkms": + elif type_name == KapitanReferencesTypes.GKMS: from kapitan.refs.secrets.gkms import GoogleKMSBackend self.register_backend(GoogleKMSBackend(self.path, **ref_kwargs)) - elif type_name == "awskms": + elif type_name == KapitanReferencesTypes.AWSKMS: from kapitan.refs.secrets.awskms import AWSKMSBackend self.register_backend(AWSKMSBackend(self.path, **ref_kwargs)) - elif type_name == "vaultkv": + elif type_name == KapitanReferencesTypes.VAULTKV: from kapitan.refs.secrets.vaultkv import VaultBackend self.register_backend(VaultBackend(self.path, **ref_kwargs)) - elif type_name == "vaulttransit": + elif type_name == KapitanReferencesTypes.VAULTTRANSIT: from kapitan.refs.secrets.vaulttransit import VaultBackend self.register_backend(VaultBackend(self.path, **ref_kwargs)) - elif type_name == "azkms": + elif type_name == KapitanReferencesTypes.AZKMS: from kapitan.refs.secrets.azkms import AzureKMSBackend self.register_backend(AzureKMSBackend(self.path, **ref_kwargs)) diff --git a/kapitan/refs/base64.py b/kapitan/refs/base64.py index 20795c2ce..b88835b53 100644 --- a/kapitan/refs/base64.py +++ b/kapitan/refs/base64.py @@ -12,7 +12,7 @@ import yaml -from kapitan.refs.base import PlainRef, PlainRefBackend +from kapitan.refs.base import KapitanReferencesTypes, PlainRef, PlainRefBackend try: from yaml import CSafeLoader as YamlLoader @@ -29,7 +29,7 @@ def __init__(self, data, from_base64=False, **kwargs): set from_base64 to load already base64 encoded data """ super().__init__(data, **kwargs) - self.type_name = "base64" + self.type_name = KapitanReferencesTypes.BASE64 self.encoding = kwargs.get("encoding", "original") self.embed_refs = kwargs.get("embed_refs", False) @@ -91,4 +91,4 @@ def dump(self): class Base64RefBackend(PlainRefBackend): def __init__(self, path, ref_type=Base64Ref, **ref_kwargs): super().__init__(path, ref_type, **ref_kwargs) - self.type_name = "base64" + self.type_name = KapitanReferencesTypes.BASE64 diff --git a/kapitan/refs/cmd_parser.py b/kapitan/refs/cmd_parser.py index 3a6bae75d..197281971 100644 --- a/kapitan/refs/cmd_parser.py +++ b/kapitan/refs/cmd_parser.py @@ -49,7 +49,7 @@ def ref_write(args, ref_controller): for line in sys.stdin: data += line else: - mime_type = mimetypes.guess_type(file_name) + mimetypes.guess_type(file_name) modifier = "rb" if is_binary else "r" with open(file_name, modifier) as fp: try: @@ -324,8 +324,8 @@ def secret_update(args, ref_controller): ] if args.target_name: inv = get_inventory(args.inventory_path) - kap_inv_params = inv.get_parameters(args.target_name)["kapitan"] - if "secrets" not in kap_inv_params: + kap_inv_params = inv.get_parameters(args.target_name).kapitan + if not kap_inv_params.secrets: raise KapitanError("parameters.kapitan.secrets not defined in {}".format(args.target_name)) try: @@ -467,45 +467,20 @@ def secret_update_validate(args, ref_controller): ret_code = 0 for target_name, token_paths in target_token_paths.items(): - kap_inv_params = inv.get_parameters(target_name)["kapitan"] - if "secrets" not in kap_inv_params: + secrets = inv.get_parameters(target_name).kapitan.secrets + if not secrets: raise KapitanError("parameters.kapitan.secrets not defined in {}".format(target_name)) - try: - recipients = kap_inv_params["secrets"]["gpg"]["recipients"] - except KeyError: - recipients = None - try: - gkey = kap_inv_params["secrets"]["gkms"]["key"] - except KeyError: - gkey = None - try: - awskey = kap_inv_params["secrets"]["awskms"]["key"] - except KeyError: - awskey = None - try: - vaultkv = kap_inv_params["secrets"]["vaultkv"]["auth"] - except KeyError: - vaultkv = None - try: - # Referenced Auth - vkey = kap_inv_params["secrets"]["vaulttransit"]["key"] - except KeyError: - vkey = None - try: - azkey = kap_inv_params["secrets"]["azkms"]["key"] - except KeyError: - azkey = None - for token_path in token_paths: if token_path.startswith("?{gpg:"): - if not recipients: + if not secrets.gpg: logger.debug( "secret_update_validate: target: %s has no inventory gpg recipients, skipping %s", target_name, token_path, ) continue + recipients = secrets.gpg.recipients secret_obj = ref_controller[token_path] target_fingerprints = set(lookup_fingerprints(recipients)) secret_fingerprints = set(lookup_fingerprints(secret_obj.recipients)) @@ -532,24 +507,25 @@ def secret_update_validate(args, ref_controller): ref_controller[token_path] = secret_obj elif token_path.startswith("?{gkms:"): - if not gkey: + if not secrets.gkms: logger.debug( "secret_update_validate: target: %s has no inventory gkms key, skipping %s", target_name, token_path, ) continue + key = secrets.gkms.key secret_obj = ref_controller[token_path] - if gkey != secret_obj.key: + if secrets.gpg.key != key: if args.validate_targets: logger.info("%s key mismatch", token_path) ret_code = 1 else: - secret_obj.update_key(gkey) + secret_obj.update_key(key) ref_controller[token_path] = secret_obj elif token_path.startswith("?{vaulttransit:"): - if not vkey: + if not secrets.vaulttransit: logger.debug( "secret_update_validate: target: %s has no inventory vaulttransit key, skipping %s", target_name, @@ -557,33 +533,35 @@ def secret_update_validate(args, ref_controller): ) continue secret_obj = ref_controller[token_path] - if vkey != secret_obj.vault_params["key"]: + key = secrets.vaulttransit.key + if key != secret_obj.vault_params["key"]: if args.validate_targets: logger.info("%s key mismatch", token_path) ret_code = 1 else: - secret_obj.update_key(vkey) + secret_obj.update_key(key) ref_controller[token_path] = secret_obj elif token_path.startswith("?{awskms:"): - if not awskey: + if not secrets.awskms: logger.debug( "secret_update_validate: target: %s has no inventory awskms key, skipping %s", target_name, token_path, ) continue + key = secrets.awskms.key secret_obj = ref_controller[token_path] - if awskey != secret_obj.key: + if key != secret_obj.key: if args.validate_targets: logger.info("%s key mismatch", token_path) ret_code = 1 else: - secret_obj.update_key(awskey) + secret_obj.update_key(key) ref_controller[token_path] = secret_obj elif token_path.startswith("?{azkms:"): - if not azkey: + if not secrets.azkey: logger.debug( "secret_update_validate: target: %s has no inventory azkms key, skipping %s", target_name, @@ -591,12 +569,13 @@ def secret_update_validate(args, ref_controller): ) continue secret_obj = ref_controller[token_path] - if azkey != secret_obj.key: + key = secrets.azkms.key + if key != secret_obj.key: if args.validate_targets: logger.info("%s key mismatch", token_path) ret_code = 1 else: - secret_obj.update_key(azkey) + secret_obj.update_key(key) ref_controller[token_path] = secret_obj else: diff --git a/kapitan/refs/env.py b/kapitan/refs/env.py index bb7dbe13c..bb5eb1184 100644 --- a/kapitan/refs/env.py +++ b/kapitan/refs/env.py @@ -5,11 +5,9 @@ "environment refs module" -import base64 -import hashlib import os -from kapitan.refs.base import PlainRef, PlainRefBackend +from kapitan.refs.base import KapitanReferencesTypes, PlainRef, PlainRefBackend DEFAULT_ENV_REF_VAR_PREFIX = "KAPITAN_VAR_" @@ -21,7 +19,7 @@ def __init__(self, data, **kwargs): environment vars prefix during the reveal phase. """ super().__init__(data, kwargs=kwargs) - self.type_name = "env" + self.type_name = KapitanReferencesTypes.ENV def reveal(self): """ @@ -43,4 +41,4 @@ class EnvRefBackend(PlainRefBackend): def __init__(self, path, ref_type=EnvRef, **ref_kwargs): "Get and create EnvRefs" super().__init__(path, ref_type, ref_kwargs=ref_kwargs) - self.type_name = "env" + self.type_name = KapitanReferencesTypes.ENV diff --git a/kapitan/refs/secrets/awskms.py b/kapitan/refs/secrets/awskms.py index beb9658e6..40713d0c3 100644 --- a/kapitan/refs/secrets/awskms.py +++ b/kapitan/refs/secrets/awskms.py @@ -11,6 +11,7 @@ from kapitan import cached from kapitan.errors import KapitanError +from kapitan.refs import KapitanReferencesTypes from kapitan.refs.base import RefError from kapitan.refs.base64 import Base64Ref, Base64RefBackend @@ -18,8 +19,6 @@ class AWSKMSError(KapitanError): """Generic AWS KMS errors""" - pass - def awskms_obj(): if not cached.awskms_obj: @@ -42,7 +41,7 @@ def __init__(self, data, key, encrypt=True, encode_base64=False, **kwargs): self.data = data self.key = key super().__init__(self.data, **kwargs) - self.type_name = "awskms" + self.type_name = KapitanReferencesTypes.AWSKMS @classmethod def from_params(cls, data, ref_params): diff --git a/kapitan/refs/secrets/azkms.py b/kapitan/refs/secrets/azkms.py index 3cd2ed264..171df8de5 100644 --- a/kapitan/refs/secrets/azkms.py +++ b/kapitan/refs/secrets/azkms.py @@ -2,7 +2,6 @@ import base64 import logging -import os from urllib.parse import urlparse from azure.identity import DefaultAzureCredential @@ -11,6 +10,7 @@ from kapitan import cached from kapitan.errors import KapitanError +from kapitan.refs import KapitanReferencesTypes from kapitan.refs.base import RefError from kapitan.refs.base64 import Base64Ref, Base64RefBackend @@ -22,8 +22,6 @@ class AzureKMSError(KapitanError): Generic Azure Key Vault error """ - pass - def azkms_obj(key_id): """ @@ -66,7 +64,7 @@ def __init__(self, data, key, encrypt=True, encode_base64=False, **kwargs): self.data = data self.key = key super().__init__(self.data, **kwargs) - self.type_name = "azkms" + self.type_name = KapitanReferencesTypes.AZKMS @classmethod def from_params(cls, data, ref_params): @@ -172,4 +170,4 @@ class AzureKMSBackend(Base64RefBackend): def __init__(self, path, ref_type=AzureKMSSecret, **ref_kwargs): "init AzureKMSBackend ref backend type" super().__init__(path, ref_type, **ref_kwargs) - self.type_name = "azkms" + self.type_name = KapitanReferencesTypes.AZKMS diff --git a/kapitan/refs/secrets/gkms.py b/kapitan/refs/secrets/gkms.py index a071b270c..d0e46892f 100644 --- a/kapitan/refs/secrets/gkms.py +++ b/kapitan/refs/secrets/gkms.py @@ -13,6 +13,7 @@ from kapitan import cached from kapitan.errors import KapitanError +from kapitan.refs import KapitanReferencesTypes from kapitan.refs.base import RefError from kapitan.refs.base64 import Base64Ref, Base64RefBackend @@ -25,8 +26,6 @@ class GoogleKMSError(KapitanError): """Generic Google KMS errors""" - pass - def gkms_obj(): if not cached.gkms_obj: @@ -53,7 +52,7 @@ def __init__(self, data, key, encrypt=True, encode_base64=False, **kwargs): self.data = data self.key = key super().__init__(self.data, **kwargs) - self.type_name = "gkms" + self.type_name = KapitanReferencesTypes.GKMS @classmethod def from_params(cls, data, ref_params): @@ -165,4 +164,4 @@ class GoogleKMSBackend(Base64RefBackend): def __init__(self, path, ref_type=GoogleKMSSecret, **ref_kwargs): "init GoogleKMSBackend ref backend type" super().__init__(path, ref_type, **ref_kwargs) - self.type_name = "gkms" + self.type_name = KapitanReferencesTypes.GKMS diff --git a/kapitan/refs/secrets/gpg.py b/kapitan/refs/secrets/gpg.py index e19078911..fb95f39da 100644 --- a/kapitan/refs/secrets/gpg.py +++ b/kapitan/refs/secrets/gpg.py @@ -13,6 +13,7 @@ from kapitan import cached from kapitan.errors import KapitanError +from kapitan.refs import KapitanReferencesTypes from kapitan.refs.base import RefError from kapitan.refs.base64 import Base64Ref, Base64RefBackend @@ -31,8 +32,6 @@ class GPGError(Exception): """Generic GPG errors""" - pass - def gpg_obj(*args, **kwargs): if not cached.gpg_obj: @@ -58,7 +57,7 @@ def __init__(self, data, recipients, encrypt=True, encode_base64=False, **kwargs self.data = data self.recipients = [{"fingerprint": f} for f in fingerprints] # TODO move to .load() method super().__init__(self.data, **kwargs) - self.type_name = "gpg" + self.type_name = KapitanReferencesTypes.GPG @classmethod def from_params(cls, data, ref_params): @@ -78,12 +77,12 @@ def from_params(cls, data, ref_params): target_inv = cached.inv.get_parameters(target_name) - if "secrets" not in target_inv["kapitan"]: + if not target_inv.kapitan.secrets: raise KapitanError( f"parameters.kapitan.secrets not defined in inventory of target {target_name}" ) - recipients = target_inv["kapitan"]["secrets"]["gpg"]["recipients"] + recipients = target_inv.kapitan.secrets.gpg.recipients return cls(data, recipients, **ref_params.kwargs) except KeyError: @@ -161,7 +160,7 @@ class GPGBackend(Base64RefBackend): def __init__(self, path, ref_type=GPGSecret, **ref_kwargs): "init GPGBackend ref backend type" super().__init__(path, ref_type, **ref_kwargs) - self.type_name = "gpg" + self.type_name = KapitanReferencesTypes.GPG def lookup_fingerprints(recipients): diff --git a/kapitan/refs/secrets/vaultkv.py b/kapitan/refs/secrets/vaultkv.py index 3ac4dd79a..09d5223cd 100644 --- a/kapitan/refs/secrets/vaultkv.py +++ b/kapitan/refs/secrets/vaultkv.py @@ -11,6 +11,7 @@ from hvac.exceptions import Forbidden, InvalidPath from kapitan import cached +from kapitan.refs import KapitanReferencesTypes from kapitan.refs.base import RefError from kapitan.refs.base64 import Base64Ref, Base64RefBackend from kapitan.refs.vault_resources import VaultClient, VaultError @@ -40,7 +41,7 @@ def __init__(self, data, vault_params, encrypt=True, encode_base64=False, **kwar self.data = data super().__init__(self.data, **kwargs) - self.type_name = "vaultkv" + self.type_name = KapitanReferencesTypes.VAULTKV @classmethod def from_params(cls, data, ref_params): @@ -244,4 +245,4 @@ class VaultBackend(Base64RefBackend): def __init__(self, path, ref_type=VaultSecret, **ref_kwargs): "init VaultBackend ref backend type" super().__init__(path, ref_type, **ref_kwargs) - self.type_name = "vaultkv" + self.type_name = KapitanReferencesTypes.VAULTKV diff --git a/kapitan/refs/secrets/vaulttransit.py b/kapitan/refs/secrets/vaulttransit.py index 3f08cdaf9..59d5f9c79 100644 --- a/kapitan/refs/secrets/vaulttransit.py +++ b/kapitan/refs/secrets/vaulttransit.py @@ -13,6 +13,7 @@ from hvac.exceptions import Forbidden, InvalidPath from kapitan import cached +from kapitan.refs import KapitanReferencesTypes from kapitan.refs.base import RefError from kapitan.refs.base64 import Base64Ref, Base64RefBackend from kapitan.refs.vault_resources import VaultClient, VaultError @@ -37,7 +38,7 @@ def __init__(self, data, vault_params, encrypt=True, encode_base64=False, **kwar self.data = data super().__init__(self.data, **kwargs) - self.type_name = "vaulttransit" + self.type_name = KapitanReferencesTypes.VAULTTRANSIT @classmethod def from_params(cls, data, ref_params): @@ -189,4 +190,4 @@ class VaultBackend(Base64RefBackend): def __init__(self, path, ref_type=VaultTransit, **ref_kwargs): "init VaultBackend ref backend type" super().__init__(path, ref_type, **ref_kwargs) - self.type_name = "vaulttransit" + self.type_name = KapitanReferencesTypes.VAULTTRANSIT diff --git a/kapitan/refs/vault_resources.py b/kapitan/refs/vault_resources.py index 5f56ac008..578cb3190 100644 --- a/kapitan/refs/vault_resources.py +++ b/kapitan/refs/vault_resources.py @@ -18,8 +18,6 @@ class VaultError(KapitanError): """Generic vault errors""" - pass - class VaultClient(hvac.Client): """client connects to vault server and authenticates itself""" diff --git a/kapitan/resources.py b/kapitan/resources.py index aa410207f..ce3e72760 100644 --- a/kapitan/resources.py +++ b/kapitan/resources.py @@ -8,7 +8,6 @@ "kapitan resources" import base64 -import dataclasses import gzip import io import json @@ -27,6 +26,7 @@ from kapitan.inventory import Inventory, get_inventory_backend from kapitan.utils import ( PrettyDumper, + StrEnum, deep_get, flatten_dict, render_jinja2_file, @@ -37,6 +37,11 @@ JSONNET_CACHE = {} +yaml.SafeDumper.add_multi_representer( + StrEnum, + yaml.representer.SafeRepresenter.represent_str, +) + def resource_callbacks(search_paths): """ @@ -284,7 +289,7 @@ def inventory(search_paths: list = [], target_name: str = None, inventory_path: if target_name: target = inv.get_target(target_name) - return target.model_dump() + return target.model_dump(by_alias=True) return inv.inventory diff --git a/kapitan/targets.py b/kapitan/targets.py index 8449942c8..642751abf 100644 --- a/kapitan/targets.py +++ b/kapitan/targets.py @@ -10,7 +10,6 @@ import multiprocessing import os import shutil -import sys import tempfile import time from functools import partial @@ -115,17 +114,11 @@ def compile_targets( fetch_objs = [] # iterate through targets for target in target_objs: - try: - # get value of "force_fetch" property - dependencies = target["dependencies"] - # dependencies is still a list - for entry in dependencies: - force_fetch = entry["force_fetch"] - if force_fetch: - fetch_objs.append(target) - except KeyError: - # targets may have no "dependencies" or "force_fetch" key - continue + for entry in target.dependencies: + force_fetch = entry.force_fetch + if entry.force_fetch: + fetch_objs.append(target) + # fetch dependencies from targets with force_fetch set to true if fetch_objs: fetch_dependencies(output_path, fetch_objs, dep_cache_dir, True, pool) @@ -151,7 +144,7 @@ def compile_targets( # if '-t' is set on compile or only a few changed, only override selected targets if len(target_objs) < len(discovered_targets): for target in target_objs: - path = target["target_full_path"] + path = target.target_full_path compile_path_target = os.path.join(compile_path, path) temp_path_target = os.path.join(temp_compile_path, path) @@ -185,10 +178,11 @@ def compile_targets( logger.exception(e) else: logger.error(e) - sys.exit(1) + raise CompileError(f"Error compiling targets: {e}") - shutil.rmtree(temp_path) - logger.debug("Removed %s", temp_path) + finally: + shutil.rmtree(temp_path) + logger.debug("Removed %s", temp_path) def load_target_inventory(inventory, requested_targets, ignore_class_not_found=False): @@ -209,13 +203,11 @@ def load_target_inventory(inventory, requested_targets, ignore_class_not_found=F else: raise InventoryError(f"InventoryError: {target_name}: parameters is empty") - kapitan_target_configs = target.parameters["kapitan"] - for comp_obj in kapitan_target_configs["compile"]: - comp_obj.setdefault("input_params", {}) + kapitan_target_configs = target.parameters.kapitan # check if parameters.kapitan is empty if not kapitan_target_configs: raise InventoryError(f"InventoryError: {target_name}: parameters.kapitan has no assignment") - kapitan_target_configs["target_full_path"] = inventory.targets[target_name].name.replace(".", "/") + kapitan_target_configs.target_full_path = inventory.targets[target_name].name.replace(".", "/") logger.debug(f"load_target_inventory: found valid kapitan target {target_name}") target_objs.append(kapitan_target_configs) except KeyError: @@ -240,7 +232,7 @@ def search_targets(inventory, targets, labels): # It should come back already rendered for target in inventory.targets.values(): - target_labels = target.parameters["kapitan"].get("labels", {}) + target_labels = target.parameters.kapitan.labels matched_all_labels = False for label, value in labels_dict.items(): try: @@ -267,9 +259,9 @@ def search_targets(inventory, targets, labels): def compile_target(target_obj, search_paths, compile_path, ref_controller, globals_cached=None, **kwargs): """Compiles target_obj and writes to compile_path""" start = time.time() - compile_objs = target_obj["compile"] - ext_vars = target_obj["vars"] - target_name = ext_vars["target"] + compile_objs = target_obj.compile + ext_vars = target_obj.vars + target_name = ext_vars.target # Only populates the cache if the subprocess doesn't have it if globals_cached and not cached.inv: @@ -280,30 +272,28 @@ def compile_target(target_obj, search_paths, compile_path, ref_controller, globa logger.debug("Using go-jsonnet over jsonnet") for comp_obj in compile_objs: - input_type = comp_obj["input_type"] - output_path = comp_obj["output_path"] - input_params = comp_obj.setdefault("input_params", {}) - continue_on_compile_error = comp_obj.get("continue_on_compile_error", False) + input_type = comp_obj.input_type + output_path = comp_obj.output_path + input_params = comp_obj.input_params + continue_on_compile_error = comp_obj.continue_on_compile_error - if input_type == "jinja2": + if input_type == input_type.JINJA2: input_compiler = Jinja2(compile_path, search_paths, ref_controller, comp_obj) - elif input_type == "jsonnet": + elif input_type == input_type.JSONNET: input_compiler = Jsonnet(compile_path, search_paths, ref_controller, use_go=use_go_jsonnet) - elif input_type == "kadet": + elif input_type == input_type.KADET: input_compiler = Kadet(compile_path, search_paths, ref_controller, input_params=input_params) - elif input_type == "helm": + elif input_type == input_type.HELM: input_compiler = Helm(compile_path, search_paths, ref_controller, comp_obj) - elif input_type == "copy": - ignore_missing = comp_obj.get("ignore_missing", False) + elif input_type == input_type.COPY: + ignore_missing = comp_obj.ignore_missing input_compiler = Copy(compile_path, search_paths, ref_controller, ignore_missing) - elif input_type == "remove": + elif input_type == input_type.REMOVE: input_compiler = Remove(compile_path, search_paths, ref_controller) - elif input_type == "external": + elif input_type == input_type.EXTERNAL: input_compiler = External(compile_path, search_paths, ref_controller) - if "args" in comp_obj: - input_compiler.set_args(comp_obj["args"]) - if "env_vars" in comp_obj: - input_compiler.set_env_vars(comp_obj["env_vars"]) + input_compiler.set_args(comp_obj.args) + input_compiler.set_env_vars(comp_obj.env_vars) else: err_msg = 'Invalid input_type: "{}". Supported input_types: jsonnet, jinja2, kadet, helm, copy, remove, external' raise CompileError(err_msg.format(input_type)) @@ -321,4 +311,4 @@ def compile_target(target_obj, search_paths, compile_path, ref_controller, globa traceback.print_exception(type(e), e, e.__traceback__) raise CompileError(f"Error compiling {target_name}: {e}") - logger.info("Compiled %s (%.2fs)", target_obj["target_full_path"], time.time() - start) + logger.info("Compiled %s (%.2fs)", target_obj.target_full_path, time.time() - start) diff --git a/kapitan/utils.py b/kapitan/utils.py index 977ad1cb9..665c68057 100644 --- a/kapitan/utils.py +++ b/kapitan/utils.py @@ -40,6 +40,11 @@ logger = logging.getLogger(__name__) +try: + from enum import StrEnum +except ImportError: + from strenum import StrEnum + try: from yaml import CSafeLoader as YamlLoader except ImportError: diff --git a/poetry.lock b/poetry.lock index ab00827fb..d2b31004c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -157,17 +157,17 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "boto3" -version = "1.35.11" +version = "1.35.14" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.35.11-py3-none-any.whl", hash = "sha256:f5834dd908edda56c3da86b908693c7cd1c17c2f8150de736e9e90c56ecc78f6"}, - {file = "boto3-1.35.11.tar.gz", hash = "sha256:bdfb8dd2564e5cf2f5095fb8e3a0a4612202654c1196692dddd9bc48aadc7657"}, + {file = "boto3-1.35.14-py3-none-any.whl", hash = "sha256:c3e138e9041d59cd34cdc28a587dfdc899dba02ea26ebc3e10fb4bc88e5cf31b"}, + {file = "boto3-1.35.14.tar.gz", hash = "sha256:7bc78d7140c353b10a637927fe4bc4c4d95a464d1b8f515d5844def2ee52cbd5"}, ] [package.dependencies] -botocore = ">=1.35.11,<1.36.0" +botocore = ">=1.35.14,<1.36.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -176,13 +176,13 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.35.11" +version = "1.35.14" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.35.11-py3-none-any.whl", hash = "sha256:e9b647b6cf1f63fd701c27433802d1c4342838a37fd152b40fe53b967fd19af4"}, - {file = "botocore-1.35.11.tar.gz", hash = "sha256:f5f671f8f9566f28bed496017ea94d275ca5c253e9e4f91cd56cb7a293e37d0c"}, + {file = "botocore-1.35.14-py3-none-any.whl", hash = "sha256:24823135232f88266b66ae8e1d0f3d40872c14cd976781f7fe52b8f0d79035a0"}, + {file = "botocore-1.35.14.tar.gz", hash = "sha256:8515a2fc7ca5bcf0b10016ba05ccf2d642b7cb77d8773026ff2fa5aa3bf38d2e"}, ] [package.dependencies] @@ -217,78 +217,78 @@ files = [ [[package]] name = "cffi" -version = "1.17.0" +version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, - {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, - {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, - {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, - {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, - {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, - {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, - {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, - {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, - {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, - {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, - {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, - {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, - {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, - {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, - {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, - {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, - {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, - {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, - {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, - {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, - {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, - {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, - {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, - {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, - {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, - {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, - {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, - {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, - {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, - {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, ] [package.dependencies] @@ -637,19 +637,19 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.15.4" +version = "3.16.0" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, - {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, + {file = "filelock-3.16.0-py3-none-any.whl", hash = "sha256:f6ed4c963184f4c84dd5557ce8fece759a3724b37b80c6c4f20a2f63a4dc6609"}, + {file = "filelock-3.16.0.tar.gz", hash = "sha256:81de9eb8453c769b63369f87f11131a7ab04e367f8d97ad39dc230daa07e3bec"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] -typing = ["typing-extensions (>=4.8)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.1.1)", "pytest (>=8.3.2)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.3)"] +typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "flake8" @@ -786,13 +786,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] [[package]] name = "google-api-python-client" -version = "2.143.0" +version = "2.144.0" description = "Google API Client Library for Python" optional = false python-versions = ">=3.7" files = [ - {file = "google_api_python_client-2.143.0-py2.py3-none-any.whl", hash = "sha256:d5654134522b9b574b82234e96f7e0aeeabcbf33643fbabcd449ef0068e3a476"}, - {file = "google_api_python_client-2.143.0.tar.gz", hash = "sha256:6a75441f9078e6e2fcdf4946a153fda1e2cc81b5e9c8d6e8c0750c85c7f8a566"}, + {file = "google_api_python_client-2.144.0-py2.py3-none-any.whl", hash = "sha256:f9c333ac4454a012adca90c297f9a22611a8953f3aae5481f90b3a56b9bdd413"}, + {file = "google_api_python_client-2.144.0.tar.gz", hash = "sha256:fe00851b257157bca600e1692ed8a54762c4a5c7d9eb7f6d4822059424b0d0a9"}, ] [package.dependencies] @@ -1334,22 +1334,22 @@ files = [ [[package]] name = "msal" -version = "1.30.0" +version = "1.31.0" description = "The Microsoft Authentication Library (MSAL) for Python library enables your app to access the Microsoft Cloud by supporting authentication of users with Microsoft Azure Active Directory accounts (AAD) and Microsoft Accounts (MSA) using industry standard OAuth2 and OpenID Connect." optional = false python-versions = ">=3.7" files = [ - {file = "msal-1.30.0-py3-none-any.whl", hash = "sha256:423872177410cb61683566dc3932db7a76f661a5d2f6f52f02a047f101e1c1de"}, - {file = "msal-1.30.0.tar.gz", hash = "sha256:b4bf00850092e465157d814efa24a18f788284c9a479491024d62903085ea2fb"}, + {file = "msal-1.31.0-py3-none-any.whl", hash = "sha256:96bc37cff82ebe4b160d5fc0f1196f6ca8b50e274ecd0ec5bf69c438514086e7"}, + {file = "msal-1.31.0.tar.gz", hash = "sha256:2c4f189cf9cc8f00c80045f66d39b7c0f3ed45873fd3d1f2af9f22db2e12ff4b"}, ] [package.dependencies] -cryptography = ">=2.5,<45" +cryptography = ">=2.5,<46" PyJWT = {version = ">=1.0.0,<3", extras = ["crypto"]} requests = ">=2.0.0,<3" [package.extras] -broker = ["pymsalruntime (>=0.13.2,<0.17)"] +broker = ["pymsalruntime (>=0.14,<0.18)", "pymsalruntime (>=0.17,<0.18)"] [[package]] name = "msal-extensions" @@ -1441,19 +1441,19 @@ files = [ [[package]] name = "platformdirs" -version = "4.2.2" +version = "4.3.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, - {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, + {file = "platformdirs-4.3.2-py3-none-any.whl", hash = "sha256:eb1c8582560b34ed4ba105009a4badf7f6f85768b30126f351328507b2beb617"}, + {file = "platformdirs-4.3.2.tar.gz", hash = "sha256:9e5e27a08aa095dd127b9f2e764d74254f482fef22b0970773bfba79d091ab8c"}, ] [package.extras] -docs = ["furo (>=2023.9.10)", "proselint (>=0.13)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)"] -type = ["mypy (>=1.8)"] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] [[package]] name = "pluggy" @@ -1593,119 +1593,120 @@ files = [ [[package]] name = "pydantic" -version = "2.8.2" +version = "2.9.0" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, - {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, + {file = "pydantic-2.9.0-py3-none-any.whl", hash = "sha256:f66a7073abd93214a20c5f7b32d56843137a7a2e70d02111f3be287035c45370"}, + {file = "pydantic-2.9.0.tar.gz", hash = "sha256:c7a8a9fdf7d100afa49647eae340e2d23efa382466a8d177efcd1381e9be5598"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.20.1" +pydantic-core = "2.23.2" typing-extensions = {version = ">=4.6.1", markers = "python_version < \"3.13\""} +tzdata = {version = "*", markers = "python_version >= \"3.9\""} [package.extras] email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.20.1" +version = "2.23.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, - {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, - {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, - {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, - {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, - {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, - {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, - {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, - {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, - {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, - {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, - {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, - {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, - {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, - {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, - {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, - {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, - {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, - {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, - {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, - {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, - {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, - {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, - {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, - {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, - {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, - {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, - {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, - {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, - {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, - {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, - {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, - {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, + {file = "pydantic_core-2.23.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7d0324a35ab436c9d768753cbc3c47a865a2cbc0757066cb864747baa61f6ece"}, + {file = "pydantic_core-2.23.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:276ae78153a94b664e700ac362587c73b84399bd1145e135287513442e7dfbc7"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:964c7aa318da542cdcc60d4a648377ffe1a2ef0eb1e996026c7f74507b720a78"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1cf842265a3a820ebc6388b963ead065f5ce8f2068ac4e1c713ef77a67b71f7c"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae90b9e50fe1bd115b24785e962b51130340408156d34d67b5f8f3fa6540938e"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ae65fdfb8a841556b52935dfd4c3f79132dc5253b12c0061b96415208f4d622"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c8aa40f6ca803f95b1c1c5aeaee6237b9e879e4dfb46ad713229a63651a95fb"}, + {file = "pydantic_core-2.23.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c53100c8ee5a1e102766abde2158077d8c374bee0639201f11d3032e3555dfbc"}, + {file = "pydantic_core-2.23.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d6b9dd6aa03c812017411734e496c44fef29b43dba1e3dd1fa7361bbacfc1354"}, + {file = "pydantic_core-2.23.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b18cf68255a476b927910c6873d9ed00da692bb293c5b10b282bd48a0afe3ae2"}, + {file = "pydantic_core-2.23.2-cp310-none-win32.whl", hash = "sha256:e460475719721d59cd54a350c1f71c797c763212c836bf48585478c5514d2854"}, + {file = "pydantic_core-2.23.2-cp310-none-win_amd64.whl", hash = "sha256:5f3cf3721eaf8741cffaf092487f1ca80831202ce91672776b02b875580e174a"}, + {file = "pydantic_core-2.23.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:7ce8e26b86a91e305858e018afc7a6e932f17428b1eaa60154bd1f7ee888b5f8"}, + {file = "pydantic_core-2.23.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7e9b24cca4037a561422bf5dc52b38d390fb61f7bfff64053ce1b72f6938e6b2"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:753294d42fb072aa1775bfe1a2ba1012427376718fa4c72de52005a3d2a22178"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:257d6a410a0d8aeb50b4283dea39bb79b14303e0fab0f2b9d617701331ed1515"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c8319e0bd6a7b45ad76166cc3d5d6a36c97d0c82a196f478c3ee5346566eebfd"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a05c0240f6c711eb381ac392de987ee974fa9336071fb697768dfdb151345ce"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d5b0ff3218858859910295df6953d7bafac3a48d5cd18f4e3ed9999efd2245f"}, + {file = "pydantic_core-2.23.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:96ef39add33ff58cd4c112cbac076726b96b98bb8f1e7f7595288dcfb2f10b57"}, + {file = "pydantic_core-2.23.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0102e49ac7d2df3379ef8d658d3bc59d3d769b0bdb17da189b75efa861fc07b4"}, + {file = "pydantic_core-2.23.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a6612c2a844043e4d10a8324c54cdff0042c558eef30bd705770793d70b224aa"}, + {file = "pydantic_core-2.23.2-cp311-none-win32.whl", hash = "sha256:caffda619099cfd4f63d48462f6aadbecee3ad9603b4b88b60cb821c1b258576"}, + {file = "pydantic_core-2.23.2-cp311-none-win_amd64.whl", hash = "sha256:6f80fba4af0cb1d2344869d56430e304a51396b70d46b91a55ed4959993c0589"}, + {file = "pydantic_core-2.23.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:4c83c64d05ffbbe12d4e8498ab72bdb05bcc1026340a4a597dc647a13c1605ec"}, + {file = "pydantic_core-2.23.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6294907eaaccf71c076abdd1c7954e272efa39bb043161b4b8aa1cd76a16ce43"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a801c5e1e13272e0909c520708122496647d1279d252c9e6e07dac216accc41"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cc0c316fba3ce72ac3ab7902a888b9dc4979162d320823679da270c2d9ad0cad"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b06c5d4e8701ac2ba99a2ef835e4e1b187d41095a9c619c5b185c9068ed2a49"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82764c0bd697159fe9947ad59b6db6d7329e88505c8f98990eb07e84cc0a5d81"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b1a195efd347ede8bcf723e932300292eb13a9d2a3c1f84eb8f37cbbc905b7f"}, + {file = "pydantic_core-2.23.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b7efb12e5071ad8d5b547487bdad489fbd4a5a35a0fc36a1941517a6ad7f23e0"}, + {file = "pydantic_core-2.23.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:5dd0ec5f514ed40e49bf961d49cf1bc2c72e9b50f29a163b2cc9030c6742aa73"}, + {file = "pydantic_core-2.23.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:820f6ee5c06bc868335e3b6e42d7ef41f50dfb3ea32fbd523ab679d10d8741c0"}, + {file = "pydantic_core-2.23.2-cp312-none-win32.whl", hash = "sha256:3713dc093d5048bfaedbba7a8dbc53e74c44a140d45ede020dc347dda18daf3f"}, + {file = "pydantic_core-2.23.2-cp312-none-win_amd64.whl", hash = "sha256:e1895e949f8849bc2757c0dbac28422a04be031204df46a56ab34bcf98507342"}, + {file = "pydantic_core-2.23.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:da43cbe593e3c87d07108d0ebd73771dc414488f1f91ed2e204b0370b94b37ac"}, + {file = "pydantic_core-2.23.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:64d094ea1aa97c6ded4748d40886076a931a8bf6f61b6e43e4a1041769c39dd2"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:084414ffe9a85a52940b49631321d636dadf3576c30259607b75516d131fecd0"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:043ef8469f72609c4c3a5e06a07a1f713d53df4d53112c6d49207c0bd3c3bd9b"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3649bd3ae6a8ebea7dc381afb7f3c6db237fc7cebd05c8ac36ca8a4187b03b30"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6db09153d8438425e98cdc9a289c5fade04a5d2128faff8f227c459da21b9703"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5668b3173bb0b2e65020b60d83f5910a7224027232c9f5dc05a71a1deac9f960"}, + {file = "pydantic_core-2.23.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1c7b81beaf7c7ebde978377dc53679c6cba0e946426fc7ade54251dfe24a7604"}, + {file = "pydantic_core-2.23.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:ae579143826c6f05a361d9546446c432a165ecf1c0b720bbfd81152645cb897d"}, + {file = "pydantic_core-2.23.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:19f1352fe4b248cae22a89268720fc74e83f008057a652894f08fa931e77dced"}, + {file = "pydantic_core-2.23.2-cp313-none-win32.whl", hash = "sha256:e1a79ad49f346aa1a2921f31e8dbbab4d64484823e813a002679eaa46cba39e1"}, + {file = "pydantic_core-2.23.2-cp313-none-win_amd64.whl", hash = "sha256:582871902e1902b3c8e9b2c347f32a792a07094110c1bca6c2ea89b90150caac"}, + {file = "pydantic_core-2.23.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:743e5811b0c377eb830150d675b0847a74a44d4ad5ab8845923d5b3a756d8100"}, + {file = "pydantic_core-2.23.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6650a7bbe17a2717167e3e23c186849bae5cef35d38949549f1c116031b2b3aa"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56e6a12ec8d7679f41b3750ffa426d22b44ef97be226a9bab00a03365f217b2b"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:810ca06cca91de9107718dc83d9ac4d2e86efd6c02cba49a190abcaf33fb0472"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:785e7f517ebb9890813d31cb5d328fa5eda825bb205065cde760b3150e4de1f7"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ef71ec876fcc4d3bbf2ae81961959e8d62f8d74a83d116668409c224012e3af"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d50ac34835c6a4a0d456b5db559b82047403c4317b3bc73b3455fefdbdc54b0a"}, + {file = "pydantic_core-2.23.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16b25a4a120a2bb7dab51b81e3d9f3cde4f9a4456566c403ed29ac81bf49744f"}, + {file = "pydantic_core-2.23.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:41ae8537ad371ec018e3c5da0eb3f3e40ee1011eb9be1da7f965357c4623c501"}, + {file = "pydantic_core-2.23.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:07049ec9306ec64e955b2e7c40c8d77dd78ea89adb97a2013d0b6e055c5ee4c5"}, + {file = "pydantic_core-2.23.2-cp38-none-win32.whl", hash = "sha256:086c5db95157dc84c63ff9d96ebb8856f47ce113c86b61065a066f8efbe80acf"}, + {file = "pydantic_core-2.23.2-cp38-none-win_amd64.whl", hash = "sha256:67b6655311b00581914aba481729971b88bb8bc7996206590700a3ac85e457b8"}, + {file = "pydantic_core-2.23.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:358331e21a897151e54d58e08d0219acf98ebb14c567267a87e971f3d2a3be59"}, + {file = "pydantic_core-2.23.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c4d9f15ffe68bcd3898b0ad7233af01b15c57d91cd1667f8d868e0eacbfe3f87"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0123655fedacf035ab10c23450163c2f65a4174f2bb034b188240a6cf06bb123"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e6e3ccebdbd6e53474b0bb7ab8b88e83c0cfe91484b25e058e581348ee5a01a5"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc535cb898ef88333cf317777ecdfe0faac1c2a3187ef7eb061b6f7ecf7e6bae"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aab9e522efff3993a9e98ab14263d4e20211e62da088298089a03056980a3e69"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05b366fb8fe3d8683b11ac35fa08947d7b92be78ec64e3277d03bd7f9b7cda79"}, + {file = "pydantic_core-2.23.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7568f682c06f10f30ef643a1e8eec4afeecdafde5c4af1b574c6df079e96f96c"}, + {file = "pydantic_core-2.23.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:cdd02a08205dc90238669f082747612cb3c82bd2c717adc60f9b9ecadb540f80"}, + {file = "pydantic_core-2.23.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a2ab4f410f4b886de53b6bddf5dd6f337915a29dd9f22f20f3099659536b2f6"}, + {file = "pydantic_core-2.23.2-cp39-none-win32.whl", hash = "sha256:0448b81c3dfcde439551bb04a9f41d7627f676b12701865c8a2574bcea034437"}, + {file = "pydantic_core-2.23.2-cp39-none-win_amd64.whl", hash = "sha256:4cebb9794f67266d65e7e4cbe5dcf063e29fc7b81c79dc9475bd476d9534150e"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e758d271ed0286d146cf7c04c539a5169a888dd0b57026be621547e756af55bc"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:f477d26183e94eaafc60b983ab25af2a809a1b48ce4debb57b343f671b7a90b6"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da3131ef2b940b99106f29dfbc30d9505643f766704e14c5d5e504e6a480c35e"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329a721253c7e4cbd7aad4a377745fbcc0607f9d72a3cc2102dd40519be75ed2"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7706e15cdbf42f8fab1e6425247dfa98f4a6f8c63746c995d6a2017f78e619ae"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e64ffaf8f6e17ca15eb48344d86a7a741454526f3a3fa56bc493ad9d7ec63936"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dd59638025160056687d598b054b64a79183f8065eae0d3f5ca523cde9943940"}, + {file = "pydantic_core-2.23.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:12625e69b1199e94b0ae1c9a95d000484ce9f0182f9965a26572f054b1537e44"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5d813fd871b3d5c3005157622ee102e8908ad6011ec915a18bd8fde673c4360e"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1eb37f7d6a8001c0f86dc8ff2ee8d08291a536d76e49e78cda8587bb54d8b329"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ce7eaf9a98680b4312b7cebcdd9352531c43db00fca586115845df388f3c465"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f087879f1ffde024dd2788a30d55acd67959dcf6c431e9d3682d1c491a0eb474"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ce883906810b4c3bd90e0ada1f9e808d9ecf1c5f0b60c6b8831d6100bcc7dd6"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:a8031074a397a5925d06b590121f8339d34a5a74cfe6970f8a1124eb8b83f4ac"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23af245b8f2f4ee9e2c99cb3f93d0e22fb5c16df3f2f643f5a8da5caff12a653"}, + {file = "pydantic_core-2.23.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c57e493a0faea1e4c38f860d6862ba6832723396c884fbf938ff5e9b224200e2"}, + {file = "pydantic_core-2.23.2.tar.gz", hash = "sha256:95d6bf449a1ac81de562d65d180af5d8c19672793c81877a2eda8fde5d08f2fd"}, ] [package.dependencies] @@ -2460,6 +2461,17 @@ files = [ {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] +[[package]] +name = "tzdata" +version = "2024.1" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, + {file = "tzdata-2024.1.tar.gz", hash = "sha256:2674120f8d891909751c38abcdfd386ac0a5a1127954fbc332af6b5ceae07efd"}, +] + [[package]] name = "uritemplate" version = "4.1.1" @@ -2504,13 +2516,13 @@ test = ["coverage", "flake8 (>=3.7)", "mypy", "pretend", "pytest"] [[package]] name = "virtualenv" -version = "20.26.3" +version = "20.26.4" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, - {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, + {file = "virtualenv-20.26.4-py3-none-any.whl", hash = "sha256:48f2695d9809277003f30776d155615ffc11328e6a0a8c1f0ec80188d7874a55"}, + {file = "virtualenv-20.26.4.tar.gz", hash = "sha256:c17f4e0f3e6036e9f26700446f85c76ab11df65ff6d8a9cbfad9f71aabfcf23c"}, ] [package.dependencies] @@ -2609,4 +2621,4 @@ reclass-rs = ["reclass-rs"] [metadata] lock-version = "2.0" python-versions = "^3.10,<3.13" -content-hash = "150d4e578d6a4d21fe39d3872a7b2ac51e0bd02eb975dd14d32b2d371d52fffb" +content-hash = "a1a8378dae81ad3d4b5b97d308c5334b9d78c2cc7a2ff502ebb2eb28df1c2c61" diff --git a/pyproject.toml b/pyproject.toml index 9f076d7aa..2e7962030 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,7 @@ omegaconf = {version = "^2.4.0.dev3", optional = true} reclass-rs = {version = "^0.4.0", optional = true } gojsonnet = { version = "^0.20.0", optional = true } kapicorp-reclass = ">=2.0.0" +pydantic = "^2.8.2" [tool.poetry.extras] gojsonnet = ["gojsonnet"] diff --git a/tests/test_azure.py b/tests/test_azure.py index ccd57e82b..47932f422 100644 --- a/tests/test_azure.py +++ b/tests/test_azure.py @@ -9,8 +9,8 @@ from kapitan import cached from kapitan.cli import main -from kapitan.refs.base import RefController, RefParams, Revealer -from kapitan.refs.secrets.azkms import AzureKMSError, AzureKMSSecret +from kapitan.refs.base import RefController, Revealer +from kapitan.refs.secrets.azkms import AzureKMSSecret REFS_HOME = tempfile.mkdtemp() REF_CONTROLLER = RefController(REFS_HOME) diff --git a/tests/test_compile.py b/tests/test_compile.py index e84463f21..61a0abc62 100644 --- a/tests/test_compile.py +++ b/tests/test_compile.py @@ -10,6 +10,7 @@ import contextlib import glob import io +import logging import os import shutil import sys @@ -24,6 +25,8 @@ from kapitan.inventory import InventoryBackends from kapitan.utils import directory_hash +logger = logging.getLogger(__name__) + TEST_PWD = os.getcwd() TEST_RESOURCES_PATH = os.path.join(os.getcwd(), "tests/test_resources") TEST_DOCKER_PATH = os.path.join(os.getcwd(), "examples/docker/") @@ -209,6 +212,7 @@ def test_compile_jsonnet_env(self): self.assertTrue(os.path.exists("compiled/jsonnet-env/jsonnet-env/env.yml")) with open("compiled/jsonnet-env/jsonnet-env/env.yml", "r", encoding="utf-8") as f: env = dict(yaml.safe_load(f)) + logger.error(env) self.assertEqual(set(env.keys()), {"applications", "parameters", "classes", "exports"}) self.assertEqual(env["applications"], ["a", "b", "c"]) self.assertEqual(env["classes"], ["common", "jsonnet-env"]) diff --git a/tests/test_compose_node_name.py b/tests/test_compose_node_name.py index 1e45b76eb..2671a2f49 100644 --- a/tests/test_compose_node_name.py +++ b/tests/test_compose_node_name.py @@ -1,5 +1,3 @@ -import glob -import logging import os import shutil import tempfile diff --git a/tests/test_dependency_manager.py b/tests/test_dependency_manager.py index 4fe9c0fee..497849ebe 100644 --- a/tests/test_dependency_manager.py +++ b/tests/test_dependency_manager.py @@ -23,6 +23,11 @@ fetch_http_source, ) from kapitan.errors import HelmFetchingError +from kapitan.inventory.model import KapitanInventorySettings +from kapitan.inventory.model.dependencies import ( + KapitanDependencyGitConfig, + KapitanDependencyHelmConfig, +) class DependencyManagerTest(unittest.TestCase): @@ -68,11 +73,15 @@ def test_clone_repo_subdir(self): output_dir = tempfile.mkdtemp() source = "https://github.com/kapicorp/kapitan.git" dep = [ - { - "output_path": os.path.join(output_dir, "subdir"), - "ref": "master", - "subdir": "tests", - } + KapitanDependencyGitConfig( + **{ + "type": "git", + "source": source, + "output_path": os.path.join(output_dir, "subdir"), + "ref": "master", + "subdir": "tests", + } + ) ] fetch_git_dependency((source, dep), temp_dir, force=False) self.assertTrue(os.path.isdir(os.path.join(output_dir, "subdir"))) @@ -90,12 +99,14 @@ def test_fetch_helm_chart(self): version = "11.3.0" repo = "https://github.com/BurdenBear/kube-charts-mirror/raw/master/docs/" dep = [ - { - "output_path": output_chart_dir, - "version": version, - "chart_name": chart_name, - "source": repo, - } + KapitanDependencyHelmConfig( + **{ + "output_path": output_chart_dir, + "version": version, + "chart_name": chart_name, + "source": repo, + } + ) ] fetch_helm_chart((HelmSource(repo, chart_name, version, None), dep), temp_dir, force=False) self.assertTrue(os.path.isdir(output_chart_dir)) @@ -115,12 +126,14 @@ def test_fetch_helm_chart_version_that_does_not_exist(self): version = "10.7.0" repo = "https://github.com/BurdenBear/kube-charts-mirror/raw/master/docs/" dep = [ - { - "output_path": output_chart_dir, - "version": version, - "chart_name": chart_name, - "source": repo, - } + KapitanDependencyHelmConfig( + **{ + "output_path": output_chart_dir, + "version": version, + "chart_name": chart_name, + "source": repo, + } + ) ] with self.assertRaises(HelmFetchingError): fetch_helm_chart((HelmSource(repo, chart_name, version, None), dep), temp_dir, force=False) @@ -134,24 +147,23 @@ def test_fetch_dependencies_unpack_parallel(self): save_dir = tempfile.mkdtemp() # use default parallelism of 4 for test with multiprocessing.Pool(4) as pool: - target_objs = [ + dependencies = [ { - "dependencies": [ - { - "type": "https", - "source": "https://github.com/BurdenBear/kube-charts-mirror/raw/master/docs/nfs-client-provisioner-1.2.8.tgz", - "output_path": "nfs-client-provisioner", - "unpack": True, - }, - { - "type": "https", - "source": "https://github.com/BurdenBear/kube-charts-mirror/raw/master/docs/prometheus-pushgateway-1.2.13.tgz", - "output_path": "prometheus-pushgateway", - "unpack": True, - }, - ] - } + "type": "https", + "source": "https://github.com/BurdenBear/kube-charts-mirror/raw/master/docs/nfs-client-provisioner-1.2.8.tgz", + "output_path": "nfs-client-provisioner", + "unpack": True, + }, + { + "type": "https", + "source": "https://github.com/BurdenBear/kube-charts-mirror/raw/master/docs/prometheus-pushgateway-1.2.13.tgz", + "output_path": "prometheus-pushgateway", + "unpack": True, + }, ] + + inventory = KapitanInventorySettings(dependencies=dependencies) + target_objs = [inventory] try: fetch_dependencies(output_path, target_objs, save_dir, False, pool) pool.close() @@ -159,9 +171,9 @@ def test_fetch_dependencies_unpack_parallel(self): pool.terminate() raise e - for obj in target_objs[0]["dependencies"]: - self.assertTrue(os.path.isdir(os.path.join(output_path, obj["output_path"]))) - self.assertTrue(os.path.isdir(os.path.join(save_dir, obj["output_path"]))) + for obj in target_objs[0].dependencies: + self.assertTrue(os.path.isdir(os.path.join(output_path, obj.output_path))) + self.assertTrue(os.path.isdir(os.path.join(save_dir, obj.output_path))) rmtree(output_path) rmtree(save_dir) diff --git a/tests/test_external_input.py b/tests/test_external_input.py index 0bae8b7eb..3c9894102 100644 --- a/tests/test_external_input.py +++ b/tests/test_external_input.py @@ -8,7 +8,6 @@ "external input tests" import os import random -import stat import string import subprocess import sys diff --git a/tests/test_from_dot_kapitan.py b/tests/test_from_dot_kapitan.py index c467cd2eb..516c77676 100644 --- a/tests/test_from_dot_kapitan.py +++ b/tests/test_from_dot_kapitan.py @@ -1,5 +1,4 @@ import os -import shutil import tempfile import unittest diff --git a/tests/test_helm_input.py b/tests/test_helm_input.py index 3cfb23c9e..ce89707b9 100644 --- a/tests/test_helm_input.py +++ b/tests/test_helm_input.py @@ -17,6 +17,7 @@ from kapitan.cli import main from kapitan.inputs.helm import Helm, HelmChart from kapitan.inputs.kadet import BaseObj +from kapitan.inventory.model.input_types import KapitanInputTypeHelmConfig class HelmInputTest(unittest.TestCase): @@ -26,10 +27,12 @@ def setUp(self): def test_render_chart(self): temp_dir = tempfile.mkdtemp() chart_path = "charts/acs-engine-autoscaler" - helm = Helm(None, None, None, {}) - _, error_message = helm.render_chart( - chart_path, temp_dir, None, {"name": "acs-engine-autoscaler"}, None, None + helm_params = {"name": "acs-engine-autoscaler"} + helm_config = KapitanInputTypeHelmConfig( + input_paths=[chart_path], helm_params=helm_params, output_path=temp_dir ) + helm = Helm(None, None, None, helm_config) + _, error_message = helm.render_chart(chart_path, temp_dir, None, helm_params, None, None) self.assertFalse(error_message) self.assertTrue( os.path.isfile(os.path.join(temp_dir, "acs-engine-autoscaler", "templates", "secrets.yaml")) @@ -38,11 +41,15 @@ def test_render_chart(self): os.path.isfile(os.path.join(temp_dir, "acs-engine-autoscaler", "templates", "deployment.yaml")) ) - def test_error_invalid_char_dir(self): + def test_error_invalid_chart_dir(self): chart_path = "./non-existent" temp_dir = tempfile.mkdtemp() - helm = Helm(None, None, None, {}) - _, error_message = helm.render_chart(chart_path, temp_dir, None, {"name": "mychart"}, None, None) + helm_params = {"name": "mychart"} + helm_config = KapitanInputTypeHelmConfig( + input_paths=[chart_path], output_path=temp_dir, helm_params=helm_params + ) + helm = Helm(None, None, None, helm_config) + _, error_message = helm.render_chart(chart_path, temp_dir, None, helm_params, None, None) self.assertTrue("path" in error_message and "not found" in error_message) def test_compile_chart(self): diff --git a/tests/test_kubernetes_compiled/jsonnet-env/jsonnet-env/env.yml b/tests/test_kubernetes_compiled/jsonnet-env/jsonnet-env/env.yml index 653c00bab..fd8c664c4 100644 --- a/tests/test_kubernetes_compiled/jsonnet-env/jsonnet-env/env.yml +++ b/tests/test_kubernetes_compiled/jsonnet-env/jsonnet-env/env.yml @@ -19,22 +19,32 @@ parameters: c: ccccc kapitan: compile: - - input_params: {} + - continue_on_compile_error: false + ignore_missing: false + input_params: {} input_paths: - components/jsonnet-env/env.jsonnet input_type: jsonnet + name: null output_path: jsonnet-env output_type: yml + prune: false + dependencies: [] + labels: {} secrets: awskms: key: alias/nameOfKey + azkms: null gkms: key: projects//locations//keyRings//cryptoKeys/ gpg: recipients: - fingerprint: D9234C61F58BEB3ED8552A57E28DC07A3CBFAE7C name: example@kapitan.dev + vaultkv: null + vaulttransit: null target_full_path: jsonnet-env + validate: [] vars: managed_by: kapitan namespace: jsonnet-env diff --git a/tests/test_omegaconf.py b/tests/test_omegaconf.py index 0848da24c..4e194b7e9 100644 --- a/tests/test_omegaconf.py +++ b/tests/test_omegaconf.py @@ -54,17 +54,20 @@ def test_load_and_resolve_single_target(self): # Manually create a new Target target = inventory.target_class(name=target_name, path="minikube-es.yml") - + logger.error(f"Loading target {target_name} from {target.path}") + logger.error(target.parameters) # Adds target to Inventory inventory.targets.update({target_name: target}) # Loads the target using the inventory inventory.load_target(target) - self.assertDictEqual(target_kapitan_metadata["_kapitan_"], target.parameters["_kapitan_"]) - self.assertEqual(target.parameters["_kapitan_"]["name"]["short"], "minikube") - self.assertEqual(target.parameters["target_name"], "minikube-es") - self.assertEqual(target.parameters["kubectl"]["insecure_skip_tls_verify"], False) + # Check if the target is loaded correctly + metadata = target.parameters.model_dump(by_alias=True)["_kapitan_"] + self.assertDictEqual(target_kapitan_metadata["_kapitan_"], metadata) + self.assertEqual(metadata["name"]["short"], "minikube") + self.assertEqual(target.parameters.target_name, "minikube-es") + self.assertEqual(target.parameters.kubectl["insecure_skip_tls_verify"], False) def tearDown(self) -> None: shutil.rmtree(self.temp_dir) diff --git a/tests/test_remove.py b/tests/test_remove.py index 1dbf2d293..3eeb48722 100644 --- a/tests/test_remove.py +++ b/tests/test_remove.py @@ -6,8 +6,6 @@ # SPDX-License-Identifier: Apache-2.0 "remove tests" -import filecmp -import hashlib import os import shutil import sys diff --git a/tests/vault_server.py b/tests/vault_server.py index 0c4b1292f..d1019a66d 100644 --- a/tests/vault_server.py +++ b/tests/vault_server.py @@ -20,8 +20,6 @@ class VaultServerError(KapitanError): """Generic vaultserver errors""" - pass - class VaultServer: """Opens a vault server in a container"""