refactor devops_build to arch
This commit is contained in:
parent
3bdc75cdca
commit
d95827e1e0
8 changed files with 110 additions and 66 deletions
2
build.py
2
build.py
|
@ -28,7 +28,7 @@ use_plugin("python.distutils")
|
||||||
default_task = "publish"
|
default_task = "publish"
|
||||||
|
|
||||||
name = "ddadevops"
|
name = "ddadevops"
|
||||||
version = "3.1.3"
|
version = "3.2.0-dev"
|
||||||
summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud"
|
summary = "tools to support builds combining gopass, terraform, dda-pallet, aws & hetzner-cloud"
|
||||||
description = __doc__
|
description = __doc__
|
||||||
authors = [Author("meissa GmbH", "buero@meissa-gmbh.de")]
|
authors = [Author("meissa GmbH", "buero@meissa-gmbh.de")]
|
||||||
|
|
|
@ -6,5 +6,10 @@ classDiagram
|
||||||
__init__(project, config)
|
__init__(project, config)
|
||||||
do_sth(project)
|
do_sth(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ProjectRepository {
|
||||||
|
get_build(project): Build
|
||||||
|
set_build(project, build)
|
||||||
|
}
|
||||||
|
|
||||||
```
|
```
|
|
@ -20,6 +20,7 @@ from .devops_build import DevopsBuild, create_devops_build_config, get_devops_bu
|
||||||
from .credential import gopass_password_from_path, gopass_field_from_path
|
from .credential import gopass_password_from_path, gopass_field_from_path
|
||||||
|
|
||||||
from .domain import Validateable, Build, DockerBuild, C4kBuild
|
from .domain import Validateable, Build, DockerBuild, C4kBuild
|
||||||
from .application import BuildService, DockerBuildService, C4kBuildService
|
from .application import DockerBuildService, C4kBuildService
|
||||||
|
from .infrastructure import ProjectRepository, ResourceApi, FileApi, DockerApi, ExecutionApi
|
||||||
|
|
||||||
__version__ = "${version}"
|
__version__ = "${version}"
|
||||||
|
|
|
@ -2,14 +2,6 @@ from .domain import Build, DockerBuild, C4kBuild
|
||||||
from .infrastructure import FileApi, ResourceApi, DockerApi, ExecutionApi
|
from .infrastructure import FileApi, ResourceApi, DockerApi, ExecutionApi
|
||||||
|
|
||||||
|
|
||||||
class BuildService:
|
|
||||||
def __init__(self):
|
|
||||||
self.file_api = FileApi()
|
|
||||||
|
|
||||||
def initialize_build_dir(self, build: Build):
|
|
||||||
self.file_api.clean_dir(build.build_path())
|
|
||||||
|
|
||||||
|
|
||||||
class DockerBuildService:
|
class DockerBuildService:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.file_api = FileApi()
|
self.file_api = FileApi()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
import deprecation
|
||||||
from .domain import Build
|
from .domain import Build
|
||||||
from .application import BuildService
|
from .infrastructure import ProjectRepository, FileApi
|
||||||
|
|
||||||
|
|
||||||
def create_devops_build_config(
|
def create_devops_build_config(
|
||||||
|
@ -12,7 +13,8 @@ def create_devops_build_config(
|
||||||
"build_dir_name": build_dir_name,
|
"build_dir_name": build_dir_name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@deprecation.deprecated(deprecated_in="3.2")
|
||||||
|
# Do not expose build to outside
|
||||||
def get_devops_build(project):
|
def get_devops_build(project):
|
||||||
return project.get_property("devops_build")
|
return project.get_property("devops_build")
|
||||||
|
|
||||||
|
@ -33,15 +35,20 @@ def get_tag_from_latest_commit():
|
||||||
|
|
||||||
class DevopsBuild:
|
class DevopsBuild:
|
||||||
def __init__(self, project, config):
|
def __init__(self, project, config):
|
||||||
self.build = Build(project, config)
|
self.project = project
|
||||||
self.build_service = BuildService()
|
self.file_api = FileApi()
|
||||||
project.set_property("devops_build", self)
|
self.repo = ProjectRepository()
|
||||||
|
config.update({"name": project.name})
|
||||||
|
build = Build(config)
|
||||||
|
self.repo.set_build(self.project, build)
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.build.name()
|
build = self.repo.get_build(self.project)
|
||||||
|
return build.name
|
||||||
|
|
||||||
def build_path(self):
|
def build_path(self):
|
||||||
return self.build.build_path()
|
build = self.repo.get_build(self.project)
|
||||||
|
return build.build_path()
|
||||||
|
|
||||||
def initialize_build_dir(self):
|
def initialize_build_dir(self):
|
||||||
self.build_service.initialize_build_dir(self.build)
|
self.file_api.clean_dir(build.build_path())
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import deprecation
|
||||||
from typing import List
|
from typing import List
|
||||||
from .python_util import filter_none
|
from .python_util import filter_none
|
||||||
|
|
||||||
|
@ -18,26 +19,29 @@ class Validateable:
|
||||||
|
|
||||||
|
|
||||||
class Build(Validateable):
|
class Build(Validateable):
|
||||||
def __init__(self, project, config):
|
def __init__(self, config):
|
||||||
self.stage = config["stage"]
|
self.stage = config["stage"]
|
||||||
|
self.name = config["name"]
|
||||||
self.project_root_path = config["project_root_path"]
|
self.project_root_path = config["project_root_path"]
|
||||||
self.module = config["module"]
|
self.module = config["module"]
|
||||||
self.build_dir_name = config["build_dir_name"]
|
self.build_dir_name = config["build_dir_name"]
|
||||||
|
# Deprecated - no longer use generic stack ...
|
||||||
self.stack = {}
|
self.stack = {}
|
||||||
self.project = project
|
|
||||||
|
|
||||||
|
@deprecation.deprecated(deprecated_in="3.2")
|
||||||
|
# use .name instead
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.project.name
|
return self.name
|
||||||
|
|
||||||
def build_path(self):
|
def build_path(self):
|
||||||
path = [self.project_root_path, self.build_dir_name, self.name(), self.module]
|
path = [self.project_root_path, self.build_dir_name, self.name, self.module]
|
||||||
return "/".join(filter_none(path))
|
return "/".join(filter_none(path))
|
||||||
|
|
||||||
# TODO: these functions should be located at TerraformBuild later on.
|
# TODO: these functions should be located at TerraformBuild later on.
|
||||||
def update_runtime_config(self, fqdn, ipv4, ipv6):
|
def update_runtime_config(self, fqdn, ipv4, ipv6):
|
||||||
self.__put__('fqdn', fqdn)
|
self.__put__("fqdn", fqdn)
|
||||||
self.__put__('ipv4', ipv4)
|
self.__put__("ipv4", ipv4)
|
||||||
self.__put__('ipv6', ipv6)
|
self.__put__("ipv6", ipv6)
|
||||||
|
|
||||||
def __put__(self, key, value):
|
def __put__(self, key, value):
|
||||||
self.stack[key] = value
|
self.stack[key] = value
|
||||||
|
@ -78,15 +82,17 @@ class C4kBuild(Validateable):
|
||||||
self.c4k_mixin_config = config["C4kMixin"]["config"]
|
self.c4k_mixin_config = config["C4kMixin"]["config"]
|
||||||
self.c4k_mixin_auth = config["C4kMixin"]["auth"]
|
self.c4k_mixin_auth = config["C4kMixin"]["auth"]
|
||||||
tmp = self.c4k_mixin_config["mon-cfg"]
|
tmp = self.c4k_mixin_config["mon-cfg"]
|
||||||
tmp.update({"cluster-name": self.build.module, "cluster-stage": self.build.stage})
|
tmp.update(
|
||||||
|
{"cluster-name": self.build.module, "cluster-stage": self.build.stage}
|
||||||
|
)
|
||||||
self.c4k_mixin_config.update({"mon-cfg": tmp})
|
self.c4k_mixin_config.update({"mon-cfg": tmp})
|
||||||
|
|
||||||
def update_runtime_config(self, fqdn, ipv4, ipv6):
|
def update_runtime_config(self, fqdn, ipv4, ipv6):
|
||||||
self.build.update_runtime_config(fqdn, ipv4, ipv6)
|
self.build.update_runtime_config(fqdn, ipv4, ipv6)
|
||||||
|
|
||||||
def config(self):
|
def config(self):
|
||||||
fqdn = self.build.__get__('fqdn')
|
fqdn = self.build.__get__("fqdn")
|
||||||
self.c4k_mixin_config.update({'fqdn': fqdn})
|
self.c4k_mixin_config.update({"fqdn": fqdn})
|
||||||
return self.c4k_mixin_config
|
return self.c4k_mixin_config
|
||||||
|
|
||||||
def command(self):
|
def command(self):
|
||||||
|
|
|
@ -3,22 +3,33 @@ from sys import stdout
|
||||||
from pkg_resources import resource_string
|
from pkg_resources import resource_string
|
||||||
from os import chmod
|
from os import chmod
|
||||||
import yaml
|
import yaml
|
||||||
|
from .domain import Build
|
||||||
from .python_util import execute
|
from .python_util import execute
|
||||||
|
|
||||||
class ResourceApi():
|
|
||||||
|
class ProjectRepository:
|
||||||
|
def get_build(self, project) -> Build:
|
||||||
|
return project.get_property("devops_build")
|
||||||
|
|
||||||
|
def set_build(self, project, build: Build):
|
||||||
|
project.set_property("devops_build", build)
|
||||||
|
|
||||||
|
|
||||||
|
class ResourceApi:
|
||||||
def read_resource(self, path: str) -> bytes:
|
def read_resource(self, path: str) -> bytes:
|
||||||
return resource_string(__name__, path)
|
return resource_string(__name__, path)
|
||||||
|
|
||||||
class FileApi():
|
|
||||||
|
class FileApi:
|
||||||
def clean_dir(self, directory: str):
|
def clean_dir(self, directory: str):
|
||||||
execute('rm -rf ' + directory, shell=True)
|
execute("rm -rf " + directory, shell=True)
|
||||||
execute('mkdir -p ' + directory, shell=True)
|
execute("mkdir -p " + directory, shell=True)
|
||||||
|
|
||||||
def cp_force(self, src: str, target_dir: str):
|
def cp_force(self, src: str, target_dir: str):
|
||||||
execute('cp -f ' + src + '* ' + target_dir, shell=True)
|
execute("cp -f " + src + "* " + target_dir, shell=True)
|
||||||
|
|
||||||
def cp_recursive(self, src: str, target_dir: str):
|
def cp_recursive(self, src: str, target_dir: str):
|
||||||
execute('cp -r ' + src + ' ' + target_dir, shell=True)
|
execute("cp -r " + src + " " + target_dir, shell=True)
|
||||||
|
|
||||||
def write_data_to_file(self, path: Path, data: bytes):
|
def write_data_to_file(self, path: Path, data: bytes):
|
||||||
with open(path, "w", encoding="utf-8") as output_file:
|
with open(path, "w", encoding="utf-8") as output_file:
|
||||||
|
@ -29,37 +40,56 @@ class FileApi():
|
||||||
yaml.dump(data, output_file)
|
yaml.dump(data, output_file)
|
||||||
chmod(path, 0o600)
|
chmod(path, 0o600)
|
||||||
|
|
||||||
class DockerApi():
|
|
||||||
|
class DockerApi:
|
||||||
def image(self, name: str, path: Path):
|
def image(self, name: str, path: Path):
|
||||||
execute('docker build -t ' + name +
|
execute(
|
||||||
' --file ' + path + '/image/Dockerfile '
|
"docker build -t "
|
||||||
+ path + '/image', shell=True)
|
+ name
|
||||||
|
+ " --file "
|
||||||
|
+ path
|
||||||
|
+ "/image/Dockerfile "
|
||||||
|
+ path
|
||||||
|
+ "/image",
|
||||||
|
shell=True,
|
||||||
|
)
|
||||||
|
|
||||||
def drun(self, name: str):
|
def drun(self, name: str):
|
||||||
execute('docker run -it --entrypoint="" ' +
|
execute('docker run -it --entrypoint="" ' + name + " /bin/bash", shell=True)
|
||||||
name + ' /bin/bash', shell=True)
|
|
||||||
|
|
||||||
def dockerhub_login(self, username: str, password: str):
|
def dockerhub_login(self, username: str, password: str):
|
||||||
execute('docker login --username ' + username +
|
execute(
|
||||||
' --password ' + password, shell=True)
|
"docker login --username " + username + " --password " + password,
|
||||||
|
shell=True,
|
||||||
|
)
|
||||||
|
|
||||||
def dockerhub_publish(self, name: str, username: str, tag=None):
|
def dockerhub_publish(self, name: str, username: str, tag=None):
|
||||||
if tag is not None:
|
if tag is not None:
|
||||||
execute('docker tag ' + name + ' ' + username +
|
execute(
|
||||||
'/' + name + ':' + tag, shell=True)
|
"docker tag " + name + " " + username + "/" + name + ":" + tag,
|
||||||
execute('docker push ' + username +
|
shell=True,
|
||||||
'/' + name + ':' + tag, shell=True)
|
)
|
||||||
execute('docker tag ' + name + ' ' + username +
|
execute("docker push " + username + "/" + name + ":" + tag, shell=True)
|
||||||
'/' + name + ':latest', shell=True)
|
execute(
|
||||||
execute('docker push ' + username +
|
"docker tag " + name + " " + username + "/" + name + ":latest", shell=True
|
||||||
'/' + name + ':latest', shell=True)
|
)
|
||||||
|
execute("docker push " + username + "/" + name + ":latest", shell=True)
|
||||||
|
|
||||||
def test(self, name: str, path: Path):
|
def test(self, name: str, path: Path):
|
||||||
execute('docker build -t ' + name + '-test ' +
|
execute(
|
||||||
'--file ' + path + '/test/Dockerfile '
|
"docker build -t "
|
||||||
+ path + '/test', shell=True)
|
+ name
|
||||||
|
+ "-test "
|
||||||
|
+ "--file "
|
||||||
|
+ path
|
||||||
|
+ "/test/Dockerfile "
|
||||||
|
+ path
|
||||||
|
+ "/test",
|
||||||
|
shell=True,
|
||||||
|
)
|
||||||
|
|
||||||
class ExecutionApi():
|
|
||||||
|
class ExecutionApi:
|
||||||
def execute(command: str, dry_run=False):
|
def execute(command: str, dry_run=False):
|
||||||
output = ""
|
output = ""
|
||||||
if dry_run:
|
if dry_run:
|
||||||
|
@ -67,4 +97,4 @@ class ExecutionApi():
|
||||||
else:
|
else:
|
||||||
output = execute(command, True)
|
output = execute(command, True)
|
||||||
print(output)
|
print(output)
|
||||||
return output
|
return output
|
||||||
|
|
|
@ -42,9 +42,10 @@ def test_validate_with_reason():
|
||||||
|
|
||||||
|
|
||||||
def test_c4k_build_should_update_fqdn(tmp_path):
|
def test_c4k_build_should_update_fqdn(tmp_path):
|
||||||
project = Project(str(tmp_path), name="test-project")
|
project = Project(str(tmp_path), name="name")
|
||||||
project_config = {
|
project_config = {
|
||||||
"stage": "test",
|
"stage": "test",
|
||||||
|
"name": "name",
|
||||||
"project_root_path": str(tmp_path),
|
"project_root_path": str(tmp_path),
|
||||||
"module": "module",
|
"module": "module",
|
||||||
"build_dir_name": "target",
|
"build_dir_name": "target",
|
||||||
|
@ -62,7 +63,7 @@ def test_c4k_build_should_update_fqdn(tmp_path):
|
||||||
grafana_cloud_user="user",
|
grafana_cloud_user="user",
|
||||||
grafana_cloud_password="password",
|
grafana_cloud_password="password",
|
||||||
)
|
)
|
||||||
sut = C4kBuild(Build(project, project_config), project, project_config)
|
sut = C4kBuild(Build(project_config), project, project_config)
|
||||||
sut.update_runtime_config("test.de", None, None)
|
sut.update_runtime_config("test.de", None, None)
|
||||||
|
|
||||||
assert {
|
assert {
|
||||||
|
@ -88,9 +89,10 @@ def test_c4k_build_should_update_fqdn(tmp_path):
|
||||||
|
|
||||||
|
|
||||||
def test_c4k_build_should_calculate_command(tmp_path):
|
def test_c4k_build_should_calculate_command(tmp_path):
|
||||||
project = Project(str(tmp_path), name="test-project")
|
project = Project(str(tmp_path), name="name")
|
||||||
project_config = {
|
project_config = {
|
||||||
"stage": "test",
|
"stage": "test",
|
||||||
|
"name": "name",
|
||||||
"project_root_path": "",
|
"project_root_path": "",
|
||||||
"module": "module",
|
"module": "module",
|
||||||
"build_dir_name": "target",
|
"build_dir_name": "target",
|
||||||
|
@ -102,17 +104,18 @@ def test_c4k_build_should_calculate_command(tmp_path):
|
||||||
grafana_cloud_user="user",
|
grafana_cloud_user="user",
|
||||||
grafana_cloud_password="password",
|
grafana_cloud_password="password",
|
||||||
)
|
)
|
||||||
sut = C4kBuild(Build(project, project_config), project, project_config)
|
sut = C4kBuild(Build(project_config), project, project_config)
|
||||||
assert (
|
assert (
|
||||||
"c4k-module-standalone.jar "
|
"c4k-module-standalone.jar "
|
||||||
+ "/target/test-project/module/out_c4k_config.yaml "
|
+ "/target/name/module/out_c4k_config.yaml "
|
||||||
+ "/target/test-project/module/out_c4k_auth.yaml > "
|
+ "/target/name/module/out_c4k_auth.yaml > "
|
||||||
+ "/target/test-project/module/out_module.yaml"
|
+ "/target/name/module/out_module.yaml"
|
||||||
== sut.command()
|
== sut.command()
|
||||||
)
|
)
|
||||||
|
|
||||||
project_config = {
|
project_config = {
|
||||||
"stage": "test",
|
"stage": "test",
|
||||||
|
"name": "name",
|
||||||
"project_root_path": "",
|
"project_root_path": "",
|
||||||
"module": "module",
|
"module": "module",
|
||||||
"build_dir_name": "target",
|
"build_dir_name": "target",
|
||||||
|
@ -125,12 +128,12 @@ def test_c4k_build_should_calculate_command(tmp_path):
|
||||||
grafana_cloud_user="user",
|
grafana_cloud_user="user",
|
||||||
grafana_cloud_password="password",
|
grafana_cloud_password="password",
|
||||||
)
|
)
|
||||||
sut = C4kBuild(Build(project, project_config), project, project_config)
|
sut = C4kBuild(Build(project_config), project, project_config)
|
||||||
assert (
|
assert (
|
||||||
"c4k-executabel_name-standalone.jar "
|
"c4k-executabel_name-standalone.jar "
|
||||||
+ "/target/test-project/module/out_c4k_config.yaml "
|
+ "/target/name/module/out_c4k_config.yaml "
|
||||||
+ "/target/test-project/module/out_c4k_auth.yaml > "
|
+ "/target/name/module/out_c4k_auth.yaml > "
|
||||||
+ "/target/test-project/module/out_module.yaml"
|
+ "/target/name/module/out_module.yaml"
|
||||||
== sut.command()
|
== sut.command()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue