Skip to content

Commit 1477512

Browse files
committed
build: add support for inherit-labels
Allows users to specify if they want to inherit labels from base image or not. Signed-off-by: flouthoc <[email protected]>
1 parent 025e3e5 commit 1477512

File tree

9 files changed

+98
-4
lines changed

9 files changed

+98
-4
lines changed

define/build.go

+3
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ type BuildOptions struct {
236236
// ID mapping options to use if we're setting up our own user namespace
237237
// when handling RUN instructions.
238238
IDMappingOptions *IDMappingOptions
239+
// InheritLabels controls whether or not built images will retain the labels
240+
// which were set in their base images
241+
InheritLabels types.OptionalBool
239242
// AddCapabilities is a list of capabilities to add to the default set when
240243
// handling RUN instructions.
241244
AddCapabilities []string

docs/buildah-build.1.md

+4
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,10 @@ Path to an alternative .containerignore (.dockerignore) file.
497497
Write the built image's ID to the file. When `--platform` is specified more
498498
than once, attempting to use this option will trigger an error.
499499

500+
**--inherit-labels** *bool-value*
501+
502+
Inherit the labels from the base image or base stages. (default true).
503+
500504
**--ipc** *how*
501505

502506
Sets the configuration for IPC namespaces when handling `RUN` instructions.

imagebuildah/executor.go

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ type Executor struct {
8282
additionalTags []string
8383
log func(format string, args ...any) // can be nil
8484
in io.Reader
85+
inheritLabels types.OptionalBool
8586
out io.Writer
8687
err io.Writer
8788
signaturePolicyPath string
@@ -261,6 +262,7 @@ func newExecutor(logger *logrus.Logger, logPrefix string, store storage.Store, o
261262
err: options.Err,
262263
reportWriter: writer,
263264
isolation: options.Isolation,
265+
inheritLabels: options.InheritLabels,
264266
namespaceOptions: options.NamespaceOptions,
265267
configureNetwork: options.ConfigureNetwork,
266268
cniPluginPath: options.CNIPluginPath,

imagebuildah/stage_executor.go

+14-4
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,11 @@ func (s *StageExecutor) prepare(ctx context.Context, from string, initializeIBCo
10691069
RootFS: rootfs,
10701070
}
10711071
dImage.Config = &dImage.ContainerConfig
1072+
if s.executor.inheritLabels == types.OptionalBoolFalse {
1073+
// If user has selected `--inherit-labels=false` lets not
1074+
// inherit labels from base image.
1075+
dImage.Config.Labels = nil
1076+
}
10721077
err = ib.FromImage(&dImage, node)
10731078
if err != nil {
10741079
if err2 := builder.Delete(); err2 != nil {
@@ -1872,6 +1877,11 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
18721877
if node == nil {
18731878
return "/bin/sh", nil
18741879
}
1880+
inheritLabels := ""
1881+
// If --inherit-label was manually set to false then update history.
1882+
if s.executor.inheritLabels == types.OptionalBoolFalse {
1883+
inheritLabels = "|inheritLabels=false"
1884+
}
18751885
switch strings.ToUpper(node.Value) {
18761886
case "ARG":
18771887
for _, variable := range strings.Fields(node.Original) {
@@ -1880,7 +1890,7 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
18801890
}
18811891
}
18821892
buildArgs := s.getBuildArgsKey()
1883-
return "/bin/sh -c #(nop) ARG " + buildArgs, nil
1893+
return "/bin/sh -c #(nop) ARG " + buildArgs + inheritLabels, nil
18841894
case "RUN":
18851895
shArg := ""
18861896
buildArgs := s.getBuildArgsResolvedForRun()
@@ -1960,16 +1970,16 @@ func (s *StageExecutor) getCreatedBy(node *parser.Node, addedContentSummary stri
19601970
if buildArgs != "" {
19611971
result = result + "|" + strconv.Itoa(len(strings.Split(buildArgs, " "))) + " " + buildArgs + " "
19621972
}
1963-
result = result + "/bin/sh -c " + shArg + heredoc + appendCheckSum
1973+
result = result + "/bin/sh -c " + shArg + heredoc + appendCheckSum + inheritLabels
19641974
return result, nil
19651975
case "ADD", "COPY":
19661976
destination := node
19671977
for destination.Next != nil {
19681978
destination = destination.Next
19691979
}
1970-
return "/bin/sh -c #(nop) " + strings.ToUpper(node.Value) + " " + addedContentSummary + " in " + destination.Value + " ", nil
1980+
return "/bin/sh -c #(nop) " + strings.ToUpper(node.Value) + " " + addedContentSummary + " in " + destination.Value + " " + inheritLabels, nil
19711981
default:
1972-
return "/bin/sh -c #(nop) " + node.Original, nil
1982+
return "/bin/sh -c #(nop) " + node.Original + inheritLabels, nil
19731983
}
19741984
}
19751985

pkg/cli/build.go

+1
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
376376
IIDFile: iopts.Iidfile,
377377
IgnoreFile: iopts.IgnoreFile,
378378
In: stdin,
379+
InheritLabels: types.NewOptionalBool(iopts.InheritLabels),
379380
Isolation: isolation,
380381
Jobs: &iopts.Jobs,
381382
Labels: iopts.Label,

pkg/cli/common.go

+2
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ type BudResults struct {
7272
Format string
7373
From string
7474
Iidfile string
75+
InheritLabels bool
7576
Label []string
7677
LayerLabel []string
7778
Logfile string
@@ -231,6 +232,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
231232
fs.StringVar(&flags.CertDir, "cert-dir", "", "use certificates at the specified path to access the registry")
232233
fs.BoolVar(&flags.Compress, "compress", false, "this is a legacy option, which has no effect on the image")
233234
fs.BoolVar(&flags.CompatVolumes, "compat-volumes", false, "preserve the contents of VOLUMEs during RUN instructions")
235+
fs.BoolVar(&flags.InheritLabels, "inherit-labels", true, "inherit the labels from the base image or base stages.")
234236
fs.StringArrayVar(&flags.CPPFlags, "cpp-flag", []string{}, "set additional flag to pass to C preprocessor (cpp)")
235237
fs.StringVar(&flags.Creds, "creds", "", "use `[username[:password]]` for accessing the registry")
236238
fs.StringVarP(&flags.CWOptions, "cw", "", "", "confidential workload `options`")

tests/bud.bats

+63
Original file line numberDiff line numberDiff line change
@@ -2670,6 +2670,69 @@ _EOF
26702670
expect_output "$want_output"
26712671
}
26722672

2673+
@test "bud and test inherit-labels" {
2674+
run_buildah --version
2675+
local -a output_fields=($output)
2676+
buildah_version=${output_fields[2]}
2677+
run_buildah build $WITH_POLICY_JSON -t exp -f $BUDFILES/base-with-labels/Containerfile
2678+
2679+
run_buildah inspect --format '{{ index .Docker.Config.Labels "license"}}' exp
2680+
expect_output "MIT" "license must be MIT from fedora base image"
2681+
run_buildah inspect --format '{{ index .Docker.Config.Labels "name"}}' exp
2682+
expect_output "fedora-minimal" "name must be fedora from base image"
2683+
2684+
run_buildah build $WITH_POLICY_JSON --inherit-labels=false --label name=world -t exp -f $BUDFILES/base-with-labels/Containerfile
2685+
# no labels should be inherited from base image only the, buildah version label
2686+
# and `hello=world` which we just added using cli flag
2687+
want_output='map["io.buildah.version":"'$buildah_version'" "name":"world"]'
2688+
run_buildah inspect --format '{{printf "%q" .Docker.Config.Labels}}' exp
2689+
expect_output "$want_output"
2690+
2691+
# Try building another file with multiple layers
2692+
run_buildah build $WITH_POLICY_JSON --iidfile ${TEST_SCRATCH_DIR}/id1 --layers -t exp -f $BUDFILES/base-with-labels/Containerfile.layer
2693+
run_buildah inspect --format '{{ index .Docker.Config.Labels "license"}}' exp
2694+
expect_output "MIT" "license must be MIT from fedora base image"
2695+
run_buildah inspect --format '{{ index .Docker.Config.Labels "name"}}' exp
2696+
expect_output "world" "name must be world from Containerfile"
2697+
2698+
# Now build same file with --inherit-labels=false and verify if we are not using the cache again.
2699+
run_buildah build $WITH_POLICY_JSON --layers --inherit-labels=false -t exp -f $BUDFILES/base-with-labels/Containerfile.layer
2700+
# Should not contain `Using cache` at all since
2701+
assert "$output" !~ "Using cache"
2702+
want_output='map["io.buildah.version":"'$buildah_version'" "name":"world"]'
2703+
run_buildah inspect --format '{{printf "%q" .Docker.Config.Labels}}' exp
2704+
expect_output "$want_output"
2705+
2706+
# Now build same file with --inherit-labels=true and verify if using the cache
2707+
run_buildah build $WITH_POLICY_JSON --iidfile ${TEST_SCRATCH_DIR}/id2 --layers --inherit-labels=true -t exp -f $BUDFILES/base-with-labels/Containerfile.layer
2708+
expect_output --substring " Using cache"
2709+
run_buildah inspect --format '{{ index .Docker.Config.Labels "license"}}' exp
2710+
expect_output "MIT" "license must be MIT from fedora base image"
2711+
run_buildah inspect --format '{{ index .Docker.Config.Labels "name"}}' exp
2712+
expect_output "world" "name must be world from Containerfile"
2713+
# Final image id should be exactly same as the one image which was built in the past.
2714+
assert "$(cat ${TEST_SCRATCH_DIR}/id1)" = "$(cat ${TEST_SCRATCH_DIR}/id2)" "expected image ids to not change"
2715+
2716+
# Now build same file with --inherit-labels=false and verify if target stage did not inherit any labels from base stage.
2717+
run_buildah build $WITH_POLICY_JSON --layers --inherit-labels=false -t exp -f $BUDFILES/base-with-labels/Containerfile.multi-stage
2718+
want_output='map["io.buildah.version":"'$buildah_version'"]'
2719+
run_buildah inspect --format '{{printf "%q" .Docker.Config.Labels}}' exp
2720+
expect_output "$want_output"
2721+
2722+
# Now build same file with --inherit-labels=true and verify if target stage inherits labels from the base stage.
2723+
run_buildah build $WITH_POLICY_JSON --iidfile ${TEST_SCRATCH_DIR}/id3 --layers --inherit-labels=true -t exp -f $BUDFILES/base-with-labels/Containerfile.multi-stage
2724+
want_output='map["io.buildah.version":"'$buildah_version'" "name":"world"]'
2725+
run_buildah inspect --format '{{printf "%q" .Docker.Config.Labels}}' exp
2726+
expect_output "$want_output"
2727+
2728+
# Rebuild again with layers should not build image again at all.
2729+
run_buildah build $WITH_POLICY_JSON --iidfile ${TEST_SCRATCH_DIR}/id4 --layers --inherit-labels=true -t exp -f $BUDFILES/base-with-labels/Containerfile.multi-stage
2730+
want_output='map["io.buildah.version":"'$buildah_version'" "name":"world"]'
2731+
run_buildah inspect --format '{{printf "%q" .Docker.Config.Labels}}' exp
2732+
expect_output "$want_output"
2733+
assert "$(cat ${TEST_SCRATCH_DIR}/id3)" = "$(cat ${TEST_SCRATCH_DIR}/id3)" "expected image ids to not change"
2734+
}
2735+
26732736
@test "build using intermediate images should not inherit label" {
26742737
_prefetch alpine
26752738

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM registry.fedoraproject.org/fedora-minimal
2+
LABEL name world
3+
RUN echo world
4+
RUN echo hello
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
FROM alpine as one
2+
LABEL name world
3+
4+
FROM one
5+
RUN echo world

0 commit comments

Comments
 (0)