Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: reset cmd when entrypoint is set #656

Merged
merged 1 commit into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
Loading