From 027c37bb3dc0ce11ee62eadac8c37d3742b53f6f Mon Sep 17 00:00:00 2001 From: Nick Santos Date: Thu, 11 Apr 2024 08:33:04 -0400 Subject: [PATCH] helm_resource: allow images to be injected twice (#569) fixes https://github.com/tilt-dev/tilt-extensions/issues/528 Signed-off-by: Nick Santos --- helm_resource/README.md | 22 +++++++++------ helm_resource/Tiltfile | 44 ++++++++++++++++++++++-------- helm_resource/helm-apply-helper.py | 41 +++++++++++++++------------- 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/helm_resource/README.md b/helm_resource/README.md index 2cb50331d..5ff988987 100644 --- a/helm_resource/README.md +++ b/helm_resource/README.md @@ -59,17 +59,21 @@ reference. how to build one of these images, this will be an error. `image_keys`: A list of specifications for how to inject images into the -chart. Must be the same length as `image_deps`. There are two common patterns. +chart. Must be the same length as `image_deps`. Examples of accepted values: -- If your chart accepts an image as a single tagged image reference, specify the key as a string. +- `'image'`: A chart that accepts a single tagged image reference, passed as a + string. -- If your chart accepts an image as a 'repository' and a 'tag', spectify the key - as a tuple ('image.repository', 'image.tag'). This is how charts created with - `helm create` are structured. - -- If your chart accepts an image as a 'registry', 'repository' and a 'tag', specify the key - as a tuple ('image.registry', 'image.repository', 'image.tag'). This is another common pattern used - by many charts. +- `('image.repository', 'image.tag')`: A chart that accepts an image as a + separate repository and tag, passed as a 2-element tuple. This is how charts + created with `helm create` are structured. + +- `('image.registry', 'image.repository', 'image.tag')`: A chart that accepts + an image as a 'registry', 'repository' and a 'tag', passed as a 3-element tuple. + This is another common pattern used by many charts. + +- `[('image.repository', 'image.tag'), ('initImage.repository', 'initImage.tag')]`: + A chart that uses the same image in two different values. Passed as a list. `flags`: Additional flags to pass to `helm install`. For example: diff --git a/helm_resource/Tiltfile b/helm_resource/Tiltfile index e2b70a3aa..f3f64b240 100644 --- a/helm_resource/Tiltfile +++ b/helm_resource/Tiltfile @@ -95,20 +95,15 @@ def helm_resource( if flags: apply_cmd.extend(flags) + dupe_deps = {} for i in range(len(image_deps)): + if image_deps[i] in dupe_deps: + fail(('helm_resource: image_deps should be unique. Found duplicate: %s\n' % image_deps[i]) + + (' If you need to inject an image twice, the corresponding element of image_keys can be a list of values')) + dupe_deps[image_deps[i]] = True + key = image_keys[i] - if type(key) == 'string': - env['TILT_IMAGE_KEY_%s' % i] = key - elif type(key) == 'tuple': - if len(key) == 2: - env['TILT_IMAGE_KEY_REPO_%s' % i] = key[0] - env['TILT_IMAGE_KEY_TAG_%s' % i] = key[1] - if len(key) == 3: - env['TILT_IMAGE_KEY_REGISTRY_%s' % i] = key[0] - env['TILT_IMAGE_KEY_REPO_%s' % i] = key[1] - env['TILT_IMAGE_KEY_TAG_%s' % i] = key[2] - else: - fail("invalid argument to image_keys at %s: %s" % (i, type(key))) + _set_image_env_helper_list(env, key, i) k8s_custom_deploy( name, @@ -168,3 +163,28 @@ def helm_repo( args.extend(['--password', password]) local_resource(resource_name, args, allow_parallel=True, **kwargs) + +# Helper functions for setting env variables for images. +def _set_image_env_helper_list(env, key, i): + if type(key) == 'list': + env['TILT_IMAGE_KEY_COUNT_%s' % i] = '%s' % len(key) + for j in range(len(key)): + _set_image_env_helper_item(env, key[j], i, '%s_%s' % (i, j)) + else: + env['TILT_IMAGE_KEY_COUNT_%s' % i] = '1' + _set_image_env_helper_item(env, key, i, '%s_0' % i) + +# Helper functions for setting env variables for images. +def _set_image_env_helper_item(env, key, i, suffix): + if type(key) == 'string': + env['TILT_IMAGE_KEY_%s' % suffix] = key + elif type(key) == 'tuple': + if len(key) == 2: + env['TILT_IMAGE_KEY_REPO_%s' % suffix] = key[0] + env['TILT_IMAGE_KEY_TAG_%s' % suffix] = key[1] + if len(key) == 3: + env['TILT_IMAGE_KEY_REGISTRY_%s' % suffix] = key[0] + env['TILT_IMAGE_KEY_REPO_%s' % suffix] = key[1] + env['TILT_IMAGE_KEY_TAG_%s' % suffix] = key[2] + else: + fail("invalid argument to image_keys at %s: %s" % (i, type(key))) diff --git a/helm_resource/helm-apply-helper.py b/helm_resource/helm-apply-helper.py index 63237e0e8..736e66534 100644 --- a/helm_resource/helm-apply-helper.py +++ b/helm_resource/helm-apply-helper.py @@ -22,28 +22,31 @@ def _parse_image_string(image: str) -> Dict: image_count = int(os.environ['TILT_IMAGE_COUNT']) for i in range(image_count): image = os.environ['TILT_IMAGE_%s' % i] - key = os.environ.get('TILT_IMAGE_KEY_%s' % i, '') - if key: - flags.extend(['--set', '%s=%s' % (key, image)]) - continue + count = int(os.environ['TILT_IMAGE_KEY_COUNT_%s' % i]) + for j in range(count): + suffix = '%s_%s' % (i, j) + key = os.environ.get('TILT_IMAGE_KEY_%s' % suffix, '') + if key: + flags.extend(['--set', '%s=%s' % (key, image)]) + continue - image_parts = _parse_image_string(image) - key0 = os.environ.get('TILT_IMAGE_KEY_REGISTRY_%s' % i, '') - key1 = os.environ.get('TILT_IMAGE_KEY_REPO_%s' % i, '') - key2 = os.environ.get('TILT_IMAGE_KEY_TAG_%s' % i, '') + image_parts = _parse_image_string(image) + key0 = os.environ.get('TILT_IMAGE_KEY_REGISTRY_%s' % suffix, '') + key1 = os.environ.get('TILT_IMAGE_KEY_REPO_%s' % suffix, '') + key2 = os.environ.get('TILT_IMAGE_KEY_TAG_%s' % suffix, '') - if image_parts['registry']: - if key0 != '': - # Image has a registry AND a specific helm key for the registry - flags.extend(['--set', '%s=%s' % (key0, image_parts["registry"]), - '--set', '%s=%s' % (key1, image_parts["repository"])]) + if image_parts['registry']: + if key0 != '': + # Image has a registry AND a specific helm key for the registry + flags.extend(['--set', '%s=%s' % (key0, image_parts["registry"]), + '--set', '%s=%s' % (key1, image_parts["repository"])]) + else: + # Image has a registry but does not have a specific helm key for registry + flags.extend(['--set', '%s=%s/%s' % (key1, image_parts["registry"], image_parts["repository"])]) else: - # Image has a registry but does not have a specific helm key for registry - flags.extend(['--set', '%s=%s/%s' % (key1, image_parts["registry"], image_parts["repository"])]) - else: - # Image does NOT have a registry component - flags.extend(['--set', '%s=%s' % (key1, image_parts["repository"])]) - flags.extend(['--set', '%s=%s' % (key2, image_parts["tag"])]) + # Image does NOT have a registry component + flags.extend(['--set', '%s=%s' % (key1, image_parts["repository"])]) + flags.extend(['--set', '%s=%s' % (key2, image_parts["tag"])]) install_cmd = ['helm', 'upgrade', '--install'] install_cmd.extend(flags)