Skip to content

Commit

Permalink
Address a few pieces of feedback from @ensonic (bazelbuild#71)
Browse files Browse the repository at this point in the history
Removes some of the friction from: bazelbuild#68
Fixes: bazelbuild#69
  • Loading branch information
mattmoor authored Nov 28, 2017
1 parent b28b5f1 commit 2cf2d16
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 53 deletions.
2 changes: 1 addition & 1 deletion examples/hellohttp/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ k8s_deploy(
name = "error-on-run",
images = {
# Simulate a typo
"us.gcr.io/not-my-porject/hello-http:staging": "//examples/hellohttp/go:server",
"hello-http_image": "//examples/hellohttp/go:server",
},
template = "deployment.yaml",
)
Expand Down
2 changes: 1 addition & 1 deletion examples/hellohttp/deployment.jsonnet
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ local container = import "../container.libsonnet";
deployment.Simple("hello-http-staging",
container.Simple(
"hello-http",
"us.gcr.io/not-my-project/hello-http:staging",
"hello-http-image",
8080))
2 changes: 1 addition & 1 deletion examples/hellohttp/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ spec:
spec:
containers:
- name: hello-http
image: us.gcr.io/not-my-project/hello-http:staging
image: hello-http-image
imagePullPolicy: Always
ports:
- containerPort: 8080
2 changes: 1 addition & 1 deletion examples/hellohttp/go/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ load("@k8s_deploy//:defaults.bzl", "k8s_deploy")
k8s_deploy(
name = "staging",
images = {
"us.gcr.io/not-my-project/hello-http:staging": ":server",
"hello-http-image": ":server",
},
template = "//examples/hellohttp:deployment.yaml",
)
2 changes: 1 addition & 1 deletion examples/hellohttp/java/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ load("@k8s_deploy//:defaults.bzl", "k8s_deploy")
k8s_deploy(
name = "staging",
images = {
"us.gcr.io/not-my-project/hello-http:staging": ":server",
"hello-http-image": ":server",
},
template = "//examples/hellohttp:deployment.json",
)
2 changes: 1 addition & 1 deletion examples/hellohttp/py/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ load("@k8s_deploy//:defaults.bzl", "k8s_deploy")
k8s_deploy(
name = "staging",
images = {
"us.gcr.io/not-my-project/hello-http:staging": ":server",
"hello-http-image": ":server",
},
template = "//examples/hellohttp:deployment.yaml",
)
28 changes: 12 additions & 16 deletions k8s/object.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,6 @@ def _deduplicate(iterable):
def _impl(ctx):
"""Core implementation of k8s_object."""

# Use expand_template with no substitutions as a glorified copy.
ctx.actions.expand_template(
template = ctx.file.template,
output = ctx.outputs.yaml,
substitutions = {},
)

all_inputs = []
image_specs = []
if ctx.attr.images:
Expand Down Expand Up @@ -98,7 +91,7 @@ def _impl(ctx):
template = ctx.file._template,
substitutions = {
"%{resolver}": _runfiles(ctx, ctx.executable._resolver),
"%{yaml}": _runfiles(ctx, ctx.outputs.yaml),
"%{yaml}": _runfiles(ctx, ctx.file.template),
"%{image_chroot}": image_chroot_arg,
"%{images}": " ".join([
"--image_spec=%s" % spec
Expand All @@ -110,7 +103,7 @@ def _impl(ctx):

return struct(runfiles = ctx.runfiles(files = [
ctx.executable._resolver,
ctx.outputs.yaml,
ctx.file.template,
] + list(ctx.attr._resolver.default_runfiles.files) + all_inputs))

def _resolve(ctx, string, output):
Expand Down Expand Up @@ -212,9 +205,6 @@ _k8s_object = rule(
),
} + _common_attrs + _layer_tools,
executable = True,
outputs = {
"yaml": "%{name}.yaml",
},
implementation = _impl,
)

Expand Down Expand Up @@ -272,7 +262,10 @@ _k8s_object_replace = rule(
_k8s_object_describe = rule(
attrs = {
"unresolved": attr.label(
allow_files = [".yaml"],
allow_files = [
".yaml",
".json",
],
single_file = True,
mandatory = True,
),
Expand All @@ -289,7 +282,10 @@ _k8s_object_describe = rule(
_k8s_object_delete = rule(
attrs = {
"unresolved": attr.label(
allow_files = [".yaml"],
allow_files = [
".yaml",
".json",
],
single_file = True,
mandatory = True,
),
Expand Down Expand Up @@ -326,7 +322,7 @@ def k8s_object(name, **kwargs):
_k8s_object_create(name=name + ".create", resolved=name,
kind=kwargs.get("kind"), cluster=kwargs.get("cluster"),
namespace=kwargs.get("namespace"))
_k8s_object_delete(name=name + ".delete", unresolved=name + ".yaml",
_k8s_object_delete(name=name + ".delete", unresolved=kwargs.get("template"),
kind=kwargs.get("kind"), cluster=kwargs.get("cluster"),
namespace=kwargs.get("namespace"))
_k8s_object_replace(name=name + ".replace", resolved=name,
Expand All @@ -336,7 +332,7 @@ def k8s_object(name, **kwargs):
kind=kwargs.get("kind"), cluster=kwargs.get("cluster"),
namespace=kwargs.get("namespace"))
if "kind" in kwargs:
_k8s_object_describe(name=name + ".describe", unresolved=name + ".yaml",
_k8s_object_describe(name=name + ".describe", unresolved=kwargs.get("template"),
kind=kwargs.get("kind"),
cluster=kwargs.get("cluster"),
namespace=kwargs.get("namespace"))
47 changes: 25 additions & 22 deletions k8s/resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
_DOCUMENT_DELIMITER = '---\n'


def Resolve(input, tag_to_digest):
def Resolve(input, string_to_digest):
"""Translate tag references within the input yaml into digests."""
def walk_dict(d):
return {
Expand All @@ -65,9 +65,7 @@ def walk_list(l):

def walk_string(s):
try:
as_tag = docker_name.Tag(s)
digest = tag_to_digest(as_tag)
return digest
return string_to_digest(s)
except:
return s

Expand All @@ -83,10 +81,13 @@ def walk(o):
return yaml.dump(walk(yaml.load(input)))


def TagToDigest(tag, overrides, transport):
"""Turn a docker_name.Tag into a stringified digest."""
if tag in overrides:
return str(overrides[tag])
def StringToDigest(string, overrides, transport):
"""Turn a string into a stringified digest."""
if string in overrides:
return str(overrides[string])

# Attempt to turn the string into a tag, this may throw.
tag = docker_name.Tag(string)

def fully_qualify_digest(digest):
return docker_name.Digest('{registry}/{repo}@{digest}'.format(
Expand All @@ -98,13 +99,13 @@ def fully_qualify_digest(digest):
with v2_2_image.FromRegistry(tag, creds, transport) as img:
if img.exists():
digest = fully_qualify_digest(img.digest())
overrides[tag] = digest
overrides[string] = digest
return str(digest)

# If the tag doesn't exists as v2.2, then try as v2.
with v2_image.FromRegistry(tag, creds, transport) as img:
digest = fully_qualify_digest(img.digest())
overrides[tag] = digest
overrides[string] = digest
return str(digest)


Expand Down Expand Up @@ -136,10 +137,12 @@ def Publish(transport, image_chroot,
digest = []
layer = []

name_to_replace = docker_name.Tag(name)
name_to_publish = name_to_replace
name_to_replace = name
if image_chroot:
name_to_publish = docker_name.Tag(os.path.join(image_chroot, name))
name_to_publish = docker_name.Tag(os.path.join(image_chroot, name), strict=False)
else:
# Without a chroot, the left-hand-side must be a valid tag.
name_to_publish = docker_name.Tag(name, strict=False)

# Resolve the appropriate credential to use based on the standard Docker
# client logic.
Expand All @@ -160,7 +163,7 @@ def main():

transport = transport_pool.Http(httplib2.Http, size=_THREADS)

unseen_tags = set()
unseen_strings = set()
overrides = {}
# TODO(mattmoor): Execute these in a threadpool and
# aggregate the results as they complete.
Expand All @@ -169,24 +172,24 @@ def main():
kwargs = dict([x.split('=', 2) for x in parts])
(tag, digest) = Publish(transport, args.image_chroot, **kwargs)
overrides[tag] = digest
unseen_tags.add(tag)
unseen_strings.add(tag)

with open(args.template, 'r') as f:
inputs = f.read()

def _TagToDigest(t):
if t in unseen_tags:
unseen_tags.remove(t)
return TagToDigest(t, overrides, transport)
def _StringToDigest(t):
if t in unseen_strings:
unseen_strings.remove(t)
return StringToDigest(t, overrides, transport)

content = _DOCUMENT_DELIMITER.join([
Resolve(x, _TagToDigest)
Resolve(x, _StringToDigest)
for x in inputs.split(_DOCUMENT_DELIMITER)
])

if len(unseen_tags) > 0:
if len(unseen_strings) > 0:
print('The following image references were not found: [%s]' % "\n".join([
str(x) for x in unseen_tags
str(x) for x in unseen_strings
]),file=sys.stderr)
sys.exit(1)

Expand Down
27 changes: 18 additions & 9 deletions k8s/resolver_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ def test_complex_walk(self):
expected = 'foo@sha256:deadbeef'
unexpected = 'bar@sha256:baadf00d'
values = {
docker_name.Tag(present): expected,
docker_name.Tag(not_present): unexpected,
present: expected,
not_present: unexpected,
}
input = """
key1:
Expand All @@ -75,10 +75,18 @@ def test_complex_walk(self):
self.assertFalse(unexpected in output)

def test_tag_to_digest_cached(self):
tag = docker_name.Tag('gcr.io/foo/bar:baz')
tag_as_string = 'gcr.io/foo/bar:baz'
expected_digest = 'gcr.io/foo/bar@sha256:deadbeef'
actual_digest = resolver.TagToDigest(tag, {
tag: expected_digest,
actual_digest = resolver.StringToDigest(tag_as_string, {
tag_as_string: expected_digest,
}, _BAD_TRANSPORT)
self.assertEqual(actual_digest, expected_digest)

def test_tag_to_digest_sentinel(self):
sentinel_string = 'XXXXX'
expected_digest = 'gcr.io/foo/bar@sha256:deadbeef'
actual_digest = resolver.StringToDigest(sentinel_string, {
sentinel_string: expected_digest,
}, _BAD_TRANSPORT)
self.assertEqual(actual_digest, expected_digest)

Expand All @@ -89,9 +97,10 @@ def test_tag_to_digest_not_cached(self):
img.exists = lambda: True
with mock.patch.object(v2_2_image, 'FromRegistry',
return_value=img):
tag = docker_name.Tag('gcr.io/foo/bar:baz')
tag_as_string = 'gcr.io/foo/bar:baz'
expected_digest = docker_name.Digest('gcr.io/foo/bar@' + img.digest())
actual_digest = resolver.TagToDigest(tag, {}, _BAD_TRANSPORT)
actual_digest = resolver.StringToDigest(
tag_as_string, {}, _BAD_TRANSPORT)
self.assertEqual(actual_digest, str(expected_digest))

def test_publish_legacy(self):
Expand All @@ -102,7 +111,7 @@ def test_publish_legacy(self):
with mock.patch.object(v2_2_session, 'Push', return_value=NopPush()):
(tag, digest) = resolver.Publish(
_BAD_TRANSPORT, None, name=str(name), tarball=td)
self.assertEqual(tag, name)
self.assertEqual(tag, str(name))
with v2_2_image.FromTarball(td) as img:
self.assertEqual(digest.digest, img.digest())

Expand All @@ -120,7 +129,7 @@ def test_publish_fast(self):
_BAD_TRANSPORT, None, name=str(name), config=config_path,
digest=','.join([h for (h, unused) in layer_data]),
layer=','.join([layer for (unused, layer) in layer_data]))
self.assertEqual(tag, name)
self.assertEqual(tag, str(name))
self.assertEqual(digest.digest, expected_digest)


Expand Down

0 comments on commit 2cf2d16

Please sign in to comment.