majuna/app/terraform/eotk/aws.py

128 lines
4.4 KiB
Python
Raw Normal View History

import os
from datetime import datetime, timezone
from typing import Any
from app import app
from app.extensions import db
from app.models.base import Group
from app.models.onions import Eotk
from app.terraform import DeterministicZip
from app.terraform.eotk import eotk_configuration
from app.terraform.terraform import TerraformAutomation
2024-12-06 18:15:47 +00:00
def update_eotk_instance(group_id: int, region: str, instance_id: str) -> None:
instance = Eotk.query.filter(
Eotk.group_id == group_id,
Eotk.region == region,
Eotk.provider == "aws",
2024-12-06 18:15:47 +00:00
Eotk.destroyed.is_(None),
).first()
if instance is None:
instance = Eotk()
instance.added = datetime.now(tz=timezone.utc)
instance.group_id = group_id
instance.provider = "aws"
instance.region = region
db.session.add(instance)
instance.updated = datetime.now(tz=timezone.utc)
instance.instance_id = instance_id
class EotkAWSAutomation(TerraformAutomation):
short_name = "eotk_aws"
description = "Deploy EOTK instances to AWS"
2024-12-06 18:15:47 +00:00
template_parameters = ["aws_access_key", "aws_secret_key"]
template = """
terraform {
{{ backend_config }}
required_providers {
aws = {
version = "~> 4.4.0"
}
}
}
2022-05-16 13:29:48 +01:00
provider "aws" {
access_key = "{{ aws_access_key }}"
secret_key = "{{ aws_secret_key }}"
region = "us-east-2"
}
2022-05-16 13:29:48 +01:00
{% for group in groups %}
module "eotk_{{ group.id }}" {
source = "{{ terraform_modules_path }}/terraform-aws-bc-eotk"
namespace = "{{ global_namespace }}"
tenant = "{{ group.group_name }}"
name = "eotk"
label_order = ["namespace", "tenant", "name", "attributes"]
tags = {
"Application" = "EOTK"
}
configuration_bundle = "{{ group.id }}.zip"
}
output "eotk_instances_{{ group.id }}" {
value = module.eotk_{{ group.id }}.instances
}
{% endfor %}
"""
2022-05-16 11:44:03 +01:00
def tf_generate(self) -> None:
if not self.working_dir:
raise RuntimeError("No working directory specified.")
self.tf_write(
self.template,
groups=Group.query.filter(
2024-12-06 18:15:47 +00:00
Group.eotk.is_(True), Group.destroyed.is_(None)
).all(),
2024-12-06 18:15:47 +00:00
global_namespace=app.config["GLOBAL_NAMESPACE"],
terraform_modules_path=os.path.join(
*list(os.path.split(app.root_path))[:-1], "terraform-modules"
),
backend_config=f"""backend "http" {{
lock_address = "{app.config['TFSTATE_BACKEND']}/{self.short_name}"
unlock_address = "{app.config['TFSTATE_BACKEND']}/{self.short_name}"
address = "{app.config['TFSTATE_BACKEND']}/{self.short_name}"
}}""",
2024-12-06 18:15:47 +00:00
**{k: app.config[k.upper()] for k in self.template_parameters},
)
2024-12-06 18:15:47 +00:00
for group in (
Group.query.filter(Group.eotk.is_(True), Group.destroyed.is_(None))
.order_by(Group.id)
.all()
):
with DeterministicZip(
os.path.join(self.working_dir, f"{group.id}.zip")
) as dzip:
dzip.add_file("sites.conf", eotk_configuration(group).encode("utf-8"))
for onion in sorted(group.onions, key=lambda o: o.onion_name):
2024-12-06 18:15:47 +00:00
dzip.add_file(
f"{onion.onion_name}.v3pub.key", onion.onion_public_key
)
dzip.add_file(
f"{onion.onion_name}.v3sec.key", onion.onion_private_key
)
dzip.add_file(
f"{onion.onion_name[:20]}-v3.cert", onion.tls_public_key
)
dzip.add_file(
f"{onion.onion_name[:20]}-v3.pem", onion.tls_private_key
)
def tf_posthook(self, *, prehook_result: Any = None) -> None:
for e in Eotk.query.all():
db.session.delete(e)
outputs = self.tf_output()
for output in outputs:
if output.startswith("eotk_instances_"):
try:
2024-12-06 18:15:47 +00:00
group_id = int(output[len("eotk_instance_") + 1 :])
for az in outputs[output]["value"]:
update_eotk_instance(group_id, az, outputs[output]["value"][az])
except ValueError:
pass
db.session.commit()