2022-03-10 14:26:22 +00:00
|
|
|
import datetime
|
2022-05-16 11:44:03 +01:00
|
|
|
from typing import Iterable, Optional, Any, List
|
2022-03-10 14:26:22 +00:00
|
|
|
|
|
|
|
from app import app
|
|
|
|
from app.extensions import db
|
2022-04-22 14:01:16 +01:00
|
|
|
from app.models.bridges import BridgeConf, Bridge
|
|
|
|
from app.models.base import Group
|
2022-05-08 17:20:04 +01:00
|
|
|
from app.terraform.terraform import TerraformAutomation
|
2022-03-10 14:26:22 +00:00
|
|
|
|
|
|
|
|
2022-05-08 17:20:04 +01:00
|
|
|
class BridgeAutomation(TerraformAutomation):
|
2022-05-16 11:44:03 +01:00
|
|
|
template: str
|
|
|
|
"""
|
|
|
|
Terraform configuration template using Jinja 2.
|
|
|
|
"""
|
|
|
|
|
|
|
|
template_parameters: List[str]
|
|
|
|
"""
|
|
|
|
List of parameters to be read from the application configuration for use
|
|
|
|
in the templating of the Terraform configuration.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def create_missing(self) -> None:
|
2022-05-01 16:23:45 +01:00
|
|
|
bridgeconfs: Iterable[BridgeConf] = BridgeConf.query.filter(
|
|
|
|
BridgeConf.provider == self.provider,
|
|
|
|
BridgeConf.destroyed == None
|
2022-03-10 14:26:22 +00:00
|
|
|
).all()
|
|
|
|
for bridgeconf in bridgeconfs:
|
|
|
|
active_bridges = Bridge.query.filter(
|
|
|
|
Bridge.conf_id == bridgeconf.id,
|
|
|
|
Bridge.deprecated == None
|
|
|
|
).all()
|
|
|
|
if len(active_bridges) < bridgeconf.number:
|
|
|
|
for i in range(bridgeconf.number - len(active_bridges)):
|
|
|
|
bridge = Bridge()
|
|
|
|
bridge.conf_id = bridgeconf.id
|
|
|
|
bridge.added = datetime.datetime.utcnow()
|
|
|
|
bridge.updated = datetime.datetime.utcnow()
|
|
|
|
db.session.add(bridge)
|
|
|
|
elif len(active_bridges) > bridgeconf.number:
|
|
|
|
active_bridge_count = len(active_bridges)
|
|
|
|
for bridge in active_bridges:
|
2022-05-09 08:11:26 +01:00
|
|
|
bridge.deprecate(reason="redundant")
|
2022-03-10 14:26:22 +00:00
|
|
|
active_bridge_count -= 1
|
|
|
|
if active_bridge_count == bridgeconf.number:
|
|
|
|
break
|
2022-05-01 16:23:45 +01:00
|
|
|
db.session.commit()
|
2022-03-10 14:26:22 +00:00
|
|
|
|
2022-05-16 11:44:03 +01:00
|
|
|
def destroy_expired(self) -> None:
|
2022-03-10 14:26:22 +00:00
|
|
|
cutoff = datetime.datetime.utcnow() - datetime.timedelta(days=0)
|
|
|
|
bridges = [b for b in Bridge.query.filter(
|
|
|
|
Bridge.destroyed == None,
|
|
|
|
Bridge.deprecated < cutoff
|
|
|
|
).all() if b.conf.provider == self.provider]
|
|
|
|
for bridge in bridges:
|
|
|
|
bridge.destroy()
|
2022-05-01 16:23:45 +01:00
|
|
|
db.session.commit()
|
2022-03-10 14:26:22 +00:00
|
|
|
|
2022-05-08 17:20:04 +01:00
|
|
|
def tf_prehook(self) -> Optional[Any]:
|
|
|
|
self.create_missing()
|
|
|
|
self.destroy_expired()
|
2022-05-16 11:44:03 +01:00
|
|
|
return None
|
2022-05-08 17:20:04 +01:00
|
|
|
|
2022-05-16 11:44:03 +01:00
|
|
|
def tf_generate(self) -> None:
|
2022-05-08 17:20:04 +01:00
|
|
|
self.tf_write(
|
2022-03-10 14:26:22 +00:00
|
|
|
self.template,
|
|
|
|
groups=Group.query.all(),
|
|
|
|
bridgeconfs=BridgeConf.query.filter(
|
|
|
|
BridgeConf.destroyed == None,
|
|
|
|
BridgeConf.provider == self.provider
|
|
|
|
).all(),
|
|
|
|
global_namespace=app.config['GLOBAL_NAMESPACE'],
|
|
|
|
**{
|
|
|
|
k: app.config[k.upper()]
|
|
|
|
for k in self.template_parameters
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-05-08 17:20:04 +01:00
|
|
|
def tf_posthook(self, *, prehook_result: Any = None) -> None:
|
|
|
|
outputs = self.tf_output()
|
2022-03-10 14:26:22 +00:00
|
|
|
for output in outputs:
|
|
|
|
if output.startswith('bridge_hashed_fingerprint_'):
|
|
|
|
parts = outputs[output]['value'].split(" ")
|
|
|
|
if len(parts) < 2:
|
|
|
|
continue
|
|
|
|
bridge = Bridge.query.filter(Bridge.id == output[len('bridge_hashed_fingerprint_'):]).first()
|
|
|
|
bridge.nickname = parts[0]
|
|
|
|
bridge.hashed_fingerprint = parts[1]
|
|
|
|
bridge.terraform_updated = datetime.datetime.utcnow()
|
|
|
|
if output.startswith('bridge_bridgeline_'):
|
|
|
|
parts = outputs[output]['value'].split(" ")
|
|
|
|
if len(parts) < 4:
|
|
|
|
continue
|
|
|
|
bridge = Bridge.query.filter(Bridge.id == output[len('bridge_bridgeline_'):]).first()
|
|
|
|
del(parts[3])
|
|
|
|
bridge.bridgeline = " ".join(parts)
|
|
|
|
bridge.terraform_updated = datetime.datetime.utcnow()
|
|
|
|
db.session.commit()
|