From dd85b7b95be62943f9ae23b36c5cb2b7c84aa536 Mon Sep 17 00:00:00 2001 From: Michael Jerger Date: Sun, 12 Mar 2023 19:09:32 +0100 Subject: [PATCH] refactor devops_c4k_mixin to arch --- doc/architecture/Domain.md | 29 ++++++++++- src/main/python/ddadevops/__init__.py | 4 +- src/main/python/ddadevops/application.py | 17 ------ src/main/python/ddadevops/c4k_mixin.py | 31 ++++++++--- src/main/python/ddadevops/devops_build.py | 4 +- .../python/ddadevops/devops_docker_build.py | 3 +- src/main/python/ddadevops/domain.py | 52 ++++++++++++------- src/main/python/ddadevops/infrastructure.py | 8 ++- src/test/python/test_c4k_mixin.py | 10 ++-- src/test/python/test_domain.py | 33 ++++++++---- 10 files changed, 128 insertions(+), 63 deletions(-) diff --git a/doc/architecture/Domain.md b/doc/architecture/Domain.md index 8684547..91d84e7 100644 --- a/doc/architecture/Domain.md +++ b/doc/architecture/Domain.md @@ -3,13 +3,38 @@ ```mermaid classDiagram class Build { - __init__(project, config) - do_sth(project) + stage + name + project_root_path + module + build_dir_name } + class C4kBuild { + executabel_name + c4k_mixin_config + c4k_mixin_auth + } + + class DnsRecord { + fqdn + ipv4 + ipv6 + } + + C4kBuild *-- DnsRecord + +``` + +# Infrastructure + +```mermaid +classDiagram class ProjectRepository { get_build(project): Build set_build(project, build) } + + ``` \ No newline at end of file diff --git a/src/main/python/ddadevops/__init__.py b/src/main/python/ddadevops/__init__.py index f1411b8..1299557 100644 --- a/src/main/python/ddadevops/__init__.py +++ b/src/main/python/ddadevops/__init__.py @@ -19,8 +19,8 @@ from .devops_terraform_build import DevopsTerraformBuild, create_devops_terrafor from .devops_build import DevopsBuild, create_devops_build_config, get_devops_build, get_tag_from_latest_commit from .credential import gopass_password_from_path, gopass_field_from_path -from .domain import Validateable, Build, DockerBuild, C4kBuild -from .application import DockerBuildService, C4kBuildService +from .domain import Validateable, DnsRecord, Build, DockerBuild, C4kBuild +from .application import DockerBuildService from .infrastructure import ProjectRepository, ResourceApi, FileApi, DockerApi, ExecutionApi __version__ = "${version}" diff --git a/src/main/python/ddadevops/application.py b/src/main/python/ddadevops/application.py index 209315f..746101b 100644 --- a/src/main/python/ddadevops/application.py +++ b/src/main/python/ddadevops/application.py @@ -48,20 +48,3 @@ class DockerBuildService: def test(self, build: Build): self.docker_api.test(build.name(), build.build_path()) - - -class C4kBuildService: - def __init__(self): - self.file_api = FileApi() - self.execution_api = ExecutionApi() - - def write_c4k_config(self, c4k_build: C4kBuild): - path = c4k_build.build.build_path() + "/out_c4k_config.yaml" - self.file_api.write_yaml_to_file(path, c4k_build.config()) - - def write_c4k_auth(self, c4k_build: C4kBuild): - path = c4k_build.build.build_path() + "/out_c4k_auth.yaml" - self.file_api.write_yaml_to_file(path, c4k_build.c4k_mixin_auth) - - def c4k_apply(self, c4k_build: C4kBuild, dry_run=False): - return self.execution_api.execute(c4k_build.command(), dry_run) diff --git a/src/main/python/ddadevops/c4k_mixin.py b/src/main/python/ddadevops/c4k_mixin.py index 333e0db..b654787 100644 --- a/src/main/python/ddadevops/c4k_mixin.py +++ b/src/main/python/ddadevops/c4k_mixin.py @@ -1,9 +1,11 @@ -from .domain import C4kBuild -from .application import C4kBuildService +from .domain import C4kBuild, DnsRecord from .devops_build import DevopsBuild from .credential import gopass_field_from_path, gopass_password_from_path +from .infrastructure import ProjectRepository, FileApi, ExecutionApi +@deprecation.deprecated(deprecated_in="3.2") +# create objects direct instead def add_c4k_mixin_config( config, c4k_config_dict, @@ -42,17 +44,32 @@ def add_c4k_mixin_config( return config +#TODO: refactor this to C4kBuild class C4kMixin(DevopsBuild): def __init__(self, project, config): super().__init__(project, config) - self.c4k_build = C4kBuild(self.build, project, config) - self.c4k_build_service = C4kBuildService() + self.execution_api = ExecutionApi() + c4k_build = C4kBuild(config) + self.repo.set_c4k_build(self.project, c4k_build) + + def update_runtime_config(self, dns_record: DnsRecord): + c4k_build = self.repo.get_c4k_build(self.project) + c4k_build.update_runtime_config(dns_record) + self.repo.set_c4k_build(self.project, c4k_build) def write_c4k_config(self): - self.c4k_build_service.write_c4k_config(self.c4k_build) + build = self.repo.get_build(self.project) + c4k_build = self.repo.get_c4k_build(self.project) + path = build.build_path() + "/out_c4k_config.yaml" + self.file_api.write_yaml_to_file(path, c4k_build.config()) def write_c4k_auth(self): - self.c4k_build_service.write_c4k_auth(self.c4k_build) + build = self.repo.get_build(self.project) + c4k_build = self.repo.get_c4k_build(self.project) + path = build.build_path() + "/out_c4k_auth.yaml" + self.file_api.write_yaml_to_file(path, c4k_build.c4k_mixin_auth) def c4k_apply(self, dry_run=False): - self.c4k_build_service.c4k_apply(self.c4k_build, dry_run) + build = self.repo.get_build(self.project) + c4k_build = self.repo.get_c4k_build(self.project) + return self.execution_api.execute(c4k_build.command(build), dry_run) diff --git a/src/main/python/ddadevops/devops_build.py b/src/main/python/ddadevops/devops_build.py index 219b0e2..01a1358 100644 --- a/src/main/python/ddadevops/devops_build.py +++ b/src/main/python/ddadevops/devops_build.py @@ -2,7 +2,8 @@ import deprecation from .domain import Build from .infrastructure import ProjectRepository, FileApi - +@deprecation.deprecated(deprecated_in="3.2") +# create objects direct instead def create_devops_build_config( stage, project_root_path, module, build_dir_name="target" ): @@ -51,4 +52,5 @@ class DevopsBuild: return build.build_path() def initialize_build_dir(self): + build = self.repo.get_build(self.project) self.file_api.clean_dir(build.build_path()) diff --git a/src/main/python/ddadevops/devops_docker_build.py b/src/main/python/ddadevops/devops_docker_build.py index 3371e35..58b9354 100644 --- a/src/main/python/ddadevops/devops_docker_build.py +++ b/src/main/python/ddadevops/devops_docker_build.py @@ -2,7 +2,8 @@ from .domain import DockerBuild from .application import DockerBuildService from .devops_build import DevopsBuild, create_devops_build_config - +@deprecation.deprecated(deprecated_in="3.2") +# create objects direct instead def create_devops_docker_build_config( stage, project_root_path, diff --git a/src/main/python/ddadevops/domain.py b/src/main/python/ddadevops/domain.py index 969a15f..17e5bd2 100644 --- a/src/main/python/ddadevops/domain.py +++ b/src/main/python/ddadevops/domain.py @@ -18,6 +18,20 @@ class Validateable: return len(self.validate()) < 1 +class DnsRecord(Validateable): + def __init__(self, fqdn, ipv4=None, ipv6=None): + self.fqdn = fqdn + self.ipv4 = ipv4 + self.ipv6 = ipv6 + + def validate(self) -> List[str]: + result = [] + result += self.__validate_is_not_empty__("fqdn") + if (not self.ipv4) and (not self.ipv6): + result.append("ipv4 & ipv6 may not both be empty.") + return result + + class Build(Validateable): def __init__(self, config): self.stage = config["stage"] @@ -37,12 +51,6 @@ class Build(Validateable): path = [self.project_root_path, self.build_dir_name, self.name, self.module] return "/".join(filter_none(path)) - # TODO: these functions should be located at TerraformBuild later on. - def update_runtime_config(self, fqdn, ipv4, ipv6): - self.__put__("fqdn", fqdn) - self.__put__("ipv4", ipv4) - self.__put__("ipv6", ipv6) - def __put__(self, key, value): self.stack[key] = value @@ -57,7 +65,7 @@ class Build(Validateable): class DockerBuild(Validateable): - def __init__(self, config): + def __init__(self, config: map): self.dockerhub_user = config["dockerhub_user"] self.dockerhub_password = config["dockerhub_password"] self.use_package_common_files = config["use_package_common_files"] @@ -71,31 +79,37 @@ class DockerBuild(Validateable): class C4kBuild(Validateable): - def __init__(self, build: Build, project, config): - self.build = build + def __init__(self, config: map): tmp_executabel_name = config["C4kMixin"]["executabel_name"] if not tmp_executabel_name: - tmp_executabel_name = self.build.module + tmp_executabel_name = config["module"] self.executabel_name = tmp_executabel_name self.c4k_mixin_config = config["C4kMixin"]["config"] self.c4k_mixin_auth = config["C4kMixin"]["auth"] tmp = self.c4k_mixin_config["mon-cfg"] - tmp.update( - {"cluster-name": self.build.module, "cluster-stage": self.build.stage} - ) + tmp.update({"cluster-name": config["module"], "cluster-stage": config["stage"]}) self.c4k_mixin_config.update({"mon-cfg": tmp}) + self.dns_record = None + + # TODO: these functions should be located at TerraformBuild later on. + def update_runtime_config(self, dns_record: DnsRecord): + self.dns_record = dns_record - def update_runtime_config(self, fqdn, ipv4, ipv6): - self.build.update_runtime_config(fqdn, ipv4, ipv6) + def validate(self) -> List[str]: + result = [] + result += self.__validate_is_not_empty__("fqdn") + if self.dns_record: + result += self.dns_record.validate() + return result def config(self): - fqdn = self.build.__get__("fqdn") + fqdn = self.dns_record.fqdn self.c4k_mixin_config.update({"fqdn": fqdn}) return self.c4k_mixin_config - def command(self): - module = self.build.module - build_path = self.build.build_path() + def command(self, build: Build): + module = build.module + build_path = build.build_path() config_path = f"{build_path}/out_c4k_config.yaml" auth_path = f"{build_path}/out_c4k_auth.yaml" output_path = f"{build_path}/out_{module}.yaml" diff --git a/src/main/python/ddadevops/infrastructure.py b/src/main/python/ddadevops/infrastructure.py index bfda2b9..9b319e3 100644 --- a/src/main/python/ddadevops/infrastructure.py +++ b/src/main/python/ddadevops/infrastructure.py @@ -3,7 +3,7 @@ from sys import stdout from pkg_resources import resource_string from os import chmod import yaml -from .domain import Build, DockerBuild +from .domain import Build, DockerBuild, C4kBuild from .python_util import execute @@ -20,6 +20,12 @@ class ProjectRepository: def set_docker_build(self, project, build: DockerBuild): project.set_property("docker_build", build) + def get_c4k_build(self, project) -> C4kBuild: + return project.get_property("c4k_build") + + def set_c4k_build(self, project, build: C4kBuild): + project.set_property("c4k_build", build) + class ResourceApi: def read_resource(self, path: str) -> bytes: diff --git a/src/test/python/test_c4k_mixin.py b/src/test/python/test_c4k_mixin.py index eca6d05..00487af 100644 --- a/src/test/python/test_c4k_mixin.py +++ b/src/test/python/test_c4k_mixin.py @@ -1,5 +1,6 @@ import os from pybuilder.core import Project +from src.main.python.ddadevops.domain import DnsRecord from src.main.python.ddadevops.c4k_mixin import C4kMixin, add_c4k_mixin_config class MyC4kMixin(C4kMixin): @@ -32,14 +33,15 @@ def test_c4k_mixin(tmp_path): mixin.initialize_build_dir() assert mixin.build_path() == f'{tmp_path_str}/{build_dir}/{project_name}/{module_name}' - mixin.build.update_runtime_config('test.de', None, None) + mixin.update_runtime_config(DnsRecord('test.de', ipv6="1::")) + sut = mixin.repo.get_c4k_build(mixin.project) + assert 'fqdn' in sut.config() + assert 'mon-cfg' in sut.config() + assert 'mon-auth' in sut.c4k_mixin_auth mixin.write_c4k_config() - assert 'fqdn' in mixin.c4k_build.config() - assert 'mon-cfg' in mixin.c4k_build.config() assert os.path.exists(f'{mixin.build_path()}/out_c4k_config.yaml') mixin.write_c4k_auth() - assert 'mon-auth' in mixin.c4k_build.c4k_mixin_auth assert os.path.exists(f'{mixin.build_path()}/out_c4k_auth.yaml') \ No newline at end of file diff --git a/src/test/python/test_domain.py b/src/test/python/test_domain.py index 32f45be..d61a0eb 100644 --- a/src/test/python/test_domain.py +++ b/src/test/python/test_domain.py @@ -1,5 +1,5 @@ from pybuilder.core import Project -from src.main.python.ddadevops.domain import Validateable, C4kBuild, Build +from src.main.python.ddadevops.domain import Validateable, DnsRecord, C4kBuild, Build from src.main.python.ddadevops.c4k_mixin import add_c4k_mixin_config @@ -41,6 +41,20 @@ def test_validate_with_reason(): assert sut.validate()[0] == "Field 'field' may not be empty." +def test_should_validate_DnsRecord(): + sut = DnsRecord(None) + assert not sut.is_valid() + + sut = DnsRecord('name') + assert not sut.is_valid() + + sut = DnsRecord('name', ipv4='1.2.3.4') + assert sut.is_valid() + + sut = DnsRecord('name', ipv6='1::') + assert sut.is_valid() + + def test_c4k_build_should_update_fqdn(tmp_path): project = Project(str(tmp_path), name="name") project_config = { @@ -63,8 +77,9 @@ def test_c4k_build_should_update_fqdn(tmp_path): grafana_cloud_user="user", grafana_cloud_password="password", ) - sut = C4kBuild(Build(project_config), project, project_config) - sut.update_runtime_config("test.de", None, None) + build = Build(project_config) + sut = C4kBuild(project_config) + sut.update_runtime_config(DnsRecord("test.de", ipv6="1::")) assert { "issuer": "staging", @@ -85,8 +100,6 @@ def test_c4k_build_should_update_fqdn(tmp_path): }, } == sut.c4k_mixin_auth - sut.update_runtime_config - def test_c4k_build_should_calculate_command(tmp_path): project = Project(str(tmp_path), name="name") @@ -104,13 +117,14 @@ def test_c4k_build_should_calculate_command(tmp_path): grafana_cloud_user="user", grafana_cloud_password="password", ) - sut = C4kBuild(Build(project_config), project, project_config) + build = Build(project_config) + sut = C4kBuild(project_config) assert ( "c4k-module-standalone.jar " + "/target/name/module/out_c4k_config.yaml " + "/target/name/module/out_c4k_auth.yaml > " + "/target/name/module/out_module.yaml" - == sut.command() + == sut.command(build) ) project_config = { @@ -128,12 +142,13 @@ def test_c4k_build_should_calculate_command(tmp_path): grafana_cloud_user="user", grafana_cloud_password="password", ) - sut = C4kBuild(Build(project_config), project, project_config) + build = Build(project_config) + sut = C4kBuild(project_config) assert ( "c4k-executabel_name-standalone.jar " + "/target/name/module/out_c4k_config.yaml " + "/target/name/module/out_c4k_auth.yaml > " + "/target/name/module/out_module.yaml" - == sut.command() + == sut.command(build) )