From ce24ab6fc25250cca330e548ff9850e5e5ee6d1a Mon Sep 17 00:00:00 2001 From: jerger Date: Tue, 28 Feb 2023 09:32:26 +0100 Subject: [PATCH] wip --- src/main/python/ddadevops/__init__.py | 4 +- src/main/python/ddadevops/application.py | 54 +++++++++++++++++-- src/main/python/ddadevops/devops_build.py | 15 +++--- .../python/ddadevops/devops_docker_build.py | 44 ++------------- src/main/python/ddadevops/domain.py | 32 ++++++++--- src/main/python/ddadevops/infrastructure.py | 53 ++++++++++++++++++ src/test/test_domain.py | 2 +- 7 files changed, 145 insertions(+), 59 deletions(-) create mode 100644 src/main/python/ddadevops/infrastructure.py diff --git a/src/main/python/ddadevops/__init__.py b/src/main/python/ddadevops/__init__.py index 3df0197..666f143 100644 --- a/src/main/python/ddadevops/__init__.py +++ b/src/main/python/ddadevops/__init__.py @@ -19,7 +19,7 @@ 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 -from .application import BuildService +from .domain import Validateable, Build, DockerBuild +from .application import BuildService, DockerBuildService __version__ = "${version}" diff --git a/src/main/python/ddadevops/application.py b/src/main/python/ddadevops/application.py index 014f871..9af97ba 100644 --- a/src/main/python/ddadevops/application.py +++ b/src/main/python/ddadevops/application.py @@ -1,8 +1,54 @@ -from .domain import Build -from .python_util import execute +from .domain import Build, DockerBuild +from .infrastructure import FileApi, ResourceApi, DockerApi class BuildService(): + def __init__(self): + self.file_api = FileApi() + def initialize_build_dir(self, build: Build): - execute('rm -rf ' + build.build_path(), shell=True) - execute('mkdir -p ' + build.build_path(), shell=True) + self.file_api.clean_dir(build.build_path()) + +class DockerBuildService(): + def __init__(self): + self.build_service = BuildService() + self.file_api = FileApi() + self.resource_api = ResourceApi() + self.docker_api = DockerApi() + + def __copy_build_resource_file_from_package__(self, build: DockerBuild): + data = self.resource_api.read_resource("src/main/resources/docker/" + build.name) + self.file_api.write_to_file(build.build_path() + '/' + build.name, data) + + def __copy_build_resources_from_package__(self, build: DockerBuild): + self.__copy_build_resource_file_from_package__( + 'image/resources/install_functions.sh') + + def __copy_build_resources_from_dir__(self, build: DockerBuild): + self.file_api.cp_force(build.docker_build_commons_path(), build.build_path()) + + def initialize_build_dir(self, build: DockerBuild): + self.build_service.initialize_build_dir(build) + self.file_api.clean_dir(build.build_path() + '/image/resources') + if build.use_package_common_files: + self.__copy_build_resources_from_package__(build) + else: + self.__copy_build_resources_from_dir__(build) + self.file_api.cp_recursive('image', build.build_path()) + self.file_api.cp_recursive('test', build.build_path()) + + def image(self, build: DockerBuild): + self.docker_api.image(build.name(), build.build_path()) + + def drun(self, build: DockerBuild): + self.docker_api.drun(build.name()) + + def dockerhub_login(self, build: DockerBuild): + self.docker_api.dockerhub_login(build.dockerhub_user, build.dockerhub_password) + + def dockerhub_publish(self, build: DockerBuild): + self.docker_api.dockerhub_publish(build.name(), build.dockerhub_user, build.docker_publish_tag) + + def test(self, build: DockerBuild): + self.docker_api.test(build.name(), build.build_path()) + diff --git a/src/main/python/ddadevops/devops_build.py b/src/main/python/ddadevops/devops_build.py index d48999b..438ccb0 100644 --- a/src/main/python/ddadevops/devops_build.py +++ b/src/main/python/ddadevops/devops_build.py @@ -11,13 +11,14 @@ def create_devops_build_config(stage, project_root_path, module, def get_devops_build(project): return project.get_property('devops_build') -# def get_tag_from_latest_commit(): -# try: -# value = run('git describe --abbrev=0 --tags --exact-match', shell=True, -# capture_output=True, check=True) -# return value.stdout.decode('UTF-8').rstrip() -# except CalledProcessError: -# return None +# TODO: Remove from here! +def get_tag_from_latest_commit(): + try: + value = run('git describe --abbrev=0 --tags --exact-match', shell=True, + capture_output=True, check=True) + return value.stdout.decode('UTF-8').rstrip() + except CalledProcessError: + return None class DevopsBuild: diff --git a/src/main/python/ddadevops/devops_docker_build.py b/src/main/python/ddadevops/devops_docker_build.py index c85344d..8478129 100644 --- a/src/main/python/ddadevops/devops_docker_build.py +++ b/src/main/python/ddadevops/devops_docker_build.py @@ -1,7 +1,5 @@ -import sys -from subprocess import run -from pkg_resources import resource_string -from .python_util import filter_none +from .domain import DockerBuild +from .application import DockerBuildService from .devops_build import DevopsBuild, create_devops_build_config def create_devops_docker_build_config(stage, @@ -28,43 +26,11 @@ def create_devops_docker_build_config(stage, class DevopsDockerBuild(DevopsBuild): def __init__(self, project, config): - super().__init__(project, config) - project.build_depends_on('dda-python-terraform') - self.dockerhub_user = config['dockerhub_user'] - self.dockerhub_password = config['dockerhub_password'] - self.use_package_common_files = config['use_package_common_files'] - self.build_commons_path = config['build_commons_path'] - self.docker_build_commons_dir_name = config['docker_build_commons_dir_name'] - self.docker_publish_tag = config['docker_publish_tag'] - - def docker_build_commons_path(self): - mylist = [self.build_commons_path, - self.docker_build_commons_dir_name] - return '/'.join(filter_none(mylist)) + '/' - - def copy_build_resource_file_from_package(self, name): - run('mkdir -p ' + self.build_path() + '/image/resources', shell=True, check=True) - my_data = resource_string( - __name__, "src/main/resources/docker/" + name) - with open(self.build_path() + '/' + name, "w", encoding="utf-8") as output_file: - output_file.write(my_data.decode(sys.stdout.encoding)) - - def copy_build_resources_from_package(self): - self.copy_build_resource_file_from_package( - 'image/resources/install_functions.sh') - - def copy_build_resources_from_dir(self): - run('cp -f ' + self.docker_build_commons_path() + - '* ' + self.build_path(), shell=True, check=True) + self.build = DockerBuild(project, config) + self.docker_build_service = DockerBuildService() def initialize_build_dir(self): - super().initialize_build_dir() - if self.use_package_common_files: - self.copy_build_resources_from_package() - else: - self.copy_build_resources_from_dir() - run('cp -r image ' + self.build_path(), shell=True, check=True) - run('cp -r test ' + self.build_path(), shell=True, check=True) + self.docker_build_service.initialize_build_dir(self.build) def image(self): run('docker build -t ' + self.name() + diff --git a/src/main/python/ddadevops/domain.py b/src/main/python/ddadevops/domain.py index 5c6c1b7..69a3e9e 100644 --- a/src/main/python/ddadevops/domain.py +++ b/src/main/python/ddadevops/domain.py @@ -3,18 +3,21 @@ from .python_util import filter_none class Validateable(): + 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}' may not be empty."] + else: + return [] + def validate(self) -> List[str]: return [] def is_valid(self) -> bool: return len(self.validate()) < 1 - 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}' may not be empty."] - else: - return [] + + class Build(Validateable): @@ -48,3 +51,20 @@ class Build(Validateable): for key in keys: result[key] = self.get(key) return result + + +class DockerBuild(Build): + def __init__(self, project, config): + super().__init__(project, config) + project.build_depends_on('dda-python-terraform') + self.dockerhub_user = config['dockerhub_user'] + self.dockerhub_password = config['dockerhub_password'] + self.use_package_common_files = config['use_package_common_files'] + self.build_commons_path = config['build_commons_path'] + self.docker_build_commons_dir_name = config['docker_build_commons_dir_name'] + self.docker_publish_tag = config['docker_publish_tag'] + + def docker_build_commons_path(self): + list = [self.build_commons_path, + self.docker_build_commons_dir_name] + return '/'.join(filter_none(list)) + '/' diff --git a/src/main/python/ddadevops/infrastructure.py b/src/main/python/ddadevops/infrastructure.py new file mode 100644 index 0000000..1005f14 --- /dev/null +++ b/src/main/python/ddadevops/infrastructure.py @@ -0,0 +1,53 @@ +from pathlib import Path +from sys import stdout +from pkg_resources import resource_string +from .python_util import execute + +class ResourceApi(): + def read_resource(self, path: str) -> bytes: + return resource_string(__name__, path) + +class FileApi(): + def clean_dir(self, directory: str): + execute('rm -rf ' + directory, shell=True) + execute('mkdir -p ' + directory, shell=True) + + def cp_force(self, src: str, target_dir: str): + execute('cp -f ' + src + '* ' + target_dir, shell=True) + + def cp_recursive(self, src: str, target_dir: str): + execute('cp -r ' + src + ' ' + target_dir, shell=True) + + def write_to_file(self, path: Path, data: bytes): + with open(path, "w", encoding=stdout.encoding) as output_file: + output_file.write(data.decode(stdout.encoding)) + +class DockerApi(): + def image(self, name: str, path: Path): + execute('docker build -t ' + name + + ' --file ' + path + '/image/Dockerfile ' + + path + '/image', shell=True) + + def drun(self, name: str): + execute('docker run -it --entrypoint="" ' + + name + ' /bin/bash', shell=True) + + def dockerhub_login(self, username: str, password: str): + execute('docker login --username ' + username + + ' --password ' + password, shell=True) + + def dockerhub_publish(self, name: str, username: str, tag=None): + if tag is not None: + execute('docker tag ' + name + ' ' + username + + '/' + name + ':' + tag, shell=True) + execute('docker push ' + username + + '/' + name + ':' + tag, shell=True) + execute('docker tag ' + name + ' ' + username + + '/' + name + ':latest', shell=True) + execute('docker push ' + username + + '/' + name + ':latest', shell=True) + + def test(self, name: str, path: Path): + execute('docker build -t ' + name + '-test ' + + '--file ' + path + '/test/Dockerfile ' + + path + '/test', shell=True) diff --git a/src/test/test_domain.py b/src/test/test_domain.py index 861f850..3ef12f0 100644 --- a/src/test/test_domain.py +++ b/src/test/test_domain.py @@ -6,7 +6,7 @@ class TestValidateable(Validateable): self.field = value def validate(self): - return self.validate_is_not_empty('field') + return self.__validate_is_not_empty__('field') def test_should_validate_non_empty_strings():