Skip to content

Commit

Permalink
Merge pull request #12 from hiddeco/helmrelease-registry-entry
Browse files Browse the repository at this point in the history
Support HelmReleases with separate registry entry
  • Loading branch information
squaremo authored Jul 1, 2019
2 parents a51ef05 + 84ca12c commit 1465a29
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 37 deletions.
58 changes: 45 additions & 13 deletions kubeyaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import argparse
import functools
import collections
import re
from ruamel.yaml import YAML

# The container name, by proclamation, used for an image supplied in a
Expand Down Expand Up @@ -167,9 +168,11 @@ def mappings(values):
def fluxhelmrelease_containers(manifest):
def get_image(values):
image = values['image']
if isinstance(image, collections.Mapping) and 'repository' in image and 'tag' in image:
if isinstance(image, collections.Mapping) and 'repository' in image:
values = image
image = image['repository']
if 'registry' in values and values['registry'] != '':
image = '%s/%s' % (values['registry'], image)
if 'tag' in values and values['tag'] != '':
image = '%s:%s' % (image, values['tag'])
return image
Expand All @@ -193,27 +196,56 @@ def get_image(values):
return containers

def set_fluxhelmrelease_container(manifest, container, replace):
# The logic within this method (almost) equals:
# https://github.com/weaveworks/flux/blob/5b15a94397d58b69a2daedae3bcc377e4901435b/image/image.go#L136
def parse_ref():
reg, im, tag = '', '', ''
try:
segments = replace.split('/')
if len(segments) == 1:
im = replace
elif len(segments) == 2:
domainComponent = '([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])'
domain = '(localhost|(%s([.]%s)+))(:[0-9]+)?' % (domainComponent, domainComponent)
if re.fullmatch(domain, segments[0]):
reg = segments[0]
im = segments[1]
else:
im = replace
else:
reg = segments[0]
im = '/'.join(segments[1:])

segments = im.split(':')
if len(segments) == 2:
im, tag = segments
elif len(segments) == 3:
im = ':'.join(segments[:2])
tag = segments[2]
except ValueError:
pass
return reg, im, tag

def set_image(values):
image = values['image']
imageKey = 'image'

if isinstance(image, collections.Mapping) and 'repository' in image and 'tag' in image:
if isinstance(image, collections.Mapping) and 'repository' in image:
values = image
imageKey = 'repository'

if 'tag' in values:
im, tag = replace, ''
try:
segments = replace.split(':')
if len(segments) == 2:
im, tag = segments
elif len(segments) == 3:
im = ':'.join(segments[:2])
tag = segments[2]
except ValueError:
pass
reg, im, tag = parse_ref()

if 'registry' in values and 'tag' in values:
values['registry'] = reg
values[imageKey] = im
values['tag'] = tag
elif 'registry' in values:
values['registry'] = reg
values[imageKey] = ':'.join(filter(None, [im, tag]))
elif 'tag' in values:
values[imageKey] = '/'.join(filter(None, [reg, im]))
values['tag'] = tag
else:
values[imageKey] = replace

Expand Down
56 changes: 32 additions & 24 deletions test_kubeyaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@
def strip(s):
return s.strip()

@composite
def image_components(draw):
bits = draw(strats.lists(
elements=strats.text(alphabet=alphanumerics, min_size=1),
min_size=1, max_size=16))
s = bits[0]
for c in bits[1:]:
sep = draw(image_separators)
s = s + sep + c
return s

# I only want things that will got on one line, so make my own printable alphabet
printable = string.ascii_letters + string.digits + string.punctuation + ' '

Expand All @@ -25,8 +36,9 @@ def strip(s):
host_components = strats.from_regex(r"^[a-zA-Z0-9]([a-zA-Z0-9-]{0,125}[a-zA-Z0-9])?$").map(strip)
port_numbers = strats.integers(min_value=1, max_value=32767)

hostnames_without_port = strats.builds('.'.join,
strats.lists(elements=host_components, min_size=1, max_size=6))
hostnames_without_port = strats.just('localhost') | \
strats.builds('.'.join,
strats.lists(elements=host_components, min_size=2, max_size=6))

hostnames_with_port = strats.builds(
lambda h, p: str(h)+':'+str(p),
Expand All @@ -41,31 +53,20 @@ def strip(s):
strats.just('__') | \
strats.integers(min_value=1, max_value=5).map(lambda n: '-' * n)

image_tags = strats.from_regex(r"^[a-z][\w.-]{0,127}$").map(strip)

@composite
def image_components(draw):
bits = draw(strats.lists(
elements=strats.text(alphabet=alphanumerics, min_size=1),
min_size=1, max_size=16))
s = bits[0]
for c in bits[1:]:
sep = draw(image_separators)
s = s + sep + c
return s

host_segments = strats.just([]) | hostnames.map(lambda x: [x])
image_names = strats.builds(lambda host, cs: '/'.join(host + cs),
host_segments,
strats.lists(elements=image_components(),
min_size=1, max_size=6))

# This results in realistic image refs
exact_image_names = strats.builds('/'.join, strats.lists(elements=image_components(), min_size=1, max_size=6))
# This is somewhat faster, if we don't care about having realistic
# image refs
sloppy_image_names = strats.text(string.ascii_letters + '-/_', min_size=1, max_size=255)
# NB override image_names
image_names = strats.builds(lambda host, cs: '/'.join(host + [cs]),
host_segments, sloppy_image_names)
sloppy_image_names = strats.text(string.ascii_letters + '-/_', min_size=1, max_size=255).map(strip)
sloppy_image_names_with_host = strats.builds(
lambda host, name: host + '/' + name,
hostnames, sloppy_image_names)
image_tags = strats.from_regex(r"^[a-z][\w.-]{0,127}$").map(strip)

# NB select the default image name format to use
image_names = sloppy_image_names | sloppy_image_names_with_host

images_with_tag = strats.builds(
lambda name, tag: name + ':' + tag,
Expand Down Expand Up @@ -203,9 +204,15 @@ def combine_containers(toplevel, subfields):
# {'foo': {'image': 'foobar', 'tag': 'v1'}, '_containers': [{'foo': 'foobar:v1'}]}
image_only_values = (image_names | images_with_tag).map(lambda image: {'image': image, '_containers': [{kubeyaml.FHR_CONTAINER: image}]})
image_tag_values = strats.builds(lambda n, t: {'image': n, 'tag': t, '_containers': [{kubeyaml.FHR_CONTAINER: '%s:%s' % (n, t)}]}, image_names, image_tags)
image_registry_values = strats.builds(lambda r, n, t: {'registry': r, 'image': '%s:%s' % (n, t), '_containers': [{kubeyaml.FHR_CONTAINER: '%s/%s:%s' % (r, n, t)}]}, hostnames, exact_image_names, image_tags)
image_registry_tag_values = strats.builds(lambda r, n, t: {'registry': r, 'image': n, 'tag': t, '_containers': [{kubeyaml.FHR_CONTAINER: '%s/%s:%s' % (r, n, t)}]}, hostnames, exact_image_names, image_tags)
image_obj_values = strats.builds(lambda n, t: {'image': {'repository': n, 'tag': t}, '_containers': [{kubeyaml.FHR_CONTAINER: '%s:%s' % (n, t)}]}, image_names, image_tags)
image_obj_repository_values = (image_names | images_with_tag).map(lambda image: {'image': {'repository': image}, '_containers': [{kubeyaml.FHR_CONTAINER: image}]})
image_obj_registry_tag_values = strats.builds(lambda r, n, t: {'image': {'registry': r, 'repository': n, 'tag': t}, '_containers': [{kubeyaml.FHR_CONTAINER: '%s/%s:%s' % (r, n, t)}]}, hostnames, exact_image_names, image_tags)
image_obj_registry_repository_values = strats.builds(lambda r, n, t: {'image': {'registry': r, 'repository': '%s:%s' % (n, t)}, '_containers': [{kubeyaml.FHR_CONTAINER: '%s/%s:%s' % (r, n, t)}]}, hostnames, exact_image_names, image_tags)

# One of the above
toplevel_image_values = image_only_values | image_tag_values | image_obj_values
toplevel_image_values = image_only_values | image_tag_values | image_registry_values | image_registry_tag_values | image_obj_values | image_obj_registry_tag_values | image_obj_registry_repository_values
# Some of the above, in fields
named_image_values = strats.dictionaries(keys=dns_labels, values=toplevel_image_values).map(lift_containers)
# Combo of top-level image, and images in subfields
Expand Down Expand Up @@ -299,6 +306,7 @@ def test_match_self(man):
spec = Spec.from_resource(man)
assert kubeyaml.match_manifest(spec, man)

@settings(suppress_health_check=[HealthCheck.too_slow])
@given(workload_resources, strats.data())
def test_find_container(man, data):
cs = kubeyaml.containers(man)
Expand Down

0 comments on commit 1465a29

Please sign in to comment.