From ca6b693a9af3ba3a0e352278a731fdb2bb10ff60 Mon Sep 17 00:00:00 2001 From: Michael Jerger Date: Wed, 17 May 2023 13:43:39 +0200 Subject: [PATCH] introduce credentials api --- src/main/python/ddadevops/credential.py | 21 +++++--- .../python/ddadevops/domain/init_service.py | 54 +++++++++++++++---- .../ddadevops/infrastructure/__init__.py | 12 ++++- .../infrastructure/infrastructure.py | 20 ++++++- src/test/python/domain/helper.py | 13 +++++ src/test/python/domain/test_init_service.py | 4 +- 6 files changed, 103 insertions(+), 21 deletions(-) diff --git a/src/main/python/ddadevops/credential.py b/src/main/python/ddadevops/credential.py index 467e5f2..12c6735 100644 --- a/src/main/python/ddadevops/credential.py +++ b/src/main/python/ddadevops/credential.py @@ -1,15 +1,24 @@ +import deprecation from .python_util import execute -def gopass_field_from_path (path, field): + +@deprecation.deprecated( + deprecated_in="3.2", details="use infrastructure.CredentialsApi instead" +) +def gopass_field_from_path(path, field): credential = None if path and field: - print('get field for: ' + path + ', ' + field) - credential = execute(['gopass', 'show', path, field]) + print("get field for: " + path + ", " + field) + credential = execute(["gopass", "show", path, field]) return credential -def gopass_password_from_path (path): + +@deprecation.deprecated( + deprecated_in="3.2", details="use infrastructure.CredentialsApi instead" +) +def gopass_password_from_path(path): credential = None if path: - print('get password for: ' + path) - credential = execute(['gopass', 'show', '--password', path]) + print("get password for: " + path) + credential = execute(["gopass", "show", "--password", path]) return credential diff --git a/src/main/python/ddadevops/domain/init_service.py b/src/main/python/ddadevops/domain/init_service.py index 087641f..5cde7a4 100644 --- a/src/main/python/ddadevops/domain/init_service.py +++ b/src/main/python/ddadevops/domain/init_service.py @@ -1,36 +1,38 @@ from pathlib import Path +from typing import List from .common import Devops, MixinType, BuildType -from .credentials import Credentials +from .credentials import Credentials, GopassType from .devops_factory import DevopsFactory from .version import Version from src.main.python.ddadevops.infrastructure import ( - BuildFileRepository + BuildFileRepository, + CredentialsApi, + EnvironmentApi, ) + class InitService: - def __init__(self, devops_factory, build_file_repository): + def __init__(self, devops_factory, build_file_repository, credentials_api, environment_api): self.devops_factory = devops_factory self.build_file_repository = build_file_repository + self.credentials_api = credentials_api + self.environment_api = environment_api @classmethod def prod(cls, base_dir: str): return cls( DevopsFactory(), BuildFileRepository(base_dir), + CredentialsApi(), + EnvironmentApi(), ) - + def initialize(self, input: dict) -> Devops: build_types = self.devops_factory.__parse_build_types__(input["build_types"]) mixin_types = self.devops_factory.__parse_mixin_types__(input["mixin_types"]) version = None - if MixinType.RELEASE in mixin_types: - primary_build_file_id = input.get("release_primary_build_file", "./project.clj") - primary_build_file = self.build_file_repository.get(Path(primary_build_file_id)) - version = primary_build_file.get_version() - - if BuildType.C4K in build_types: default_mappings = [ { @@ -40,8 +42,38 @@ class InitService: { "gopass_path": "server/meissa/grafana-cloud", "name": "grafana_cloud_password", - } + }, ] credentials = Credentials(input, default_mappings) + passwords = self.resolve_passwords(credentials) + + # merge passwords & input + + if MixinType.RELEASE in mixin_types: + primary_build_file_id = input.get( + "release_primary_build_file", "./project.clj" + ) + primary_build_file = self.build_file_repository.get( + Path(primary_build_file_id) + ) + version = primary_build_file.get_version() return self.devops_factory.build_devops(input, version=version) + + def resolve_passwords(self, credentials: Credentials) -> List[str]: + result = {} + for name in credentials.mappings.keys(): + mapping = credentials.mappings[name] + env_value = self.environment_api.get(mapping.name_for_environment) + if env_value: + result[name] = env_value + else: + if mapping.gopass_type == GopassType.FIELD: + result[name] = self.credentials_api.gopass_field_from_path( + mapping.gopass_path, mapping.gopass_field + ) + if mapping.gopass_type == GopassType.PASSWORD: + result[name] = self.credentials_api.gopass_password_from_path( + mapping.gopass_path + ) + return result diff --git a/src/main/python/ddadevops/infrastructure/__init__.py b/src/main/python/ddadevops/infrastructure/__init__.py index 8ba4491..037a5df 100644 --- a/src/main/python/ddadevops/infrastructure/__init__.py +++ b/src/main/python/ddadevops/infrastructure/__init__.py @@ -1,2 +1,10 @@ -from .infrastructure import FileApi, ImageApi, ResourceApi, ExecutionApi, ProjectRepository, EnvironmentApi -from .repository import DevopsRepository, BuildFileRepository \ No newline at end of file +from .infrastructure import ( + FileApi, + ImageApi, + ResourceApi, + ExecutionApi, + ProjectRepository, + EnvironmentApi, + CredentialsApi, +) +from .repository import DevopsRepository, BuildFileRepository diff --git a/src/main/python/ddadevops/infrastructure/infrastructure.py b/src/main/python/ddadevops/infrastructure/infrastructure.py index 4406e8a..95773ee 100644 --- a/src/main/python/ddadevops/infrastructure/infrastructure.py +++ b/src/main/python/ddadevops/infrastructure/infrastructure.py @@ -101,6 +101,24 @@ class ExecutionApi: return output class EnvironmentApi(): - def get(self, key): return environ.get(key) + + +class CredentialsApi(): + def __init__ (self): + self.execution_api = ExecutionApi() + + def gopass_field_from_path (self, path, field): + credential = None + if path and field: + print('get field for: ' + path + ', ' + field) + credential = self.execution_api.execute(['gopass', 'show', path, field]) + return credential + + def gopass_password_from_path (elf, path): + credential = None + if path: + print('get password for: ' + path) + credential = self.execution_api.execute(['gopass', 'show', '--password', path]) + return credential diff --git a/src/test/python/domain/helper.py b/src/test/python/domain/helper.py index a661caa..55b7b86 100644 --- a/src/test/python/domain/helper.py +++ b/src/test/python/domain/helper.py @@ -49,3 +49,16 @@ class BuildFileRepositoryMock: def write(self, build_file: BuildFile): pass + +class EnvironmentApiMock(): + def get(self, key): + pass + + +class CredentialsApiMock(): + def gopass_field_from_path (self, path, field): + pass + + def gopass_password_from_path (elf, path): + pass + diff --git a/src/test/python/domain/test_init_service.py b/src/test/python/domain/test_init_service.py index 5ae5c2a..f0b1426 100644 --- a/src/test/python/domain/test_init_service.py +++ b/src/test/python/domain/test_init_service.py @@ -5,13 +5,15 @@ from src.main.python.ddadevops.domain import ( Version, MixinType, ) -from .helper import BuildFileRepositoryMock, devops_config +from .helper import BuildFileRepositoryMock, EnvironmentApiMock, CredentialsApiMock, devops_config def test_sould_load_build_file(): sut = InitService( DevopsFactory(), BuildFileRepositoryMock(), + CredentialsApiMock(), + EnvironmentApiMock(), ) assert ( Version.from_str("1.1.5-SNAPSHOT")