From 634e89407eae0f4f810cdfb2eca2eff90b983611 Mon Sep 17 00:00:00 2001 From: Michael Jerger Date: Sat, 29 Apr 2023 14:53:59 +0200 Subject: [PATCH] multi inheritance requires more than one build extension --- doc/architecture/Domain.md | 4 +-- .../python/ddadevops/devops_image_build.py | 4 +-- src/main/python/ddadevops/domain/common.py | 21 +++++++++----- .../python/ddadevops/domain/devops_factory.py | 22 ++++++++------ src/test/python/domain/test_devops_factory.py | 29 +++++++++---------- src/test/python/domain/test_domain.py | 3 +- src/test/python/domain/test_helper.py | 2 +- 7 files changed, 47 insertions(+), 38 deletions(-) diff --git a/doc/architecture/Domain.md b/doc/architecture/Domain.md index 92d12dc..2e9cd5a 100644 --- a/doc/architecture/Domain.md +++ b/doc/architecture/Domain.md @@ -43,8 +43,8 @@ classDiagram current_branch } - Devops *-- Image: spcialized_build - Devops *-- C4k: spcialized_build + Devops *-- "0..1" Image: spcialized_builds + Devops *-- "0..1" C4k: spcialized_builds Devops *-- Release: release C4k *-- DnsRecord Release *-- "0..1" ReleaseContext diff --git a/src/main/python/ddadevops/devops_image_build.py b/src/main/python/ddadevops/devops_image_build.py index b39855d..db55b7e 100644 --- a/src/main/python/ddadevops/devops_image_build.py +++ b/src/main/python/ddadevops/devops_image_build.py @@ -37,8 +37,8 @@ class DevopsImageBuild(DevopsBuild): super().__init__(project, input) self.image_build_service = ImageBuildService() devops = self.repo.get_devops(self.project) - if devops.build_type != BuildType.IMAGE: - raise ValueError(f"ImageBuild requires BuildType.IMAGE but was: {devops.build_type}") + if BuildType.IMAGE not in devops.specialized_builds: + raise ValueError(f"ImageBuild requires BuildType.IMAGE") def initialize_build_dir(self): super().initialize_build_dir() diff --git a/src/main/python/ddadevops/domain/common.py b/src/main/python/ddadevops/domain/common.py index 5792765..1a3594c 100644 --- a/src/main/python/ddadevops/domain/common.py +++ b/src/main/python/ddadevops/domain/common.py @@ -1,6 +1,6 @@ import deprecation from enum import Enum -from typing import List +from typing import List, TypedDict import logging import deprecation @@ -12,11 +12,16 @@ class BuildType(Enum): C4K = 1 class Validateable: + def __validate_is_not_none__(self, field_name: str) -> List[str]: + value = self.__dict__[field_name] + if value is None: + return [f"Field '{field_name}' must not be None."] + return [] + def __validate_is_not_empty__(self, field_name: str) -> List[str]: value = self.__dict__[field_name] if value is None or value == "": return [f"Field '{field_name}' must not be empty."] - return [] def validate(self) -> List[str]: @@ -45,14 +50,13 @@ class DnsRecord(Validateable): class Devops(Validateable): - def __init__(self, input: dict, build_type: BuildType, specialized_build: Validateable): + def __init__(self, input: dict, specialized_builds: dict[BuildType, Validateable]): self.stage = input.get('stage') self.project_root_path = input.get('project_root_path') self.module = input.get('module') self.name = input.get('name', self.module) self.build_dir_name = input.get('build_dir_name', 'target') - self.build_type = build_type - self.specialized_build=specialized_build + self.specialized_builds=specialized_builds def build_path(self): path = [self.project_root_path, self.build_dir_name, self.name, self.module] @@ -63,9 +67,10 @@ class Devops(Validateable): result += self.__validate_is_not_empty__("stage") result += self.__validate_is_not_empty__("project_root_path") result += self.__validate_is_not_empty__("module") - result += self.__validate_is_not_empty__("specialized_build") - if self.specialized_build: - result += self.specialized_build.validate() + result += self.__validate_is_not_none__("specialized_builds") + if self.specialized_builds: + for build in self.specialized_builds: + result += self.specialized_builds[build].validate() return result def __put__(self, key, value): diff --git a/src/main/python/ddadevops/domain/devops_factory.py b/src/main/python/ddadevops/domain/devops_factory.py index 3da7ea8..6324180 100644 --- a/src/main/python/ddadevops/domain/devops_factory.py +++ b/src/main/python/ddadevops/domain/devops_factory.py @@ -12,20 +12,24 @@ class DevopsFactory: pass def build_devops(self, input) -> Devops: - build_type = BuildType[input["build_type"]] - specialized_build = None - if build_type == BuildType.IMAGE: - specialized_build = Image(input) - elif build_type == BuildType.C4K: + build_types = self.__parse_build_types__(input["build_types"]) + specialized_builds = {} + if BuildType.IMAGE in build_types: + specialized_builds[BuildType.IMAGE] = Image(input) + elif BuildType.C4K in build_types: pass - devops = Devops( - input, build_type=build_type, specialized_build=specialized_build - ) + devops = Devops(input, specialized_builds=specialized_builds) devops.throw_if_invalid() return devops - def merge(input, autorization, context) -> dict: + def merge(self, input, autorization, context) -> dict: pass + + def __parse_build_types__(self, build_types: List[str]) -> List[BuildType]: + result = [] + for build_type in build_types: + result += [BuildType[build_type]] + return result diff --git a/src/test/python/domain/test_devops_factory.py b/src/test/python/domain/test_devops_factory.py index df7e15f..e6e3633 100644 --- a/src/test/python/domain/test_devops_factory.py +++ b/src/test/python/domain/test_devops_factory.py @@ -3,25 +3,24 @@ from src.main.python.ddadevops.domain.devops_factory import ( DevopsFactory, ) + def test_devops_factory(): with pytest.raises(Exception): - DevopsFactory().build_devops( - {'build_type': 'NOTEXISTING'} - ) + DevopsFactory().build_devops({"build_types": ["NOTEXISTING"]}) with pytest.raises(Exception): - DevopsFactory().build_devops( - {'build_type': 'IMAGE'} - ) + DevopsFactory().build_devops({'build_types': ['IMAGE'],}) sut = DevopsFactory().build_devops( - {'build_type': 'IMAGE', - 'stage': 'test', - 'project_root_path': "../../..", - 'name': 'mybuild', - 'module': 'test_image', - 'dockerhub_user': 'dockerhub_user', - 'dockerhub_password': 'dockerhub_password', - 'docker_image_tag': 'docker_image_tag',} - ) + { + "build_types": ["IMAGE"], + "stage": "test", + "project_root_path": "../../..", + "name": "mybuild", + "module": "test_image", + "dockerhub_user": "dockerhub_user", + "dockerhub_password": "dockerhub_password", + "docker_image_tag": "docker_image_tag", + } + ) assert sut != None diff --git a/src/test/python/domain/test_domain.py b/src/test/python/domain/test_domain.py index bee073d..375e10d 100644 --- a/src/test/python/domain/test_domain.py +++ b/src/test/python/domain/test_domain.py @@ -4,6 +4,7 @@ from src.main.python.ddadevops.domain.common import ( Validateable, DnsRecord, Devops, + BuildType, ) from src.main.python.ddadevops.domain import ( Version, @@ -222,4 +223,4 @@ def test_release(tmp_path): def test_devops_build_commons_path(): sut = build_devops({}) - assert "docker/" == sut.specialized_build.docker_build_commons_path() + assert "docker/" == sut.specialized_builds[BuildType.IMAGE].docker_build_commons_path() diff --git a/src/test/python/domain/test_helper.py b/src/test/python/domain/test_helper.py index 6af661f..4a5b171 100644 --- a/src/test/python/domain/test_helper.py +++ b/src/test/python/domain/test_helper.py @@ -2,7 +2,7 @@ from src.main.python.ddadevops.domain import DevopsFactory, Devops def devops_config(overrides: dict) -> dict: default = { - "build_type": "IMAGE", + "build_types": ["IMAGE"], "stage": "test", "project_root_path": "../../..", "name": "mybuild",