diff --git a/doc/architecture/Domain.md b/doc/architecture/Domain.md index e0971e2..c6d6da6 100644 --- a/doc/architecture/Domain.md +++ b/doc/architecture/Domain.md @@ -50,6 +50,12 @@ classDiagram tf_terraform_semantic_version } + class Digitalocean { + do_api_key + do_spaces_access_key + do_spaces_secret_key + } + class DnsRecord { fqdn ipv4 @@ -92,18 +98,13 @@ classDiagram create_bump(snapshot_suffix) } - class DigitaloceanTerraform { - do_api_key - do_spaces_access_key - do_spaces_secret_key - } Devops *-- "0..1" Image: specialized_builds Devops *-- "0..1" C4k: specialized_builds Devops *-- "0..1" ProvsK3s: specialized_builds Devops *-- "0..1" TerraformDomain: specialized_builds - Devops *-- "0..1" DigitaloceanTerraform: specialized_builds Devops *-- "0..1" Release: mixins + TerraformDomain *-- "0..1" Digitalocean: provider Release o-- "0..1" BuildFile: primary_build_file Release o-- "0..n" BuildFile: secondary_build_files BuildFile *-- "1" Version diff --git a/src/main/python/ddadevops/__init__.py b/src/main/python/ddadevops/__init__.py index 7cde593..f66936f 100644 --- a/src/main/python/ddadevops/__init__.py +++ b/src/main/python/ddadevops/__init__.py @@ -10,7 +10,6 @@ from .aws_mfa_mixin import AwsMfaMixin, add_aws_mfa_mixin_config from .aws_backend_properties_mixin import AwsBackendPropertiesMixin, add_aws_backend_properties_mixin_config from .c4k_build import C4kBuild from .digitalocean_backend_properties_mixin import DigitaloceanBackendPropertiesMixin, add_digitalocean_backend_properties_mixin_config -from .digitalocean_terraform_build import DigitaloceanTerraformBuild, create_digitalocean_terraform_build_config from .hetzner_mixin import HetznerMixin, add_hetzner_mixin_config from .devops_image_build import DevopsImageBuild from .devops_terraform_build import DevopsTerraformBuild, create_devops_terraform_build_config diff --git a/src/main/python/ddadevops/digitalocean_terraform_build.py b/src/main/python/ddadevops/digitalocean_terraform_build.py index 7d8ae0a..685de23 100644 --- a/src/main/python/ddadevops/digitalocean_terraform_build.py +++ b/src/main/python/ddadevops/digitalocean_terraform_build.py @@ -4,81 +4,9 @@ from .devops_terraform_build import ( ) -def create_digitalocean_terraform_build_config( - stage, - project_root_path, - module, - additional_vars, - do_api_key, - do_spaces_access_id, - do_spaces_secret_key, - build_dir_name="target", - output_json_name=None, - use_workspace=True, - use_package_common_files=True, - build_commons_path=None, - terraform_build_commons_dir_name="terraform", - debug_print_terraform_command=False, - additional_tfvar_files=None, - terraform_semantic_version="1.0.8", -): - if not additional_tfvar_files: - additional_tfvar_files = [] - config = create_devops_terraform_build_config( - stage, - project_root_path, - module, - additional_vars, - build_dir_name, - output_json_name, - use_workspace, - use_package_common_files, - build_commons_path, - terraform_build_commons_dir_name, - debug_print_terraform_command, - additional_tfvar_files, - terraform_semantic_version, - ) - config.update( - { - "DigitaloceanTerraformBuild": { - "do_api_key": do_api_key, - "do_spaces_access_id": do_spaces_access_id, - "do_spaces_secret_key": do_spaces_secret_key, - } - } - ) - return config +def create_digitalocean_terraform_build_config(): + pass class DigitaloceanTerraformBuild(DevopsTerraformBuild): - def __init__(self, project, config): - additional_resources = config.get("tf_additional_resources_from_package", []) - additional_resources += [ - "provider_registry.tf", - "do_provider.tf", - "do_mixin_vars.tf", - ] - config["tf_additional_resources_from_package"] = additional_resources - - additional_vars = config.get("tf_additional_vars", {}) - additional_vars.update( - { - "do_api_key": config.get("do_api_key"), - "do_spaces_access_id": config.get("do_spaces_access_id"), - "do_spaces_secret_key": config.get("do_spaces_secret_key"), - } - ) - super().__init__(project, config) - - self.terraform_service = TerraformService.prod() - - def project_vars(self): - ret = super().project_vars() - ret["do_api_key"] = self.do_api_key - ret["do_spaces_access_id"] = self.do_spaces_access_id - ret["do_spaces_secret_key"] = self.do_spaces_secret_key - return ret - - def copy_build_resources_from_package(self): - super().copy_build_resources_from_package() + pass diff --git a/src/main/python/ddadevops/domain/__init__.py b/src/main/python/ddadevops/domain/__init__.py index e8f0454..d6258b4 100644 --- a/src/main/python/ddadevops/domain/__init__.py +++ b/src/main/python/ddadevops/domain/__init__.py @@ -1,9 +1,9 @@ -from .common import Validateable, DnsRecord, Devops, BuildType, MixinType, ReleaseType +from .common import Validateable, DnsRecord, Devops, BuildType, MixinType, ReleaseType, ProviderType from .devops_factory import DevopsFactory from .image import Image from .c4k import C4k from .terraform import TerraformDomain -from .digitalocean_terraform import DigitaloceanTerraform +from .provider_digitalocean import Digitalocean from .provs_k3s import K3s from .release import Release from .credentials import Credentials, CredentialMapping, GopassType diff --git a/src/main/python/ddadevops/domain/common.py b/src/main/python/ddadevops/domain/common.py index af62ed0..3495b2b 100644 --- a/src/main/python/ddadevops/domain/common.py +++ b/src/main/python/ddadevops/domain/common.py @@ -11,7 +11,10 @@ class BuildType(Enum): C4K = 1 K3S = 2 TERRAFORM = 3 - DIGITALOCEAN_TERRAFORM = 4 + + +class ProviderType(Enum): + DIGITALOCEAN = 0 class MixinType(Enum): diff --git a/src/main/python/ddadevops/domain/devops_factory.py b/src/main/python/ddadevops/domain/devops_factory.py index 07ce39a..915bc4c 100644 --- a/src/main/python/ddadevops/domain/devops_factory.py +++ b/src/main/python/ddadevops/domain/devops_factory.py @@ -4,7 +4,6 @@ from .image import Image from .c4k import C4k from .provs_k3s import K3s from .terraform import TerraformDomain -from .digitalocean_terraform import DigitaloceanTerraform from .release import Release from .version import Version @@ -26,10 +25,6 @@ class DevopsFactory: specialized_builds[BuildType.K3S] = K3s(inp) if BuildType.TERRAFORM in build_types: specialized_builds[BuildType.TERRAFORM] = TerraformDomain(inp) - if BuildType.DIGITALOCEAN_TERRAFORM in build_types: - specialized_builds[ - BuildType.DIGITALOCEAN_TERRAFORM - ] = DigitaloceanTerraform(inp) mixins: Dict[MixinType, Validateable] = {} if MixinType.RELEASE in mixin_types: diff --git a/src/main/python/ddadevops/domain/init_service.py b/src/main/python/ddadevops/domain/init_service.py index cf8f37c..ca0b9ec 100644 --- a/src/main/python/ddadevops/domain/init_service.py +++ b/src/main/python/ddadevops/domain/init_service.py @@ -63,7 +63,7 @@ class InitService: "name": "image_dockerhub_password", }, ] - if BuildType.DIGITALOCEAN_TERRAFORM in build_types: + if False: default_mappings += [ { "gopass_path": "server/devops/digitalocean/s3", diff --git a/src/main/python/ddadevops/domain/digitalocean_terraform.py b/src/main/python/ddadevops/domain/provider_digitalocean.py similarity index 61% rename from src/main/python/ddadevops/domain/digitalocean_terraform.py rename to src/main/python/ddadevops/domain/provider_digitalocean.py index 10585ce..a27057d 100644 --- a/src/main/python/ddadevops/domain/digitalocean_terraform.py +++ b/src/main/python/ddadevops/domain/provider_digitalocean.py @@ -4,7 +4,7 @@ from .common import ( ) -class DigitaloceanTerraform(Validateable): +class Digitalocean(Validateable): def __init__( self, inp: dict, @@ -19,3 +19,11 @@ class DigitaloceanTerraform(Validateable): result += self.__validate_is_not_empty__("do_spaces_access_id") result += self.__validate_is_not_empty__("do_spaces_secret_key") return result + + def resources_from_package(self) -> List[str]: + return ["provider_registry.tf", "do_provider.tf", "do_mixin_vars.tf"] + + def project_vars(self): + return {"do_api_key": self.do_api_key, + "do_spaces_access_id": self.do_spaces_access_id, + "do_spaces_secret_key": self.do_spaces_secret_key,} diff --git a/src/main/python/ddadevops/domain/terraform.py b/src/main/python/ddadevops/domain/terraform.py index f5cecf4..5a46073 100644 --- a/src/main/python/ddadevops/domain/terraform.py +++ b/src/main/python/ddadevops/domain/terraform.py @@ -2,10 +2,12 @@ from typing import List, Optional from pathlib import Path from .common import ( Validateable, + ProviderType, DnsRecord, Devops, filter_none, ) +from .provider_digitalocean import Digitalocean class TerraformDomain(Validateable): @@ -15,6 +17,7 @@ class TerraformDomain(Validateable): self.tf_additional_vars = inp.get("tf_additional_vars") self.tf_output_json_name = inp.get("tf_output_json_name") self.tf_build_commons_path = inp.get("tf_build_commons_path") + self.tf_provider_types = inp.get("tf_provider_types", []) self.tf_additional_resources_from_package = inp.get( "tf_additional_resources_from_package", [] ) @@ -31,6 +34,11 @@ class TerraformDomain(Validateable): ) self.tf_use_package_common_files = inp.get("tf_use_package_common_files", True) + provider_types = self.__parse_provider_types__(self.tf_provider_types) + self.providers = {} + if ProviderType.DIGITALOCEAN in provider_types: + self.providers[ProviderType.DIGITALOCEAN] = Digitalocean(inp) + def validate(self) -> List[str]: result = [] result += self.__validate_is_not_empty__("module") @@ -38,6 +46,9 @@ class TerraformDomain(Validateable): result += self.__validate_is_not_empty__("tf_build_commons_dir_name") result += self.__validate_is_not_none__("tf_additional_resources_from_package") result += self.__validate_is_not_none__("tf_additional_tfvar_files") + result += self.__validate_is_not_none__("tf_provider_types") + for provider in self.providers.values(): + result += provider.validate() return result def output_json_name(self) -> str: @@ -51,12 +62,24 @@ class TerraformDomain(Validateable): return Path("/".join(filter_none(mylist)) + "/") def project_vars(self): - ret = {"stage": self.stage, "module": self.module} + result = {"stage": self.stage, "module": self.module} + for provider in self.providers.values(): + result.update(provider.project_vars()) if self.tf_additional_vars: - ret.update(self.tf_additional_vars) - return ret + result.update(self.tf_additional_vars) + return result def resources_from_package(self) -> List[str]: result = ["version.tf", "terraform_build_vars.tf"] + for provider in self.providers.values(): + result += provider.resources_from_package() result += self.tf_additional_resources_from_package return result + + def __parse_provider_types__( + self, tf_provider_types: List[str] + ) -> List[ProviderType]: + result = [] + for provider_type in tf_provider_types: + result.append(ProviderType[provider_type]) + return result diff --git a/src/test/python/domain/helper.py b/src/test/python/domain/helper.py index c0012fa..d18f276 100644 --- a/src/test/python/domain/helper.py +++ b/src/test/python/domain/helper.py @@ -24,6 +24,7 @@ def devops_config(overrides: dict) -> dict: "k3s_letsencrypt_endpoint": "k3s_letsencrypt_endpoint", "k3s_enable_echo": "false", "k3s_app_filename_to_provision": "k3s_app.yaml", + "tf_provider_types": ["DIGITALOCEAN"], "tf_additional_vars": [], "tf_output_json_name": "the_out.json", "tf_use_workspace": None, diff --git a/src/test/python/domain/test_devops_factory.py b/src/test/python/domain/test_devops_factory.py index 2ea8d1b..60bab56 100644 --- a/src/test/python/domain/test_devops_factory.py +++ b/src/test/python/domain/test_devops_factory.py @@ -50,23 +50,6 @@ def test_devops_factory(): assert sut is not None assert sut.specialized_builds[BuildType.C4K] is not None - sut = DevopsFactory().build_devops( - { - "stage": "test", - "name": "mybuild", - "module": "test_image", - "project_root_path": "../../..", - "build_types": ["DIGITALOCEAN_TERRAFORM"], - "mixin_types": [], - "do_api_key": "api_key", - "do_spaces_access_id": "spaces_id", - "do_spaces_secret_key": "spaces_secret", - }, - Version.from_str("1.0.0"), - ) - assert sut is not None - assert sut.specialized_builds[BuildType.DIGITALOCEAN_TERRAFORM] is not None - sut = DevopsFactory().build_devops( { "stage": "test", diff --git a/src/test/python/domain/test_digitalocean_terraform.py b/src/test/python/domain/test_provider_digitalocean.py similarity index 81% rename from src/test/python/domain/test_digitalocean_terraform.py rename to src/test/python/domain/test_provider_digitalocean.py index 7e6e6d5..d24f45f 100644 --- a/src/test/python/domain/test_digitalocean_terraform.py +++ b/src/test/python/domain/test_provider_digitalocean.py @@ -2,13 +2,13 @@ from pybuilder.core import Project from pathlib import Path from src.main.python.ddadevops.domain import ( BuildType, - DigitaloceanTerraform, + Digitalocean, ) from .helper import devops_config -def test_digitalocean_terraform(): - sut = DigitaloceanTerraform( +def test_digitalocean_creation(): + sut = Digitalocean( devops_config( { "do_api_key": "api_key", diff --git a/src/test/python/domain/test_terraform.py b/src/test/python/domain/test_terraform.py index 86d8907..22285af 100644 --- a/src/test/python/domain/test_terraform.py +++ b/src/test/python/domain/test_terraform.py @@ -1,13 +1,20 @@ import pytest from pathlib import Path -from src.main.python.ddadevops.domain import DnsRecord, BuildType, TerraformDomain +from src.main.python.ddadevops.domain import ( + DnsRecord, + BuildType, + ProviderType, + TerraformDomain, +) from .helper import build_devops, devops_config def test_creation(): - sut = build_devops({}) - assert BuildType.TERRAFORM in sut.specialized_builds - assert sut.specialized_builds[BuildType.TERRAFORM] + devops = build_devops({}) + sut = devops.specialized_builds[BuildType.TERRAFORM] + assert BuildType.TERRAFORM in devops.specialized_builds + assert sut + assert sut.providers[ProviderType.DIGITALOCEAN] def test_should_calculate_output_json_name(): @@ -21,6 +28,20 @@ def test_should_calculate_output_json_name(): assert "out_module.json" == sut.output_json_name() +def test_should_validate(): + config = devops_config({}) + sut = TerraformDomain(config) + assert sut.is_valid() + + config = devops_config( + { + "do_api_key": "", + } + ) + sut = TerraformDomain(config) + assert not sut.is_valid() + + def test_should_calculate_terraform_build_commons_path(): config = devops_config({}) del config["tf_build_commons_path"] @@ -32,16 +53,53 @@ def test_should_calculate_terraform_build_commons_path(): sut = TerraformDomain(config) assert Path("build_commons_path/terraform") == sut.terraform_build_commons_path() + def test_should_calculate_project_vars(): + config = devops_config( + { + "tf_provider_types": [], + } + ) + sut = TerraformDomain(config) + assert {"module": "module", "stage": "test"} == sut.project_vars() + config = devops_config({}) sut = TerraformDomain(config) - assert {'module': 'module', 'stage': 'test'} == sut.project_vars() + assert { + "module": "module", + "stage": "test", + "do_api_key": "api_key", + "do_spaces_access_id": "spaces_id", + "do_spaces_secret_key": "spaces_secret", + } == sut.project_vars() + def test_should_calculate_resources_from_package(): - config = devops_config({}) + config = devops_config( + { + "tf_provider_types": [], + } + ) sut = TerraformDomain(config) assert ["version.tf", "terraform_build_vars.tf"] == sut.resources_from_package() + config = devops_config({}) + sut = TerraformDomain(config) + assert [ + "version.tf", + "terraform_build_vars.tf", + "provider_registry.tf", + "do_provider.tf", + "do_mixin_vars.tf", + ] == sut.resources_from_package() + config = devops_config({"tf_additional_resources_from_package": ["my.file"]}) sut = TerraformDomain(config) - assert ["version.tf", "terraform_build_vars.tf", "my.file"] == sut.resources_from_package() \ No newline at end of file + assert [ + "version.tf", + "terraform_build_vars.tf", + "provider_registry.tf", + "do_provider.tf", + "do_mixin_vars.tf", + "my.file", + ] == sut.resources_from_package()