eotk: import instance information from terraform

This commit is contained in:
Iain Learmonth 2022-05-13 15:40:59 +01:00
parent 567fcce0bb
commit ce520b87a5
11 changed files with 233 additions and 74 deletions

View file

@ -12,7 +12,7 @@ from app.terraform.block_bridge_github import BlockBridgeGitHubAutomation
from app.terraform.block_external import BlockExternalAutomation
from app.terraform.block_ooni import BlockOONIAutomation
from app.terraform.block_roskomsvoboda import BlockRoskomsvobodaAutomation
from app.terraform.eotk import EotkAutomation
from app.terraform.eotk.aws import EotkAWSAutomation
from app.terraform.alarms.proxy_azure_cdn import AlarmProxyAzureCdnAutomation
from app.terraform.alarms.proxy_cloudfront import AlarmProxyCloudfrontAutomation
from app.terraform.alarms.proxy_http_status import AlarmProxyHTTPStatusAutomation
@ -41,7 +41,7 @@ jobs = {
BridgeGandiAutomation,
BridgeHcloudAutomation,
BridgeOvhAutomation,
EotkAutomation,
EotkAWSAutomation,
ListGithubAutomation,
ListGitlabAutomation,
ListS3Automation,

View file

@ -13,6 +13,7 @@ class Onion(AbstractConfiguration):
class Eotk(AbstractResource):
group_id = db.Column(db.Integer(), db.ForeignKey("group.id"), nullable=False)
instance_id = db.Column(db.String(100), nullable=True)
provider = db.Column(db.String(20), nullable=False)
region = db.Column(db.String(20), nullable=False)
group = db.relationship("Group", back_populates="eotks")

View file

@ -10,6 +10,7 @@ from app.portal.list import NewMirrorListForm
from app.portal.automation import bp as automation
from app.portal.bridgeconf import bp as bridgeconf
from app.portal.bridge import bp as bridge
from app.portal.eotk import bp as eotk
from app.portal.group import bp as group
from app.portal.list import bp as list_
from app.portal.origin import bp as origin
@ -20,6 +21,7 @@ portal = Blueprint("portal", __name__, template_folder="templates", static_folde
portal.register_blueprint(automation, url_prefix="/automation")
portal.register_blueprint(bridgeconf, url_prefix="/bridgeconf")
portal.register_blueprint(bridge, url_prefix="/bridge")
portal.register_blueprint(eotk, url_prefix="/eotk")
portal.register_blueprint(group, url_prefix="/group")
portal.register_blueprint(list_, url_prefix="/list")
portal.register_blueprint(origin, url_prefix="/origin")

16
app/portal/eotk.py Normal file
View file

@ -0,0 +1,16 @@
from flask import render_template, Blueprint
from sqlalchemy import desc
from app.models.onions import Eotk
bp = Blueprint("eotk", __name__)
@bp.route("/list")
def eotk_list():
instances = Eotk.query.filter(Eotk.destroyed == None).order_by(desc(Eotk.added)).all()
return render_template("list.html.j2",
section="eotk",
title="EOTK Instances",
item="eotk",
items=instances)

View file

@ -132,8 +132,8 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link{% if section == "eotk" %} active{% endif %} disabled text-secondary"
href="#">
<a class="nav-link{% if section == "eotk" %} active{% endif %}"
href="{{ url_for("portal.eotk.eotk_list") }}">
{{ icon("server") }} EOTK Instances
</a>
</li>

View file

@ -1,5 +1,5 @@
{% extends "base.html.j2" %}
{% from "tables.html.j2" import alarms_table, automations_table, bridgeconfs_table, bridges_table,
{% from "tables.html.j2" import alarms_table, automations_table, bridgeconfs_table, bridges_table, eotk_table,
groups_table, mirrorlists_table, origins_table, origin_onion_table, onions_table, proxies_table %}
{% block content %}

View file

@ -55,12 +55,62 @@
</div>
{% endmacro %}
{% macro eotk_table(eotks) %}
<div class="alert alert-danger">Not implemented yet.</div>
{% macro eotk_table(instances) %}
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th scope="col">Group</th>
<th scope="col">Provider</th>
<th scope="col">Region</th>
<th scope="col">Instance ID</th>
<th scope="col">Created</th>
<th scope="col">Alarms</th>
<th scope="col">Actions</th>
</tr>
</thead>
<tbody>
{% for instance in instances %}
{% if not instance.destroyed %}
<tr class="align-middle{% if instance.deprecated %} bg-warning{% endif %}">
<td>
<a href="{{ url_for("portal.group.group_edit", group_id=instance.group.id) }}">{{ instance.group.group_name }}</a>
</td>
<td>{{ instance.provider }}</td>
<td>{{ instance.region }}</td>
<td>
<code>{{ instance.instance_id }}</code>
</td>
<td>
{{ instance.added | format_datetime }}
</td>
<td>
{% for alarm in [] %}
<span title="{{ alarm.alarm_type }}">
{% if alarm.alarm_state.name == "OK" %}
{{ alarm_ok() }}
{% elif alarm.alarm_state.name == "UNKNOWN" %}
{{ alarm_unknown() }}
{% else %}
{{ alarm_critical() }}
{% endif %}
</span>
{% endfor %}
</td>
<td>
<a href="#"
class="btn btn-primary btn-sm">Generate Configuration</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endmacro %}
{% macro automations_table(automations) %}
<div class="table-responsive">
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>

View file

@ -1,66 +0,0 @@
from app import app
from app.models.base import Group
from app.terraform.terraform import TerraformAutomation
class EotkAutomation(TerraformAutomation):
short_name = "eotk"
description = "Deploy EOTK instances to AWS"
template_parameters = [
"aws_access_key",
"aws_secret_key"
]
template = """
terraform {
required_providers {
aws = {
version = "~> 4.4.0"
}
}
}
provider "aws" {
access_key = "{{ aws_access_key }}"
secret_key = "{{ aws_secret_key }}"
region = "us-east-2"
}
provider "aws" {
access_key = "{{ aws_access_key }}"
secret_key = "{{ aws_secret_key }}"
region = "eu-central-1"
alias = "second_region"
}
{% for group in groups %}
module "eotk_{{ group.id }}" {
providers = {
aws = aws,
aws.second_region = aws.second_region
}
source = "sr2c/eotk/aws"
version = "0.0.5"
namespace = "{{ global_namespace }}"
tenant = "{{ group.group_name }}"
name = "eotk"
label_order = ["namespace", "tenant", "name", "attributes"]
disable_api_termination = true
}
{% endfor %}
"""
def tf_generate(self):
self.tf_write(
self.template,
groups=Group.query.filter(
Group.eotk == True,
Group.destroyed == None
).all(),
global_namespace=app.config['GLOBAL_NAMESPACE'],
**{
k: app.config[k.upper()]
for k in self.template_parameters
}
)

View file

110
app/terraform/eotk/aws.py Normal file
View file

@ -0,0 +1,110 @@
import datetime
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.terraform import TerraformAutomation
def update_eotk_instance(group_id: int, region: str, instance_id: str):
instance = Eotk.query.filter(
Eotk.group_id == group_id,
Eotk.region == region,
Eotk.provider == "aws",
Eotk.destroyed == None
).first()
if instance is None:
instance = Eotk()
instance.added = datetime.datetime.utcnow()
instance.group_id = group_id
instance.provider = "aws"
instance.region = region
db.session.add(instance)
instance.updated = datetime.datetime.utcnow()
instance.instance_id = instance_id
class EotkAWSAutomation(TerraformAutomation):
short_name = "eotk_aws"
description = "Deploy EOTK instances to AWS"
template_parameters = [
"aws_access_key",
"aws_secret_key"
]
template = """
terraform {
required_providers {
aws = {
version = "~> 4.4.0"
}
}
}
provider "aws" {
access_key = "{{ aws_access_key }}"
secret_key = "{{ aws_secret_key }}"
region = "us-east-2"
}
provider "aws" {
access_key = "{{ aws_access_key }}"
secret_key = "{{ aws_secret_key }}"
region = "eu-central-1"
alias = "second_region"
}
{% for group in groups %}
module "eotk_{{ group.id }}" {
providers = {
aws = aws,
aws.second_region = aws.second_region
}
source = "sr2c/eotk/aws"
version = "0.0.5"
namespace = "{{ global_namespace }}"
tenant = "{{ group.group_name }}"
name = "eotk"
label_order = ["namespace", "tenant", "name", "attributes"]
disable_api_termination = true
}
{% endfor %}
"""
def tf_generate(self):
self.tf_write(
self.template,
groups=Group.query.filter(
Group.eotk == True,
Group.destroyed == None
).all(),
global_namespace=app.config['GLOBAL_NAMESPACE'],
**{
k: app.config[k.upper()]
for k in self.template_parameters
}
)
def tf_posthook(self, *, prehook_result: Any = None) -> None:
state = self.tf_show()
for g in state["values"]["root_module"]["child_modules"]:
if g["address"].startswith("module.eotk_"):
group_id = int(g["address"][len("module.eotk_"):])
for i in g["child_modules"]:
if ".module.instance_" in i["address"]:
instance = int(i["address"][-1])
region = "us-east-2" if instance == 1 else "eu-central-1"
for s in i["child_modules"]:
if s["address"].endswith(".module.instance"):
for x in s["resources"]:
if x["address"].endswith(".module.instance.aws_instance.default[0]"):
update_eotk_instance(group_id, region, x['values']['id'])
db.session.commit()
with app.app_context():
auto = EotkAWSAutomation()
auto.tf_posthook()

View file

@ -0,0 +1,46 @@
"""add eotk provider
Revision ID: 7ecfb305d243
Revises: 7155ba7dec60
Create Date: 2022-05-13 15:34:59.922410
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '7ecfb305d243'
down_revision = '7155ba7dec60'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('eotk_instance',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('added', sa.DateTime(), nullable=False),
sa.Column('updated', sa.DateTime(), nullable=False),
sa.Column('deprecated', sa.DateTime(), nullable=True),
sa.Column('deprecation_reason', sa.String(), nullable=True),
sa.Column('destroyed', sa.DateTime(), nullable=True),
sa.Column('group_id', sa.Integer(), nullable=False),
sa.Column('provider', sa.String(length=20), nullable=False),
sa.Column('region', sa.String(length=20), nullable=False),
sa.Column('instance_id', sa.String(length=255), nullable=True),
sa.ForeignKeyConstraint(['group_id'], ['group.id'], name=op.f('fk_eotk_instance_group_id_group')),
sa.PrimaryKeyConstraint('id', name=op.f('pk_eotk_instance'))
)
with op.batch_alter_table('eotk', schema=None) as batch_op:
batch_op.add_column(sa.Column('provider', sa.String(length=20), nullable=False))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('eotk', schema=None) as batch_op:
batch_op.drop_column('provider')
op.drop_table('eotk_instance')
# ### end Alembic commands ###