Add deployment update and deploy-webapp-from-registry commands. #676

Merged
telackey merged 23 commits from telackey/deployer into main 2023-12-14 03:02:34 +00:00
2 changed files with 95 additions and 37 deletions
Showing only changes of commit a6e4b6c62d - Show all commits

View File

@ -26,7 +26,8 @@ import click
from stack_orchestrator.deploy.webapp import deploy_webapp
from stack_orchestrator.deploy.webapp.util import (AttrDict, LaconicRegistryClient,
build_container_image, push_container_image,
file_hash, deploy_to_k8s, publish_deployment)
file_hash, deploy_to_k8s, publish_deployment,
hostname_for_deployment_request, generate_hostname_for_app)
def process_app_deployment_request(
@ -54,6 +55,26 @@ def process_app_deployment_request(
container_tag = "%s:local" % app.attributes.name.replace("@", "")
# 3. check ownership of existing dnsrecord vs this request
# TODO: Support foreign DNS
dns_crn = f"{dns_record_namespace}/{fqdn}"
dns_record = laconic.get_record(dns_crn)
if dns_record:
dns_record_owners = dns_record.owners
dns_request_owners = []
if dns_record.request:
prev_request = laconic.get_record(dns_record.request, require=True)
dns_request_owners = prev_request.owners
owner_match = None
for owner in app_deployment_request.owners:
if owner in dns_request_owners or owner in dns_record_owners:
owner_match = owner
if owner_match:
print("Matched DnsRecord ownership to", owner)
else:
raise Exception("Unable to confirm ownership of DnsRecord %s for request %s" %
(dns_record.id, app_deployment_request.id))
# 4. get build and runtime config from request
env_filename = None
@ -109,34 +130,13 @@ def process_app_deployment_request(
app,
deployment_record,
app_deployment_crn,
dns_record,
dns_crn,
deployment_dir,
app_deployment_request
)
def hostname_for_deployment_request(app_deployment_request, laconic):
dns_name = app_deployment_request.attributes.dns
if not dns_name:
app = laconic.get_record(app_deployment_request.attributes.application, require=True)
dns_name = generate_hostname_for_app(app)
elif dns_name.startswith("crn://"):
record = laconic.get_record(dns_name, require=True)
dns_name = record.attributes.name
return dns_name
def generate_hostname_for_app(app):
last_part = app.attributes.name.split("/")[-1]
m = hashlib.sha256()
m.update(app.attributes.name.encode())
m.update(b"|")
if isinstance(app.attributes.repository, list):
m.update(app.attributes.repository[0].encode())
else:
m.update(app.attributes.repository.encode())
return "%s-%s" % (last_part, m.hexdigest()[0:10])
def load_known_requests(filename):
if filename and os.path.exists(filename):
return json.load(open(filename, "r"))

View File

@ -20,6 +20,8 @@ import random
import subprocess
import sys
import tempfile
import uuid
import yaml
@ -219,28 +221,84 @@ def deploy_to_k8s(deploy_record, deployment_dir):
result.check_returncode()
def publish_deployment(laconic: LaconicRegistryClient, app_record, deploy_record, deployment_crn, deployment_dir, app_deployment_request=None):
def publish_deployment(laconic: LaconicRegistryClient,
app_record,
deploy_record,
deployment_crn,
dns_record,
dns_crn,
deployment_dir,
app_deployment_request=None):
if not deploy_record:
version = "0.0.1"
deploy_ver = "0.0.1"
else:
version = "0.0.%d" % (int(deploy_record["attributes"]["version"].split(".")[-1]) + 1)
deploy_ver = "0.0.%d" % (int(deploy_record.attributes.version.split(".")[-1]) + 1)
if not dns_record:
dns_ver = "0.0.1"
else:
dns_ver = "0.0.%d" % (int(dns_record.attributes.version.split(".")[-1]) + 1)
spec = yaml.full_load(open(os.path.join(deployment_dir, "spec.yml")))
hostname = spec["network"]["http-proxy"][0]["host-name"]
fqdn = spec["network"]["http-proxy"][0]["host-name"]
record = {
uniq = uuid.uuid4()
new_dns_record = {
"record": {
"type": "ApplicationDeploymentRecord",
"version": version,
"url": f"https://{hostname}",
"name": hostname,
"application": app_record["id"],
"type": "DnsRecord",
"version": dns_ver,
"name": fqdn,
"resource_type": "A",
"meta": {
"config": file_hash(os.path.join(deployment_dir, "config.env"))
"so": uniq.hex
},
}
}
if app_deployment_request:
record["record"]["request"] = app_deployment_request.id
new_dns_record["record"]["request"] = app_deployment_request.id
return laconic.publish(record, [deployment_crn])
dns_id = laconic.publish(new_dns_record, [dns_crn])
new_deployment_record = {
"record": {
"type": "ApplicationDeploymentRecord",
"version": deploy_ver,
"url": f"https://{fqdn}",
"name": app_record.attributes.name,
"application": app_record.id,
"dns": dns_id,
"meta": {
"config": file_hash(os.path.join(deployment_dir, "config.env")),
"so": uniq.hex
},
}
}
if app_deployment_request:
new_deployment_record["record"]["request"] = app_deployment_request.id
deployment_id = laconic.publish(new_deployment_record, [deployment_crn])
return {"dns": dns_id, "deployment": deployment_id}
def hostname_for_deployment_request(app_deployment_request, laconic):
dns_name = app_deployment_request.attributes.dns
if not dns_name:
app = laconic.get_record(app_deployment_request.attributes.application, require=True)
dns_name = generate_hostname_for_app(app)
elif dns_name.startswith("crn://"):
record = laconic.get_record(dns_name, require=True)
dns_name = record.attributes.name
return dns_name
def generate_hostname_for_app(app):
last_part = app.attributes.name.split("/")[-1]
m = hashlib.sha256()
m.update(app.attributes.name.encode())
m.update(b"|")
if isinstance(app.attributes.repository, list):
m.update(app.attributes.repository[0].encode())
else:
m.update(app.attributes.repository.encode())
return "%s-%s" % (last_part, m.hexdigest()[0:10])