diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf26206..16a1820 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,10 +30,10 @@ jobs: CGO_ENABLED: "0" COSIGN_VERSION: v2.4.0 GGCR_VERSION: v0.20.2 - KUBEBUILDER_VERSION: "2.3.2" - KUBECTL_VERSION: v1.30.3 + KUBEBUILDER_VERSION: "4.2.0" + KUBECTL_VERSION: v1.31.1 REGISTRY: ghcr.io - SKAFFOLD_VERSION: v2.13.1 + SKAFFOLD_VERSION: v2.13.2 SKAFFOLD_CACHE_ARTIFACTS: "false" SKAFFOLD_DETECT_MINIKUBE: "false" SKAFFOLD_INTERACTIVE: "false" diff --git a/cmd/function/function.go b/cmd/function/function.go index a4fa68f..2f83c1f 100644 --- a/cmd/function/function.go +++ b/cmd/function/function.go @@ -40,7 +40,11 @@ func Cmd(ctx context.Context) *cobra.Command { log := logging.CreateStdLogger("digester") resourceFn := createResourceFn(ctx, log) cmd := command.Build(framework.ResourceListProcessorFunc(resourceFn), command.StandaloneDisabled, false) - customizeCmd(cmd) + if err := customizeCmd(cmd); err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + return cmd } @@ -51,6 +55,7 @@ func createResourceFn(ctx context.Context, log logr.Logger) framework.ResourceLi log.V(2).Info("kubeconfig", "kubeconfig", viper.GetString("kubeconfig")) log.V(2).Info("offline", "offline", viper.GetBool("offline")) log.V(2).Info("skip-prefixes", "skip-prefixes", util.StringArray(viper.GetString("skip-prefixes"))) + log.V(2).Info("platform", "platform", viper.GetString("platform")) var config *rest.Config if !viper.GetBool("offline") { var kubeconfig string @@ -66,7 +71,7 @@ func createResourceFn(ctx context.Context, log logr.Logger) framework.ResourceLi } } for _, r := range resourceList.Items { - if err := resolve.ImageTags(ctx, log, config, r, util.StringArray(viper.GetString("skip-prefixes"))); err != nil { + if err := resolve.ImageTags(ctx, log, config, r, util.StringArray(viper.GetString("skip-prefixes")), viper.GetString("platform")); err != nil { return err } } @@ -76,7 +81,7 @@ func createResourceFn(ctx context.Context, log logr.Logger) framework.ResourceLi // customizeCmd modifies the kyaml function framework command by adding flags // that this KRM function needs, and to make it more user-friendly. -func customizeCmd(cmd *cobra.Command) { +func customizeCmd(cmd *cobra.Command) error { cmd.Use = "digester" cmd.Short = "Resolve container image tags to digests" cmd.Long = "Digester adds digests to container and " + @@ -85,15 +90,34 @@ func customizeCmd(cmd *cobra.Command) { "or as a client-side KRM function with kpt or kustomize." cmd.Flags().String("kubeconfig", getKubeconfigDefault(), "(optional) absolute path to the kubeconfig file. Requires offline=false.") - viper.BindPFlag("kubeconfig", cmd.Flags().Lookup("kubeconfig")) - viper.BindEnv("kubeconfig") + if err := viper.BindPFlag("kubeconfig", cmd.Flags().Lookup("kubeconfig")); err != nil { + return err + } + if err := viper.BindEnv("kubeconfig"); err != nil { + return err + } cmd.Flags().Bool("offline", true, "do not connect to Kubernetes API server to retrieve imagePullSecrets") - viper.BindPFlag("offline", cmd.Flags().Lookup("offline")) - viper.BindEnv("offline") + if err := viper.BindPFlag("offline", cmd.Flags().Lookup("offline")); err != nil { + return err + } + if err := viper.BindEnv("offline"); err != nil { + return err + } cmd.Flags().String("skip-prefixes", "", "(optional) image prefixes that should not be resolved to digests, colon separated") - viper.BindPFlag("skip-prefixes", cmd.Flags().Lookup("skip-prefixes")) - viper.BindEnv("skip-prefixes", "SKIP_PREFIXES") + if err := viper.BindPFlag("skip-prefixes", cmd.Flags().Lookup("skip-prefixes")); err != nil { + return err + } + if err := viper.BindEnv("skip-prefixes", "SKIP_PREFIXES"); err != nil { + return err + } + if err := viper.BindPFlag("platform", cmd.Flags().Lookup("platform")); err != nil { + return err + } + if err := viper.BindEnv("platform"); err != nil { + return err + } + return nil } // getKubeconfigDefault determines the default value of the --kubeconfig flag. diff --git a/cmd/webhook/webhook.go b/cmd/webhook/webhook.go index 0faf588..c72e444 100644 --- a/cmd/webhook/webhook.go +++ b/cmd/webhook/webhook.go @@ -81,6 +81,7 @@ var ( port int ignoreErrors bool skipPrefixes string + platform string ) func init() { @@ -94,6 +95,7 @@ func init() { Cmd.Flags().IntVar(&port, "port", defaultPort, "webhook server port") Cmd.Flags().BoolVar(&ignoreErrors, "ignore-errors", false, "do not fail on webhook admission errors, just log them") Cmd.Flags().StringVar(&skipPrefixes, "skip-prefixes", "", "(optional) image prefixes that should not be resolved to digests, colon separated") + Cmd.Flags().StringVar(&platform, "platform", "", "resolve only to platform specific images i.e. linux/amd64") } func run(ctx context.Context) error { @@ -156,7 +158,7 @@ func run(ctx context.Context) error { close(certSetupFinished) } - go setupControllers(mgr, log, dryRun, ignoreErrors, certSetupFinished, util.StringArray(skipPrefixes)) + go setupControllers(mgr, log, dryRun, ignoreErrors, certSetupFinished, util.StringArray(skipPrefixes), platform) log.Info("starting manager") if err := mgr.Start(ctx); err != nil { @@ -165,7 +167,7 @@ func run(ctx context.Context) error { return nil } -func setupControllers(mgr manager.Manager, log logr.Logger, dryRun bool, ignoreErrors bool, certSetupFinished chan struct{}, skipPrefixes []string) { +func setupControllers(mgr manager.Manager, log logr.Logger, dryRun bool, ignoreErrors bool, certSetupFinished chan struct{}, skipPrefixes []string, platform string) { log.Info("waiting for cert rotation setup") <-certSetupFinished log.Info("done waiting for cert rotation setup") @@ -179,6 +181,7 @@ func setupControllers(mgr manager.Manager, log logr.Logger, dryRun bool, ignoreE IgnoreErrors: ignoreErrors, Config: k8sClientConfig, SkipPrefixes: skipPrefixes, + Platform: platform, } mwh := &admission.Webhook{Handler: whh} log.Info("starting webhook server", "path", webhookPath) diff --git a/docs/authentication.md b/docs/authentication.md index 3647509..782db92 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -156,6 +156,10 @@ You can provide an alternative kubeconfig file by setting the value of the `--kubeconfig` command-line flag or the `KUBECONFIG` environment variable to the full path of an alternative kubeconfig file. +You can also limit the resolve of image tags to only a specific platform by +specifying the `--platform` command-line flag with the target platform +e.g. `linux/amd64`. + ## Webhook online authentication The webhook uses online authentication by default, and it uses the diff --git a/go.mod b/go.mod index 65f1eb9..a5def2c 100644 --- a/go.mod +++ b/go.mod @@ -14,29 +14,32 @@ module github.com/google/k8s-digester -go 1.22.0 +go 1.23.0 + +toolchain go1.23.1 require ( - github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240809155957-ac94a3401898 + github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240918142057-e21b7a4e92d1 github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 github.com/go-logr/logr v1.4.2 github.com/go-logr/stdr v1.2.2 github.com/go-logr/zapr v1.3.0 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.20.2 - github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20240810014151-b8e87ed57b80 + github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20240826191751-a07d1cab8700 github.com/open-policy-agent/cert-controller v0.11.0 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 + github.com/stretchr/testify v1.9.0 go.uber.org/zap v1.27.0 gomodules.xyz/jsonpatch/v2 v2.4.0 - k8s.io/api v0.30.3 - k8s.io/apimachinery v0.30.3 - k8s.io/client-go v0.30.3 + k8s.io/api v0.31.1 + k8s.io/apimachinery v0.31.1 + k8s.io/client-go v0.31.1 k8s.io/klog/v2 v2.130.1 - sigs.k8s.io/controller-runtime v0.18.4 - sigs.k8s.io/kustomize/kyaml v0.17.2 + sigs.k8s.io/controller-runtime v0.19.0 + sigs.k8s.io/kustomize/kyaml v0.18.0 ) require ( @@ -51,21 +54,21 @@ require ( github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect - github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ecr v1.32.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect - github.com/aws/smithy-go v1.20.3 // indirect + github.com/aws/aws-sdk-go-v2 v1.30.5 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.34 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.32 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.33.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 // indirect + github.com/aws/smithy-go v1.20.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect @@ -78,6 +81,7 @@ require ( github.com/evanphx/json-patch v5.9.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-errors/errors v1.5.1 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.21.0 // indirect @@ -109,6 +113,7 @@ require ( github.com/opencontainers/image-spec v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.19.1 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect @@ -121,6 +126,7 @@ require ( github.com/spf13/cast v1.7.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/vbatts/tar-split v0.11.5 // indirect + github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.2.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -134,11 +140,12 @@ require ( golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.6.0 // indirect google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.30.3 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index 1a501a8..e3b35e1 100644 --- a/go.sum +++ b/go.sum @@ -26,38 +26,38 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY= -github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc= -github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90= -github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg= -github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI= -github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/service/ecr v1.32.0 h1:lZoKOTEQUf5Oi9qVaZM/Hb0Z6SHIwwpDjbLFOVgB2t8= -github.com/aws/aws-sdk-go-v2/service/ecr v1.32.0/go.mod h1:RhaP7Wil0+uuuhiE4FzOOEFZwkmFAk1ZflXzK+O3ptU= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.3 h1:n2eqzO9VabUkd77b88Hos6OEtbGohB/TRrtXLTZi38Y= -github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.3/go.mod h1:Oy3yHBGkKtTmsn6iJGEZxytzZQrEvoFRWldB4XmzlO4= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ= -github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE= -github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240809155957-ac94a3401898 h1:AvFUc3gOvaw2avFhMTgbyWoa8lTAiwUqiHQzRyfJgOE= -github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240809155957-ac94a3401898/go.mod h1:g/jwspvaX2Kvy+cuE6NRlboLhoS2kHeYDmfc880tS1Y= +github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g= +github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/config v1.27.34 h1:5sLceuETg/215nLtY/QIVB2O6cosS0iC/Tx5oyqUhbw= +github.com/aws/aws-sdk-go-v2/config v1.27.34/go.mod h1:kEqdYzRb8dd8Sy2pOdEbExTTF5v7ozEXX0McgPE7xks= +github.com/aws/aws-sdk-go-v2/credentials v1.17.32 h1:7Cxhp/BnT2RcGy4VisJ9miUPecY+lyE9I8JvcZofn9I= +github.com/aws/aws-sdk-go-v2/credentials v1.17.32/go.mod h1:P5/QMF3/DCHbXGEGkdbilXHsyTBX5D3HSwcrSc9p20I= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13 h1:pfQ2sqNpMVK6xz2RbqLEL0GH87JOwSxPV2rzm8Zsb74= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.13/go.mod h1:NG7RXPUlqfsCLLFfi0+IpKN4sCB9D9fw/qTaSB+xRoU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/ecr v1.33.0 h1:/xDTA98i4mebwufX9B39eoQmKq4ffRgCnNbsTvkwaj4= +github.com/aws/aws-sdk-go-v2/service/ecr v1.33.0/go.mod h1:keOS9j4fv5ASh7dV29lIpGw2QgoJwGFAyMU0uPvfax4= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.6 h1:D9C5XIIciGM6mRZTi7zDdFsBsPsgzbsPwwN0wLCymnc= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.6/go.mod h1:Mrlicf7xXyuelm+q8XVMblDxJq2pKpKGXiWx/3uqjqs= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19 h1:rfprUlsdzgl7ZL2KlXiUAoJnI/VxfHCvDFr2QDFj6u4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.19/go.mod h1:SCWkEdRq8/7EK60NcvvQ6NXKuTcchAD4ROAsC37VEZE= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.7 h1:pIaGg+08llrP7Q5aiz9ICWbY8cqhTkyy+0SHvfzQpTc= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.7/go.mod h1:eEygMHnTKH/3kNp9Jr1n3PdejuSNcgwLe1dWgQtO0VQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7 h1:/Cfdu0XV3mONYKaOt1Gr0k1KvQzkzPyiKUdlWJqy+J4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.7/go.mod h1:bCbAxKDqNvkHxRaIMnyVPXPo+OaPRwvmgzMxbz1VKSA= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.7 h1:NKTa1eqZYw8tiHSRGpP0VtTdub/8KNk8sDkNPFaOKDE= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.7/go.mod h1:NXi1dIAGteSaRLqYgarlhP/Ij0cFT+qmCwiJqWh/U5o= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240918142057-e21b7a4e92d1 h1:SlKqHasm//EZ5eJI3J6+HQWMCw2QS8ha1V7JtMsX6Tc= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240918142057-e21b7a4e92d1/go.mod h1:TZP0PQALiGqPiKB35wBb4Z6E/3DCFVh/o2Eul3lVS9Q= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= @@ -89,6 +89,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk= github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -104,7 +106,6 @@ github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -124,8 +125,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo= github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8= -github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20240810014151-b8e87ed57b80 h1:PMk5q9/NEVTRdLB/HA8YIbseJbCPOT1B6X6A7gcuKAo= -github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20240810014151-b8e87ed57b80/go.mod h1:RB6ySfigDZP2t4gpmGD16CCTRxZRnB3MzoVQC1NxG18= +github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20240826191751-a07d1cab8700 h1:5Fj+qP/sqw8OLuSy7qkyrYqhFtqv1Iodx8o8ddrXbuI= +github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20240826191751-a07d1cab8700/go.mod h1:RB6ySfigDZP2t4gpmGD16CCTRxZRnB3MzoVQC1NxG18= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20240810014151-b8e87ed57b80 h1:73nGyDsn5/LTbSP3/jAgFwKwcKLHZzG/Anj+XLeAzQ4= github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20240810014151-b8e87ed57b80/go.mod h1:A/t21FsvDGrcFe4XuXz17iXnD/I5/uwKC++LHGi+Tv0= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -201,8 +202,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= @@ -241,6 +242,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -340,6 +343,8 @@ google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWn gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= @@ -352,14 +357,14 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= -k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ= -k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04= -k8s.io/apiextensions-apiserver v0.30.3 h1:oChu5li2vsZHx2IvnGP3ah8Nj3KyqG3kRSaKmijhB9U= -k8s.io/apiextensions-apiserver v0.30.3/go.mod h1:uhXxYDkMAvl6CJw4lrDN4CPbONkF3+XL9cacCT44kV4= -k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc= -k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= -k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k= -k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-aggregator v0.30.3 h1:hy5zfQ7p6BuJgc/XtGp3GBh2MPfOj6b1n3raKKMHOQE= @@ -368,12 +373,12 @@ k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8 h1:1Wof1cGQgA5pqgo8MxKPtf k8s.io/kube-openapi v0.0.0-20240808142205-8e686545bdb8/go.mod h1:Os6V6dZwLNii3vxFpxcNaTmH8LJJBkOTg1N0tOA0fvA= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.18.4 h1:87+guW1zhvuPLh1PHybKdYFLU0YJp4FhJRmiHvm5BZw= -sigs.k8s.io/controller-runtime v0.18.4/go.mod h1:TVoGrfdpbA9VRFaRnKgk9P5/atA0pMwq+f+msb9M8Sg= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/kyaml v0.17.2 h1:+AzvoJUY0kq4QAhH/ydPHHMRLijtUKiyVyh7fOSshr0= -sigs.k8s.io/kustomize/kyaml v0.17.2/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= +sigs.k8s.io/kustomize/kyaml v0.18.0 h1:OAsBL2NzDLu3X7t4HmdIB7GdRTePai4whzaoOJw+C/E= +sigs.k8s.io/kustomize/kyaml v0.18.0/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/pkg/handler/handler.go b/pkg/handler/handler.go index 8d06c3e..87ccfe8 100644 --- a/pkg/handler/handler.go +++ b/pkg/handler/handler.go @@ -45,6 +45,7 @@ type Handler struct { IgnoreErrors bool Config *rest.Config SkipPrefixes []string + Platform string } var resolveImageTags = resolve.ImageTags // override for testing @@ -75,7 +76,7 @@ func (h *Handler) Handle(ctx context.Context, req admission.Request) admission.R return h.admissionError(err) } - if err = resolveImageTags(ctx, h.Log, h.Config, r, h.SkipPrefixes); err != nil { + if err = resolveImageTags(ctx, h.Log, h.Config, r, h.SkipPrefixes, h.Platform); err != nil { return h.admissionError(err) } diff --git a/pkg/handler/handler_test.go b/pkg/handler/handler_test.go index d55e004..b77404c 100644 --- a/pkg/handler/handler_test.go +++ b/pkg/handler/handler_test.go @@ -122,7 +122,7 @@ func Test_Handle_NotPatchedWhenNoChange(t *testing.T) { }, }, } - resolveImageTags = func(_ context.Context, _ logr.Logger, _ *rest.Config, _ *yaml.RNode, _ []string) error { + resolveImageTags = func(_ context.Context, _ logr.Logger, _ *rest.Config, _ *yaml.RNode, _ []string, platform string) error { return nil } h := &Handler{Log: log} @@ -145,7 +145,7 @@ func Test_Handle_Patch(t *testing.T) { }, } imageWithDigest := "registry.example.com/repository/image:tag@sha256:digest" - resolveImageTags = func(_ context.Context, _ logr.Logger, _ *rest.Config, n *yaml.RNode, _ []string) error { + resolveImageTags = func(_ context.Context, _ logr.Logger, _ *rest.Config, n *yaml.RNode, _ []string, platform string) error { return n.PipeE(yaml.Lookup("spec", "containers", "0", "image"), yaml.FieldSetter{StringValue: imageWithDigest}) } h := &Handler{Log: log} diff --git a/pkg/keychain/keychain.go b/pkg/keychain/keychain.go index 1f29183..54499c8 100644 --- a/pkg/keychain/keychain.go +++ b/pkg/keychain/keychain.go @@ -18,8 +18,6 @@ package keychain import ( "context" "fmt" - "io/ioutil" - "github.com/awslabs/amazon-ecr-credential-helper/ecr-login" "github.com/chrismellard/docker-credential-acr-env/pkg/credhelper" "github.com/go-logr/logr" @@ -27,13 +25,14 @@ import ( "github.com/google/go-containerregistry/pkg/authn/github" "github.com/google/go-containerregistry/pkg/authn/k8schain" "github.com/google/go-containerregistry/pkg/v1/google" + "io" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "sigs.k8s.io/kustomize/kyaml/yaml" ) var ( - amazonKeychain = authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithLogger(ioutil.Discard))) + amazonKeychain = authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithLogger(io.Discard))) azureKeychain = authn.NewKeychainFromHelper(credhelper.NewACRCredentialsHelper()) createClientFn = createClient // override for testing diff --git a/pkg/logging/klog.go b/pkg/logging/klog.go index 6fd78c4..fae7864 100644 --- a/pkg/logging/klog.go +++ b/pkg/logging/klog.go @@ -16,10 +16,10 @@ package logging import ( "github.com/go-logr/logr" - "k8s.io/klog/v2/klogr" + "k8s.io/klog/v2/textlogger" ) // CreateKlogLogger using Kubernetes klog func CreateKlogLogger() logr.Logger { - return klogr.New() + return textlogger.NewLogger(textlogger.NewConfig()) } diff --git a/pkg/resolve/resolve.go b/pkg/resolve/resolve.go index b057bb7..1e86112 100644 --- a/pkg/resolve/resolve.go +++ b/pkg/resolve/resolve.go @@ -19,6 +19,7 @@ package resolve import ( "context" "fmt" + v1 "github.com/google/go-containerregistry/pkg/v1" "strings" "github.com/go-logr/logr" @@ -45,7 +46,7 @@ var resolveTagFn = resolveTag // override for unit testing // - `spec.jobTemplate.spec.template.spec.initContainers` // The `config` input parameter can be null. In this case, the function // will not attempt to retrieve imagePullSecrets from the cluster. -func ImageTags(ctx context.Context, log logr.Logger, config *rest.Config, n *yaml.RNode, skipPrefixes []string) error { +func ImageTags(ctx context.Context, log logr.Logger, config *rest.Config, n *yaml.RNode, skipPrefixes []string, platform string) error { kc, err := keychain.Create(ctx, log, config, n) if err != nil { return fmt.Errorf("could not create keychain: %w", err) @@ -54,6 +55,7 @@ func ImageTags(ctx context.Context, log logr.Logger, config *rest.Config, n *yam Log: log, Keychain: kc, SkipPrefixes: &skipPrefixes, + Platform: platform, } // if input is a CronJob, we need to look up the image tags in the // `spec.jobTemplate.spec.template.spec` path as well @@ -80,6 +82,7 @@ type ImageTagFilter struct { Log logr.Logger Keychain authn.Keychain SkipPrefixes *[]string + Platform string } var _ yaml.Filter = &ImageTagFilter{} @@ -108,18 +111,29 @@ func (f *ImageTagFilter) filterImage(n *yaml.RNode) error { if strings.Contains(image, "@") { return nil // already has digest, skip } - digest, err := resolveTagFn(image, f.Keychain) + digest, err := resolveTagFn(image, f.Platform, f.Keychain) if err != nil { return fmt.Errorf("could not get digest for %s: %w", image, err) } f.Log.V(1).Info("resolved tag to digest", "image", image, "digest", digest) imageWithDigest := fmt.Sprintf("%s@%s", image, digest) - n.Pipe(yaml.Lookup("image"), yaml.Set(yaml.NewStringRNode(imageWithDigest))) + if _, err := n.Pipe(yaml.Lookup("image"), yaml.Set(yaml.NewStringRNode(imageWithDigest))); err != nil { + return fmt.Errorf("could not set image: %w", err) + } return nil } -func resolveTag(image string, keychain authn.Keychain) (string, error) { - return crane.Digest(image, +func resolveTag(image string, platform string, keychain authn.Keychain) (string, error) { + opts := []crane.Option{ crane.WithAuthFromKeychain(keychain), - crane.WithUserAgent(fmt.Sprintf("cloud-solutions/%s-%s", "k8s-digester", version.Version))) + crane.WithUserAgent(fmt.Sprintf("cloud-solutions/%s-%s", "k8s-digester", version.Version)), + } + if platform != "" { + pf, err := v1.ParsePlatform(platform) + if err != nil { + return "", err + } + opts = append(opts, crane.WithPlatform(pf)) + } + return crane.Digest(image, opts...) } diff --git a/pkg/resolve/resolve_test.go b/pkg/resolve/resolve_test.go index d380bf5..c85dfa1 100644 --- a/pkg/resolve/resolve_test.go +++ b/pkg/resolve/resolve_test.go @@ -19,6 +19,8 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/stretchr/testify/assert" "strings" "testing" @@ -52,12 +54,17 @@ func init() { // Implementation of resolveTagFn that computes the SHA-256 sum of the // image name. We could make this simpler since it's just for testing, but // it means the digest values have the same 'shape' as real values. - resolveTagFn = func(image string, _ authn.Keychain) (string, error) { + resolveTagFn = func(image string, platform string, _ authn.Keychain) (string, error) { if image == "" || image == "error" { return "", fmt.Errorf("intentional error resolving image [%s]", image) } sumBytes := sha256.Sum256([]byte(image)) digest := strings.TrimRight(hex.EncodeToString(sumBytes[:]), "\r\n") + if platform != "" { + if _, err := v1.ParsePlatform(platform); err != nil { + return "", err + } + } return fmt.Sprintf("sha256:%s", digest), nil } } @@ -101,7 +108,7 @@ func Test_ImageTags_Pod(t *testing.T) { t.Fatalf("could not create pod node: %v", err) } - if err := ImageTags(ctx, log, nil, node, []string{}); err != nil { + if err := ImageTags(ctx, log, nil, node, []string{}, ""); err != nil { t.Fatalf("problem resolving image tags: %v", err) } t.Log(node.MustString()) @@ -118,7 +125,7 @@ func Test_ImageTags_Pod_Skip_Prefixes(t *testing.T) { t.Fatalf("could not create pod node: %v", err) } - if err := ImageTags(ctx, log, nil, node, []string{"skip1.local", "skip2.local"}); err != nil { + if err := ImageTags(ctx, log, nil, node, []string{"skip1.local", "skip2.local"}, ""); err != nil { t.Fatalf("problem resolving image tags: %v", err) } t.Log(node.MustString()) @@ -135,7 +142,7 @@ func Test_ImageTags_CronJob(t *testing.T) { t.Fatalf("could not create pod node: %v", err) } - if err := ImageTags(ctx, log, nil, node, []string{}); err != nil { + if err := ImageTags(ctx, log, nil, node, []string{}, ""); err != nil { t.Fatalf("problem resolving image tags: %v", err) } t.Log(node.MustString()) @@ -152,7 +159,7 @@ func Test_ImageTags_Deployment(t *testing.T) { t.Fatalf("could not create deployment node: %v", err) } - if err := ImageTags(ctx, log, nil, node, []string{}); err != nil { + if err := ImageTags(ctx, log, nil, node, []string{}, ""); err != nil { t.Fatalf("problem resolving image tags: %v", err) } t.Log(node.MustString()) @@ -163,6 +170,29 @@ func Test_ImageTags_Deployment(t *testing.T) { assertContainer(t, node, "image3@sha256:b0542da3f90bad69318e16ec7fcb6b13b089971886999e08bec91cea34891f0f", "spec", "template", "spec", "initContainers", "[name=initcontainer1]") } +func Test_ImageTags_ForPlatform(t *testing.T) { + node, err := createDeploymentNode([]string{"image0", "image1"}, []string{"image2", "image3"}) + if err != nil { + t.Fatalf("could not create deployment node: %v", err) + } + + if err := ImageTags(ctx, log, nil, node, []string{}, "linux/amd64"); err != nil { + t.Fatalf("problem resolving image tags: %v", err) + } + t.Log(node.MustString()) +} + +func Test_ImageTags_InvalidPlatform(t *testing.T) { + node, err := createDeploymentNode([]string{"image0", "image1"}, []string{"image2", "image3"}) + if err != nil { + t.Fatalf("could not create deployment node: %v", err) + } + + err = ImageTags(ctx, log, nil, node, []string{}, "some/other/linux/variant") + assert.ErrorContains(t, err, "too many slashes in platform spec") + t.Log(node.MustString()) +} + func assertContainer(t *testing.T, n *yaml.RNode, imageWithDigest string, path ...string) { container, err := n.Pipe(yaml.Lookup(path...), yaml.Get("image")) if err != nil { diff --git a/pkg/util/pod_info.go b/pkg/util/pod_info.go index 995e25b..2c239fe 100644 --- a/pkg/util/pod_info.go +++ b/pkg/util/pod_info.go @@ -15,7 +15,6 @@ package util import ( - "io/ioutil" "os" ) @@ -27,7 +26,7 @@ func GetPodName() string { if found { return pod } - podb, err := ioutil.ReadFile("/etc/hostname") + podb, err := os.ReadFile("/etc/hostname") if err == nil && len(podb) > 0 { return string(podb) } @@ -40,7 +39,7 @@ func GetNamespace() string { if found { return ns } - nsb, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") + nsb, err := os.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") if err == nil && len(nsb) > 0 { return string(nsb) }