141 lines
5.4 KiB
Python
141 lines
5.4 KiB
Python
import logging
|
|
import os
|
|
from datetime import datetime, timezone
|
|
from typing import Any, List
|
|
|
|
from flask import current_app
|
|
|
|
from app.extensions import db
|
|
from app.models.base import Group
|
|
from app.models.cloud import CloudAccount, CloudProvider
|
|
from app.models.mirrors import StaticOrigin
|
|
from app.terraform.terraform import TerraformAutomation
|
|
|
|
|
|
def import_state(state: Any) -> None:
|
|
if not isinstance(state, dict):
|
|
raise RuntimeError("The Terraform state object returned was not a dict.")
|
|
if "values" not in state or "child_modules" not in state['values']['root_module']:
|
|
# There are no CloudFront origins deployed to import state for
|
|
return
|
|
# CloudFront distributions (origins)
|
|
for mod in state['values']['root_module']['child_modules']:
|
|
if mod['address'].startswith('module.static_'):
|
|
static_id = mod['address'][len('module.static_'):]
|
|
logging.debug("Found static module in state: %s", static_id)
|
|
for res in mod['resources']:
|
|
if res['address'].endswith('aws_cloudfront_distribution.this'):
|
|
logging.debug("and found related cloudfront distribution")
|
|
static = StaticOrigin.query.filter(StaticOrigin.id == static_id).first()
|
|
static.origin_domain_name = res['values']['domain_name']
|
|
logging.debug("and found static origin: %s to update with domain name: %s", static.id,
|
|
static.origin_domain_name)
|
|
static.terraform_updated = datetime.now(tz=timezone.utc)
|
|
break
|
|
db.session.commit()
|
|
|
|
|
|
class StaticAWSAutomation(TerraformAutomation):
|
|
short_name = "static_aws"
|
|
description = "Deploy static origins to AWS"
|
|
provider = CloudProvider.AWS
|
|
cloud_name = "aws"
|
|
|
|
template_parameters: List[str] = []
|
|
|
|
template = """
|
|
terraform {
|
|
{{ backend_config }}
|
|
required_providers {
|
|
aws = {
|
|
version = "~> 4.67.0"
|
|
}
|
|
gitlab = {
|
|
source = "gitlabhq/gitlab"
|
|
version = "~> 15.11.0"
|
|
}
|
|
}
|
|
}
|
|
|
|
{% for group in groups %}
|
|
module "label_{{ group.id }}" {
|
|
source = "cloudposse/label/null"
|
|
version = "0.25.0"
|
|
namespace = "{{ global_namespace }}"
|
|
tenant = "{{ group.group_name }}"
|
|
label_order = ["namespace", "tenant", "name", "attributes"]
|
|
}
|
|
{% endfor %}
|
|
|
|
{% for account in source_cloud_accounts -%}
|
|
provider "gitlab" {
|
|
token = "{{ account.credentials['gitlab_token'] }}"
|
|
alias = "account_{{ account.id }}"
|
|
}
|
|
{% endfor -%}
|
|
|
|
{% for account in storage_cloud_accounts -%}
|
|
provider "aws" {
|
|
access_key = "{{ account.credentials['aws_access_key'] }}"
|
|
secret_key = "{{ account.credentials['aws_secret_key'] }}"
|
|
region = "{{ account.credentials['aws_region'] }}"
|
|
alias = "account_{{ account.id }}"
|
|
}
|
|
|
|
provider "aws" {
|
|
access_key = "{{ account.credentials['aws_access_key'] }}"
|
|
secret_key = "{{ account.credentials['aws_secret_key'] }}"
|
|
region = "us-east-1"
|
|
alias = "account_{{ account.id }}_us_east_1"
|
|
}
|
|
|
|
{% for static in account.statics | selectattr("destroyed", "none") %}
|
|
module "static_{{ static.id }}" {
|
|
providers = {
|
|
aws = aws.account_{{ account.id }}
|
|
aws.us_east_1 = aws.account_{{ account.id }}_us_east_1
|
|
gitlab = gitlab.account_{{ static.source_cloud_account_id }}
|
|
}
|
|
source = "{{ terraform_modules_path }}/terraform-aws-bc-static-origin"
|
|
name = "static"
|
|
context = module.label_{{ static.group.id }}.context
|
|
{% if static.keanu_convene_path -%}
|
|
keanu_convene_path = "{{ static.keanu_convene_path }}"
|
|
{%- endif %}
|
|
{% if static.keanu_convene_config -%}
|
|
keanu_convene_config = "{{ static.keanu_convene_config | replace('"', '\\\\"') }}"
|
|
{%- endif %}
|
|
{% if static.matrix_homeserver -%}
|
|
matrix_homeserver = "{{ static.matrix_homeserver }}"
|
|
{%- endif %}
|
|
gitlab_project = "{{ static.source_project }}"
|
|
attributes = ["{{ static.id }}"]
|
|
}
|
|
{% endfor -%}
|
|
{%- endfor %}
|
|
"""
|
|
|
|
def tf_generate(self) -> None:
|
|
groups = Group.query.all()
|
|
storage_cloud_accounts = CloudAccount.query.filter(
|
|
CloudAccount.provider == CloudProvider.AWS
|
|
).all()
|
|
source_cloud_accounts = CloudAccount.query.filter(
|
|
CloudAccount.provider == CloudProvider.GITLAB
|
|
).all()
|
|
self.tf_write(
|
|
self.template,
|
|
groups=groups,
|
|
storage_cloud_accounts=storage_cloud_accounts,
|
|
source_cloud_accounts=source_cloud_accounts,
|
|
global_namespace=current_app.config['GLOBAL_NAMESPACE'], bypass_token=current_app.config['BYPASS_TOKEN'],
|
|
terraform_modules_path=os.path.join(*list(os.path.split(current_app.root_path))[:-1], 'terraform-modules'),
|
|
backend_config=f"""backend "http" {{
|
|
lock_address = "{current_app.config['TFSTATE_BACKEND']}/{self.short_name}"
|
|
unlock_address = "{current_app.config['TFSTATE_BACKEND']}/{self.short_name}"
|
|
address = "{current_app.config['TFSTATE_BACKEND']}/{self.short_name}"
|
|
}}""",
|
|
**{k: current_app.config[k.upper()] for k in self.template_parameters})
|
|
|
|
def tf_posthook(self, *, prehook_result: Any = None) -> None:
|
|
import_state(self.tf_show())
|