Skip to content

Commit

Permalink
fix: reset cmd when entrypoint is set (#656)
Browse files Browse the repository at this point in the history
  • Loading branch information
thesayyn authored Jul 19, 2024
1 parent e822897 commit 0b7d48f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 16 deletions.
2 changes: 1 addition & 1 deletion docs/image.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 6 additions & 4 deletions examples/assert.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ config_digest=$$($(JQ_BIN) -r '.config.digest | sub(":"; "/")' $$image_path/blob
$(JQ_BIN) 'def pick(p): . as $$v | reduce path(p) as $$p ({{}}; setpath($$p; $$v | getpath($$p))); pick({keys})' "$$image_path/blobs/$$config_digest" > $@
"""

_DEFAULT_ = {"____I_WILL_NOT_MATCH_ANYTHING__": True}

# buildifier: disable=function-docstring-args
def assert_oci_config(
name,
image,
entrypoint_eq = None,
cmd_eq = None,
entrypoint_eq = _DEFAULT_,
cmd_eq = _DEFAULT_,
env_eq = None,
exposed_ports_eq = None,
volumes_eq = None,
Expand All @@ -37,9 +39,9 @@ def assert_oci_config(
config = {}

# .config
if entrypoint_eq:
if entrypoint_eq != _DEFAULT_:
config["Entrypoint"] = entrypoint_eq
if cmd_eq:
if cmd_eq != _DEFAULT_:
config["Cmd"] = cmd_eq
if env_eq:
config["Env"] = ["=".join(e) for e in env_eq.items()]
Expand Down
49 changes: 49 additions & 0 deletions examples/assertion/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,55 @@ sh_test(
data = [":case12"],
)

# Case 15: Setting entrypoint resets cmd
oci_image(
name = "case15_base",
architecture = "arm64",
cmd = [
"-c",
"test",
],
os = "linux",
)

assert_oci_config(
name = "test_case15_base",
cmd_eq = [
"-c",
"test",
],
image = ":case15_base",
)

oci_image(
name = "case15",
base = ":case15_base",
entrypoint = ["/custom_bin"],
)

assert_oci_config(
name = "test_case15",
cmd_eq = None, # cmd should not exist
entrypoint_eq = [
"/custom_bin",
],
image = ":case15",
)

oci_image(
name = "case15_cmd",
base = ":case15_base",
cmd = ["--arg"],
entrypoint = ["/custom_bin"],
)

assert_oci_config(
name = "test_case15_cmd",
cmd_eq = ["--arg"],
entrypoint_eq = ["/custom_bin"],
image = ":case15_cmd",
)

# build them as test.
build_test(
name = "test",
Expand Down
8 changes: 4 additions & 4 deletions examples/dockerfile/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ oci_image(
assert_oci_config(
name = "assert_metadata",
cmd_eq = ["/app/say.py"],
entrypoint_eq = [],
entrypoint_eq = None,
image = ":image",
)

Expand All @@ -50,8 +50,8 @@ assert_oci_image_command(
"jq",
"--version",
],
image = ":image",
exit_code_eq = 0,
image = ":image",
output_eq = "jq-1.6\n",
)

Expand All @@ -61,8 +61,8 @@ assert_oci_image_command(
"file",
"/var/lib/apt/lists",
],
image = ":image",
exit_code_eq = 0,
image = ":image",
output_eq = "/var/lib/apt/lists: directory\n",
)

Expand All @@ -72,8 +72,8 @@ assert_oci_image_command(
"python",
"/app/say.py",
],
image = ":image",
exit_code_eq = 0,
image = ":image",
output_eq = """\
____
| moo! |
Expand Down
13 changes: 8 additions & 5 deletions oci/private/image.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ _attrs = {
The authors recommend [dive](https://github.com/wagoodman/dive) to explore the layering of the resulting image.
"""),
# See: https://github.com/opencontainers/image-spec/blob/main/config.md#properties
"entrypoint": attr.label(doc = "A file containing a comma separated list to be used as the `entrypoint` to execute when the container starts. These values act as defaults and may be replaced by an entrypoint specified when creating a container.", allow_single_file = True),
"entrypoint": attr.label(doc = "A file containing a comma separated list to be used as the `entrypoint` to execute when the container starts. These values act as defaults and may be replaced by an entrypoint specified when creating a container. NOTE: Setting this attribute will reset the `cmd` attribute", allow_single_file = True),
"cmd": attr.label(doc = "A file containing a comma separated list to be used as the `command & args` of the container. These values act as defaults and may be replaced by any specified when creating a container.", allow_single_file = True),
"env": attr.label(doc = """\
A file containing the default values for the environment variables of the container. These values act as defaults and are merged with any specified when creating a container. Entries replace the base environment variables if any of the entries has conflicting keys.
Expand Down Expand Up @@ -191,10 +191,17 @@ def _oci_image_impl(ctx):
# tars are already added as input above.
args.add_joined([layer, descriptor], join_with = "=", format_joined = "--layer=%s")

# WARNING: entrypoint should always be added before the cmd argument.
# This due to implicit behavior which setting entrypoint deletes `cmd`.
# See: https://github.com/bazel-contrib/rules_oci/issues/649
if ctx.attr.entrypoint:
args.add(ctx.file.entrypoint.path, format = "--entrypoint=%s")
inputs.append(ctx.file.entrypoint)

if ctx.attr.cmd:
args.add(ctx.file.cmd.path, format = "--cmd=%s")
inputs.append(ctx.file.cmd)

if ctx.attr.exposed_ports:
args.add(ctx.file.exposed_ports.path, format = "--exposed-ports=%s")
inputs.append(ctx.file.exposed_ports)
Expand All @@ -203,10 +210,6 @@ def _oci_image_impl(ctx):
args.add(ctx.file.volumes.path, format = "--volumes=%s")
inputs.append(ctx.file.volumes)

if ctx.attr.cmd:
args.add(ctx.file.cmd.path, format = "--cmd=%s")
inputs.append(ctx.file.cmd)

if ctx.attr.env:
args.add(ctx.file.env.path, format = "--env=%s")
inputs.append(ctx.file.env)
Expand Down
7 changes: 5 additions & 2 deletions oci/private/image.sh
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ for ARG in "$@"; do
CONFIG=$(jq --rawfile cmd "${ARG#--cmd=}" '.config.Cmd = ($cmd | split(",|\n"; "") | map(select(. | length > 0)))' <<<"$CONFIG")
;;
--entrypoint=*)
CONFIG=$(jq --rawfile entrypoint "${ARG#--entrypoint=}" '.config.Entrypoint = ($entrypoint | split(",|\n"; "") | map(select(. | length > 0)))' <<<"$CONFIG")
# NOTE: setting entrypoint deletes `.config.Cmd` which is consistent with crane and Dockerfile behavior.
# See: https://github.com/bazel-contrib/rules_oci/issues/649
# See: https://github.com/google/go-containerregistry/blob/c3d1dcc932076c15b65b8b9acfff1d47ded2ebf9/cmd/crane/cmd/mutate.go#L107
CONFIG=$(jq --rawfile entrypoint "${ARG#--entrypoint=}" '.config.Cmd = null | .config.Entrypoint = ($entrypoint | split(",|\n"; "") | map(select(. | length > 0)))' <<<"$CONFIG")
;;
--exposed-ports=*)
CONFIG=$(jq --rawfile ep "${ARG#--exposed-ports=}" '.config.ExposedPorts = ($ep | split(",") | map({key: ., value: {}}) | from_entries)' <<<"$CONFIG")
Expand Down Expand Up @@ -179,6 +182,6 @@ for ARG in "$@"; do
esac
done

get_config | jq --argjson config "$CONFIG" '. *= $config' | update_config >/dev/null
get_config | jq --argjson config "$CONFIG" '. *= $config | del(.config.Cmd|nulls)' | update_config >/dev/null
## TODO: container structure is broken
(JSON="$(coreutils cat "$OUTPUT/index.json")" && jq "del(.manifests[].annotations)" >"$OUTPUT/index.json" <<<"$JSON")

0 comments on commit 0b7d48f

Please sign in to comment.