Skip to content

Commit

Permalink
Make remote image tags unique to the deployment (#838)
Browse files Browse the repository at this point in the history
Reviewed-on: https://git.vdb.to/cerc-io/stack-orchestrator/pulls/838
Reviewed-by: Thomas E Lackey <[email protected]>
Co-authored-by: David Boreham <[email protected]>
Co-committed-by: David Boreham <[email protected]>
  • Loading branch information
dboreham authored and David Boreham committed Jun 13, 2024
1 parent 4acb063 commit 3fb025b
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 10 deletions.
29 changes: 22 additions & 7 deletions stack_orchestrator/deploy/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,29 @@ def _image_needs_pushed(image: str):
return image.endswith(":local")


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)
image_name_with_version = major_parts[1] if 2 == len(major_parts) else major_parts[0]
(image_name, image_version) = image_name_with_version.split(":")
if image_version == "local":
return f"{remote_repo_url}/{image_name}:deploy"
else:
return image


# Note: do not add any calls this function
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)
remote_tag = _remote_tag_for_image(local_tag, remote_repo_url)
result = docker.manifest.inspect(remote_tag)
return True if result else False
except Exception: # noqa: E722
return False


# Note: do not add any calls this function
def add_tags_to_image(remote_repo_url: str, local_tag: str, *additional_tags):
if not additional_tags:
return
Expand All @@ -47,18 +60,20 @@ def add_tags_to_image(remote_repo_url: str, local_tag: str, *additional_tags):
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]
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):
def remote_tag_for_image_unique(image: str, remote_repo_url: str, deployment_id: str):
# Turns image tags of the form: foo/bar:local into remote.repo/org/bar:deploy
major_parts = image.split("/", 2)
image_name_with_version = major_parts[1] if 2 == len(major_parts) else major_parts[0]
(image_name, image_version) = image_name_with_version.split(":")
if image_version == "local":
return f"{remote_repo_url}/{image_name}:deploy"
# Salt the tag with part of the deployment id to make it unique to this deployment
deployment_tag = deployment_id[0, 7]
return f"{remote_repo_url}/{image_name}:deploy-{deployment_tag}"
else:
return image

Expand All @@ -73,14 +88,14 @@ def push_images_operation(command_context: DeployCommandContext, deployment_cont
docker = DockerClient()
for image in images:
if _image_needs_pushed(image):
remote_tag = remote_tag_for_image(image, remote_repo_url)
remote_tag = remote_tag_for_image_unique(image, remote_repo_url, deployment_context.id)
if opts.o.verbose:
print(f"Tagging {image} to {remote_tag}")
docker.image.tag(image, remote_tag)
# Run docker push commands to upload
for image in images:
if _image_needs_pushed(image):
remote_tag = remote_tag_for_image(image, remote_repo_url)
remote_tag = remote_tag_for_image_unique(image, remote_repo_url, deployment_context.id)
if opts.o.verbose:
print(f"Pushing image {remote_tag}")
docker.image.push(remote_tag)
9 changes: 6 additions & 3 deletions stack_orchestrator/deploy/k8s/cluster_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from stack_orchestrator.deploy.deploy_util import parsed_pod_files_map_from_file_names, images_for_deployment
from stack_orchestrator.deploy.deploy_types import DeployEnvVars
from stack_orchestrator.deploy.spec import Spec, Resources, ResourceLimits
from stack_orchestrator.deploy.images import remote_tag_for_image
from stack_orchestrator.deploy.images import remote_tag_for_image_unique

DEFAULT_VOLUME_RESOURCES = Resources({
"reservations": {"storage": "2Gi"}
Expand Down Expand Up @@ -326,8 +326,11 @@ def get_deployment(self, image_pull_policy: str = None):
if opts.o.debug:
print(f"Merged envs: {envs}")
# Re-write the image tag for remote deployment
image_to_use = remote_tag_for_image(
image, self.spec.get_image_registry()) if self.spec.get_image_registry() is not None else image
# Note self.app_name has the same value as deployment_id
image_to_use = remote_tag_for_image_unique(
image,
self.spec.get_image_registry(),
self.app_name) if self.spec.get_image_registry() is not None else image
volume_mounts = volume_mounts_for_service(self.parsed_pod_yaml_map, service_name)
container = client.V1Container(
name=container_name,
Expand Down

0 comments on commit 3fb025b

Please sign in to comment.