diff --git a/kubetest2/go.mod b/kubetest2/go.mod index 09a935a69..5038907fb 100644 --- a/kubetest2/go.mod +++ b/kubetest2/go.mod @@ -1,12 +1,12 @@ module github.com/aws/aws-k8s-tester/kubetest2 -go 1.22.5 +go 1.23.2 -toolchain go1.23.0 +toolchain go1.23.4 require ( github.com/aws/aws-sdk-go v1.51.2 - github.com/aws/aws-sdk-go-v2 v1.32.6 + github.com/aws/aws-sdk-go-v2 v1.32.7 github.com/aws/aws-sdk-go-v2/config v1.27.8 github.com/aws/aws-sdk-go-v2/service/autoscaling v1.40.4 github.com/aws/aws-sdk-go-v2/service/cloudformation v1.48.0 @@ -18,31 +18,31 @@ require ( github.com/octago/sflags v0.2.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 - golang.org/x/crypto v0.25.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - k8s.io/api v0.31.0 - k8s.io/apimachinery v0.31.0 - k8s.io/client-go v0.31.0 + k8s.io/api v0.31.3 + k8s.io/apimachinery v0.31.3 + k8s.io/client-go v0.31.3 k8s.io/klog v1.0.0 k8s.io/klog/v2 v2.130.1 - sigs.k8s.io/controller-runtime v0.19.1 - sigs.k8s.io/karpenter v1.0.5 + sigs.k8s.io/controller-runtime v0.19.3 + sigs.k8s.io/karpenter v1.1.1 sigs.k8s.io/kubetest2 v0.0.0-20240309080311-0d7ca9ccb41e ) require ( - github.com/awslabs/operatorpkg v0.0.0-20240805231134-67d0acfb6306 // indirect + github.com/aws/aws-sdk-go-v2/service/iam v1.38.3 // indirect + github.com/awslabs/operatorpkg v0.0.0-20241205163410-0fff9f28d115 // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/zapr v1.3.0 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect - github.com/samber/lo v1.46.0 // indirect + github.com/samber/lo v1.47.0 // indirect github.com/x448/float16 v0.8.4 // indirect + golang.org/x/crypto v0.28.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/component-base v0.31.0 // indirect - knative.dev/pkg v0.0.0-20230712131115-7051d301e7f4 // indirect + k8s.io/apiextensions-apiserver v0.31.3 // indirect ) require ( @@ -84,8 +84,8 @@ require ( github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.17.8 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.4 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect github.com/aws/aws-sdk-go-v2/service/ecr v1.27.3 // indirect github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.3 // indirect @@ -119,7 +119,7 @@ require ( github.com/dimchansky/utfbom v1.1.1 // indirect github.com/docker/cli v25.0.4+incompatible // indirect github.com/docker/distribution v2.8.3+incompatible // indirect - github.com/docker/docker v27.1.1+incompatible // indirect + github.com/docker/docker v27.3.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/emicklei/go-restful/v3 v3.12.0 // indirect @@ -181,7 +181,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.9 // indirect github.com/knqyf263/go-rpmdb v0.1.0 // indirect github.com/letsencrypt/boulder v0.0.0-20240318162201-5e68cbe552b9 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -209,7 +209,7 @@ require ( github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect - github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_golang v1.20.5 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.55.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -266,16 +266,16 @@ require ( go.opentelemetry.io/otel/trace v1.28.0 // indirect go.step.sm/crypto v0.43.1 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect + go.uber.org/zap v1.27.0 + golang.org/x/mod v0.21.0 // indirect + golang.org/x/net v0.30.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.8.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 - golang.org/x/time v0.6.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/term v0.25.0 // indirect + golang.org/x/text v0.20.0 // indirect + golang.org/x/time v0.8.0 // indirect + golang.org/x/tools v0.26.0 // indirect golang.org/x/tools/go/vcs v0.1.0-deprecated // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/api v0.170.0 // indirect @@ -283,7 +283,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect google.golang.org/grpc v1.65.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + google.golang.org/protobuf v1.35.1 // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -292,7 +292,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/release v0.16.5 // indirect - k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 modernc.org/libc v1.45.2 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.7.2 // indirect diff --git a/kubetest2/go.sum b/kubetest2/go.sum index 374078df9..e61d3b108 100644 --- a/kubetest2/go.sum +++ b/kubetest2/go.sum @@ -132,6 +132,8 @@ github.com/aws/aws-sdk-go v1.51.2 h1:Ruwgz5aqIXin5Yfcgc+PCzoqW5tEGb9aDL/JWDsre7k github.com/aws/aws-sdk-go v1.51.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw= +github.com/aws/aws-sdk-go-v2 v1.32.7/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= github.com/aws/aws-sdk-go-v2/config v1.27.8 h1:0r8epOsiJ7YJz65MGcb8i91ehFp4kvvFe2qkq5oYeRI= github.com/aws/aws-sdk-go-v2/config v1.27.8/go.mod h1:XsmYKxYNuIhLsFddpNds+j9H5XKzjWDdg/SZngiwFio= github.com/aws/aws-sdk-go-v2/credentials v1.17.8 h1:WUdNLXbyNbU07V/WFrSOBXqZTDgmmMNMgUFzpYOKJhw= @@ -140,8 +142,12 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.4 h1:S+L2QSKhUuShih3aq9P/mkz github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.4/go.mod h1:nQ3how7DMnFMWiU1SpECohgC82fpn4cKZ875NDMmwtA= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 h1:I/5wmGMffY4happ8NOCuIUEWGUvvFp5NSeQcXl9RHcI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26/go.mod h1:FR8f4turZtNy6baO0KJ5FJUmXH/cSkI9fOngs0yl6mA= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 h1:zXFLuEuMMUOvEARXFUVJdfqZ4bvvSgdGRq/ATcrQxzM= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26/go.mod h1:3o2Wpy0bogG1kyOPrgkXA8pgIfEEv0+m19O9D5+W8y8= 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/autoscaling v1.40.4 h1:f4pkN5PVSqlGxD2gZvboz6SRaeoykgknflMPBVuhcGs= @@ -158,6 +164,8 @@ github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.3 h1:gaq/4fd2/bQeJ33m4csgL7 github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.23.3/go.mod h1:vn+Rz9fAFGJtDXbBmYdTc71Q8iF/W/uK1/ec93hinD8= github.com/aws/aws-sdk-go-v2/service/eks v1.53.0 h1:ACTxnLwL6YNmuYbxtp/VR3HGL9SWXU6VZkXPjWST9ZQ= github.com/aws/aws-sdk-go-v2/service/eks v1.53.0/go.mod h1:ZzOjZXGGUQxOq+T3xmfPLKCZe4OaB5vm1LdGaC8IPn4= +github.com/aws/aws-sdk-go-v2/service/iam v1.38.3 h1:2sFIoFzU1IEL9epJWubJm9Dhrn45aTNEJuwsesaCGnk= +github.com/aws/aws-sdk-go-v2/service/iam v1.38.3/go.mod h1:KzlNINwfr/47tKkEhgk0r10/OZq3rjtyWy0txL3lM+I= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc= @@ -176,8 +184,8 @@ github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240318154307-a1a918375412 h1:tfbmGNeOidVXzO1I7zo/WsT5QX7Aa0BGTbnEAE4FG3E= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20240318154307-a1a918375412/go.mod h1:kcUkjB9HwuV7PSck2b60kJtgDy+eTHWuAP0kb93FXsk= -github.com/awslabs/operatorpkg v0.0.0-20240805231134-67d0acfb6306 h1:0dzaVod1XLEc38H4IB+KOgStoCt8RkCVI4t+XsSPrWE= -github.com/awslabs/operatorpkg v0.0.0-20240805231134-67d0acfb6306/go.mod h1:7u2ugtOiWSvqqwNlnQ8W+2TjwnSTbHoMHnR1AKpKVMA= +github.com/awslabs/operatorpkg v0.0.0-20241205163410-0fff9f28d115 h1:9nhjY3dzCpEmhpQ0vMlhB7wqucAiftLjAIEQu8uT2J4= +github.com/awslabs/operatorpkg v0.0.0-20241205163410-0fff9f28d115/go.mod h1:TTs6HGuqmgdNyNlbdv29v1OoON+kQKVPojZgJaJVtNk= 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 v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= @@ -257,8 +265,8 @@ github.com/docker/cli v25.0.4+incompatible h1:DatRkJ+nrFoYL2HZUzjM5Z5sAmcA5XGp+A github.com/docker/cli v25.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v27.1.1+incompatible h1:hO/M4MtV36kzKldqnA37IWhebRA+LnqqcqDja6kVaKY= -github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI= +github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo= github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= @@ -428,8 +436,8 @@ github.com/google/licenseclassifier/v2 v2.0.0/go.mod h1:cOjbdH0kyC9R22sdQbYsFkto github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= -github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/tink/go v1.7.0 h1:6Eox8zONGebBFcCBqkVmt60LaWZa6xg1cl/DwAh/J1w= @@ -508,8 +516,8 @@ github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4 github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 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.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/knqyf263/go-rpmdb v0.1.0 h1:pOgjtOGtW0B+ibY905hP3ETrYFmLZsHiReKsplcs+to= github.com/knqyf263/go-rpmdb v0.1.0/go.mod h1:9LQcoMCMQ9vrF7HcDtXfvqGO4+ddxFQ8+YF/0CVGDww= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -579,14 +587,14 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.19.1 h1:QXgq3Z8Crl5EL1WBAC98A5sEBHARrAJNzAmMxzLcRF0= -github.com/onsi/ginkgo/v2 v2.19.1/go.mod h1:O3DtEWQkPa/F7fBMgmZQKKsluAy8pd3rEQdrjkPb9zA= +github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg= +github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/onsi/gomega v1.36.0 h1:Pb12RlruUtj4XUuPUqeEWc6j5DkVVVA49Uf6YLfC95Y= +github.com/onsi/gomega v1.36.0/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/open-policy-agent/opa v0.62.1 h1:UcxBQ0fe6NEjkYc775j4PWoUFFhx4f6yXKIKSTAuTVk= github.com/open-policy-agent/opa v0.62.1/go.mod h1:YqiSIIuvKwyomtnnXkJvy0E3KtVKbavjPJ/hNMuOmeM= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -616,8 +624,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= -github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y= +github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= @@ -642,8 +650,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/samber/lo v1.46.0 h1:w8G+oaCPgz1PoCJztqymCFaKwXt+5cCXn51uPxExFfQ= -github.com/samber/lo v1.46.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= +github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= +github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= github.com/sassoftware/relic v7.2.1+incompatible h1:Pwyh1F3I0r4clFJXkSI8bOyJINGqpgjJU3DYAZeI05A= github.com/sassoftware/relic v7.2.1+incompatible/go.mod h1:CWfAxv73/iLZ17rbyhIEq3K9hs5w6FpNMdUT//qR+zk= github.com/sassoftware/relic/v7 v7.6.1 h1:O5s8ewCgq5QYNpv45dK4u6IpBmDM9RIcsbf/G1uXepQ= @@ -826,8 +834,8 @@ golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -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/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= +golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= @@ -838,8 +846,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -865,8 +873,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -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/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -878,8 +886,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -914,8 +922,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -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/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -925,8 +933,8 @@ golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= -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/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= +golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= 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= @@ -938,10 +946,10 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -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.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= -golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -955,8 +963,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/tools/go/vcs v0.1.0-deprecated h1:cOIJqWBl99H1dH5LWizPa+0ImeeJq3t3cJjaeOWUAL4= golang.org/x/tools/go/vcs v0.1.0-deprecated/go.mod h1:zUrvATBAvEI9535oC0yWYsLsHIV4Z7g63sNPVMtuBy8= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1000,8 +1008,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1034,20 +1042,20 @@ gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= -k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= -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.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= -k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= -k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= -k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= -k8s.io/cloud-provider v0.30.3 h1:SNWZmllTymOTzIPJuhtZH6il/qVi75dQARRQAm9k6VY= -k8s.io/cloud-provider v0.30.3/go.mod h1:Ax0AVdHnM7tMYnJH1Ycy4SMBD98+4zA+tboUR9eYsY8= -k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= -k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= -k8s.io/csi-translation-lib v0.30.3 h1:wBaPWnOi14/vANRIrp8pmbdx/Pgz2QRcroH7wkodezc= -k8s.io/csi-translation-lib v0.30.3/go.mod h1:3AizNZbDttVDH1RO0x1yGEQP74e9Xbfb60IBP1oWO1o= +k8s.io/api v0.31.3 h1:umzm5o8lFbdN/hIXbrK9oRpOproJO62CV1zqxXrLgk8= +k8s.io/api v0.31.3/go.mod h1:UJrkIp9pnMOI9K2nlL6vwpxRzzEX5sWgn8kGQe92kCE= +k8s.io/apiextensions-apiserver v0.31.3 h1:+GFGj2qFiU7rGCsA5o+p/rul1OQIq6oYpQw4+u+nciE= +k8s.io/apiextensions-apiserver v0.31.3/go.mod h1:2DSpFhUZZJmn/cr/RweH1cEVVbzFw9YBu4T+U3mf1e4= +k8s.io/apimachinery v0.31.3 h1:6l0WhcYgasZ/wk9ktLq5vLaoXJJr5ts6lkaQzgeYPq4= +k8s.io/apimachinery v0.31.3/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/client-go v0.31.3 h1:CAlZuM+PH2cm+86LOBemaJI/lQ5linJ6UFxKX/SoG+4= +k8s.io/client-go v0.31.3/go.mod h1:2CgjPUTpv3fE5dNygAr2NcM8nhHzXvxB8KL5gYc3kJs= +k8s.io/cloud-provider v0.31.3 h1:7C3CHQUUwnv/HWWVIaibZH06iPg663RYQ6C6Zy4FnO8= +k8s.io/cloud-provider v0.31.3/go.mod h1:c7csKppoVb9Ej6upJ28AvHy4B3BtlRMzXfgezsDdPKw= +k8s.io/component-base v0.31.3 h1:DMCXXVx546Rfvhj+3cOm2EUxhS+EyztH423j+8sOwhQ= +k8s.io/component-base v0.31.3/go.mod h1:xME6BHfUOafRgT0rGVBGl7TuSg8Z9/deT7qq6w7qjIU= +k8s.io/csi-translation-lib v0.31.3 h1:hxcPRNdtEsk766jCXSKjgH1V8jUNx5tVqdooQ1Ars/M= +k8s.io/csi-translation-lib v0.31.3/go.mod h1:0B1gQwd868XUIDwJYy5gB2jDXWEwlcWvSsfcQEgzbRk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= @@ -1058,8 +1066,6 @@ k8s.io/release v0.16.5 h1:aITTxdJ0JwKDD5/cb3jNuCbb3MfQrdq9BdfEOh2SFmw= k8s.io/release v0.16.5/go.mod h1:PVmynXUd/jSgARt/DsTmG2la/MyIu5YvN1VeXtxiJtM= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -knative.dev/pkg v0.0.0-20230712131115-7051d301e7f4 h1:oO/BQJpVCFTSTMHF/S6u+nPtIvbHDTsvbPZvdCZAFjs= -knative.dev/pkg v0.0.0-20230712131115-7051d301e7f4/go.mod h1:eXobTqst4aI7CNa6W7sG73VhEsHGWPSrkefeMTb++a0= modernc.org/cc/v4 v4.19.3 h1:vE9kmJqUcyvNOf8F2Hn8od14SOMq34BiqcZ2tMzLk5c= modernc.org/cc/v4 v4.19.3/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= modernc.org/ccgo/v4 v4.11.0 h1:2uc2kRvZLC/oHylsrirRW6f1I4wljQST2BBbm+aKiXM= @@ -1086,12 +1092,12 @@ modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= sigs.k8s.io/bom v0.6.0 h1:IPMPHx6XdmMeW2oEeF66DgNyP5d4RxfuXwiC1qn+n9o= sigs.k8s.io/bom v0.6.0/go.mod h1:MV0D3vdGlkaPgi5EwpwMBeQ8n8QS8Q2u1lJ5LyE7RLM= -sigs.k8s.io/controller-runtime v0.19.1 h1:Son+Q40+Be3QWb+niBXAg2vFiYWolDjjRfO8hn/cxOk= -sigs.k8s.io/controller-runtime v0.19.1/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= +sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= +sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM= 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/karpenter v1.0.5 h1:QePds7w1dGCzTXI59fKpYyV5GL/LQgodOCMC1pYjqhM= -sigs.k8s.io/karpenter v1.0.5/go.mod h1:3NLmsnHHw8p4VutpjTOPUZyhE3qH6yGTs8O94Lsu8uw= +sigs.k8s.io/karpenter v1.1.1 h1:QPpVC8DsaLgJ/YWcFpZKE4m3jD+Qp88/GtSPvMfffck= +sigs.k8s.io/karpenter v1.1.1/go.mod h1:NQouOJNK6s1d4EIKa5cY7nAV3IG74qZ6gPzHBeCZNPw= sigs.k8s.io/kubetest2 v0.0.0-20240309080311-0d7ca9ccb41e h1:qvGAwPBj9Yi/XXYcMX3IQNN2IntLiz4ywruWpG+MQk4= sigs.k8s.io/kubetest2 v0.0.0-20240309080311-0d7ca9ccb41e/go.mod h1:0FsjmDUaeJjXDmIiNAYusNykIgkqouCX0cyOGEWOFkc= sigs.k8s.io/promo-tools/v3 v3.6.0 h1:C2L08ezrWm1aZI8Emd3iZPZQserLPRgzuqQVxvI0PUI= diff --git a/kubetest2/internal/deployers/eksapi/aws.go b/kubetest2/internal/deployers/eksapi/aws.go index 4dd79bb38..fe22b26c0 100644 --- a/kubetest2/internal/deployers/eksapi/aws.go +++ b/kubetest2/internal/deployers/eksapi/aws.go @@ -6,6 +6,7 @@ import ( "github.com/aws/aws-sdk-go-v2/service/cloudformation" "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/aws/aws-sdk-go-v2/service/eks" + "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/aws/aws-sdk-go-v2/service/ssm" ) @@ -15,6 +16,7 @@ type awsClients struct { _ec2 *ec2.Client _asg *autoscaling.Client _ssm *ssm.Client + _iam *iam.Client } func newAWSClients(config aws.Config, eksEndpointURL string) *awsClients { @@ -23,6 +25,7 @@ func newAWSClients(config aws.Config, eksEndpointURL string) *awsClients { _ec2: ec2.NewFromConfig(config), _asg: autoscaling.NewFromConfig(config), _ssm: ssm.NewFromConfig(config), + _iam: iam.NewFromConfig(config), } if eksEndpointURL != "" { clients._eks = eks.NewFromConfig(config, func(o *eks.Options) { @@ -53,3 +56,7 @@ func (c *awsClients) ASG() *autoscaling.Client { func (c *awsClients) SSM() *ssm.Client { return c._ssm } + +func (c *awsClients) IAM() *iam.Client { + return c._iam +} diff --git a/kubetest2/internal/deployers/eksapi/cluster.go b/kubetest2/internal/deployers/eksapi/cluster.go index c5678e029..1fccee6c4 100644 --- a/kubetest2/internal/deployers/eksapi/cluster.go +++ b/kubetest2/internal/deployers/eksapi/cluster.go @@ -40,9 +40,9 @@ type Cluster struct { } func (m *ClusterManager) getOrCreateCluster(infra *Infrastructure, opts *deployerOptions) (*Cluster, error) { - targetClusterName := &opts.StaticClusterName - if *targetClusterName == "" { - klog.Infof("No StaticClusterName specified creating new cluster...") + targetClusterName := opts.StaticClusterName + if targetClusterName == "" { + klog.Infof("creating cluster...") input := eks.CreateClusterInput{ Name: aws.String(m.resourceID), ResourcesVpcConfig: &ekstypes.VpcConfigRequest{ @@ -50,7 +50,7 @@ func (m *ClusterManager) getOrCreateCluster(infra *Infrastructure, opts *deploye EndpointPublicAccess: aws.Bool(true), SubnetIds: append(infra.subnetsPublic, infra.subnetsPrivate...), }, - RoleArn: aws.String(infra.clusterRole), + RoleArn: aws.String(infra.clusterRoleARN), KubernetesNetworkConfig: &ekstypes.KubernetesNetworkConfigRequest{ IpFamily: ekstypes.IpFamily(opts.IPFamily), }, @@ -58,9 +58,12 @@ func (m *ClusterManager) getOrCreateCluster(infra *Infrastructure, opts *deploye } if opts.AutoMode { input.ComputeConfig = &ekstypes.ComputeConfigRequest{ + // we don't enable any of the default node pools, we'll create our own Enabled: aws.Bool(true), - NodePools: []string{"general-purpose", "system"}, - NodeRoleArn: &infra.nodeRole, + NodeRoleArn: aws.String(infra.nodeRoleARN), + // TODO: we can't currently enable managed compute without a default NodePool + // the system NodePool is tainted for critical addons only, so will be ignored for our test workloads + NodePools: []string{"system"}, } input.StorageConfig = &ekstypes.StorageConfigRequest{ BlockStorage: &ekstypes.BlockStorage{ @@ -86,48 +89,44 @@ func (m *ClusterManager) getOrCreateCluster(infra *Infrastructure, opts *deploye if err != nil { return nil, fmt.Errorf("failed to create cluster: %v", err) } - targetClusterName = createOutput.Cluster.Name + targetClusterName = aws.ToString(createOutput.Cluster.Name) } else { - klog.Infof("reusing existing static cluster %s", *targetClusterName) + klog.Infof("reusing existing static cluster %s", opts.StaticClusterName) } - cluster, waitErr := m.waitClusterReady(targetClusterName) + cluster, waitErr := m.waitForClusterActive(targetClusterName) if waitErr != nil { return nil, fmt.Errorf("failed to wait for cluster to become active: %v", waitErr) } return cluster, nil } -func (m *ClusterManager) waitClusterReady(clusterName *string) (*Cluster, error) { - describeInput := eks.DescribeClusterInput{ - Name: clusterName, - } - klog.Infof("waiting for cluster to be active: %s", *clusterName) - waitErr := eks.NewClusterActiveWaiter(m.clients.EKS()).Wait(context.TODO(), &describeInput, clusterCreationTimeout) - describeOutput, describeErr := m.clients.EKS().DescribeCluster(context.TODO(), &describeInput) - if describeErr != nil { - return nil, fmt.Errorf("failed to describe cluster after creation: %v", describeErr) - } - klog.Infof("cluster details after creation: %+v", describeOutput.Cluster) - if waitErr != nil { - return nil, waitErr +func (m *ClusterManager) waitForClusterActive(clusterName string) (*Cluster, error) { + klog.Infof("waiting for cluster to be active: %s", clusterName) + out, err := eks.NewClusterActiveWaiter(m.clients.EKS()).WaitForOutput(context.TODO(), &eks.DescribeClusterInput{ + Name: aws.String(clusterName), + }, clusterCreationTimeout) + // log whether there was an error or not + klog.Infof("cluster details: %+v", out.Cluster) + if err != nil { + return nil, fmt.Errorf("failed waiting for cluster be active: %v", err) } - klog.Infof("cluster is active: %s", *describeOutput.Cluster.Arn) + klog.Infof("cluster is active: %s", *out.Cluster.Arn) var cidr string - switch describeOutput.Cluster.KubernetesNetworkConfig.IpFamily { + switch out.Cluster.KubernetesNetworkConfig.IpFamily { case ekstypes.IpFamilyIpv4: - cidr = *describeOutput.Cluster.KubernetesNetworkConfig.ServiceIpv4Cidr + cidr = *out.Cluster.KubernetesNetworkConfig.ServiceIpv4Cidr case ekstypes.IpFamilyIpv6: - cidr = *describeOutput.Cluster.KubernetesNetworkConfig.ServiceIpv6Cidr + cidr = *out.Cluster.KubernetesNetworkConfig.ServiceIpv6Cidr default: - return nil, fmt.Errorf("unknown cluster IP family: '%v'", describeOutput.Cluster.KubernetesNetworkConfig.IpFamily) + return nil, fmt.Errorf("unknown cluster IP family: '%v'", out.Cluster.KubernetesNetworkConfig.IpFamily) } return &Cluster{ - arn: *describeOutput.Cluster.Arn, - certificateAuthorityData: *describeOutput.Cluster.CertificateAuthority.Data, + arn: *out.Cluster.Arn, + certificateAuthorityData: *out.Cluster.CertificateAuthority.Data, cidr: cidr, - endpoint: *describeOutput.Cluster.Endpoint, - name: *describeOutput.Cluster.Name, - securityGroupId: *describeOutput.Cluster.ResourcesVpcConfig.ClusterSecurityGroupId, + endpoint: *out.Cluster.Endpoint, + name: *out.Cluster.Name, + securityGroupId: *out.Cluster.ResourcesVpcConfig.ClusterSecurityGroupId, }, nil } diff --git a/kubetest2/internal/deployers/eksapi/deployer.go b/kubetest2/internal/deployers/eksapi/deployer.go index a41d079ad..58bc45eb1 100644 --- a/kubetest2/internal/deployers/eksapi/deployer.go +++ b/kubetest2/internal/deployers/eksapi/deployer.go @@ -16,7 +16,6 @@ import ( "github.com/octago/sflags/gen/gpflag" "github.com/spf13/pflag" "golang.org/x/exp/slices" - "k8s.io/client-go/kubernetes" "k8s.io/klog" "sigs.k8s.io/kubetest2/pkg/types" ) @@ -50,38 +49,39 @@ type deployer struct { infra *Infrastructure cluster *Cluster - k8sClient *kubernetes.Clientset + k8sClient *k8sClient initTime time.Time } type deployerOptions struct { - Addons []string `flag:"addons" desc:"Managed addons (name:version pairs) to create in the cluster. Use 'latest' for the most recent version, or 'default' for the default version."` - AMI string `flag:"ami" desc:"AMI for unmanaged nodes"` - AMIType string `flag:"ami-type" desc:"AMI type for managed nodes"` - AutoMode bool `flag:"auto-mode" desc:"Enable EKS Auto Mode"` - CapacityReservation bool `flag:"capacity-reservation" desc:"Use capacity reservation for the unmanaged nodegroup"` - ClusterRoleServicePrincipal string `flag:"cluster-role-service-principal" desc:"Additional service principal that can assume the cluster role"` - EFA bool `flag:"efa" desc:"Create EFA interfaces on the node of an unmanaged nodegroup. Requires --unmanaged-nodes."` - EKSEndpointURL string `flag:"endpoint-url" desc:"Endpoint URL for the EKS API"` - EmitMetrics bool `flag:"emit-metrics" desc:"Record and emit metrics to CloudWatch"` - ExpectedAMI string `flag:"expected-ami" desc:"Expected AMI of nodes. Up will fail if the actual nodes are not utilizing the expected AMI. Defaults to --ami if defined."` - GenerateSSHKey bool `flag:"generate-ssh-key" desc:"Generate an SSH key to use for tests. The generated key should not be used in production, as it will not have a passphrase."` - InstanceTypes []string `flag:"instance-types" desc:"Node instance types"` - IPFamily string `flag:"ip-family" desc:"IP family for the cluster (ipv4 or ipv6)"` - KubeconfigPath string `flag:"kubeconfig" desc:"Path to kubeconfig"` - KubernetesVersion string `flag:"kubernetes-version" desc:"cluster Kubernetes version"` - LogBucket string `flag:"log-bucket" desc:"S3 bucket for storing logs for each run. If empty, logs will not be stored."` - NodeCreationTimeout time.Duration `flag:"node-creation-timeout" desc:"Time to wait for nodes to be created/launched. This should consider instance availability."` - NodeReadyTimeout time.Duration `flag:"node-ready-timeout" desc:"Time to wait for all nodes to become ready"` - Nodes int `flag:"nodes" desc:"number of nodes to launch in cluster"` - NodeNameStrategy string `flag:"node-name-strategy" desc:"Specifies the naming strategy for node. Allowed values: ['SessionName', 'EC2PrivateDNSName'], default to EC2PrivateDNSName"` - Region string `flag:"region" desc:"AWS region for EKS cluster"` - StaticClusterName string `flag:"static-cluster-name" desc:"Optional when re-use existing cluster and node group by querying the kubeconfig and run test"` - TuneVPCCNI bool `flag:"tune-vpc-cni" desc:"Apply tuning parameters to the VPC CNI DaemonSet"` - UnmanagedNodes bool `flag:"unmanaged-nodes" desc:"Use an AutoScalingGroup instead of an EKS-managed nodegroup. Requires --ami"` - UpClusterHeaders []string `flag:"up-cluster-header" desc:"Additional header to add to eks:CreateCluster requests. Specified in the same format as curl's -H flag."` - UserDataFormat string `flag:"user-data-format" desc:"Format of the node instance user data"` + Addons []string `flag:"addons" desc:"Managed addons (name:version pairs) to create in the cluster. Use 'latest' for the most recent version, or 'default' for the default version."` + AMI string `flag:"ami" desc:"AMI for unmanaged nodes"` + AMIType string `flag:"ami-type" desc:"AMI type for managed nodes"` + AutoMode bool `flag:"auto-mode" desc:"Enable EKS Auto Mode"` + CapacityReservation bool `flag:"capacity-reservation" desc:"Use capacity reservation for the unmanaged nodegroup"` + ClusterRoleServicePrincipal string `flag:"cluster-role-service-principal" desc:"Additional service principal that can assume the cluster role"` + EFA bool `flag:"efa" desc:"Create EFA interfaces on the node of an unmanaged nodegroup. Requires --unmanaged-nodes."` + EKSEndpointURL string `flag:"endpoint-url" desc:"Endpoint URL for the EKS API"` + EmitMetrics bool `flag:"emit-metrics" desc:"Record and emit metrics to CloudWatch"` + ExpectedAMI string `flag:"expected-ami" desc:"Expected AMI of nodes. Up will fail if the actual nodes are not utilizing the expected AMI. Defaults to --ami if defined."` + // TODO: remove this once it's no longer used in downstream jobs + GenerateSSHKey bool `flag:"generate-ssh-key" desc:"Generate an SSH key to use for tests. The generated key should not be used in production, as it will not have a passphrase."` + InstanceTypes []string `flag:"instance-types" desc:"Node instance types"` + IPFamily string `flag:"ip-family" desc:"IP family for the cluster (ipv4 or ipv6)"` + KubeconfigPath string `flag:"kubeconfig" desc:"Path to kubeconfig"` + KubernetesVersion string `flag:"kubernetes-version" desc:"cluster Kubernetes version"` + LogBucket string `flag:"log-bucket" desc:"S3 bucket for storing logs for each run. If empty, logs will not be stored."` + NodeCreationTimeout time.Duration `flag:"node-creation-timeout" desc:"Time to wait for nodes to be created/launched. This should consider instance availability."` + NodeReadyTimeout time.Duration `flag:"node-ready-timeout" desc:"Time to wait for all nodes to become ready"` + Nodes int `flag:"nodes" desc:"number of nodes to launch in cluster"` + NodeNameStrategy string `flag:"node-name-strategy" desc:"Specifies the naming strategy for node. Allowed values: ['SessionName', 'EC2PrivateDNSName'], default to EC2PrivateDNSName"` + Region string `flag:"region" desc:"AWS region for EKS cluster"` + StaticClusterName string `flag:"static-cluster-name" desc:"Optional when re-use existing cluster and node group by querying the kubeconfig and run test"` + TuneVPCCNI bool `flag:"tune-vpc-cni" desc:"Apply tuning parameters to the VPC CNI DaemonSet"` + UnmanagedNodes bool `flag:"unmanaged-nodes" desc:"Use an AutoScalingGroup instead of an EKS-managed nodegroup. Requires --ami"` + UpClusterHeaders []string `flag:"up-cluster-header" desc:"Additional header to add to eks:CreateCluster requests. Specified in the same format as curl's -H flag."` + UserDataFormat string `flag:"user-data-format" desc:"Format of the node instance user data"` } // NewDeployer implements deployer.New for EKS using the EKS (and other AWS) API(s) directly (no cloudformation) @@ -164,11 +164,6 @@ func (d *deployer) Up() error { if err := d.verifyUpFlags(); err != nil { return fmt.Errorf("up flags are invalid: %v", err) } - if d.GenerateSSHKey { - if err := generateSSHKey(); err != nil { - return err - } - } if d.deployerOptions.StaticClusterName == "" { if infra, err := d.infraManager.createInfrastructureStack(&d.deployerOptions); err != nil { return err @@ -185,7 +180,7 @@ func (d *deployer) Up() error { if err != nil { return err } - d.k8sClient, err = newKubernetesClient(kubeconfig) + d.k8sClient, err = newK8sClient(kubeconfig) if err != nil { return err } @@ -200,7 +195,7 @@ func (d *deployer) Up() error { return nil } if d.UnmanagedNodes { - if err := createAWSAuthConfigMap(d.k8sClient, d.NodeNameStrategy, d.infra.nodeRole); err != nil { + if err := d.k8sClient.createAWSAuthConfigMap(d.NodeNameStrategy, d.infra.nodeRoleARN); err != nil { return err } } @@ -211,18 +206,18 @@ func (d *deployer) Up() error { return err } if d.deployerOptions.TuneVPCCNI { - if err := tuneVPCCNI(d.k8sClient); err != nil { + if err := d.k8sClient.tuneVPCCNI(); err != nil { return err } } if err := d.nodeManager.createNodes(d.infra, d.cluster, &d.deployerOptions, d.k8sClient); err != nil { return err } - if err := waitForReadyNodes(d.k8sClient, d.Nodes, d.NodeReadyTimeout); err != nil { + if err := d.k8sClient.waitForReadyNodes(d.Nodes, d.NodeReadyTimeout); err != nil { return err } if d.EmitMetrics { - if err := emitNodeMetrics(d.metrics, d.k8sClient, d.awsClients.EC2()); err != nil { + if err := d.k8sClient.emitNodeMetrics(d.metrics, d.awsClients.EC2()); err != nil { return err } } diff --git a/kubetest2/internal/deployers/eksapi/infra.go b/kubetest2/internal/deployers/eksapi/infra.go index 53cf59e44..7c3ad52c2 100644 --- a/kubetest2/internal/deployers/eksapi/infra.go +++ b/kubetest2/internal/deployers/eksapi/infra.go @@ -16,6 +16,9 @@ import ( cloudwatchtypes "github.com/aws/aws-sdk-go-v2/service/cloudwatch/types" "github.com/aws/aws-sdk-go-v2/service/ec2" ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/aws/aws-sdk-go-v2/service/iam" + iamtypes "github.com/aws/aws-sdk-go-v2/service/iam/types" + "github.com/aws/aws-sdk-go/aws/arn" "k8s.io/klog" "github.com/aws/aws-k8s-tester/kubetest2/internal/deployers/eksapi/templates" @@ -67,13 +70,12 @@ func NewInfrastructureManager(clients *awsClients, resourceID string, metrics me } type Infrastructure struct { - vpc string - subnetsPublic []string - subnetsPrivate []string - clusterRole string - nodeRole string - sshSecurityGroup string - sshKeyPair string + vpc string + subnetsPublic []string + subnetsPrivate []string + clusterRoleARN string + nodeRoleARN string + nodeRoleName string } func (i *Infrastructure) subnets() []string { @@ -81,10 +83,6 @@ func (i *Infrastructure) subnets() []string { } func (m *InfrastructureManager) createInfrastructureStack(opts *deployerOptions) (*Infrastructure, error) { - publicKeyMaterial, err := loadSSHPublicKey() - if err != nil { - return nil, err - } // get two AZs for the subnets azs, err := m.clients.EC2().DescribeAvailabilityZones(context.TODO(), &ec2.DescribeAvailabilityZonesInput{}) if err != nil { @@ -115,10 +113,6 @@ func (m *InfrastructureManager) createInfrastructureStack(opts *deployerOptions) TemplateBody: aws.String(templates.Infrastructure), Capabilities: []cloudformationtypes.Capability{cloudformationtypes.CapabilityCapabilityIam}, Parameters: []cloudformationtypes.Parameter{ - { - ParameterKey: aws.String("SSHPublicKeyMaterial"), - ParameterValue: aws.String(publicKeyMaterial), - }, { ParameterKey: aws.String("ResourceId"), ParameterValue: aws.String(m.resourceID), @@ -177,7 +171,7 @@ func (m *InfrastructureManager) getInfrastructureStackResources() (*Infrastructu StackName: aws.String(m.resourceID), }) if err != nil { - return nil, fmt.Errorf("failed to describe infrastructure stack: %w", err) + return nil, err } infra := Infrastructure{} for _, output := range stack.Stacks[0].Outputs { @@ -190,24 +184,43 @@ func (m *InfrastructureManager) getInfrastructureStackResources() (*Infrastructu case "SubnetsPrivate": infra.subnetsPrivate = strings.Split(value, ",") case "ClusterRole": - infra.clusterRole = value + arn, err := arn.Parse(value) + if err != nil { + return nil, fmt.Errorf("infrastructure stack ClusterRole output is not a valid ARN: '%s': %v", value, err) + } + infra.clusterRoleARN = arn.String() case "NodeRole": - infra.nodeRole = value - case "SSHSecurityGroup": - infra.sshSecurityGroup = value - case "SSHKeyPair": - infra.sshKeyPair = value + arn, err := arn.Parse(value) + if err != nil { + return nil, fmt.Errorf("infrastructure stack NodeRole output is not a valid ARN: '%s': %v", value, err) + } + infra.nodeRoleARN = arn.String() + // Resource looks like 'role:/MyRole' + resourceParts := strings.Split(arn.Resource, "/") + infra.nodeRoleName = resourceParts[len(resourceParts)-1] } } return &infra, nil } func (m *InfrastructureManager) deleteInfrastructureStack() error { + infra, err := m.getInfrastructureStackResources() + if err != nil { + var notFound *cloudformationtypes.StackNotFoundException + if errors.As(err, ¬Found) { + klog.Infof("infrastructure stack does not exist: %s", m.resourceID) + return nil + } + return err + } + if err := m.deleteLeakedInstanceProfiles(infra); err != nil { + return err + } input := cloudformation.DeleteStackInput{ StackName: aws.String(m.resourceID), } klog.Infof("deleting infrastructure stack: %s", m.resourceID) - _, err := m.clients.CFN().DeleteStack(context.TODO(), &input) + _, err = m.clients.CFN().DeleteStack(context.TODO(), &input) if err != nil { var notFound *cloudformationtypes.StackNotFoundException if errors.As(err, ¬Found) { @@ -233,6 +246,53 @@ func (m *InfrastructureManager) deleteInfrastructureStack() error { return nil } +// deleteLeakedIntanceProfiles deletes any instance profiles to which the node role is attached, +// because this will block node role deletion (and deletion of the infrastructure stack). +// For example, when --auto-mode is used, an instance profile will be created for us and won't be deleted automatically with the cluster. +func (m *InfrastructureManager) deleteLeakedInstanceProfiles(infra *Infrastructure) error { + out, err := m.clients.IAM().ListInstanceProfilesForRole(context.TODO(), &iam.ListInstanceProfilesForRoleInput{ + RoleName: aws.String(infra.nodeRoleName), + }) + if err != nil { + var notFound *iamtypes.NoSuchEntityException + if errors.As(err, ¬Found) { + klog.Infof("instance profile for role does not exist: %s", m.resourceID) + // continue deletion + } + return fmt.Errorf("failed to list instance profiles for role name: '%s': %v", infra.nodeRoleName, err) + } else if len(out.InstanceProfiles) > 0 { + var deletedInstanceProfiles []string + for _, instanceProfile := range out.InstanceProfiles { + _, err := m.clients.IAM().RemoveRoleFromInstanceProfile(context.TODO(), &iam.RemoveRoleFromInstanceProfileInput{ + RoleName: aws.String(infra.nodeRoleName), + InstanceProfileName: instanceProfile.InstanceProfileName, + }) + if err != nil { + var notFound *iamtypes.NoSuchEntityException + if errors.As(err, ¬Found) { + klog.Infof("instance profile does not exist: %s", aws.ToString(instanceProfile.InstanceProfileName)) + continue + } + return fmt.Errorf("failed to remove node role %s from instance profile: %s: %v", infra.nodeRoleName, aws.ToString(instanceProfile.InstanceProfileName), err) + } + _, err = m.clients.IAM().DeleteInstanceProfile(context.TODO(), &iam.DeleteInstanceProfileInput{ + InstanceProfileName: instanceProfile.InstanceProfileName, + }) + if err != nil { + var notFound *iamtypes.NoSuchEntityException + if errors.As(err, ¬Found) { + klog.Infof("instance profile does not exist: %s", aws.ToString(instanceProfile.InstanceProfileName)) + continue + } + return fmt.Errorf("failed to delete instance profile: %s: %v", aws.ToString(instanceProfile.InstanceProfileName), err) + } + deletedInstanceProfiles = append(deletedInstanceProfiles, aws.ToString(instanceProfile.InstanceProfileName)) + } + klog.Infof("deleted %d leaked instance profile(s): %v", len(deletedInstanceProfiles), deletedInstanceProfiles) + } + return nil +} + // deleteLeakedENIs deletes Elastic Network Interfaces that may have been allocated (and left behind) by the VPC CNI. // These leaked ENIs will prevent deletion of their associated subnets and security groups. func (m *InfrastructureManager) deleteLeakedENIs() error { diff --git a/kubetest2/internal/deployers/eksapi/k8s.go b/kubetest2/internal/deployers/eksapi/k8s.go index 2cf645417..b49161657 100644 --- a/kubetest2/internal/deployers/eksapi/k8s.go +++ b/kubetest2/internal/deployers/eksapi/k8s.go @@ -9,35 +9,55 @@ import ( "time" "github.com/aws/aws-k8s-tester/kubetest2/internal/metrics" + "github.com/aws/aws-k8s-tester/kubetest2/internal/util" "github.com/aws/aws-sdk-go-v2/service/ec2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + crlog "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" corev1 "k8s.io/api/core/v1" ) -func newKubernetesClient(kubeconfigPath string) (*kubernetes.Clientset, error) { - c, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) +func init() { + // controller-runtime will complain loudly if this isn't set, even though we don't use this logger + crlog.SetLogger(zap.New()) +} + +type k8sClient struct { + config *rest.Config + clientset kubernetes.Interface + client client.Client +} + +func newK8sClient(kubeconfigPath string) (*k8sClient, error) { + config, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) if err != nil { return nil, err } - return kubernetes.NewForConfig(c) + return &k8sClient{ + config: config, + clientset: kubernetes.NewForConfigOrDie(config), + client: util.Must(client.New(config, client.Options{})), + }, nil } -func waitForReadyNodes(client *kubernetes.Clientset, nodeCount int, timeout time.Duration) error { +func (k *k8sClient) waitForReadyNodes(nodeCount int, timeout time.Duration) error { klog.Infof("waiting up to %v for %d node(s) to be ready...", timeout, nodeCount) readyNodes := sets.NewString() - watcher, err := client.CoreV1().Nodes().Watch(context.TODO(), metav1.ListOptions{}) + watcher, err := k.clientset.CoreV1().Nodes().Watch(context.TODO(), metav1.ListOptions{}) if err != nil { return fmt.Errorf("failed to create node watcher: %v", err) } defer watcher.Stop() - initialReadyNodes, err := getReadyNodes(client) + initialReadyNodes, err := k.getReadyNodes() if err != nil { return fmt.Errorf("failed to get ready nodes: %v", err) } @@ -75,8 +95,8 @@ func waitForReadyNodes(client *kubernetes.Clientset, nodeCount int, timeout time return nil } -func getReadyNodes(client kubernetes.Interface) ([]corev1.Node, error) { - nodes, err := client.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{}) +func (k *k8sClient) getReadyNodes() ([]corev1.Node, error) { + nodes, err := k.clientset.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{}) if err != nil { return nil, err } @@ -106,13 +126,13 @@ func getNodeReadyCondition(node *corev1.Node) *corev1.NodeCondition { return nil } -func createAWSAuthConfigMap(client *kubernetes.Clientset, nodeNameStrategy string, nodeRoleARN string) error { +func (k *k8sClient) createAWSAuthConfigMap(nodeNameStrategy string, nodeRoleARN string) error { mapRoles, err := generateAuthMapRole(nodeNameStrategy, nodeRoleARN) if err != nil { return err } klog.Infof("generated AuthMapRole %s", mapRoles) - _, err = client.CoreV1().ConfigMaps("kube-system").Create(context.TODO(), &corev1.ConfigMap{ + _, err = k.clientset.CoreV1().ConfigMaps("kube-system").Create(context.TODO(), &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "aws-auth", Namespace: "kube-system", @@ -141,8 +161,8 @@ func getNodeInstanceIDs(nodes []corev1.Node) ([]string, error) { return instanceIds, nil } -func emitNodeMetrics(metricRegistry metrics.MetricRegistry, k8sClient *kubernetes.Clientset, ec2Client *ec2.Client) error { - nodes, err := getReadyNodes(k8sClient) +func (k *k8sClient) emitNodeMetrics(metricRegistry metrics.MetricRegistry, ec2Client *ec2.Client) error { + nodes, err := k.getReadyNodes() if err != nil { return err } diff --git a/kubetest2/internal/deployers/eksapi/logs.go b/kubetest2/internal/deployers/eksapi/logs.go index 18daa0654..fa93e1481 100644 --- a/kubetest2/internal/deployers/eksapi/logs.go +++ b/kubetest2/internal/deployers/eksapi/logs.go @@ -11,7 +11,6 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ssm" ssmtypes "github.com/aws/aws-sdk-go-v2/service/ssm/types" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" ) @@ -34,7 +33,7 @@ func NewLogManager(clients *awsClients, resourceID string) *logManager { } } -func (m *logManager) gatherLogsFromNodes(k8sClient *kubernetes.Clientset, opts *deployerOptions, phase deployerPhase) error { +func (m *logManager) gatherLogsFromNodes(k8sClient *k8sClient, opts *deployerOptions, phase deployerPhase) error { if opts.LogBucket == "" { klog.Info("--log-bucket is empty, no logs will be gathered!") return nil @@ -58,9 +57,9 @@ var logCollectorScriptSsmDocumentContent string const logCollectorSsmDocumentTimeout = 5 * time.Minute -func (m *logManager) gatherLogsUsingScript(k8sClient *kubernetes.Clientset, opts *deployerOptions, phase deployerPhase) error { +func (m *logManager) gatherLogsUsingScript(k8sClient *k8sClient, opts *deployerOptions, phase deployerPhase) error { klog.Info("gathering logs from nodes...") - nodes, err := k8sClient.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{}) + nodes, err := k8sClient.clientset.CoreV1().Nodes().List(context.TODO(), v1.ListOptions{}) if err != nil { return err } diff --git a/kubetest2/internal/deployers/eksapi/node.go b/kubetest2/internal/deployers/eksapi/node.go index 9571354ac..3629c2f41 100644 --- a/kubetest2/internal/deployers/eksapi/node.go +++ b/kubetest2/internal/deployers/eksapi/node.go @@ -23,9 +23,9 @@ import ( appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" "k8s.io/utils/pointer" + karpv1 "sigs.k8s.io/karpenter/pkg/apis/v1" "github.com/aws/aws-k8s-tester/kubetest2/internal/deployers/eksapi/templates" ) @@ -76,40 +76,126 @@ func NewNodeManager(clients *awsClients, resourceID string) *nodeManager { } } -func (m *nodeManager) createNodes(infra *Infrastructure, cluster *Cluster, opts *deployerOptions, k8sClient *kubernetes.Clientset) error { +func (m *nodeManager) createNodes(infra *Infrastructure, cluster *Cluster, opts *deployerOptions, k8sClient *k8sClient) error { + if err := m.resolveInstanceTypes(opts); err != nil { + return fmt.Errorf("failed to resolve instance types: %v", err) + } if opts.AutoMode { - _, err := m.createPlaceholderDeployment(k8sClient, opts.Nodes) + if err := m.createNodePool(opts, k8sClient); err != nil { + return err + } + _, err := m.createPlaceholderDeployment(opts, k8sClient) return err } else if opts.UnmanagedNodes { - if len(opts.InstanceTypes) == 0 { + if opts.EFA { + return m.createUnmanagedNodegroupWithEFA(infra, cluster, opts) + } + return m.createUnmanagedNodegroup(infra, cluster, opts) + } else { + return m.createManagedNodegroup(infra, cluster, opts) + } +} + +func (m *nodeManager) resolveInstanceTypes(opts *deployerOptions) (err error) { + instanceTypes := opts.InstanceTypes + if len(instanceTypes) == 0 { + if opts.UnmanagedNodes { + klog.Infof("choosing instance types based on AMI architecture...") if out, err := m.clients.EC2().DescribeImages(context.TODO(), &ec2.DescribeImagesInput{ ImageIds: []string{opts.AMI}, }); err != nil { - return fmt.Errorf("failed to describe AMI when populating default instance types: %s: %v", opts.AMI, err) + return fmt.Errorf("failed to describe AMI: %s: %v", opts.AMI, err) } else { amiArch := out.Images[0].Architecture - defaultInstanceTypes, err := m.getValidDefaultInstanceTypesByEC2Arch(amiArch) - if err != nil { - return fmt.Errorf("failed to get default instance types for AmiArch: %s: %v", amiArch, err) + instanceTypesForAMIArchitecture, ok := defaultInstanceTypesByEC2ArchitectureValues[amiArch] + if !ok { + return fmt.Errorf("no default instance types known for AMI architecture: %v", amiArch) } - opts.InstanceTypes = defaultInstanceTypes - klog.V(2).Infof("Using default instance types for AMI architecture: %v: %v", amiArch, opts.InstanceTypes) + instanceTypes = instanceTypesForAMIArchitecture } + } else { + // we don't rely on the service's default instance types, because they're a bit too small for the k8s e2e suite + klog.Infof("choosing instance types based on managed nodegroup's AMI type...") + instanceTypesForAMIType, ok := defaultInstanceTypesByEKSAMITypes[ekstypes.AMITypes(opts.AMIType)] + if !ok { + return fmt.Errorf("no default instance types known for AMI type: %v", opts.AMIType) + } + instanceTypes = instanceTypesForAMIType } - if opts.EFA { - return m.createUnmanagedNodegroupWithEFA(infra, cluster, opts) - } - return m.createUnmanagedNodegroup(infra, cluster, opts) - } else { - return m.createManagedNodegroup(infra, cluster, opts) } + validInstanceTypes, err := m.getValidInstanceTypes(instanceTypes) + if err != nil { + return err + } + opts.InstanceTypes = validInstanceTypes + klog.Infof("using instance types: %v", opts.InstanceTypes) + return nil +} + +func (m *nodeManager) createNodePool(opts *deployerOptions, k8sClient *k8sClient) error { + nodePool := karpv1.NodePool{ + ObjectMeta: metav1.ObjectMeta{ + Name: m.resourceID, + }, + Spec: karpv1.NodePoolSpec{ + Weight: pointer.Int32(100), // max + Disruption: karpv1.Disruption{ + Budgets: []karpv1.Budget{ + { + Nodes: "10%", + }, + }, + ConsolidationPolicy: karpv1.ConsolidationPolicyWhenEmpty, + ConsolidateAfter: karpv1.MustParseNillableDuration("600s"), + }, + Template: karpv1.NodeClaimTemplate{ + Spec: karpv1.NodeClaimTemplateSpec{ + ExpireAfter: karpv1.MustParseNillableDuration("24h"), + NodeClassRef: &karpv1.NodeClassReference{ + Group: "eks.amazonaws.com", + Kind: "NodeClass", + Name: "default", + }, + Requirements: []karpv1.NodeSelectorRequirementWithMinValues{ + { + NodeSelectorRequirement: corev1.NodeSelectorRequirement{ + Key: "kubernetes.io/os", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"linux"}, + }, + }, + { + NodeSelectorRequirement: corev1.NodeSelectorRequirement{ + Key: "karpenter.sh/capacity-type", + Operator: corev1.NodeSelectorOpIn, + Values: []string{"on-demand"}, + }, + }, + { + NodeSelectorRequirement: corev1.NodeSelectorRequirement{ + Key: "node.kubernetes.io/instance-type", + Operator: corev1.NodeSelectorOpIn, + Values: opts.InstanceTypes, + }, + }, + }, + }, + }, + }, + } + klog.Infof("creating node pool...") + if err := k8sClient.client.Create(context.TODO(), &nodePool); err != nil { + return fmt.Errorf("failed to create node pool: %v", err) + } + klog.Infof("created node pool: %+v", nodePool) + return nil } // createPlaceholderDeployment creates a Deployment with the specified number of replicas that requires // each replica to be scheduled on different nodes. // This ensures that (at least) the specified number of nodes exist in an EKS Auto cluster -func (m *nodeManager) createPlaceholderDeployment(k8sClient *kubernetes.Clientset, replicas int) (*appsv1.Deployment, error) { - if replicas == 0 { +func (m *nodeManager) createPlaceholderDeployment(opts *deployerOptions, k8sClient *k8sClient) (*appsv1.Deployment, error) { + if opts.Nodes == 0 { klog.Info("not creating placeholder deployment!") return nil, nil } @@ -120,7 +206,7 @@ func (m *nodeManager) createPlaceholderDeployment(k8sClient *kubernetes.Clientse d := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{Name: "placeholder" + disambiguator, Namespace: "default"}, Spec: appsv1.DeploymentSpec{ - Replicas: pointer.Int32(int32(replicas)), + Replicas: pointer.Int32(int32(opts.Nodes)), Selector: &metav1.LabelSelector{ MatchLabels: labels, }, @@ -153,7 +239,7 @@ func (m *nodeManager) createPlaceholderDeployment(k8sClient *kubernetes.Clientse }, } klog.Infof("creating placeholder deployment...") - d, err := k8sClient.AppsV1().Deployments("default").Create(context.TODO(), d, metav1.CreateOptions{}) + d, err := k8sClient.clientset.AppsV1().Deployments("default").Create(context.TODO(), d, metav1.CreateOptions{}) if err != nil { return nil, fmt.Errorf("failed to create placeholder deployment: %v", err) } @@ -166,7 +252,7 @@ func (m *nodeManager) createManagedNodegroup(infra *Infrastructure, cluster *Clu input := eks.CreateNodegroupInput{ ClusterName: aws.String(m.resourceID), NodegroupName: aws.String(m.resourceID), - NodeRole: aws.String(infra.nodeRole), + NodeRole: aws.String(infra.nodeRoleARN), Subnets: infra.subnets(), DiskSize: aws.Int32(100), CapacityType: ekstypes.CapacityTypesOnDemand, @@ -175,18 +261,8 @@ func (m *nodeManager) createManagedNodegroup(infra *Infrastructure, cluster *Clu MaxSize: aws.Int32(int32(opts.Nodes)), DesiredSize: aws.Int32(int32(opts.Nodes)), }, - AmiType: ekstypes.AMITypes(opts.AMIType), - } - if len(opts.InstanceTypes) > 0 { - input.InstanceTypes = opts.InstanceTypes - } else { - // managed nodegroups uses a t3.medium by default at the time of writing - // this only supports 17 pods, which can cause some flakes in the k8s e2e suite - defaultInstanceTypes, err := m.getValidDefaultInstanceTypesByEKSAMIType(input.AmiType) - if err != nil { - return fmt.Errorf("failed to get default instance types for AmiType: %s: %v", input.AmiType, err) - } - input.InstanceTypes = defaultInstanceTypes + AmiType: ekstypes.AMITypes(opts.AMIType), + InstanceTypes: opts.InstanceTypes, } out, err := m.clients.EKS().CreateNodegroup(context.TODO(), &input) if err != nil { @@ -242,9 +318,6 @@ func (m *nodeManager) createUnmanagedNodegroup(infra *Infrastructure, cluster *C if opts.UserDataFormat == "bottlerocket" { volumeMountPath = "/dev/xvdb" } - // pull the role name out of the ARN - nodeRoleArnParts := strings.Split(infra.nodeRole, "/") - nodeRoleName := nodeRoleArnParts[len(nodeRoleArnParts)-1] input := cloudformation.CreateStackInput{ StackName: aws.String(stackName), TemplateBody: aws.String(templateBuf.String()), @@ -276,7 +349,7 @@ func (m *nodeManager) createUnmanagedNodegroup(infra *Infrastructure, cluster *C }, { ParameterKey: aws.String("NodeRoleName"), - ParameterValue: aws.String(nodeRoleName), + ParameterValue: aws.String(infra.nodeRoleName), }, { ParameterKey: aws.String("NodeCount"), @@ -286,14 +359,6 @@ func (m *nodeManager) createUnmanagedNodegroup(infra *Infrastructure, cluster *C ParameterKey: aws.String("SecurityGroup"), ParameterValue: aws.String(cluster.securityGroupId), }, - { - ParameterKey: aws.String("SSHSecurityGroup"), - ParameterValue: aws.String(infra.sshSecurityGroup), - }, - { - ParameterKey: aws.String("SSHKeyPair"), - ParameterValue: aws.String(infra.sshKeyPair), - }, { ParameterKey: aws.String("AMIId"), ParameterValue: aws.String(opts.AMI), @@ -350,10 +415,6 @@ func (m *nodeManager) createUnmanagedNodegroupWithEFA(infra *Infrastructure, clu if opts.UserDataFormat == "bottlerocket" { volumeMountPath = "/dev/xvdb" } - - // pull the role name out of the ARN - nodeRoleArnParts := strings.Split(infra.nodeRole, "/") - nodeRoleName := nodeRoleArnParts[len(nodeRoleArnParts)-1] input := cloudformation.CreateStackInput{ StackName: aws.String(stackName), TemplateBody: aws.String(templates.UnmanagedNodegroupEFA), @@ -389,7 +450,7 @@ func (m *nodeManager) createUnmanagedNodegroupWithEFA(infra *Infrastructure, clu }, { ParameterKey: aws.String("NodeRoleName"), - ParameterValue: aws.String(nodeRoleName), + ParameterValue: aws.String(infra.nodeRoleName), }, { ParameterKey: aws.String("NodeCount"), @@ -399,10 +460,6 @@ func (m *nodeManager) createUnmanagedNodegroupWithEFA(infra *Infrastructure, clu ParameterKey: aws.String("SecurityGroup"), ParameterValue: aws.String(cluster.securityGroupId), }, - { - ParameterKey: aws.String("SSHKeyPair"), - ParameterValue: aws.String(infra.sshKeyPair), - }, { ParameterKey: aws.String("AMIId"), ParameterValue: aws.String(opts.AMI), @@ -599,23 +656,7 @@ func (m *nodeManager) getSubnetWithCapacity(infra *Infrastructure, opts *deploye return subnetId, capacityReservationId, nil } -func (m *nodeManager) getValidDefaultInstanceTypesByEKSAMIType(amiType ekstypes.AMITypes) ([]string, error) { - defaults, ok := defaultInstanceTypesByEKSAMITypes[amiType] - if !ok { - return nil, fmt.Errorf("no default instance types known for AmiType: %v", amiType) - } - return m.getValidInstanceTypesFromList(defaults) -} - -func (m *nodeManager) getValidDefaultInstanceTypesByEC2Arch(arch ec2types.ArchitectureValues) ([]string, error) { - defaults, ok := defaultInstanceTypesByEC2ArchitectureValues[arch] - if !ok { - return nil, fmt.Errorf("no default instance types known for AMI architecture: %v", arch) - } - return m.getValidInstanceTypesFromList(defaults) -} - -func (m *nodeManager) getValidInstanceTypesFromList(desiredInstanceTypes []string) ([]string, error) { +func (m *nodeManager) getValidInstanceTypes(desiredInstanceTypes []string) ([]string, error) { var validInstanceTypes []string for _, instanceType := range desiredInstanceTypes { ec2InstanceType := ec2types.InstanceType(instanceType) diff --git a/kubetest2/internal/deployers/eksapi/ssh.go b/kubetest2/internal/deployers/eksapi/ssh.go deleted file mode 100644 index 5176b7ac6..000000000 --- a/kubetest2/internal/deployers/eksapi/ssh.go +++ /dev/null @@ -1,108 +0,0 @@ -package eksapi - -import ( - "errors" - "fmt" - "os" - "path" - - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - - "golang.org/x/crypto/ssh" - "k8s.io/klog" -) - -const sshKeyBits = 2048 - -func loadSSHPublicKey() (string, error) { - home, err := os.UserHomeDir() - if err != nil { - return "", err - } - publicKeyFile := path.Join(home, ".ssh", "id_rsa.pub") - material, err := os.ReadFile(publicKeyFile) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - return "", fmt.Errorf("SSH public key does not exist: %s", publicKeyFile) - } - return "", err - } - return string(material), err -} - -func generateSSHKey() error { - home, err := os.UserHomeDir() - if err != nil { - return err - } - privateKeyFile := path.Join(home, ".ssh", "id_rsa") - publicKeyFile := privateKeyFile + ".pub" - if err := generateSSHKeyToFile(privateKeyFile, publicKeyFile); err != nil { - return fmt.Errorf("failed to generate ssh key: %v", err) - } - return nil -} - -func generateSSHKeyToFile(privateKeyPath string, publicKeyPath string) error { - if _, err := os.Stat(privateKeyPath); !errors.Is(err, os.ErrNotExist) { - return err - } - if _, err := os.Stat(publicKeyPath); !errors.Is(err, os.ErrNotExist) { - return err - } - klog.Infof("Generating SSH key: %s", privateKeyPath) - privateKey, err := generatePrivateKey(sshKeyBits) - if err != nil { - return err - } - publicKeyBytes, err := encodePublicKey(privateKey) - if err != nil { - return err - } - privateKeyBytes := encodePrivateKeyToPEM(privateKey) - keyDir := path.Dir(privateKeyPath) - if err := os.MkdirAll(keyDir, 0700); err != nil { - return fmt.Errorf("failed to create directory for SSH key: %v", err) - } - if err := os.WriteFile(privateKeyPath, privateKeyBytes, 0600); err != nil { - return fmt.Errorf("failed to write SSH private key to %s: %v", privateKeyPath, err) - } - if err := os.WriteFile(publicKeyPath, publicKeyBytes, 0600); err != nil { - return fmt.Errorf("failed to write SSH public key to %s: %v", publicKeyPath, err) - } - return nil -} - -func generatePrivateKey(bitSize int) (*rsa.PrivateKey, error) { - privateKey, err := rsa.GenerateKey(rand.Reader, bitSize) - if err != nil { - return nil, err - } - err = privateKey.Validate() - if err != nil { - return nil, err - } - return privateKey, nil -} - -func encodePrivateKeyToPEM(privateKey *rsa.PrivateKey) []byte { - privDER := x509.MarshalPKCS1PrivateKey(privateKey) - privBlock := pem.Block{ - Type: "RSA PRIVATE KEY", - Headers: nil, - Bytes: privDER, - } - return pem.EncodeToMemory(&privBlock) -} - -func encodePublicKey(privateKey *rsa.PrivateKey) ([]byte, error) { - publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey) - if err != nil { - return nil, err - } - publicKeyBytes := ssh.MarshalAuthorizedKey(publicKey) - return publicKeyBytes, nil -} diff --git a/kubetest2/internal/deployers/eksapi/ssh_test.go b/kubetest2/internal/deployers/eksapi/ssh_test.go deleted file mode 100644 index 96f2468f3..000000000 --- a/kubetest2/internal/deployers/eksapi/ssh_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package eksapi - -import ( - "path" - "testing" -) - -func Test_generateSSHKey(t *testing.T) { - tmp := t.TempDir() - privateKeyPath := path.Join(tmp, ".ssh", "id_rsa") - publicKeyPath := privateKeyPath + ".pub" - if err := generateSSHKeyToFile(privateKeyPath, publicKeyPath); err != nil { - t.Fatal(err) - } -} diff --git a/kubetest2/internal/deployers/eksapi/templates/infra.yaml b/kubetest2/internal/deployers/eksapi/templates/infra.yaml index d7d504c1e..5560d4b4b 100644 --- a/kubetest2/internal/deployers/eksapi/templates/infra.yaml +++ b/kubetest2/internal/deployers/eksapi/templates/infra.yaml @@ -33,9 +33,6 @@ Parameters: Default: "" Description: Additional service principal with sts:AssumeRole permissions on the ClusterRole - SSHPublicKeyMaterial: - Type: String - ResourceId: Type: String @@ -509,23 +506,6 @@ Resources: Roles: - !Ref NodeRole - SSHSecurityGroup: - Type: AWS::EC2::SecurityGroup - Properties: - GroupDescription: "SSH access for worker nodes" - VpcId: !Ref VPC - SecurityGroupIngress: - - IpProtocol: tcp - FromPort: 22 - ToPort: 22 - CidrIp: 127.0.0.1/32 - - SSHKeyPair: - Type: AWS::EC2::KeyPair - Properties: - PublicKeyMaterial: !Ref SSHPublicKeyMaterial - KeyName: !Ref ResourceId - Outputs: SubnetsPrivate: Value: @@ -554,19 +534,6 @@ Outputs: Name: Fn::Sub: "${AWS::StackName}::VPC" - SSHSecurityGroup: - Value: !GetAtt SSHSecurityGroup.GroupId - Export: - Name: - Fn::Sub: "${AWS::StackName}::SSHSecurityGroup" - - SSHKeyPair: - Value: - Ref: SSHKeyPair - Export: - Name: - Fn::Sub: "${AWS::StackName}::SSHKeyPair" - ClusterRole: Value: Fn::Join: diff --git a/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup-efa.yaml b/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup-efa.yaml index 4acf8c013..1113a6412 100644 --- a/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup-efa.yaml +++ b/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup-efa.yaml @@ -35,9 +35,6 @@ Parameters: Description: The IAM role name of worker nodes. Type: String - SSHKeyPair: - Type: String - UserData: Type: String @@ -124,28 +121,6 @@ Resources: CidrIpv6: "::/0" GroupId: !Ref EFASecurityGroup IpProtocol: "-1" - - EFASecurityGroupIngressSSHIpv4: - Type: "AWS::EC2::SecurityGroupIngress" - DependsOn: EFASecurityGroup - Properties: - Description: Allow SSH - FromPort: 22 - ToPort: 22 - CidrIp: "0.0.0.0/0" - GroupId: !Ref EFASecurityGroup - IpProtocol: "tcp" - - EFASecurityGroupIngressSSHIpv6: - Type: "AWS::EC2::SecurityGroupIngress" - DependsOn: EFASecurityGroup - Properties: - Description: Allow SSH - FromPort: 22 - ToPort: 22 - CidrIpv6: "::/0" - GroupId: !Ref EFASecurityGroup - IpProtocol: "tcp" EFASecurityGroupIngressControlPlane: Type: "AWS::EC2::SecurityGroupIngress" @@ -230,7 +205,6 @@ Resources: Arn: !GetAtt NodeInstanceProfile.Arn ImageId: !Ref AMIId InstanceType: !Ref InstanceType - KeyName: !Ref SSHKeyPair NetworkInterfaces: !If - IsP5Node - diff --git a/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup.yaml.template b/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup.yaml.template index 58772524e..dbbb831ce 100644 --- a/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup.yaml.template +++ b/kubetest2/internal/deployers/eksapi/templates/unmanaged-nodegroup.yaml.template @@ -36,12 +36,6 @@ Parameters: Description: The IAM role name of worker nodes. Type: String - SSHKeyPair: - Type: String - - SSHSecurityGroup: - Type: String - UserData: Type: String @@ -102,8 +96,6 @@ Resources: LaunchTemplateData: SecurityGroupIds: - !Ref SecurityGroup - - !Ref SSHSecurityGroup - KeyName: !Ref SSHKeyPair UserData: Fn::Base64: Fn::If: diff --git a/kubetest2/internal/deployers/eksapi/vpccni.go b/kubetest2/internal/deployers/eksapi/vpccni.go index b5a1e946f..1dc954dae 100644 --- a/kubetest2/internal/deployers/eksapi/vpccni.go +++ b/kubetest2/internal/deployers/eksapi/vpccni.go @@ -7,7 +7,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/kubernetes" ) const vpcCNIDaemonSetPatch = `{ @@ -39,11 +38,11 @@ const vpcCNIDaemonSetPatch = `{ }` // tuneVPCCNI applies configuration to the VPC CNI DaemonSet that helps prevent test flakiness -func tuneVPCCNI(client *kubernetes.Clientset) error { +func (k *k8sClient) tuneVPCCNI() error { var patch bytes.Buffer if err := json.Compact(&patch, []byte(vpcCNIDaemonSetPatch)); err != nil { return err } - _, err := client.AppsV1().DaemonSets("kube-system").Patch(context.TODO(), "aws-node", types.StrategicMergePatchType, patch.Bytes(), metav1.PatchOptions{}) + _, err := k.clientset.AppsV1().DaemonSets("kube-system").Patch(context.TODO(), "aws-node", types.StrategicMergePatchType, patch.Bytes(), metav1.PatchOptions{}) return err } diff --git a/kubetest2/internal/util/lang.go b/kubetest2/internal/util/lang.go new file mode 100644 index 000000000..88ee0a286 --- /dev/null +++ b/kubetest2/internal/util/lang.go @@ -0,0 +1,8 @@ +package util + +func Must[T any](t T, err error) T { + if err != nil { + panic(err) + } + return t +}