From b0d003cc017d4a20ad3d24fb46174cb1525de5b2 Mon Sep 17 00:00:00 2001 From: Thomas E Lackey Date: Fri, 23 Feb 2024 18:52:37 -0600 Subject: [PATCH] Working --- stack_orchestrator/deploy/images.py | 15 ++++++++++++- .../webapp/deploy_webapp_from_registry.py | 22 +++++++++++++------ 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/stack_orchestrator/deploy/images.py b/stack_orchestrator/deploy/images.py index 78ce99db..77713d18 100644 --- a/stack_orchestrator/deploy/images.py +++ b/stack_orchestrator/deploy/images.py @@ -29,7 +29,7 @@ def _image_needs_pushed(image: str): return image.endswith(":local") -def remote_image_exists(local_tag: str, remote_repo_url: str): +def remote_image_exists(remote_repo_url: str, local_tag: str): docker = DockerClient() try: remote_tag = remote_tag_for_image(local_tag, remote_repo_url) @@ -39,6 +39,19 @@ def remote_image_exists(local_tag: str, remote_repo_url: str): return False +def add_tags_to_image(remote_repo_url: str, local_tag: str, *additional_tags): + if not additional_tags: + return + + if not remote_image_exists(remote_repo_url, local_tag): + raise Exception(f"{local_tag} does not exist in {remote_repo_url}") + + docker = DockerClient() + remote_tag = remote_tag_for_image(local_tag, remote_repo_url) + new_remote_tags = [remote_tag_for_image(tag, remote_repo_url) for tag in additional_tags] + docker.buildx.imagetools.create(sources=[remote_tag], tags=new_remote_tags) + + def remote_tag_for_image(image: str, remote_repo_url: str): # Turns image tags of the form: foo/bar:local into remote.repo/org/bar:deploy major_parts = image.split("/", 2) diff --git a/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py b/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py index aa40e792..3178a668 100644 --- a/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py +++ b/stack_orchestrator/deploy/webapp/deploy_webapp_from_registry.py @@ -12,6 +12,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import hashlib import json import os import shlex @@ -23,7 +24,7 @@ import uuid import click -from stack_orchestrator.deploy.images import remote_image_exists +from stack_orchestrator.deploy.images import remote_image_exists, add_tags_to_image from stack_orchestrator.deploy.webapp import deploy_webapp from stack_orchestrator.deploy.webapp.util import (LaconicRegistryClient, build_container_image, push_container_image, @@ -92,34 +93,41 @@ def process_app_deployment_request( deployment_record = laconic.get_record(app_deployment_crn) deployment_dir = os.path.join(deployment_parent_dir, fqdn) deployment_config_file = os.path.join(deployment_dir, "config.env") - deployment_container_tag = f"laconic-webapp/{app.id}:local" + deployment_container_unique_tag = "laconic-webapp/%s:local" % hashlib.md5(deployment_dir.encode()).hexdigest() + deployment_container_shared_tag = f"laconic-webapp/{app.id}:local" # b. check for deployment directory (create if necessary) if not os.path.exists(deployment_dir): if deployment_record: raise Exception("Deployment record %s exists, but not deployment dir %s. Please remove name." % (app_deployment_crn, deployment_dir)) print("deploy_webapp", deployment_dir) - deploy_webapp.create_deployment(ctx, deployment_dir, deployment_container_tag, + deploy_webapp.create_deployment(ctx, deployment_dir, deployment_container_unique_tag, f"https://{fqdn}", kube_config, image_registry, env_filename) elif env_filename: shutil.copyfile(env_filename, deployment_config_file) needs_k8s_deploy = False + built_images = False # 6. build container (if needed) if not deployment_record or deployment_record.attributes.application != app.id: # check if the image already exists - if force_rebuild or not remote_image_exists(deployment_container_tag, image_registry): + if force_rebuild or not remote_image_exists(image_registry, deployment_container_shared_tag): # TODO: pull from request extra_build_args = [] - build_container_image(app, deployment_container_tag, extra_build_args, log_file) + build_container_image(app, deployment_container_shared_tag, extra_build_args, log_file) push_container_image(deployment_dir, log_file) + built_images = True needs_k8s_deploy = True - # 7. update config (if needed) + # 7. Add tags (as needed) + if built_images or not remote_image_exists(image_registry, deployment_container_unique_tag): + add_tags_to_image(image_registry, deployment_container_shared_tag, deployment_container_unique_tag) + + # 8. update config (if needed) if not deployment_record or file_hash(deployment_config_file) != deployment_record.attributes.meta.config: needs_k8s_deploy = True - # 8. update k8s deployment + # 9. update k8s deployment if needs_k8s_deploy: print("Deploying to k8s") deploy_to_k8s(