diff --git a/src/main/python/ddadevops/application/terraform_service.py b/src/main/python/ddadevops/application/terraform_service.py index 18f48cc..75d5fd9 100644 --- a/src/main/python/ddadevops/application/terraform_service.py +++ b/src/main/python/ddadevops/application/terraform_service.py @@ -9,12 +9,12 @@ from ..infrastructure import FileApi, ResourceApi, TerraformApi, TerraformBacken # TODO: mv more fkt to Terraform_api ? class TerraformService: def __init__( - self, file_api: FileApi, resource_api: ResourceApi, terraform_api: TerraformApi, tf_backend_git_api: TerraformBackendGitApi + self, file_api: FileApi, resource_api: ResourceApi, terraform_api: TerraformApi, tf_backend_api: TerraformBackendGitApi ): self.file_api = file_api self.resource_api = resource_api self.terraform_api = terraform_api - self.tf_backend_git_api = tf_backend_git_api + self.tf_backend_git_api = tf_backend_api @classmethod def prod(cls): @@ -166,7 +166,6 @@ class TerraformService: def post_build(self, devops: Devops): self.__rescue_local_state__(devops) self.tf_backend_git_api.stop() - def __copy_build_resource_file_from_package__(self, resource_name, devops: Devops): data = self.resource_api.read_resource( diff --git a/src/main/python/ddadevops/devops_terraform_build.py b/src/main/python/ddadevops/devops_terraform_build.py index ed84b2a..0976db7 100644 --- a/src/main/python/ddadevops/devops_terraform_build.py +++ b/src/main/python/ddadevops/devops_terraform_build.py @@ -14,6 +14,7 @@ class DevopsTerraformBuild(DevopsBuild): super().__init__(project, inp) project.build_depends_on("dda-python-terraform") self.terraform_service = TerraformService.prod() + # TODO: we might want to make this private in the future, keeping this for compatibility def initialize_build_dir(self): super().initialize_build_dir() @@ -24,7 +25,7 @@ class DevopsTerraformBuild(DevopsBuild): self.initialize_build_dir() devops = self.devops_repo.get_devops(self.project) if self.terraform_service.uses_backend_git(devops): - self.terraform_service.start_tf_backend_git_daemon() + self.terraform_service.start_tf_backend_git_daemon(devops) def post_build(self): devops = self.devops_repo.get_devops(self.project) diff --git a/src/main/python/ddadevops/domain/backend_tf_backend_git.py b/src/main/python/ddadevops/domain/backend_tf_backend_git.py index 0289a79..e7d9287 100644 --- a/src/main/python/ddadevops/domain/backend_tf_backend_git.py +++ b/src/main/python/ddadevops/domain/backend_tf_backend_git.py @@ -1,69 +1,70 @@ -from typing import List, Dict, Any +from typing import List, Dict, Set, Any from .common import Validateable, CredentialMappingDefault class TerraformBackendGit(Validateable, CredentialMappingDefault): - def __init__( - self, - inp: dict, - ): - self.stage = inp.get("stage") - self.module = inp.get("module") - self.git_backend_repo = inp.get("git_backend_repo") - self.git_backend_ref = inp.get("git_backend_ref") - self.git_backend_state = inp.get("git_backend_state") - self.git_backend_username = inp.get("git_backend_username") - self.git_backend_token = inp.get("git_backend_token") + def __init__( + self, + inp: dict, + ): + self.stage = inp.get("stage") + self.module = inp.get("module") + self.git_backend_repo = inp.get("git_backend_repo") + self.git_backend_ref = inp.get("git_backend_ref") + self.git_backend_state = inp.get("git_backend_state") + self.git_backend_username = inp.get("git_backend_username") + self.git_backend_token = inp.get("git_backend_token") - def validate(self) -> List[str]: - result = [] - result += self.__validate_is_not_empty__("stage") - result += self.__validate_is_not_empty__("module") - result += self.__validate_is_not_empty__("git_backend_repo") - result += self.__validate_is_not_empty__("git_backend_ref") - result += self.__validate_is_not_empty__("git_backend_state") - result += self.__validate_is_not_empty__("git_backend_username") - result += self.__validate_is_not_empty__("git_backend_token") + def validate(self) -> List[str]: + result = [] + result += self.__validate_is_not_empty__("stage") + result += self.__validate_is_not_empty__("module") + result += self.__validate_is_not_empty__("git_backend_repo") + result += self.__validate_is_not_empty__("git_backend_ref") + result += self.__validate_is_not_empty__("git_backend_state") + result += self.__validate_is_not_empty__("git_backend_username") + result += self.__validate_is_not_empty__("git_backend_token") - return result + return result - # See: https://developer.hashicorp.com/terraform/language/settings/backends/configuration#command-line-key-value-pairs - # and https://github.com/plumber-cd/terraform-backend-git?tab=readme-ov-file#standalone-terraform-http-backend-mode - def backend_config(self) -> Dict[str, Any]: - return { - "address": self.__make_http_backend_address__(), - "lock_address": self.__make_http_backend_address__(), - "unlock_address": self.__make_http_backend_address__(), - } - - def resources_from_package(self) -> List[str]: - return {"tf_backend_git_backend.tf", "tf_backend_git_backend_vars.tf"} - - # TODO: This can not be used for backend config, as the backend block can not reference vars. - def project_vars(self) -> Dict[str, Any]: - return { - "http_backend_address": self.__make_http_backend_address__(self.git_backend_ref, self.git_backend_repo, self.git_backend_state) - } - - def is_local_state(self): - return False + # See: https://developer.hashicorp.com/terraform/language/settings/backends/configuration#command-line-key-value-pairs + # and https://github.com/plumber-cd/terraform-backend-git?tab=readme-ov-file#standalone-terraform-http-backend-mode + def backend_config(self) -> Dict[str, Any]: + return { + "address": self.__make_http_backend_address__(), + "lock_address": self.__make_http_backend_address__(), + "unlock_address": self.__make_http_backend_address__(), + } - def __make_http_backend_address__(self) -> str: - # TODO Should we make this configurable? - base_string = "http://localhost:6061/?type=git" - return f"{base_string}&repository={self.git_backend_repo}&ref={self.git_backend_ref}&state={self.stage}/{self.module}/{self.git_backend_state}.json" + def resources_from_package(self) -> Set[str]: + return {"tf_backend_git_backend.tf", "tf_backend_git_backend_vars.tf"} - # TODO: Implement ssh auth too - @classmethod - def get_mapping_default(cls) -> List[Dict[str, str]]: - return [ - { - "gopass_path": "server/meissa/repo/terraform-backend-git-test", - "gopass_field": "user", - "name": "git_backend_username", - }, - { - "gopass_path": "server/meissa/repo/terraform-backend-git-test", - "gopass_field": "token", - "name": "git_backend_token", - }, - ] + # TODO: This can not be used for backend config, as the backend block can not reference vars. + def project_vars(self) -> Dict[str, Any]: + return { + "http_backend_address": self.__make_http_backend_address__() + } + + def is_local_state(self): + return False + + def __make_http_backend_address__(self) -> str: + # TODO Should we make this configurable? + base_string = "http://localhost:6061/?type=git" + state = f"{self.stage}/{self.module}/{self.git_backend_state}" + return f"{base_string}&repository={self.git_backend_repo}&ref={self.git_backend_ref}&state={state}" + + # TODO: Implement ssh auth too + @classmethod + def get_mapping_default(cls) -> List[Dict[str, str]]: + return [ + { + "gopass_path": "server/meissa/repo/terraform-backend-git-test", + "gopass_field": "user", + "name": "git_backend_username", + }, + { + "gopass_path": "server/meissa/repo/terraform-backend-git-test", + "gopass_field": "token", + "name": "git_backend_token", + }, + ] diff --git a/src/main/python/ddadevops/domain/common.py b/src/main/python/ddadevops/domain/common.py index 1049a27..dbeb1de 100644 --- a/src/main/python/ddadevops/domain/common.py +++ b/src/main/python/ddadevops/domain/common.py @@ -12,6 +12,7 @@ class BuildType(Enum): K3S = 2 TERRAFORM = 3 + # TODO: We could follow domain implications and make a 'BackendType' enum class ProviderType(Enum): DIGITALOCEAN = 0 diff --git a/src/main/python/ddadevops/domain/terraform.py b/src/main/python/ddadevops/domain/terraform.py index c9f8df6..2296226 100644 --- a/src/main/python/ddadevops/domain/terraform.py +++ b/src/main/python/ddadevops/domain/terraform.py @@ -88,20 +88,22 @@ class TerraformDomain(Validateable): for provider in self.providers.values(): result = result and provider.is_local_state() return result - + def uses_backend_git(self) -> bool: - return ProviderType.TERRAFORM_BACKEND_GIT in self.providers.keys() - + if ProviderType.TERRAFORM_BACKEND_GIT in self.providers.keys(): + return True + return False + # TODO: Add ssh method case and make this default # TODO: How do we get to the credentials? def env_credentials(self) -> Dict[str, str]: tf_backend_git = self.providers[ProviderType.TERRAFORM_BACKEND_GIT] if tf_backend_git.git_backend_token != "": return { - "GITHUB_TOKEN" : tf_backend_git.git_backend_token, - "GIT_USERNAME" : tf_backend_git.git_backend_username, - } - return {"" : ""} + "GITHUB_TOKEN": tf_backend_git.git_backend_token, + "GIT_USERNAME": tf_backend_git.git_backend_username, + } + return {"": ""} def backend_config(self) -> Dict[str, Any]: result = {} diff --git a/src/main/python/ddadevops/infrastructure/infrastructure.py b/src/main/python/ddadevops/infrastructure/infrastructure.py index 3389503..2731971 100644 --- a/src/main/python/ddadevops/infrastructure/infrastructure.py +++ b/src/main/python/ddadevops/infrastructure/infrastructure.py @@ -216,17 +216,21 @@ class GitApi: class TerraformApi: pass + class TerraformBackendGitApi: def __init__(self): self.execution_api = ExecutionApi() + def start(self, credentials: Dict[str, str]): env = "" for key in credentials: env = env + f'{key}' + "=" + f'{credentials[key]}' + " " self.execution_api.execute(f'{env}' + " " + "terraform-backend-git &") + def stop(self): self.execution_api.execute("terraform-backend-git stop") + class ArtifactDeploymentApi: def __init__(self): self.execution_api = ExecutionApi()