From 0c4d023822c4952c31c132c2479620f6c36aeaab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Va=C5=A1ek?= Date: Fri, 25 Apr 2025 17:18:49 +0200 Subject: [PATCH 1/2] Fix: inheritlabels=true if query param absent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The inheritlabels param must default to true if query param is absent. Signed-off-by: Matej VaĊĦek --- pkg/api/handlers/compat/images_build.go | 156 ++++++++++++------------ pkg/api/handlers/decoder.go | 26 ++++ 2 files changed, 104 insertions(+), 78 deletions(-) diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 16b03d4340..452f201037 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -95,83 +95,83 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { } query := struct { - AddHosts string `schema:"extrahosts"` - AdditionalCapabilities string `schema:"addcaps"` - AdditionalBuildContexts string `schema:"additionalbuildcontexts"` - AllPlatforms bool `schema:"allplatforms"` - Annotations string `schema:"annotations"` - AppArmor string `schema:"apparmor"` - BuildArgs string `schema:"buildargs"` - CacheFrom string `schema:"cachefrom"` - CacheTo string `schema:"cacheto"` - CacheTTL string `schema:"cachettl"` - CgroupParent string `schema:"cgroupparent"` - CompatVolumes bool `schema:"compatvolumes"` - Compression uint64 `schema:"compression"` - ConfigureNetwork string `schema:"networkmode"` - CPPFlags string `schema:"cppflags"` - CpuPeriod uint64 `schema:"cpuperiod"` - CpuQuota int64 `schema:"cpuquota"` - CpuSetCpus string `schema:"cpusetcpus"` - CpuSetMems string `schema:"cpusetmems"` - CpuShares uint64 `schema:"cpushares"` - DNSOptions string `schema:"dnsoptions"` - DNSSearch string `schema:"dnssearch"` - DNSServers string `schema:"dnsservers"` - Devices string `schema:"devices"` - Dockerfile string `schema:"dockerfile"` - DropCapabilities string `schema:"dropcaps"` - Envs []string `schema:"setenv"` - Excludes string `schema:"excludes"` - ForceRm bool `schema:"forcerm"` - From string `schema:"from"` - GroupAdd []string `schema:"groupadd"` - HTTPProxy bool `schema:"httpproxy"` - IDMappingOptions string `schema:"idmappingoptions"` - IdentityLabel bool `schema:"identitylabel"` - Ignore bool `schema:"ignore"` - InheritLabels bool `schema:"inheritlabels"` - Isolation string `schema:"isolation"` - Jobs int `schema:"jobs"` - LabelOpts string `schema:"labelopts"` - Labels string `schema:"labels"` - LayerLabels []string `schema:"layerLabel"` - Layers bool `schema:"layers"` - LogRusage bool `schema:"rusage"` - Manifest string `schema:"manifest"` - MemSwap int64 `schema:"memswap"` - Memory int64 `schema:"memory"` - NamespaceOptions string `schema:"nsoptions"` - NoCache bool `schema:"nocache"` - NoHosts bool `schema:"nohosts"` - OmitHistory bool `schema:"omithistory"` - OSFeatures []string `schema:"osfeature"` - OSVersion string `schema:"osversion"` - OutputFormat string `schema:"outputformat"` - Platform []string `schema:"platform"` - Pull bool `schema:"pull"` - PullPolicy string `schema:"pullpolicy"` - Quiet bool `schema:"q"` - Registry string `schema:"registry"` - Rm bool `schema:"rm"` - RusageLogFile string `schema:"rusagelogfile"` - Remote string `schema:"remote"` - Retry int `schema:"retry"` - RetryDelay string `schema:"retry-delay"` - Seccomp string `schema:"seccomp"` - Secrets string `schema:"secrets"` - SecurityOpt string `schema:"securityopt"` - ShmSize int `schema:"shmsize"` - SkipUnusedStages bool `schema:"skipunusedstages"` - Squash bool `schema:"squash"` - TLSVerify bool `schema:"tlsVerify"` - Tags []string `schema:"t"` - Target string `schema:"target"` - Timestamp int64 `schema:"timestamp"` - Ulimits string `schema:"ulimits"` - UnsetEnvs []string `schema:"unsetenv"` - UnsetLabels []string `schema:"unsetlabel"` - Volumes []string `schema:"volume"` + AddHosts string `schema:"extrahosts"` + AdditionalCapabilities string `schema:"addcaps"` + AdditionalBuildContexts string `schema:"additionalbuildcontexts"` + AllPlatforms bool `schema:"allplatforms"` + Annotations string `schema:"annotations"` + AppArmor string `schema:"apparmor"` + BuildArgs string `schema:"buildargs"` + CacheFrom string `schema:"cachefrom"` + CacheTo string `schema:"cacheto"` + CacheTTL string `schema:"cachettl"` + CgroupParent string `schema:"cgroupparent"` + CompatVolumes bool `schema:"compatvolumes"` + Compression uint64 `schema:"compression"` + ConfigureNetwork string `schema:"networkmode"` + CPPFlags string `schema:"cppflags"` + CpuPeriod uint64 `schema:"cpuperiod"` + CpuQuota int64 `schema:"cpuquota"` + CpuSetCpus string `schema:"cpusetcpus"` + CpuSetMems string `schema:"cpusetmems"` + CpuShares uint64 `schema:"cpushares"` + DNSOptions string `schema:"dnsoptions"` + DNSSearch string `schema:"dnssearch"` + DNSServers string `schema:"dnsservers"` + Devices string `schema:"devices"` + Dockerfile string `schema:"dockerfile"` + DropCapabilities string `schema:"dropcaps"` + Envs []string `schema:"setenv"` + Excludes string `schema:"excludes"` + ForceRm bool `schema:"forcerm"` + From string `schema:"from"` + GroupAdd []string `schema:"groupadd"` + HTTPProxy bool `schema:"httpproxy"` + IDMappingOptions string `schema:"idmappingoptions"` + IdentityLabel bool `schema:"identitylabel"` + Ignore bool `schema:"ignore"` + InheritLabels types.OptionalBool `schema:"inheritlabels"` + Isolation string `schema:"isolation"` + Jobs int `schema:"jobs"` + LabelOpts string `schema:"labelopts"` + Labels string `schema:"labels"` + LayerLabels []string `schema:"layerLabel"` + Layers bool `schema:"layers"` + LogRusage bool `schema:"rusage"` + Manifest string `schema:"manifest"` + MemSwap int64 `schema:"memswap"` + Memory int64 `schema:"memory"` + NamespaceOptions string `schema:"nsoptions"` + NoCache bool `schema:"nocache"` + NoHosts bool `schema:"nohosts"` + OmitHistory bool `schema:"omithistory"` + OSFeatures []string `schema:"osfeature"` + OSVersion string `schema:"osversion"` + OutputFormat string `schema:"outputformat"` + Platform []string `schema:"platform"` + Pull bool `schema:"pull"` + PullPolicy string `schema:"pullpolicy"` + Quiet bool `schema:"q"` + Registry string `schema:"registry"` + Rm bool `schema:"rm"` + RusageLogFile string `schema:"rusagelogfile"` + Remote string `schema:"remote"` + Retry int `schema:"retry"` + RetryDelay string `schema:"retry-delay"` + Seccomp string `schema:"seccomp"` + Secrets string `schema:"secrets"` + SecurityOpt string `schema:"securityopt"` + ShmSize int `schema:"shmsize"` + SkipUnusedStages bool `schema:"skipunusedstages"` + Squash bool `schema:"squash"` + TLSVerify bool `schema:"tlsVerify"` + Tags []string `schema:"t"` + Target string `schema:"target"` + Timestamp int64 `schema:"timestamp"` + Ulimits string `schema:"ulimits"` + UnsetEnvs []string `schema:"unsetenv"` + UnsetLabels []string `schema:"unsetlabel"` + Volumes []string `schema:"volume"` }{ Dockerfile: "Dockerfile", IdentityLabel: true, @@ -745,7 +745,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { IDMappingOptions: &idMappingOptions, IgnoreUnrecognizedInstructions: query.Ignore, IgnoreFile: ignoreFile, - InheritLabels: types.NewOptionalBool(query.InheritLabels), + InheritLabels: query.InheritLabels, Isolation: isolation, Jobs: &jobs, Labels: labels, diff --git a/pkg/api/handlers/decoder.go b/pkg/api/handlers/decoder.go index fe13ede9d0..c2764dea9e 100644 --- a/pkg/api/handlers/decoder.go +++ b/pkg/api/handlers/decoder.go @@ -5,10 +5,12 @@ package handlers import ( "encoding/json" "reflect" + "strconv" "strings" "syscall" "time" + "github.com/containers/image/v5/types" "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/pkg/util" "github.com/gorilla/schema" @@ -28,6 +30,9 @@ func NewAPIDecoder() *schema.Decoder { var Signal syscall.Signal d.RegisterConverter(Signal, convertSignal) + + d.RegisterConverter(types.OptionalBoolUndefined, convertOptionalBool) + return d } @@ -39,6 +44,16 @@ func NewCompatAPIDecoder() *schema.Decoder { s = strings.ToLower(strings.TrimSpace(s)) return reflect.ValueOf(s != "" && s != "0" && s != "no" && s != "false" && s != "none") }) + dec.RegisterConverter(types.OptionalBoolUndefined, func(s string) reflect.Value { + if len(s) == 0 { + return reflect.ValueOf(types.OptionalBoolUndefined) + } + s = strings.ToLower(strings.TrimSpace(s)) + if s != "0" && s != "no" && s != "false" && s != "none" { + return reflect.ValueOf(types.OptionalBoolTrue) + } + return reflect.ValueOf(types.OptionalBoolFalse) + }) return dec } @@ -143,3 +158,14 @@ func convertSignal(query string) reflect.Value { } return reflect.ValueOf(signal) } + +func convertOptionalBool(s string) reflect.Value { + if len(s) == 0 { + return reflect.ValueOf(types.OptionalBoolUndefined) + } + val, _ := strconv.ParseBool(s) + if val { + return reflect.ValueOf(types.OptionalBoolTrue) + } + return reflect.ValueOf(types.OptionalBoolFalse) +} From 4268c61dd0cb83f87b67c9b076d125ab0dce1240 Mon Sep 17 00:00:00 2001 From: flouthoc Date: Fri, 25 Apr 2025 19:26:07 +0200 Subject: [PATCH 2/2] Added tests for inheritlabel fix Signed-off-by: flouthoc --- test/apiv2/90-build.at | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 test/apiv2/90-build.at diff --git a/test/apiv2/90-build.at b/test/apiv2/90-build.at new file mode 100644 index 0000000000..8c667f8db2 --- /dev/null +++ b/test/apiv2/90-build.at @@ -0,0 +1,26 @@ +# -*- sh -*- +# +# Tests for build-related endpoints +# + +# test if default compat build contains labels from base image +TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX) +function cleanBuildTest() { + podman rmi -a -f + rm -rf "${TMPD}" &> /dev/null +} +CONTAINERFILE_TAR="${TMPD}/containerfile.tar" +cat > $TMPD/containerfile << EOF +FROM $IMAGE +RUN echo hello +EOF +tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_TAR} containerfile &> /dev/null + +t POST "/build?dockerfile=containerfile&t=labeltest" $CONTAINERFILE_TAR 200 \ + '.aux|select(has("ID")).ID~^sha256:[0-9a-f]\{64\}$' + +t GET images/labeltest/json 200 \ + .Config.Labels.created_by="test/system/build-testimage" +cleanBuildTest + +# vim: filetype=sh