This commit is contained in:
patdyn 2024-06-27 12:43:24 +02:00
parent ff61ff383e
commit d6b6cb7a72
6 changed files with 80 additions and 72 deletions

View file

@ -9,12 +9,12 @@ from ..infrastructure import FileApi, ResourceApi, TerraformApi, TerraformBacken
# TODO: mv more fkt to Terraform_api ? # TODO: mv more fkt to Terraform_api ?
class TerraformService: class TerraformService:
def __init__( 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.file_api = file_api
self.resource_api = resource_api self.resource_api = resource_api
self.terraform_api = terraform_api self.terraform_api = terraform_api
self.tf_backend_git_api = tf_backend_git_api self.tf_backend_git_api = tf_backend_api
@classmethod @classmethod
def prod(cls): def prod(cls):
@ -166,7 +166,6 @@ class TerraformService:
def post_build(self, devops: Devops): def post_build(self, devops: Devops):
self.__rescue_local_state__(devops) self.__rescue_local_state__(devops)
self.tf_backend_git_api.stop() self.tf_backend_git_api.stop()
def __copy_build_resource_file_from_package__(self, resource_name, devops: Devops): def __copy_build_resource_file_from_package__(self, resource_name, devops: Devops):
data = self.resource_api.read_resource( data = self.resource_api.read_resource(

View file

@ -14,6 +14,7 @@ class DevopsTerraformBuild(DevopsBuild):
super().__init__(project, inp) super().__init__(project, inp)
project.build_depends_on("dda-python-terraform") project.build_depends_on("dda-python-terraform")
self.terraform_service = TerraformService.prod() self.terraform_service = TerraformService.prod()
# TODO: we might want to make this private in the future, keeping this for compatibility # TODO: we might want to make this private in the future, keeping this for compatibility
def initialize_build_dir(self): def initialize_build_dir(self):
super().initialize_build_dir() super().initialize_build_dir()
@ -24,7 +25,7 @@ class DevopsTerraformBuild(DevopsBuild):
self.initialize_build_dir() self.initialize_build_dir()
devops = self.devops_repo.get_devops(self.project) devops = self.devops_repo.get_devops(self.project)
if self.terraform_service.uses_backend_git(devops): 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): def post_build(self):
devops = self.devops_repo.get_devops(self.project) devops = self.devops_repo.get_devops(self.project)

View file

@ -1,69 +1,70 @@
from typing import List, Dict, Any from typing import List, Dict, Set, Any
from .common import Validateable, CredentialMappingDefault from .common import Validateable, CredentialMappingDefault
class TerraformBackendGit(Validateable, CredentialMappingDefault): class TerraformBackendGit(Validateable, CredentialMappingDefault):
def __init__( def __init__(
self, self,
inp: dict, inp: dict,
): ):
self.stage = inp.get("stage") self.stage = inp.get("stage")
self.module = inp.get("module") self.module = inp.get("module")
self.git_backend_repo = inp.get("git_backend_repo") self.git_backend_repo = inp.get("git_backend_repo")
self.git_backend_ref = inp.get("git_backend_ref") self.git_backend_ref = inp.get("git_backend_ref")
self.git_backend_state = inp.get("git_backend_state") self.git_backend_state = inp.get("git_backend_state")
self.git_backend_username = inp.get("git_backend_username") self.git_backend_username = inp.get("git_backend_username")
self.git_backend_token = inp.get("git_backend_token") self.git_backend_token = inp.get("git_backend_token")
def validate(self) -> List[str]: def validate(self) -> List[str]:
result = [] result = []
result += self.__validate_is_not_empty__("stage") result += self.__validate_is_not_empty__("stage")
result += self.__validate_is_not_empty__("module") result += self.__validate_is_not_empty__("module")
result += self.__validate_is_not_empty__("git_backend_repo") 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_ref")
result += self.__validate_is_not_empty__("git_backend_state") 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_username")
result += self.__validate_is_not_empty__("git_backend_token") 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 # 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 # 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]: def backend_config(self) -> Dict[str, Any]:
return { return {
"address": self.__make_http_backend_address__(), "address": self.__make_http_backend_address__(),
"lock_address": self.__make_http_backend_address__(), "lock_address": self.__make_http_backend_address__(),
"unlock_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
def __make_http_backend_address__(self) -> str: def resources_from_package(self) -> Set[str]:
# TODO Should we make this configurable? return {"tf_backend_git_backend.tf", "tf_backend_git_backend_vars.tf"}
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"
# TODO: Implement ssh auth too # TODO: This can not be used for backend config, as the backend block can not reference vars.
@classmethod def project_vars(self) -> Dict[str, Any]:
def get_mapping_default(cls) -> List[Dict[str, str]]: return {
return [ "http_backend_address": self.__make_http_backend_address__()
{ }
"gopass_path": "server/meissa/repo/terraform-backend-git-test",
"gopass_field": "user", def is_local_state(self):
"name": "git_backend_username", return False
},
{ def __make_http_backend_address__(self) -> str:
"gopass_path": "server/meissa/repo/terraform-backend-git-test", # TODO Should we make this configurable?
"gopass_field": "token", base_string = "http://localhost:6061/?type=git"
"name": "git_backend_token", 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",
},
]

View file

@ -12,6 +12,7 @@ class BuildType(Enum):
K3S = 2 K3S = 2
TERRAFORM = 3 TERRAFORM = 3
# TODO: We could follow domain implications and make a 'BackendType' enum # TODO: We could follow domain implications and make a 'BackendType' enum
class ProviderType(Enum): class ProviderType(Enum):
DIGITALOCEAN = 0 DIGITALOCEAN = 0

View file

@ -88,20 +88,22 @@ class TerraformDomain(Validateable):
for provider in self.providers.values(): for provider in self.providers.values():
result = result and provider.is_local_state() result = result and provider.is_local_state()
return result return result
def uses_backend_git(self) -> bool: 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: Add ssh method case and make this default
# TODO: How do we get to the credentials? # TODO: How do we get to the credentials?
def env_credentials(self) -> Dict[str, str]: def env_credentials(self) -> Dict[str, str]:
tf_backend_git = self.providers[ProviderType.TERRAFORM_BACKEND_GIT] tf_backend_git = self.providers[ProviderType.TERRAFORM_BACKEND_GIT]
if tf_backend_git.git_backend_token != "": if tf_backend_git.git_backend_token != "":
return { return {
"GITHUB_TOKEN" : tf_backend_git.git_backend_token, "GITHUB_TOKEN": tf_backend_git.git_backend_token,
"GIT_USERNAME" : tf_backend_git.git_backend_username, "GIT_USERNAME": tf_backend_git.git_backend_username,
} }
return {"" : ""} return {"": ""}
def backend_config(self) -> Dict[str, Any]: def backend_config(self) -> Dict[str, Any]:
result = {} result = {}

View file

@ -216,17 +216,21 @@ class GitApi:
class TerraformApi: class TerraformApi:
pass pass
class TerraformBackendGitApi: class TerraformBackendGitApi:
def __init__(self): def __init__(self):
self.execution_api = ExecutionApi() self.execution_api = ExecutionApi()
def start(self, credentials: Dict[str, str]): def start(self, credentials: Dict[str, str]):
env = "" env = ""
for key in credentials: for key in credentials:
env = env + f'{key}' + "=" + f'{credentials[key]}' + " " env = env + f'{key}' + "=" + f'{credentials[key]}' + " "
self.execution_api.execute(f'{env}' + " " + "terraform-backend-git &") self.execution_api.execute(f'{env}' + " " + "terraform-backend-git &")
def stop(self): def stop(self):
self.execution_api.execute("terraform-backend-git stop") self.execution_api.execute("terraform-backend-git stop")
class ArtifactDeploymentApi: class ArtifactDeploymentApi:
def __init__(self): def __init__(self):
self.execution_api = ExecutionApi() self.execution_api = ExecutionApi()