eotk: import instance information from terraform
This commit is contained in:
parent
567fcce0bb
commit
ce520b87a5
11 changed files with 233 additions and 74 deletions
|
@ -12,7 +12,7 @@ from app.terraform.block_bridge_github import BlockBridgeGitHubAutomation
|
||||||
from app.terraform.block_external import BlockExternalAutomation
|
from app.terraform.block_external import BlockExternalAutomation
|
||||||
from app.terraform.block_ooni import BlockOONIAutomation
|
from app.terraform.block_ooni import BlockOONIAutomation
|
||||||
from app.terraform.block_roskomsvoboda import BlockRoskomsvobodaAutomation
|
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_azure_cdn import AlarmProxyAzureCdnAutomation
|
||||||
from app.terraform.alarms.proxy_cloudfront import AlarmProxyCloudfrontAutomation
|
from app.terraform.alarms.proxy_cloudfront import AlarmProxyCloudfrontAutomation
|
||||||
from app.terraform.alarms.proxy_http_status import AlarmProxyHTTPStatusAutomation
|
from app.terraform.alarms.proxy_http_status import AlarmProxyHTTPStatusAutomation
|
||||||
|
@ -41,7 +41,7 @@ jobs = {
|
||||||
BridgeGandiAutomation,
|
BridgeGandiAutomation,
|
||||||
BridgeHcloudAutomation,
|
BridgeHcloudAutomation,
|
||||||
BridgeOvhAutomation,
|
BridgeOvhAutomation,
|
||||||
EotkAutomation,
|
EotkAWSAutomation,
|
||||||
ListGithubAutomation,
|
ListGithubAutomation,
|
||||||
ListGitlabAutomation,
|
ListGitlabAutomation,
|
||||||
ListS3Automation,
|
ListS3Automation,
|
||||||
|
|
|
@ -13,6 +13,7 @@ class Onion(AbstractConfiguration):
|
||||||
class Eotk(AbstractResource):
|
class Eotk(AbstractResource):
|
||||||
group_id = db.Column(db.Integer(), db.ForeignKey("group.id"), nullable=False)
|
group_id = db.Column(db.Integer(), db.ForeignKey("group.id"), nullable=False)
|
||||||
instance_id = db.Column(db.String(100), nullable=True)
|
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)
|
region = db.Column(db.String(20), nullable=False)
|
||||||
|
|
||||||
group = db.relationship("Group", back_populates="eotks")
|
group = db.relationship("Group", back_populates="eotks")
|
||||||
|
|
|
@ -10,6 +10,7 @@ from app.portal.list import NewMirrorListForm
|
||||||
from app.portal.automation import bp as automation
|
from app.portal.automation import bp as automation
|
||||||
from app.portal.bridgeconf import bp as bridgeconf
|
from app.portal.bridgeconf import bp as bridgeconf
|
||||||
from app.portal.bridge import bp as bridge
|
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.group import bp as group
|
||||||
from app.portal.list import bp as list_
|
from app.portal.list import bp as list_
|
||||||
from app.portal.origin import bp as origin
|
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(automation, url_prefix="/automation")
|
||||||
portal.register_blueprint(bridgeconf, url_prefix="/bridgeconf")
|
portal.register_blueprint(bridgeconf, url_prefix="/bridgeconf")
|
||||||
portal.register_blueprint(bridge, url_prefix="/bridge")
|
portal.register_blueprint(bridge, url_prefix="/bridge")
|
||||||
|
portal.register_blueprint(eotk, url_prefix="/eotk")
|
||||||
portal.register_blueprint(group, url_prefix="/group")
|
portal.register_blueprint(group, url_prefix="/group")
|
||||||
portal.register_blueprint(list_, url_prefix="/list")
|
portal.register_blueprint(list_, url_prefix="/list")
|
||||||
portal.register_blueprint(origin, url_prefix="/origin")
|
portal.register_blueprint(origin, url_prefix="/origin")
|
||||||
|
|
16
app/portal/eotk.py
Normal file
16
app/portal/eotk.py
Normal 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)
|
|
@ -132,8 +132,8 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link{% if section == "eotk" %} active{% endif %} disabled text-secondary"
|
<a class="nav-link{% if section == "eotk" %} active{% endif %}"
|
||||||
href="#">
|
href="{{ url_for("portal.eotk.eotk_list") }}">
|
||||||
{{ icon("server") }} EOTK Instances
|
{{ icon("server") }} EOTK Instances
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{% extends "base.html.j2" %}
|
{% 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 %}
|
groups_table, mirrorlists_table, origins_table, origin_onion_table, onions_table, proxies_table %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
|
@ -55,8 +55,58 @@
|
||||||
</div>
|
</div>
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro eotk_table(eotks) %}
|
{% macro eotk_table(instances) %}
|
||||||
<div class="alert alert-danger">Not implemented yet.</div>
|
<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 %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro automations_table(automations) %}
|
{% macro automations_table(automations) %}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
)
|
|
0
app/terraform/eotk/__init__.py
Normal file
0
app/terraform/eotk/__init__.py
Normal file
110
app/terraform/eotk/aws.py
Normal file
110
app/terraform/eotk/aws.py
Normal 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()
|
46
migrations/versions/7ecfb305d243_add_eotk_provider.py
Normal file
46
migrations/versions/7ecfb305d243_add_eotk_provider.py
Normal 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 ###
|
Loading…
Add table
Add a link
Reference in a new issue