From b26cf9ff0a0c8cff5808eeca887cfdf2c2b5bc22 Mon Sep 17 00:00:00 2001 From: bom Date: Fri, 26 May 2023 08:29:32 +0200 Subject: [PATCH] Implement Hetzner provider --- src/main/python/ddadevops/domain/__init__.py | 1 + src/main/python/ddadevops/domain/common.py | 1 + .../python/ddadevops/domain/init_service.py | 6 +++++ .../ddadevops/domain/provider_hetzner.py | 26 +++++++++++++++++++ src/main/python/ddadevops/domain/terraform.py | 3 +++ src/test/python/domain/helper.py | 3 ++- .../python/domain/test_provider_hetzner.py | 19 ++++++++++++++ src/test/python/domain/test_terraform.py | 25 +++++++++++++++++- 8 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 src/main/python/ddadevops/domain/provider_hetzner.py create mode 100644 src/test/python/domain/test_provider_hetzner.py diff --git a/src/main/python/ddadevops/domain/__init__.py b/src/main/python/ddadevops/domain/__init__.py index 3972995..b281a61 100644 --- a/src/main/python/ddadevops/domain/__init__.py +++ b/src/main/python/ddadevops/domain/__init__.py @@ -4,6 +4,7 @@ from .image import Image from .c4k import C4k from .terraform import TerraformDomain from .provider_digitalocean import Digitalocean +from .provider_hetzner import Hetzner 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 3533b04..01dc29d 100644 --- a/src/main/python/ddadevops/domain/common.py +++ b/src/main/python/ddadevops/domain/common.py @@ -15,6 +15,7 @@ class BuildType(Enum): class ProviderType(Enum): DIGITALOCEAN = 0 + HETZNER = 1 class MixinType(Enum): diff --git a/src/main/python/ddadevops/domain/init_service.py b/src/main/python/ddadevops/domain/init_service.py index 0adbaa1..76a23db 100644 --- a/src/main/python/ddadevops/domain/init_service.py +++ b/src/main/python/ddadevops/domain/init_service.py @@ -5,6 +5,7 @@ from .credentials import CredentialMapping, Credentials, GopassType from .devops_factory import DevopsFactory from .terraform import TerraformDomain from .provider_digitalocean import Digitalocean +from .provider_hetzner import Hetzner from .c4k import C4k from .image import Image from .release import ReleaseType @@ -53,6 +54,11 @@ class InitService: and ProviderType.DIGITALOCEAN in provider_types ): default_mappings += Digitalocean.get_mapping_default() + if ( + BuildType.TERRAFORM in build_types + and ProviderType.HETZNER in provider_types + ): + default_mappings += Hetzner.get_mapping_default() if MixinType.RELEASE in mixin_types: primary_build_file_id = inp.get( diff --git a/src/main/python/ddadevops/domain/provider_hetzner.py b/src/main/python/ddadevops/domain/provider_hetzner.py new file mode 100644 index 0000000..636b007 --- /dev/null +++ b/src/main/python/ddadevops/domain/provider_hetzner.py @@ -0,0 +1,26 @@ +from typing import List, Dict +from .common import Validateable, CredentialMappingDefault + +class Hetzner(Validateable, CredentialMappingDefault): + def __init__( + self, + inp: dict, + ): + self.hetzner_api_key = inp.get("hetzner_api_key") + + def validate(self) -> List[str]: + result = [] + result += self.__validate_is_not_empty__("hetzner_api_key") + return result + + def resources_from_package(self) -> List[str]: + return ["provider_registry.tf", "hetzner_provider.tf", "hetzner_mixin_vars.tf"] + + def project_vars(self): + return { + "hetzner_api_key": self.hetzner_api_key + } + + @classmethod + def get_mapping_default(cls) -> List[Dict[str, str]]: + return [] \ No newline at end of file diff --git a/src/main/python/ddadevops/domain/terraform.py b/src/main/python/ddadevops/domain/terraform.py index ddce425..42304af 100644 --- a/src/main/python/ddadevops/domain/terraform.py +++ b/src/main/python/ddadevops/domain/terraform.py @@ -6,6 +6,7 @@ from .common import ( filter_none, ) from .provider_digitalocean import Digitalocean +from .provider_hetzner import Hetzner class TerraformDomain(Validateable): @@ -36,6 +37,8 @@ class TerraformDomain(Validateable): self.providers = {} if ProviderType.DIGITALOCEAN in provider_types: self.providers[ProviderType.DIGITALOCEAN] = Digitalocean(inp) + if ProviderType.HETZNER in provider_types: + self.providers[ProviderType.HETZNER] = Hetzner(inp) def validate(self) -> List[str]: result = [] diff --git a/src/test/python/domain/helper.py b/src/test/python/domain/helper.py index d18f276..a72a0ff 100644 --- a/src/test/python/domain/helper.py +++ b/src/test/python/domain/helper.py @@ -24,7 +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_provider_types": ["DIGITALOCEAN", "HETZNER"], "tf_additional_vars": [], "tf_output_json_name": "the_out.json", "tf_use_workspace": None, @@ -37,6 +37,7 @@ def devops_config(overrides: dict) -> dict: "do_api_key": "api_key", "do_spaces_access_id": "spaces_id", "do_spaces_secret_key": "spaces_secret", + "hetzner_api_key": "hetzner_api_key", "release_type": "NONE", "release_main_branch": "main", "release_current_branch": "my_feature", diff --git a/src/test/python/domain/test_provider_hetzner.py b/src/test/python/domain/test_provider_hetzner.py new file mode 100644 index 0000000..adc0479 --- /dev/null +++ b/src/test/python/domain/test_provider_hetzner.py @@ -0,0 +1,19 @@ +from pybuilder.core import Project +from pathlib import Path +from src.main.python.ddadevops.domain import ( + BuildType, + Hetzner, +) +from .helper import devops_config + + +def test_hetzner_creation(): + sut = Hetzner( + devops_config( + { + "hetzner_api_key": "api_key", + } + ) + ) + assert sut is not None + assert sut.is_valid() diff --git a/src/test/python/domain/test_terraform.py b/src/test/python/domain/test_terraform.py index da61342..ac6a377 100644 --- a/src/test/python/domain/test_terraform.py +++ b/src/test/python/domain/test_terraform.py @@ -15,6 +15,7 @@ def test_creation(): assert BuildType.TERRAFORM in devops.specialized_builds assert sut assert sut.providers[ProviderType.DIGITALOCEAN] + assert sut.providers[ProviderType.HETZNER] def test_should_calculate_output_json_name(): @@ -71,6 +72,7 @@ def test_should_calculate_project_vars(): "do_api_key": "api_key", "do_spaces_access_id": "spaces_id", "do_spaces_secret_key": "spaces_secret", + "hetzner_api_key": "hetzner_api_key" } == sut.project_vars() @@ -83,7 +85,11 @@ def test_should_calculate_resources_from_package(): sut = TerraformDomain(config) assert ["versions.tf", "terraform_build_vars.tf"] == sut.resources_from_package() - config = devops_config({}) + config = devops_config( + { + "tf_provider_types": ["DIGITALOCEAN"] + } + ) sut = TerraformDomain(config) assert [ "versions.tf", @@ -93,6 +99,20 @@ def test_should_calculate_resources_from_package(): "do_mixin_vars.tf", ] == sut.resources_from_package() + config = devops_config( + { + "tf_provider_types": ["HETZNER"] + } + ) + sut = TerraformDomain(config) + assert [ + "versions.tf", + "terraform_build_vars.tf", + "provider_registry.tf", + "hetzner_provider.tf", + "hetzner_mixin_vars.tf", + ] == sut.resources_from_package() + config = devops_config({"tf_additional_resources_from_package": ["my.file"]}) sut = TerraformDomain(config) assert [ @@ -101,5 +121,8 @@ def test_should_calculate_resources_from_package(): "provider_registry.tf", "do_provider.tf", "do_mixin_vars.tf", + "provider_registry.tf", + "hetzner_provider.tf", + "hetzner_mixin_vars.tf", "my.file", ] == sut.resources_from_package()