refactor terraform_devops_build to provider domain object

This commit is contained in:
Michael Jerger 2023-05-25 17:57:57 +02:00
parent 85aa41b2a8
commit cb17b39433
13 changed files with 121 additions and 122 deletions

View file

@ -50,6 +50,12 @@ classDiagram
tf_terraform_semantic_version tf_terraform_semantic_version
} }
class Digitalocean {
do_api_key
do_spaces_access_key
do_spaces_secret_key
}
class DnsRecord { class DnsRecord {
fqdn fqdn
ipv4 ipv4
@ -92,18 +98,13 @@ classDiagram
create_bump(snapshot_suffix) 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" Image: specialized_builds
Devops *-- "0..1" C4k: specialized_builds Devops *-- "0..1" C4k: specialized_builds
Devops *-- "0..1" ProvsK3s: specialized_builds Devops *-- "0..1" ProvsK3s: specialized_builds
Devops *-- "0..1" TerraformDomain: specialized_builds Devops *-- "0..1" TerraformDomain: specialized_builds
Devops *-- "0..1" DigitaloceanTerraform: specialized_builds
Devops *-- "0..1" Release: mixins Devops *-- "0..1" Release: mixins
TerraformDomain *-- "0..1" Digitalocean: provider
Release o-- "0..1" BuildFile: primary_build_file Release o-- "0..1" BuildFile: primary_build_file
Release o-- "0..n" BuildFile: secondary_build_files Release o-- "0..n" BuildFile: secondary_build_files
BuildFile *-- "1" Version BuildFile *-- "1" Version

View file

@ -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 .aws_backend_properties_mixin import AwsBackendPropertiesMixin, add_aws_backend_properties_mixin_config
from .c4k_build import C4kBuild from .c4k_build import C4kBuild
from .digitalocean_backend_properties_mixin import DigitaloceanBackendPropertiesMixin, add_digitalocean_backend_properties_mixin_config 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 .hetzner_mixin import HetznerMixin, add_hetzner_mixin_config
from .devops_image_build import DevopsImageBuild from .devops_image_build import DevopsImageBuild
from .devops_terraform_build import DevopsTerraformBuild, create_devops_terraform_build_config from .devops_terraform_build import DevopsTerraformBuild, create_devops_terraform_build_config

View file

@ -4,81 +4,9 @@ from .devops_terraform_build import (
) )
def create_digitalocean_terraform_build_config( def create_digitalocean_terraform_build_config():
stage, pass
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
class DigitaloceanTerraformBuild(DevopsTerraformBuild): class DigitaloceanTerraformBuild(DevopsTerraformBuild):
def __init__(self, project, config): pass
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()

View file

@ -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 .devops_factory import DevopsFactory
from .image import Image from .image import Image
from .c4k import C4k from .c4k import C4k
from .terraform import TerraformDomain from .terraform import TerraformDomain
from .digitalocean_terraform import DigitaloceanTerraform from .provider_digitalocean import Digitalocean
from .provs_k3s import K3s from .provs_k3s import K3s
from .release import Release from .release import Release
from .credentials import Credentials, CredentialMapping, GopassType from .credentials import Credentials, CredentialMapping, GopassType

View file

@ -11,7 +11,10 @@ class BuildType(Enum):
C4K = 1 C4K = 1
K3S = 2 K3S = 2
TERRAFORM = 3 TERRAFORM = 3
DIGITALOCEAN_TERRAFORM = 4
class ProviderType(Enum):
DIGITALOCEAN = 0
class MixinType(Enum): class MixinType(Enum):

View file

@ -4,7 +4,6 @@ from .image import Image
from .c4k import C4k from .c4k import C4k
from .provs_k3s import K3s from .provs_k3s import K3s
from .terraform import TerraformDomain from .terraform import TerraformDomain
from .digitalocean_terraform import DigitaloceanTerraform
from .release import Release from .release import Release
from .version import Version from .version import Version
@ -26,10 +25,6 @@ class DevopsFactory:
specialized_builds[BuildType.K3S] = K3s(inp) specialized_builds[BuildType.K3S] = K3s(inp)
if BuildType.TERRAFORM in build_types: if BuildType.TERRAFORM in build_types:
specialized_builds[BuildType.TERRAFORM] = TerraformDomain(inp) specialized_builds[BuildType.TERRAFORM] = TerraformDomain(inp)
if BuildType.DIGITALOCEAN_TERRAFORM in build_types:
specialized_builds[
BuildType.DIGITALOCEAN_TERRAFORM
] = DigitaloceanTerraform(inp)
mixins: Dict[MixinType, Validateable] = {} mixins: Dict[MixinType, Validateable] = {}
if MixinType.RELEASE in mixin_types: if MixinType.RELEASE in mixin_types:

View file

@ -63,7 +63,7 @@ class InitService:
"name": "image_dockerhub_password", "name": "image_dockerhub_password",
}, },
] ]
if BuildType.DIGITALOCEAN_TERRAFORM in build_types: if False:
default_mappings += [ default_mappings += [
{ {
"gopass_path": "server/devops/digitalocean/s3", "gopass_path": "server/devops/digitalocean/s3",

View file

@ -4,7 +4,7 @@ from .common import (
) )
class DigitaloceanTerraform(Validateable): class Digitalocean(Validateable):
def __init__( def __init__(
self, self,
inp: dict, 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_access_id")
result += self.__validate_is_not_empty__("do_spaces_secret_key") result += self.__validate_is_not_empty__("do_spaces_secret_key")
return result 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,}

View file

@ -2,10 +2,12 @@ from typing import List, Optional
from pathlib import Path from pathlib import Path
from .common import ( from .common import (
Validateable, Validateable,
ProviderType,
DnsRecord, DnsRecord,
Devops, Devops,
filter_none, filter_none,
) )
from .provider_digitalocean import Digitalocean
class TerraformDomain(Validateable): class TerraformDomain(Validateable):
@ -15,6 +17,7 @@ class TerraformDomain(Validateable):
self.tf_additional_vars = inp.get("tf_additional_vars") self.tf_additional_vars = inp.get("tf_additional_vars")
self.tf_output_json_name = inp.get("tf_output_json_name") self.tf_output_json_name = inp.get("tf_output_json_name")
self.tf_build_commons_path = inp.get("tf_build_commons_path") 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( self.tf_additional_resources_from_package = inp.get(
"tf_additional_resources_from_package", [] "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) 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]: def validate(self) -> List[str]:
result = [] result = []
result += self.__validate_is_not_empty__("module") 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_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_resources_from_package")
result += self.__validate_is_not_none__("tf_additional_tfvar_files") 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 return result
def output_json_name(self) -> str: def output_json_name(self) -> str:
@ -51,12 +62,24 @@ class TerraformDomain(Validateable):
return Path("/".join(filter_none(mylist)) + "/") return Path("/".join(filter_none(mylist)) + "/")
def project_vars(self): 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: if self.tf_additional_vars:
ret.update(self.tf_additional_vars) result.update(self.tf_additional_vars)
return ret return result
def resources_from_package(self) -> List[str]: def resources_from_package(self) -> List[str]:
result = ["version.tf", "terraform_build_vars.tf"] 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 result += self.tf_additional_resources_from_package
return result 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

View file

@ -24,6 +24,7 @@ def devops_config(overrides: dict) -> dict:
"k3s_letsencrypt_endpoint": "k3s_letsencrypt_endpoint", "k3s_letsencrypt_endpoint": "k3s_letsencrypt_endpoint",
"k3s_enable_echo": "false", "k3s_enable_echo": "false",
"k3s_app_filename_to_provision": "k3s_app.yaml", "k3s_app_filename_to_provision": "k3s_app.yaml",
"tf_provider_types": ["DIGITALOCEAN"],
"tf_additional_vars": [], "tf_additional_vars": [],
"tf_output_json_name": "the_out.json", "tf_output_json_name": "the_out.json",
"tf_use_workspace": None, "tf_use_workspace": None,

View file

@ -50,23 +50,6 @@ def test_devops_factory():
assert sut is not None assert sut is not None
assert sut.specialized_builds[BuildType.C4K] 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( sut = DevopsFactory().build_devops(
{ {
"stage": "test", "stage": "test",

View file

@ -2,13 +2,13 @@ from pybuilder.core import Project
from pathlib import Path from pathlib import Path
from src.main.python.ddadevops.domain import ( from src.main.python.ddadevops.domain import (
BuildType, BuildType,
DigitaloceanTerraform, Digitalocean,
) )
from .helper import devops_config from .helper import devops_config
def test_digitalocean_terraform(): def test_digitalocean_creation():
sut = DigitaloceanTerraform( sut = Digitalocean(
devops_config( devops_config(
{ {
"do_api_key": "api_key", "do_api_key": "api_key",

View file

@ -1,13 +1,20 @@
import pytest import pytest
from pathlib import Path 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 from .helper import build_devops, devops_config
def test_creation(): def test_creation():
sut = build_devops({}) devops = build_devops({})
assert BuildType.TERRAFORM in sut.specialized_builds sut = devops.specialized_builds[BuildType.TERRAFORM]
assert sut.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(): 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() 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(): def test_should_calculate_terraform_build_commons_path():
config = devops_config({}) config = devops_config({})
del config["tf_build_commons_path"] del config["tf_build_commons_path"]
@ -32,16 +53,53 @@ def test_should_calculate_terraform_build_commons_path():
sut = TerraformDomain(config) sut = TerraformDomain(config)
assert Path("build_commons_path/terraform") == sut.terraform_build_commons_path() assert Path("build_commons_path/terraform") == sut.terraform_build_commons_path()
def test_should_calculate_project_vars(): 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({}) config = devops_config({})
sut = TerraformDomain(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(): def test_should_calculate_resources_from_package():
config = devops_config({}) config = devops_config(
{
"tf_provider_types": [],
}
)
sut = TerraformDomain(config) sut = TerraformDomain(config)
assert ["version.tf", "terraform_build_vars.tf"] == sut.resources_from_package() 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"]}) config = devops_config({"tf_additional_resources_from_package": ["my.file"]})
sut = TerraformDomain(config) sut = TerraformDomain(config)
assert ["version.tf", "terraform_build_vars.tf", "my.file"] == sut.resources_from_package() assert [
"version.tf",
"terraform_build_vars.tf",
"provider_registry.tf",
"do_provider.tf",
"do_mixin_vars.tf",
"my.file",
] == sut.resources_from_package()