From 6496163482629ca23de9e022ff806ed66953951d Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 07:20:51 -0600 Subject: [PATCH 1/8] feat: oci client [WIP] Signed-off-by: Tyler Gillson --- go.mod | 47 ++++++- go.sum | 116 +++++++++++++++++- .../controller/validatorconfig_controller.go | 15 ++- pkg/oci/oci_client.go | 112 +++++++++++++++++ 4 files changed, 283 insertions(+), 7 deletions(-) create mode 100644 pkg/oci/oci_client.go diff --git a/go.mod b/go.mod index 652e9fa7..4f13fba1 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,10 @@ require ( buf.build/gen/go/spectrocloud/spectro-cleanup/connectrpc/go v1.16.2-20240205164452-95dfd137cb54.1 buf.build/gen/go/spectrocloud/spectro-cleanup/protocolbuffers/go v1.34.2-20240205164452-95dfd137cb54.2 connectrpc.com/connect v1.16.2 + github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240708141356-efa334f881fc + github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 github.com/go-logr/logr v1.4.2 + github.com/google/go-containerregistry v0.20.0 github.com/onsi/ginkgo/v2 v2.19.0 github.com/onsi/gomega v1.33.1 github.com/pkg/errors v0.9.1 @@ -24,10 +27,42 @@ require ( ) require ( + cloud.google.com/go/compute v1.23.3 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/Azure/azure-sdk-for-go v46.4.0+incompatible // indirect + github.com/Azure/go-autorest v14.2.0+incompatible // indirect + github.com/Azure/go-autorest/autorest v0.11.28 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.21 // indirect + github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect + github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect + github.com/Azure/go-autorest/logger v0.2.1 // indirect + github.com/Azure/go-autorest/tracing v0.6.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.30.1 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.24 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.24 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.13 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.13 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect + github.com/aws/aws-sdk-go-v2/service/ecr v1.30.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.1 // 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.15 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 // indirect + github.com/aws/smithy-go v1.20.3 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/docker/cli v24.0.0+incompatible // indirect + github.com/docker/distribution v2.8.2+incompatible // indirect + github.com/docker/docker v24.0.0+incompatible // indirect + github.com/docker/docker-credential-helpers v0.8.2 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -38,6 +73,7 @@ require ( github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobuffalo/flect v1.0.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect @@ -47,23 +83,32 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/imdario/mergo v0.3.13 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.17.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc3 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.45.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.9.0 // indirect + github.com/vbatts/tar-split v0.11.3 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect diff --git a/go.sum b/go.sum index 3f2c9cb1..04a48c88 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,36 @@ buf.build/gen/go/spectrocloud/spectro-cleanup/connectrpc/go v1.16.2-202402051644 buf.build/gen/go/spectrocloud/spectro-cleanup/connectrpc/go v1.16.2-20240205164452-95dfd137cb54.1/go.mod h1:bqoQOw8W1G5zi7Kwiqw0Cov3HU9mv+Z8aFnFUhTEWFI= buf.build/gen/go/spectrocloud/spectro-cleanup/protocolbuffers/go v1.34.2-20240205164452-95dfd137cb54.2 h1:XFGx+iSe54xF55xfdmDvDxs6w6JwFI1zM/a8kqbMiIA= buf.build/gen/go/spectrocloud/spectro-cleanup/protocolbuffers/go v1.34.2-20240205164452-95dfd137cb54.2/go.mod h1:+5E+swTLrpHN9s3rESZ69ywgLIBTeW+wxXdAGiNZyXY= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= connectrpc.com/connect v1.16.2 h1:ybd6y+ls7GOlb7Bh5C8+ghA6SvCBajHwxssO2CGFjqE= connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc= +github.com/Azure/azure-sdk-for-go v46.4.0+incompatible h1:fCN6Pi+tEiEwFa8RSmtVlFHRXEZ+DJm9gfx/MKqYWw4= +github.com/Azure/azure-sdk-for-go v46.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= +github.com/Azure/go-autorest/autorest v0.11.28 h1:ndAExarwr5Y+GaHE6VCaY1kyS/HwwGGyuimVhWsHOEM= +github.com/Azure/go-autorest/autorest v0.11.28/go.mod h1:MrkzG3Y3AH668QyF9KRk5neJnGgmhQ6krbhR8Q5eMvA= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/adal v0.9.21 h1:jjQnVFXPfekaqb8vIsv2G1lxshoW+oGv4MDlhRtnYZk= +github.com/Azure/go-autorest/autorest/adal v0.9.21/go.mod h1:zua7mBUaCc5YnSLKYgGJR/w5ePdMDA6H56upLsHzA9U= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.11 h1:P6bYXFoao05z5uhOQzbC3Qd8JqF3jUoocoTeIxkp2cA= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.11/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 h1:0W/yGmFdTIT77fvdlGZ0LMISoLHFJ7Tx4U0yeB+uFs4= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.5/go.mod h1:ADQAXrkgm7acgWVUNamOgh8YNrv4p27l3Wc55oVfpzg= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= @@ -16,23 +44,70 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go-v2 v1.30.1 h1:4y/5Dvfrhd1MxRDD77SrfsDaj8kUkkljU7XE83NPV+o= +github.com/aws/aws-sdk-go-v2 v1.30.1/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc= +github.com/aws/aws-sdk-go-v2/config v1.27.24 h1:NM9XicZ5o1CBU/MZaHwFtimRpWx9ohAUAqkG6AqSqPo= +github.com/aws/aws-sdk-go-v2/config v1.27.24/go.mod h1:aXzi6QJTuQRVVusAO8/NxpdTeTyr/wRcybdDtfUwJSs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.24 h1:YclAsrnb1/GTQNt2nzv+756Iw4mF8AOzcDfweWwwm/M= +github.com/aws/aws-sdk-go-v2/credentials v1.17.24/go.mod h1:Hld7tmnAkoBQdTMNYZGzztzKRdA4fCdn9L83LOoigac= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9 h1:Aznqksmd6Rfv2HQN9cpqIV/lQRMaIpJkLLaJ1ZI76no= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.9/go.mod h1:WQr3MY7AxGNxaqAtsDWn+fBxmd4XvLkzeqQ8P1VM0/w= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.13 h1:5SAoZ4jYpGH4721ZNoS1znQrhOfZinOhc4XuTXx/nVc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.13/go.mod h1:+rdA6ZLpaSeM7tSg/B0IEDinCIBJGmW8rKDFkYpP04g= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.13 h1:WIijqeaAO7TYFLbhsZmi2rgLEAtWOC1LhxCAVTJlSKw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.13/go.mod h1:i+kbfa76PQbWw/ULoWnp51EYVWH4ENln76fLQE3lXT8= +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.30.1 h1:zV3FlyuyPzfyFOXKu6mJW9JBGzdtOgpdlj3va+naOD8= +github.com/aws/aws-sdk-go-v2/service/ecr v1.30.1/go.mod h1:l0zC7cSb2vAH1fr8+BRlolWT9cwlKpbRC8PjW6tyyIU= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.1 h1:54/7zy+oA2ep9UzWjAtccawCj3ZAXhMXxwBg0yNRxTA= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.1/go.mod h1:2UjSvHCwdRoPF17osaRvfBXuo32KPSvTlGMii5YbjyU= +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.15 h1:I9zMeF107l0rJrpnHpjEiiTSCKYAIw8mALiXcPsGBiA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.15/go.mod h1:9xWJ3Q/S6Ojusz1UIkfycgD1mGirJfLLKqq3LPT7WN8= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.1 h1:p1GahKIjyMDZtiKoIn0/jAj/TkMzfzndDv5+zi2Mhgc= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.1/go.mod h1:/vWdhoIoYA5hYoPZ6fm7Sv4d8701PiG5VKe8/pPJL60= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2 h1:ORnrOK0C4WmYV/uYt3koHEWBLYsRDwk2Np+eEoyV4Z0= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.2/go.mod h1:xyFHA4zGxgYkdD73VeezHt3vSKEG9EmFnGwoKlP00u4= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.1 h1:+woJ607dllHJQtsnJLi52ycuqHMwlW+Wqm2Ppsfp4nQ= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.1/go.mod h1:jiNR3JqT15Dm+QWq2SRgh0x0bCNSRP2L25+CqPNpJlQ= +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-20240708141356-efa334f881fc h1:i/hSTHoe0WO1I7N5BCyB3Ei6PDtOXn82e3YSs9W4F4Y= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240708141356-efa334f881fc/go.mod h1:vSzBu9U6tslAOAc0l7k5kx2ipWxrNezy0LZEWK3472A= 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/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= +github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= +github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= +github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0= github.com/coredns/caddy v1.1.0/go.mod h1:A6ntJQlAWuQfFlsd9hvigKbo2WS0VUs2l1e2F+BawD4= github.com/coredns/corefile-migration v1.0.21 h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE= github.com/coredns/corefile-migration v1.0.21/go.mod h1:XnhgULOEouimnzgn0t4WPuFDN2/PJQcTxdWKC5eXNGE= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qeXMx3O0wqM= +github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= +github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.0+incompatible h1:z4bf8HvONXX9Tde5lGBMQ7yCJgNahmJumdrStZAbeY4= +github.com/docker/docker v24.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.8.2 h1:bX3YxiGzFP5sOXWc3bTPEXdEaZSeVMrFgOr3T+zrFAo= +github.com/docker/docker-credential-helpers v0.8.2/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= @@ -59,6 +134,10 @@ github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -72,6 +151,8 @@ github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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.0 h1:wRqHpOeVh3DnenOrPy9xDOLdnLatiGuuNRVelR2gSbg= +github.com/google/go-containerregistry v0.20.0/go.mod h1:YCMFNQeeXeLF+dnhhWkqDItx/JSkH01j1Kis4PsjzFI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -86,12 +167,18 @@ github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4 github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -105,6 +192,8 @@ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvls github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -120,10 +209,13 @@ github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8= +github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= @@ -134,8 +226,12 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.13.0 h1:7my/pR2ubZJ9912p9FtvALYpbt0cQPAqkRy2jaSI1PQ= github.com/slack-go/slack v0.13.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= @@ -149,11 +245,15 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= +github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck= +github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= @@ -165,6 +265,9 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= @@ -176,6 +279,8 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= @@ -188,13 +293,20 @@ golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220906165534-d0df966e6959/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -232,6 +344,8 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI= k8s.io/apiextensions-apiserver v0.30.1 h1:4fAJZ9985BmpJG6PkoxVRpXv9vmPUOVzl614xarePws= diff --git a/internal/controller/validatorconfig_controller.go b/internal/controller/validatorconfig_controller.go index e23185a4..509c2570 100644 --- a/internal/controller/validatorconfig_controller.go +++ b/internal/controller/validatorconfig_controller.go @@ -46,6 +46,7 @@ import ( v1alpha1 "github.com/validator-labs/validator/api/v1alpha1" "github.com/validator-labs/validator/pkg/helm" helmrelease "github.com/validator-labs/validator/pkg/helm/release" + "github.com/validator-labs/validator/pkg/oci" ) const ( @@ -183,18 +184,22 @@ func (r *ValidatorConfigReconciler) redeployIfNeeded(ctx context.Context, vc *v1 if strings.HasPrefix(p.Chart.Repository, "oci://") { r.Log.V(0).Info("Pulling plugin Helm chart", "name", p.Chart.Name) - opts.Untar = true - opts.UntarDir = "/charts" + opts.Path = fmt.Sprintf("/charts/%s", opts.Chart) opts.Version = strings.TrimPrefix(opts.Version, "v") - if err := r.HelmClient.Pull(*opts); err != nil { - r.Log.V(0).Error(err, "failed to pull Helm chart from OCI repository") + ociClient := oci.NewOCIClient(oci.WithMultiAuth()) + ociOpts := oci.ImageOptions{ + Ref: fmt.Sprintf("%s/%s:%s", opts.Repo, opts.Chart, opts.Version), + OutDir: opts.Path, + OutFile: opts.Chart, + } + if err := ociClient.PullChart(ociOpts); err != nil { + r.Log.V(0).Error(err, "failed to pull Helm chart from OCI registry") conditions[i] = r.buildHelmChartCondition(p.Chart.Name, err) continue } r.Log.V(0).Info("Reconfiguring Helm options to deploy local chart", "name", p.Chart.Name) - opts.Path = fmt.Sprintf("/charts/%s", opts.Chart) opts.Chart = "" cleanupLocalChart = true } diff --git a/pkg/oci/oci_client.go b/pkg/oci/oci_client.go new file mode 100644 index 00000000..1311ab55 --- /dev/null +++ b/pkg/oci/oci_client.go @@ -0,0 +1,112 @@ +// Package oci contains the OCI client interface and implementation. +package oci + +import ( + "fmt" + "io" + "os" + "path/filepath" + + "github.com/awslabs/amazon-ecr-credential-helper/ecr-login" + "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/api" + acr "github.com/chrismellard/docker-credential-acr-env/pkg/credhelper" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/google/go-containerregistry/pkg/name" + v1 "github.com/google/go-containerregistry/pkg/v1" + "github.com/google/go-containerregistry/pkg/v1/google" + "github.com/google/go-containerregistry/pkg/v1/remote" + klog "k8s.io/klog/v2" +) + +// Client is an interface for interacting with an OCI registry. +type Client struct { + auth authn.Keychain +} + +// ImageOptions defines the options for pulling an image. +type ImageOptions struct { + Ref string + OutDir string + OutFile string +} + +// Option is a functional option for configuring the OCI client. +type Option func(*Client) + +// NewOCIClient creates a new OCI client with the given options. +func NewOCIClient(opts ...Option) *Client { + c := &Client{} + for _, o := range opts { + o(c) + } + return c +} + +// WithMultiAuth configures the OCI client with multiple authentication keychains. +func WithMultiAuth() Option { + return func(c *Client) { + c.auth = authn.NewMultiKeychain( + authn.DefaultKeychain, + google.Keychain, + authn.NewKeychainFromHelper(ecr.NewECRHelper(ecr.WithClientFactory(api.DefaultClientFactory{}))), + authn.NewKeychainFromHelper(acr.ACRCredHelper{}), + ) + } +} + +// PullChart pulls a Helm chart from the given ImageOptions. +func (c Client) PullChart(opts ImageOptions) error { + ref, err := name.ParseReference(opts.Ref) + if err != nil { + return fmt.Errorf("failed to parse chart reference: %w", err) + } + // Assume the chart is in the first layer & extract it + layers, err := c.PullImage(ref) + if err != nil { + return fmt.Errorf("failed to pull chart: %w", err) + } + return c.WriteLayer(opts, layers[0]) +} + +// PullImage pulls an image from the given name.Reference. +func (c Client) PullImage(ref name.Reference) ([]v1.Layer, error) { + img, err := remote.Image(ref, remote.WithAuthFromKeychain(c.auth)) + if err != nil { + return nil, fmt.Errorf("failed to fetch image from registry: %w", err) + } + return img.Layers() +} + +// WriteLayer writes a layer to the filesystem. +func (c Client) WriteLayer(opts ImageOptions, layer v1.Layer) error { + r, err := layer.Uncompressed() + if err != nil { + return fmt.Errorf("failed to uncompress layer: %w", err) + } + defer func() { + closeErr := r.Close() + if err == nil { + err = closeErr + } else { + klog.Errorf("failed to close layer reader: %v", closeErr) + } + }() + + content, err := io.ReadAll(r) + if err != nil { + return fmt.Errorf("failed to read layer content: %w", err) + } + + if err := os.MkdirAll(opts.OutDir, os.ModePerm); err != nil { + return fmt.Errorf("failed to create output directory: %w", err) + } + + path := filepath.Join(opts.OutDir, fmt.Sprintf("%s.tgz", opts.OutFile)) + + if err := os.WriteFile(path, content, os.ModePerm); err != nil { + return fmt.Errorf("failed to write layer file: %w", err) + } + + klog.Infof("Layer saved successfully to %s\n", path) + return nil +} From 1034487c5be60298563b010cbb311b581e3d2573 Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 07:27:12 -0600 Subject: [PATCH 2/8] chore: reinstate CAFile Signed-off-by: Tyler Gillson --- api/v1alpha1/validatorconfig_types.go | 3 +++ .../bases/validation.spectrocloud.labs_validatorconfigs.yaml | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/api/v1alpha1/validatorconfig_types.go b/api/v1alpha1/validatorconfig_types.go index e78fe9f5..7c7808cb 100644 --- a/api/v1alpha1/validatorconfig_types.go +++ b/api/v1alpha1/validatorconfig_types.go @@ -60,6 +60,9 @@ type HelmChart struct { // Version of the Helm chart. Version string `json:"version" yaml:"version"` + // CAFile is the path to the CA certificate for the Helm repository. + CAFile string `json:"caFile,omitempty" yaml:"caFile,omitempty"` + // InsecureSkipTLSVerify skips the verification of the server's certificate chain and host name. InsecureSkipTLSVerify bool `json:"insecureSkipVerify,omitempty" yaml:"insecureSkipVerify,omitempty"` diff --git a/config/crd/bases/validation.spectrocloud.labs_validatorconfigs.yaml b/config/crd/bases/validation.spectrocloud.labs_validatorconfigs.yaml index e732032f..e1e422f6 100644 --- a/config/crd/bases/validation.spectrocloud.labs_validatorconfigs.yaml +++ b/config/crd/bases/validation.spectrocloud.labs_validatorconfigs.yaml @@ -52,6 +52,10 @@ spec: description: AuthSecretName is the name of the K8s secret containing the authentication details for the Helm repository. type: string + caFile: + description: CAFile is the path to the CA certificate for + the Helm repository. + type: string insecureSkipVerify: description: InsecureSkipTLSVerify skips the verification of the server's certificate chain and host name. From 96e862da9db76516550ef722c099018ae4a8a729 Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 07:45:44 -0600 Subject: [PATCH 3/8] docs: justify OCI client Signed-off-by: Tyler Gillson --- internal/controller/validatorconfig_controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/controller/validatorconfig_controller.go b/internal/controller/validatorconfig_controller.go index 509c2570..7dc74ee2 100644 --- a/internal/controller/validatorconfig_controller.go +++ b/internal/controller/validatorconfig_controller.go @@ -187,6 +187,7 @@ func (r *ValidatorConfigReconciler) redeployIfNeeded(ctx context.Context, vc *v1 opts.Path = fmt.Sprintf("/charts/%s", opts.Chart) opts.Version = strings.TrimPrefix(opts.Version, "v") + // use OCI client instead of Helm client due to https://github.com/helm/helm/issues/12810 ociClient := oci.NewOCIClient(oci.WithMultiAuth()) ociOpts := oci.ImageOptions{ Ref: fmt.Sprintf("%s/%s:%s", opts.Repo, opts.Chart, opts.Version), From 5b6228189e98e13e0e321b4342c97d6b4225c0da Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 07:52:35 -0600 Subject: [PATCH 4/8] feat: hauler support for air-gap [WIP] Signed-off-by: Tyler Gillson --- internal/controller/validatorconfig_controller.go | 4 ++-- pkg/oci/oci_client.go | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/controller/validatorconfig_controller.go b/internal/controller/validatorconfig_controller.go index 7dc74ee2..ba2223a6 100644 --- a/internal/controller/validatorconfig_controller.go +++ b/internal/controller/validatorconfig_controller.go @@ -181,7 +181,7 @@ func (r *ValidatorConfigReconciler) redeployIfNeeded(ctx context.Context, vc *v1 } var cleanupLocalChart bool - if strings.HasPrefix(p.Chart.Repository, "oci://") { + if strings.HasPrefix(p.Chart.Repository, oci.Scheme) { r.Log.V(0).Info("Pulling plugin Helm chart", "name", p.Chart.Name) opts.Path = fmt.Sprintf("/charts/%s", opts.Chart) @@ -190,7 +190,7 @@ func (r *ValidatorConfigReconciler) redeployIfNeeded(ctx context.Context, vc *v1 // use OCI client instead of Helm client due to https://github.com/helm/helm/issues/12810 ociClient := oci.NewOCIClient(oci.WithMultiAuth()) ociOpts := oci.ImageOptions{ - Ref: fmt.Sprintf("%s/%s:%s", opts.Repo, opts.Chart, opts.Version), + Ref: fmt.Sprintf("%s/%s:%s", strings.TrimPrefix(opts.Repo, oci.Scheme), opts.Chart, opts.Version), OutDir: opts.Path, OutFile: opts.Chart, } diff --git a/pkg/oci/oci_client.go b/pkg/oci/oci_client.go index 1311ab55..89997c00 100644 --- a/pkg/oci/oci_client.go +++ b/pkg/oci/oci_client.go @@ -18,6 +18,9 @@ import ( klog "k8s.io/klog/v2" ) +// Scheme is the URI scheme for an OCI registry. +const Scheme = "oci://" + // Client is an interface for interacting with an OCI registry. type Client struct { auth authn.Keychain From 146af8d3edd697bfaf16f60b3f0dd236014df19e Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 08:21:21 -0600 Subject: [PATCH 5/8] feat: hauler support for air-gap [WIP] Signed-off-by: Tyler Gillson --- pkg/oci/oci_client.go | 16 +++++++----- pkg/util/file.go | 57 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 pkg/util/file.go diff --git a/pkg/oci/oci_client.go b/pkg/oci/oci_client.go index 89997c00..d0c5604d 100644 --- a/pkg/oci/oci_client.go +++ b/pkg/oci/oci_client.go @@ -15,6 +15,7 @@ import ( v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/google/go-containerregistry/pkg/v1/google" "github.com/google/go-containerregistry/pkg/v1/remote" + "github.com/validator-labs/validator/pkg/util" klog "k8s.io/klog/v2" ) @@ -63,12 +64,19 @@ func (c Client) PullChart(opts ImageOptions) error { if err != nil { return fmt.Errorf("failed to parse chart reference: %w", err) } + + path := filepath.Join(opts.OutDir, opts.OutFile) + // Assume the chart is in the first layer & extract it layers, err := c.PullImage(ref) if err != nil { return fmt.Errorf("failed to pull chart: %w", err) } - return c.WriteLayer(opts, layers[0]) + if err := c.WriteLayer(opts, layers[0], path); err != nil { + return fmt.Errorf("failed to write chart layer: %w", err) + } + + return util.Gzip(path, fmt.Sprintf("%s.tgz", path)) } // PullImage pulls an image from the given name.Reference. @@ -81,7 +89,7 @@ func (c Client) PullImage(ref name.Reference) ([]v1.Layer, error) { } // WriteLayer writes a layer to the filesystem. -func (c Client) WriteLayer(opts ImageOptions, layer v1.Layer) error { +func (c Client) WriteLayer(opts ImageOptions, layer v1.Layer, path string) error { r, err := layer.Uncompressed() if err != nil { return fmt.Errorf("failed to uncompress layer: %w", err) @@ -99,13 +107,9 @@ func (c Client) WriteLayer(opts ImageOptions, layer v1.Layer) error { if err != nil { return fmt.Errorf("failed to read layer content: %w", err) } - if err := os.MkdirAll(opts.OutDir, os.ModePerm); err != nil { return fmt.Errorf("failed to create output directory: %w", err) } - - path := filepath.Join(opts.OutDir, fmt.Sprintf("%s.tgz", opts.OutFile)) - if err := os.WriteFile(path, content, os.ModePerm); err != nil { return fmt.Errorf("failed to write layer file: %w", err) } diff --git a/pkg/util/file.go b/pkg/util/file.go new file mode 100644 index 00000000..611c90dc --- /dev/null +++ b/pkg/util/file.go @@ -0,0 +1,57 @@ +package util + +import ( + "compress/gzip" + "fmt" + "io" + "os" + + klog "k8s.io/klog/v2" +) + +// Gzip compresses a file using gzip and writes the result to disk +func Gzip(input, output string) error { + // Open input file + inputFile, err := os.Open(input) + if err != nil { + return fmt.Errorf("failed to open input file: %w", err) + } + defer func() { + closeErr := inputFile.Close() + if err == nil { + err = closeErr + } else { + klog.Errorf("failed to close input file: %v", err) + } + }() + + // Create the output .tgz file + outputFile, err := os.Create(output) + if err != nil { + return fmt.Errorf("failed to create output file: %w", err) + } + defer func() { + closeErr := outputFile.Close() + if err == nil { + err = closeErr + } else { + klog.Errorf("failed to close output file: %v", err) + } + }() + + // Do the gzip + gzipWriter := gzip.NewWriter(outputFile) + defer func() { + closeErr := gzipWriter.Close() + if err == nil { + err = closeErr + } else { + klog.Errorf("failed to close gzipWriter: %v", err) + } + }() + if _, err := io.Copy(gzipWriter, inputFile); err != nil { + return fmt.Errorf("failed to write compressed data: %w", err) + } + + return nil +} From 85fb9fea5cbf3821245930324e30a41ddea1ad03 Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 08:24:25 -0600 Subject: [PATCH 6/8] feat: hauler support for air-gap [WIP] Signed-off-by: Tyler Gillson --- internal/controller/validatorconfig_controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/controller/validatorconfig_controller.go b/internal/controller/validatorconfig_controller.go index ba2223a6..b1bd582e 100644 --- a/internal/controller/validatorconfig_controller.go +++ b/internal/controller/validatorconfig_controller.go @@ -201,6 +201,7 @@ func (r *ValidatorConfigReconciler) redeployIfNeeded(ctx context.Context, vc *v1 } r.Log.V(0).Info("Reconfiguring Helm options to deploy local chart", "name", p.Chart.Name) + opts.Path = fmt.Sprintf("%s/%s.tgz", opts.Path, opts.Chart) opts.Chart = "" cleanupLocalChart = true } From 827d477b7678eea42225f2788153ac4038e38316 Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 08:53:41 -0600 Subject: [PATCH 7/8] feat: hauler support for air-gap [WIP] Signed-off-by: Tyler Gillson --- .../controller/validatorconfig_controller.go | 5 +- pkg/oci/oci_client.go | 55 +++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/internal/controller/validatorconfig_controller.go b/internal/controller/validatorconfig_controller.go index b1bd582e..be6eb111 100644 --- a/internal/controller/validatorconfig_controller.go +++ b/internal/controller/validatorconfig_controller.go @@ -188,7 +188,10 @@ func (r *ValidatorConfigReconciler) redeployIfNeeded(ctx context.Context, vc *v1 opts.Version = strings.TrimPrefix(opts.Version, "v") // use OCI client instead of Helm client due to https://github.com/helm/helm/issues/12810 - ociClient := oci.NewOCIClient(oci.WithMultiAuth()) + ociClient := oci.NewOCIClient( + oci.WithMultiAuth(), + oci.WithTLSConfig(opts.InsecureSkipTLSVerify, opts.CaFile), + ) ociOpts := oci.ImageOptions{ Ref: fmt.Sprintf("%s/%s:%s", strings.TrimPrefix(opts.Repo, oci.Scheme), opts.Chart, opts.Version), OutDir: opts.Path, diff --git a/pkg/oci/oci_client.go b/pkg/oci/oci_client.go index d0c5604d..4df33a90 100644 --- a/pkg/oci/oci_client.go +++ b/pkg/oci/oci_client.go @@ -2,8 +2,11 @@ package oci import ( + "crypto/tls" + "crypto/x509" "fmt" "io" + "net/http" "os" "path/filepath" @@ -24,7 +27,9 @@ const Scheme = "oci://" // Client is an interface for interacting with an OCI registry. type Client struct { - auth authn.Keychain + auth authn.Keychain + caFile string + insecureSkipTLSVerify bool } // ImageOptions defines the options for pulling an image. @@ -46,6 +51,14 @@ func NewOCIClient(opts ...Option) *Client { return c } +// WithTLSConfig configures the OCI client with the given TLS options. +func WithTLSConfig(insecureSkipTLSVerify bool, caFile string) Option { + return func(c *Client) { + c.caFile = caFile + c.insecureSkipTLSVerify = insecureSkipTLSVerify + } +} + // WithMultiAuth configures the OCI client with multiple authentication keychains. func WithMultiAuth() Option { return func(c *Client) { @@ -72,7 +85,7 @@ func (c Client) PullChart(opts ImageOptions) error { if err != nil { return fmt.Errorf("failed to pull chart: %w", err) } - if err := c.WriteLayer(opts, layers[0], path); err != nil { + if err := c.WriteLayer(layers[0], path, opts); err != nil { return fmt.Errorf("failed to write chart layer: %w", err) } @@ -81,7 +94,14 @@ func (c Client) PullChart(opts ImageOptions) error { // PullImage pulls an image from the given name.Reference. func (c Client) PullImage(ref name.Reference) ([]v1.Layer, error) { - img, err := remote.Image(ref, remote.WithAuthFromKeychain(c.auth)) + transport, err := c.transport() + if err != nil { + return nil, err + } + img, err := remote.Image(ref, + remote.WithAuthFromKeychain(c.auth), + remote.WithTransport(transport), + ) if err != nil { return nil, fmt.Errorf("failed to fetch image from registry: %w", err) } @@ -89,7 +109,7 @@ func (c Client) PullImage(ref name.Reference) ([]v1.Layer, error) { } // WriteLayer writes a layer to the filesystem. -func (c Client) WriteLayer(opts ImageOptions, layer v1.Layer, path string) error { +func (c Client) WriteLayer(layer v1.Layer, path string, opts ImageOptions) error { r, err := layer.Uncompressed() if err != nil { return fmt.Errorf("failed to uncompress layer: %w", err) @@ -117,3 +137,30 @@ func (c Client) WriteLayer(opts ImageOptions, layer v1.Layer, path string) error klog.Infof("Layer saved successfully to %s\n", path) return nil } + +func (c Client) transport() (*http.Transport, error) { + transport := remote.DefaultTransport.(*http.Transport) + transport.TLSClientConfig = &tls.Config{} + + caCertPool, err := x509.SystemCertPool() + if err != nil { + return nil, fmt.Errorf("failed to load system cert pool: %w", err) + } + if c.caFile != "" { + bs, err := os.ReadFile(c.caFile) + if err != nil { + return nil, fmt.Errorf("failed to read CA cert file: %w", err) + } + if ok := caCertPool.AppendCertsFromPEM(bs); !ok { + return nil, fmt.Errorf("failed to append CA cert from %s", c.caFile) + } + } + + if c.insecureSkipTLSVerify { + transport.TLSClientConfig.InsecureSkipVerify = true + } + + transport.TLSClientConfig.RootCAs = caCertPool + + return transport, nil +} From 09e91bfa513220e3ffb6501f4220652775f1030e Mon Sep 17 00:00:00 2001 From: Tyler Gillson Date: Fri, 12 Jul 2024 12:57:39 -0600 Subject: [PATCH 8/8] chore: fix gosec issues Signed-off-by: Tyler Gillson --- pkg/oci/oci_client.go | 4 +++- pkg/util/file.go | 7 ++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkg/oci/oci_client.go b/pkg/oci/oci_client.go index 4df33a90..62f2cb48 100644 --- a/pkg/oci/oci_client.go +++ b/pkg/oci/oci_client.go @@ -140,7 +140,9 @@ func (c Client) WriteLayer(layer v1.Layer, path string, opts ImageOptions) error func (c Client) transport() (*http.Transport, error) { transport := remote.DefaultTransport.(*http.Transport) - transport.TLSClientConfig = &tls.Config{} + transport.TLSClientConfig = &tls.Config{ + MinVersion: tls.VersionTLS12, + } caCertPool, err := x509.SystemCertPool() if err != nil { diff --git a/pkg/util/file.go b/pkg/util/file.go index 611c90dc..bcb42b8a 100644 --- a/pkg/util/file.go +++ b/pkg/util/file.go @@ -11,8 +11,7 @@ import ( // Gzip compresses a file using gzip and writes the result to disk func Gzip(input, output string) error { - // Open input file - inputFile, err := os.Open(input) + inputFile, err := os.Open(input) // #nosec G304 if err != nil { return fmt.Errorf("failed to open input file: %w", err) } @@ -25,8 +24,7 @@ func Gzip(input, output string) error { } }() - // Create the output .tgz file - outputFile, err := os.Create(output) + outputFile, err := os.Create(output) // #nosec G304 if err != nil { return fmt.Errorf("failed to create output file: %w", err) } @@ -39,7 +37,6 @@ func Gzip(input, output string) error { } }() - // Do the gzip gzipWriter := gzip.NewWriter(outputFile) defer func() { closeErr := gzipWriter.Close()