diff --git a/.gitignore b/.gitignore index c139c83..5c919e4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.DS_Store .idea # ignore the compiled binary diff --git a/cmd/kubernetes.go b/cmd/kubernetes.go index ea3f9fa..3ea50b3 100644 --- a/cmd/kubernetes.go +++ b/cmd/kubernetes.go @@ -8,6 +8,7 @@ import ( "github.com/kong/kubernetes-testing-framework/pkg/clusters/addons/metallb" "github.com/kong/kubernetes-testing-framework/pkg/environments" "github.com/kumahq/kuma-smoke/pkg/cluster-providers" + _ "github.com/kumahq/kuma-smoke/pkg/cluster-providers/eks" _ "github.com/kumahq/kuma-smoke/pkg/cluster-providers/gke" _ "github.com/kumahq/kuma-smoke/pkg/cluster-providers/kind" "github.com/kumahq/kuma-smoke/pkg/utils" @@ -136,10 +137,7 @@ var k8sCleanupCmd = &cobra.Command{ cobra.CheckErr(err) utils.CmdStdErr(cmd, "cleaning up cluster of environment %s\n", k8sCleanupOpt.envName) - err = existingCls.Cleanup(ctx) - cobra.CheckErr(err) - - return nil + return existingCls.Cleanup(ctx) }, } diff --git a/go.mod b/go.mod index 1ee2e83..a13da59 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/onsi/ginkgo/v2 v2.22.2 github.com/onsi/gomega v1.36.2 github.com/spf13/cobra v1.8.1 + github.com/weaveworks/eksctl v0.200.1-0.20250111135130-435cf341ad56 k8s.io/api v0.32.0 // indirect k8s.io/apimachinery v0.32.0 k8s.io/client-go v0.32.0 @@ -22,7 +23,18 @@ require ( github.com/kennygrant/sanitize v1.2.4 // indirect ) -require github.com/pkg/errors v0.9.1 +require ( + github.com/aws/aws-sdk-go-v2 v1.32.8 + github.com/aws/aws-sdk-go-v2/config v1.28.9 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 + github.com/aws/aws-sdk-go-v2/service/eks v1.56.1 + github.com/aws/aws-sdk-go-v2/service/iam v1.38.3 + github.com/aws/aws-sdk-go-v2/service/sts v1.33.5 + github.com/aws/smithy-go v1.22.1 + github.com/google/uuid v1.6.0 + github.com/kris-nova/logger v0.2.1 + github.com/pkg/errors v0.9.1 +) require ( cel.dev/expr v0.18.0 // indirect @@ -31,50 +43,57 @@ require ( cloud.google.com/go/compute/metadata v0.6.0 // indirect cloud.google.com/go/container v1.42.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect + github.com/Azure/azure-pipeline-go v0.2.3 // indirect + github.com/Azure/azure-storage-blob-go v0.15.0 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/BurntSushi/toml v1.4.0 // indirect - github.com/Masterminds/semver/v3 v3.3.0 // indirect + github.com/Masterminds/semver/v3 v3.3.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/Nordix/simple-ipam v1.0.0 // indirect + github.com/apparentlymart/go-cidr v1.1.0 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/avast/retry-go/v4 v4.6.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.32.5 // indirect + github.com/aws/aws-sdk-go v1.51.16 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect - github.com/aws/aws-sdk-go-v2/config v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.46 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.50 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.23 // indirect github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.27 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.27 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 // indirect github.com/aws/aws-sdk-go-v2/service/acm v1.30.6 // indirect - github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0 // indirect - github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0 // indirect + github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.3 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.4 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.5 // indirect + github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.2 // indirect github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 // indirect github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 // indirect github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0 // indirect - github.com/aws/aws-sdk-go-v2/service/iam v1.38.1 // indirect + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.9 // indirect + github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.4 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.5 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8 // indirect github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 // indirect github.com/aws/aws-sdk-go-v2/service/kms v1.37.6 // indirect github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0 // indirect + github.com/aws/aws-sdk-go-v2/service/outposts v1.48.1 // indirect github.com/aws/aws-sdk-go-v2/service/rds v1.91.0 // indirect github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2 // indirect github.com/aws/aws-sdk-go-v2/service/s3 v1.69.0 // indirect github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.6 // indirect github.com/aws/aws-sdk-go-v2/service/sns v1.33.6 // indirect github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1 // indirect - github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 // indirect - github.com/aws/smithy-go v1.22.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssm v1.56.3 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.9 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8 // indirect + github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20240508073157-fbfa1bc129f5 // indirect + github.com/awslabs/goformation/v4 v4.19.5 // indirect github.com/bakito/go-log-logr-adapter v0.0.3-0.20231211113354-bfa42fa7e121 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/blang/semver v3.5.1+incompatible // indirect github.com/boombuler/barcode v1.0.1 // indirect github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect @@ -93,6 +112,7 @@ require ( github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/go-errors/errors v1.4.2 // indirect + github.com/go-ini/ini v1.67.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect @@ -117,14 +137,15 @@ require ( github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect github.com/google/s2a-go v0.1.8 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect github.com/googleapis/gax-go/v2 v2.14.1 // indirect + github.com/gophercloud/gophercloud v1.6.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect github.com/gruntwork-io/go-commons v0.8.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-version v1.7.0 // indirect github.com/hoisie/mustache v0.0.0-20160804235033-6375acf62c69 // indirect github.com/homeport/dyff v1.6.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -137,9 +158,12 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect github.com/klauspost/compress v1.17.9 // indirect + github.com/kr/fs v0.1.0 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 // indirect + github.com/mattn/go-ieproxy v0.0.1 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -147,6 +171,7 @@ require ( github.com/mitchellh/hashstructure v1.1.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/spdystream v0.5.0 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect @@ -155,6 +180,8 @@ require ( github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect + github.com/pelletier/go-toml v1.9.5 // indirect + github.com/pkg/sftp v1.13.6 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pquerna/otp v1.4.0 // indirect @@ -164,6 +191,8 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.47.0 // indirect + github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b // indirect + github.com/sanathkr/yaml v0.0.0-20170819201035-0056894fa522 // indirect github.com/sergi/go-diff v1.3.1 // indirect github.com/sethvargo/go-retry v0.3.0 // indirect github.com/shopspring/decimal v1.4.0 // indirect @@ -185,6 +214,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect + goformation/v4 v4.0.0 // indirect golang.org/x/crypto v0.31.0 // indirect golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect golang.org/x/net v0.33.0 // indirect @@ -209,8 +239,12 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect gotest.tools/v3 v3.5.1 // indirect k8s.io/apiextensions-apiserver v0.32.0 // indirect + k8s.io/cli-runtime v0.32.0 // indirect + k8s.io/component-base v0.32.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kops v1.28.4 // indirect k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect + k8s.io/kubelet v0.29.1 // indirect sigs.k8s.io/controller-runtime v0.19.3 // indirect sigs.k8s.io/gateway-api v1.2.1 // indirect sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect @@ -230,3 +264,10 @@ replace github.com/envoyproxy/go-control-plane => github.com/kumahq/go-control-p // being tracked in https://github.com/Kong/kubernetes-testing-framework/issues/1249 // Remove this replace once the issue is resolved. replace github.com/kong/kubernetes-testing-framework => github.com/jijiechen/kubernetes-testing-framework v0.0.0-20250108063744-231b0c34b842 + +// the following dependency replacements (bufpipe, goformation) are added by "eksctl" +// Ensure k8s dependencies are also pinned accordingly +replace github.com/acomagu/bufpipe => github.com/acomagu/bufpipe v1.0.4 + +// Use a local fork of goformation +replace goformation/v4 => github.com/weaveworks/eksctl/goformation/v4 v4.0.0-20250111135130-435cf341ad56 diff --git a/go.sum b/go.sum index e116499..bcb8c59 100644 --- a/go.sum +++ b/go.sum @@ -14,53 +14,82 @@ dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= +github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= +github.com/Azure/azure-storage-blob-go v0.15.0 h1:rXtgp8tN1p29GvpGgfJetavIG0V7OgcSXPpwp3tx6qk= +github.com/Azure/azure-storage-blob-go v0.15.0/go.mod h1:vbjsVbX0dlxnRc4FFMPsS9BsJWPcne7GB7onqlPvz58= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +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.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.22 h1:/GblQdIudfEM3AWWZ0mrYJQSd7JS4S/Mbzh6F0ov0Xc= +github.com/Azure/go-autorest/autorest/adal v0.9.22/go.mod h1:XuAbAEUv2Tta//+voMI038TrJBqjKam0me7qR+L8Cmk= +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/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 v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0= -github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= +github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4= +github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Nordix/simple-ipam v1.0.0 h1:oMyASgx2EEH0ccjAEBgCgCviu7z4uB+Od7UUCBxqcFE= github.com/Nordix/simple-ipam v1.0.0/go.mod h1:7d9TR/lF/zpNDHYhT43qhewce8vNdzVG5kCk7K9dPac= +github.com/apparentlymart/go-cidr v1.1.0 h1:2mAhrMoF+nhXqxTzSZMUzDHkLjmIHC+Zzn4tdgBZjnU= +github.com/apparentlymart/go-cidr v1.1.0/go.mod h1:EBcsNrHc3zQeuaeCeCtQruQm+n9/YjEn/vI25Lg7Gwc= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= -github.com/aws/aws-sdk-go-v2 v1.32.5 h1:U8vdWJuY7ruAkzaOdD7guwJjD06YSKmnKCJs7s3IkIo= -github.com/aws/aws-sdk-go-v2 v1.32.5/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/amazon-ec2-instance-selector/v2 v2.4.2-0.20230601180523-74e721cb8c1e h1:zWGlJnXe5BLiqYuIHozuCGH5imE12AVhi2ss68pbpxI= +github.com/aws/amazon-ec2-instance-selector/v2 v2.4.2-0.20230601180523-74e721cb8c1e/go.mod h1:X1GFUTX6aorSJmVLgfAD56jdNPvnNSOIpsRLgxA1LLE= +github.com/aws/aws-sdk-go v1.51.16 h1:vnWKK8KjbftEkuPX8bRj3WHsLy1uhotn0eXptpvrxJI= +github.com/aws/aws-sdk-go v1.51.16/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go-v2 v1.32.8 h1:cZV+NUS/eGxKXMtmyhtYPJ7Z4YLoI/V8bkTdRZfYhGo= +github.com/aws/aws-sdk-go-v2 v1.32.8/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc= -github.com/aws/aws-sdk-go-v2/config v1.28.5 h1:Za41twdCXbuyyWv9LndXxZZv3QhTG1DinqlFsSuvtI0= -github.com/aws/aws-sdk-go-v2/config v1.28.5/go.mod h1:4VsPbHP8JdcdUDmbTVgNL/8w9SqOkM5jyY8ljIxLO3o= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46 h1:AU7RcriIo2lXjUfHFnFKYsLCwgbz1E7Mm95ieIRDNUg= -github.com/aws/aws-sdk-go-v2/credentials v1.17.46/go.mod h1:1FmYyLGL08KQXQ6mcTlifyFXfJVCNJTVGuQP4m0d/UA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20 h1:sDSXIrlsFSFJtWKLQS4PUWRvrT580rrnuLydJrCQ/yA= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.20/go.mod h1:WZ/c+w0ofps+/OUqMwWgnfrgzZH1DZO1RIkktICsqnY= +github.com/aws/aws-sdk-go-v2/config v1.28.9 h1:7/P2J1MGkava+2c9Xlk7CTPTpGqFAOaM4874wJsGi4Q= +github.com/aws/aws-sdk-go-v2/config v1.28.9/go.mod h1:ce/HX8tHlIh4VTPaLz/aQIvA5+/rUghFy+nGMrXHQ9U= +github.com/aws/aws-sdk-go-v2/credentials v1.17.50 h1:63pBzfU7EG4RbMMVRv4Hgm34cIaPXICCnHojKdPbTR0= +github.com/aws/aws-sdk-go-v2/credentials v1.17.50/go.mod h1:m5ThO5y87w0fiAHBt9cYXS5BVsebOeJEFCGUQeZZYLw= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.23 h1:IBAoD/1d8A8/1aA8g4MBVtTRHhXRiNAgwdbo/xRM2DI= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.23/go.mod h1:vfENuCM7dofkgKpYzuzf1VT1UKkA/YL3qanfBn7HCaA= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41 h1:hqcxMc2g/MwwnRMod9n6Bd+t+9Nf7d5qRg7RaXKPd6o= github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.41/go.mod h1:d1eH0VrttvPmrCraU68LOyNdu26zFxQFjrVSb5vdhog= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24 h1:4usbeaes3yJnCFC7kfeyhkdkPtoRYPa/hTmCqMpKpLI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.24/go.mod h1:5CI1JemjVwde8m2WG3cz23qHKPOxbpkq0HaoreEgLIY= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24 h1:N1zsICrQglfzaBnrfM0Ys00860C+QFwu6u/5+LomP+o= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.24/go.mod h1:dCn9HbJ8+K31i8IQ8EWmWj0EiIk0+vKiHNMxTTYveAg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.27 h1:jSJjSBzw8VDIbWv+mmvBSP8ezsztMYJGH+eKqi9AmNs= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.27/go.mod h1:/DAhLbFRgwhmvJdOfSm+WwikZrCuUJiA4WgJG0fTNSw= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.27 h1:l+X4K77Dui85pIj5foXDhPlnqcNRG2QUyvca300lXh8= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.27/go.mod h1:KvZXSFEXm6x84yE8qffKvT3x8J5clWnVFXphpohhzJ8= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24 h1:JX70yGKLj25+lMC5Yyh8wBtvB01GDilyRuJvXJ4piD0= github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.24/go.mod h1:+Ln60j9SUTD0LEwnhEB0Xhg61DHqplBrbZpLgyjoEHg= github.com/aws/aws-sdk-go-v2/service/acm v1.30.6 h1:fDg0RlN30Xf/yYzEUL/WXqhmgFsjVb/I3230oCfyI5w= github.com/aws/aws-sdk-go-v2/service/acm v1.30.6/go.mod h1:zRR6jE3v/TcbfO8C2P+H0Z+kShiKKVaVyoIl8NQRjyg= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0 h1:1KzQVZi7OTixxaVJ8fWaJAUBjme+iQ3zBOCZhE4RgxQ= -github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.0/go.mod h1:I1+/2m+IhnK5qEbhS3CrzjeiVloo9sItE/2K+so0fkU= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0 h1:OREVd94+oXW5a+3SSUAo4K0L5ci8cucCLu+PSiek8OU= -github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.44.0/go.mod h1:Qbr4yfpNqVNl69l/GEDK+8wxLf/vHi0ChoiSDzD7thU= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.3 h1:1QljimH+yYwrCPgmF2S/vnIE/sBEBS0IdZIvE5+bRJY= +github.com/aws/aws-sdk-go-v2/service/autoscaling v1.51.3/go.mod h1:t5bdAowh8MWq51TuDmltU+wtxMl/VaegNwSBaznkUYc= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.4 h1:uH6So7Ee+2JQf+TKbfifXKUDNN0JfaJ6CgJ6Bh/u1sc= +github.com/aws/aws-sdk-go-v2/service/cloudformation v1.56.4/go.mod h1:GdDLBO8SzD4wvQ6fhqU1QCmvG1waj1MPHL4cBtuSgdQ= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.5 h1:+fSJTvw91AyBSgS7iaPlSe0NVwa1DJqb6F6GClah+0s= +github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.46.5/go.mod h1:2lQF0aEQAXkUf/Td7RqGIuylJlJO6wSv/onvNdShVyA= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.2 h1:9zwK03mlPPGzTaiLh1AJS6IhOAWDYnVXfZTwdyBhQtg= +github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs v1.45.2/go.mod h1:u8Bi6DG9tLOVIS9MNqtE3vh9T6I/U/8RBpYvy/VyMjc= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1 h1:vucMirlM6D+RDU8ncKaSZ/5dGrXNajozVwpmWNPn2gQ= github.com/aws/aws-sdk-go-v2/service/dynamodb v1.37.1/go.mod h1:fceORfs010mNxZbQhfqUjUeHlTwANmIT4mvHamuUaUg= github.com/aws/aws-sdk-go-v2/service/ec2 v1.193.0 h1:RhSoBFT5/8tTmIseJUXM6INTXTQDF8+0oyxWBnozIms= @@ -69,22 +98,32 @@ github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6 h1:zg+3FGHA0PBs0KM25qE/rOf2o5zs github.com/aws/aws-sdk-go-v2/service/ecr v1.36.6/go.mod h1:ZSq54Z9SIsOTf1Efwgw1msilSs4XVEfVQiP9nYVnKpM= github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0 h1:7/vgFWplkusJN/m+3QOa+W9FNRqa8ujMPNmdufRaJpg= github.com/aws/aws-sdk-go-v2/service/ecs v1.52.0/go.mod h1:dPTOvmjJQ1T7Q+2+Xs2KSPrMvx+p0rpyV+HsQVnUK4o= -github.com/aws/aws-sdk-go-v2/service/iam v1.38.1 h1:hfkzDZHBp9jAT4zcd5mtqckpU4E3Ax0LQaEWWk1VgN8= -github.com/aws/aws-sdk-go-v2/service/iam v1.38.1/go.mod h1:u36ahDtZcQHGmVm/r+0L1sfKX4fzLEMdCqiKRKkUMVM= +github.com/aws/aws-sdk-go-v2/service/eks v1.56.1 h1:TbZoGON9WoQSDC86lTA+eDCXTCqJElgM4TTiqdVcSG4= +github.com/aws/aws-sdk-go-v2/service/eks v1.56.1/go.mod h1:kNUWaiotRWCnfQlprrxSMg8ALqbZyA9xLCwKXuLumSk= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.9 h1:phUmuRbBmJKpPBbGx34uZJuV1PPg4u0/RMzIecVVR0E= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancing v1.28.9/go.mod h1:EH2+vt500M2IewoiYVo4rP0gfRhIXzh6BDFZ5KbidUI= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.4 h1:tC9S2BkqlMWP3N2t4UasxIhIJSNY5g7EINjz94VK+3U= +github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.43.4/go.mod h1:OhWF5Dd6Ge4VW/RcFQKOO0eEv1JInQJoo6/tkCjlvrM= +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.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5 h1:gvZOjQKPxFXy1ft3QnEyXmT+IqneM9QAUWlM3r0mfqw= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.5/go.mod h1:DLWnfvIcm9IET/mmjdxeXbBKmTCm0ZB8p1za9BVteM8= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.5 h1:3Y457U2eGukmjYjeHG6kanZpDzJADa2m0ADqnuePYVQ= github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.5/go.mod h1:CfwEHGkTjYZpkQ/5PvcbEtT7AJlG68KkEvmtwU8z3/U= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5 h1:wtpJ4zcwrSbwhECWQoI/g6WM9zqCcSpHDJIWSbMLOu4= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.5/go.mod h1:qu/W9HXQbbQ4+1+JcZp0ZNPV31ym537ZJN+fiS7Ti8E= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8 h1:cWno7lefSH6Pp+mSznagKCgfDGeZRin66UvYUqAkyeA= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.8/go.mod h1:tPD+VjU3ABTBoEJ3nctu5Nyg4P4yjqSH5bJGGkY4+XE= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5 h1:P1doBzv5VEg1ONxnJss1Kh5ZG/ewoIE4MQtKKc6Crgg= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.5/go.mod h1:NOP+euMW7W3Ukt28tAxPuoWao4rhhqJD3QEBk7oCg7w= github.com/aws/aws-sdk-go-v2/service/kms v1.37.6 h1:CZImQdb1QbU9sGgJ9IswhVkxAcjkkD1eQTMA1KHWk+E= github.com/aws/aws-sdk-go-v2/service/kms v1.37.6/go.mod h1:YJDdlK0zsyxVBxGU48AR/Mi8DMrGdc1E3Yij4fNrONA= github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0 h1:BXt75frE/FYtAmEDBJRBa2HexOw+oAZWZl6QknZEFgg= github.com/aws/aws-sdk-go-v2/service/lambda v1.69.0/go.mod h1:guz2K3x4FKSdDaoeB+TPVgJNU9oj2gftbp5cR8ela1A= +github.com/aws/aws-sdk-go-v2/service/outposts v1.48.1 h1:UpEOfSzEsykGrXBc90elNcE6eGX//z0n4W4+gaxE8Bs= +github.com/aws/aws-sdk-go-v2/service/outposts v1.48.1/go.mod h1:g0Txg8E+JL0CZT5l5kYqQQLBcwYu2SWPs8Tkzi6lMuk= +github.com/aws/aws-sdk-go-v2/service/pricing v1.17.0 h1:RQOMvPwte2H4ZqsiZmrla1crhBWDFnW8bZynkec5cGU= +github.com/aws/aws-sdk-go-v2/service/pricing v1.17.0/go.mod h1:LJyh9figH3ZpSiVjR5umzbl6V3EpQdZR4Se1ayoUtfI= github.com/aws/aws-sdk-go-v2/service/rds v1.91.0 h1:eqHz3Uih+gb0vLE5Cc4Xf733vOxsxDp6GFUUVQU4d7w= github.com/aws/aws-sdk-go-v2/service/rds v1.91.0/go.mod h1:h2jc7IleH3xHY7y+h8FH7WAZcz3IVLOB6/jXotIQ/qU= github.com/aws/aws-sdk-go-v2/service/route53 v1.46.2 h1:wmt05tPp/CaRZpPV5B4SaJ5TwkHKom07/BzHoLdkY1o= @@ -97,40 +136,62 @@ github.com/aws/aws-sdk-go-v2/service/sns v1.33.6 h1:lEUtRHICiXsd7VRwRjXaY7MApT2X github.com/aws/aws-sdk-go-v2/service/sns v1.33.6/go.mod h1:SODr0Lu3lFdT0SGsGX1TzFTapwveBrT5wztVoYtppm8= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1 h1:39WvSrVq9DD6UHkD+fx5x19P5KpRQfNdtgReDVNbelc= github.com/aws/aws-sdk-go-v2/service/sqs v1.37.1/go.mod h1:3gwPzC9LER/BTQdQZ3r6dUktb1rSjABF1D3Sr6nS7VU= -github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0 h1:mADKqoZaodipGgiZfuAjtlcr4IVBtXPZKVjkzUZCCYM= -github.com/aws/aws-sdk-go-v2/service/ssm v1.56.0/go.mod h1:l9qF25TzH95FhcIak6e4vt79KE4I7M2Nf59eMUVjj6c= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6 h1:3zu537oLmsPfDMyjnUS2g+F2vITgy5pB74tHI+JBNoM= -github.com/aws/aws-sdk-go-v2/service/sso v1.24.6/go.mod h1:WJSZH2ZvepM6t6jwu4w/Z45Eoi75lPN7DcydSRtJg6Y= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5 h1:K0OQAsDywb0ltlFrZm0JHPY3yZp/S9OaoLU33S7vPS8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.5/go.mod h1:ORITg+fyuMoeiQFiVGoqB3OydVTLkClw/ljbblMq6Cc= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1 h1:6SZUVRQNvExYlMLbHdlKB48x0fLbc2iVROyaNEwBHbU= -github.com/aws/aws-sdk-go-v2/service/sts v1.33.1/go.mod h1:GqWyYCwLXnlUB1lOAXQyNSPqPLQJvmo8J0DWBzp9mtg= +github.com/aws/aws-sdk-go-v2/service/ssm v1.56.3 h1:QMx9lj524IOWjI1IpmcXSkHaazGBzTPgBmECzbppF5s= +github.com/aws/aws-sdk-go-v2/service/ssm v1.56.3/go.mod h1:RKWoqC9FlgMCkrfVOtgfqfwdaUIaq8H93UAt4xNaR0A= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.9 h1:YqtxripbjWb2QLyzRK9pByfEDvgg95gpC2AyDq4hFE8= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.9/go.mod h1:lV8iQpg6OLOfBnqbGMBKYjilBlf633qwHnBEiMSPoHY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8 h1:6dBT1Lz8fK11m22R+AqfRsFn8320K0T5DTGxxOQBSMw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.8/go.mod h1:/kiBvRQXBc6xeJTYzhSdGvJ5vm1tjaDEjH+MSeRJnlY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.5 h1:URp6kw3vHAnuU9pgP4K1SohwWLDzgtqA/qgeBfgBxn0= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.5/go.mod h1:+8h7PZb3yY5ftmVLD7ocEoE98hdc8PoKS0H3wfx1dlc= 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-eks-ami/nodeadm v0.0.0-20240508073157-fbfa1bc129f5 h1:F80UWAvCDH3PgWIkMhwhKN7FRlkn9MhI+nBHFq739ZM= +github.com/awslabs/amazon-eks-ami/nodeadm v0.0.0-20240508073157-fbfa1bc129f5/go.mod h1:wLKtvVfT0IdSJ3Pf6QoeLN+UTUeU28CmSAnoja6/l5s= +github.com/awslabs/goformation/v4 v4.19.5 h1:Y+Tzh01tWg8gf//AgGKUamaja7Wx9NPiJf1FpZu4/iU= +github.com/awslabs/goformation/v4 v4.19.5/go.mod h1:JoNpnVCBOUtEz9bFxc9sjy8uBUCLF5c4D1L7RhRTVM8= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/bakito/go-log-logr-adapter v0.0.3-0.20231211113354-bfa42fa7e121 h1:0mA5T6mV0/9+t7TfYAWINV3V6PNrXl0G0bnUgSIpq4E= github.com/bakito/go-log-logr-adapter v0.0.3-0.20231211113354-bfa42fa7e121/go.mod h1:0I6DOlUOuXiVency29rZX1chhXtuZBH1p9TVzKkMw60= 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/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= 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/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs= github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= +github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/bubbles v0.15.0 h1:c5vZ3woHV5W2b8YZI1q7v4ZNQaPetfHuoHzx+56Z6TI= +github.com/charmbracelet/bubbles v0.15.0/go.mod h1:Y7gSFbBzlMpUDR/XM9MhZI374Q+1p1kluf1uLl8iK74= +github.com/charmbracelet/bubbletea v0.24.1 h1:LpdYfnu+Qc6XtvMz6d/6rRY71yttHTP5HtrjMgWvixc= +github.com/charmbracelet/bubbletea v0.24.1/go.mod h1:rK3g/2+T8vOSEkNHvtq40umJpeVYDn6bLaqbgzhL/hg= +github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= +github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c= +github.com/cloudflare/cfssl v1.6.4 h1:NMOvfrEjFfC63K3SGXgAnFdsgkmiq4kATme5BfcqrO8= +github.com/cloudflare/cfssl v1.6.4/go.mod h1:8b3CQMxfWPAeom3zBnGJ6sd+G1NkL5TXqmDXacb+1J0= github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI= github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= +github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc= github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= 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= @@ -151,9 +212,16 @@ github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evertras/bubble-table v0.15.2 h1:hVj27V9tk5TD5p6mVv0RK/KJu2sHq0U+mBMux/HptkU= +github.com/evertras/bubble-table v0.15.2/go.mod h1:SPOZKbIpyYWPHBNki3fyNpiPBQkvkULAtOT7NTD5fKY= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= @@ -163,6 +231,8 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= +github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -178,16 +248,28 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/goburrow/cache v0.1.4 h1:As4KzO3hgmzPlnaMniZU9+VmoNYseUhuELbxy9mRBfw= github.com/goburrow/cache v0.1.4/go.mod h1:cDFesZDnIlrHoNlMYqqMpCRawuXulgx+y7mXU8HZ+/c= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= 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.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo= github.com/golang-jwt/jwt/v4 v4.5.1/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.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/gonvenience/bunt v1.3.5 h1:wSQquifvwEWtzn27k1ngLfeLaStyt0k1b/K6TrlCNAs= @@ -202,8 +284,14 @@ github.com/gonvenience/wrap v1.1.2 h1:xPKxNwL1HCguwyM+HlP/1CIuc9LRd7k8RodLwe9YTZ github.com/gonvenience/wrap v1.1.2/go.mod h1:GiryBSXoI3BAAhbWD1cZVj7RZmtiu0ERi/6R6eJfslI= github.com/gonvenience/ytbx v1.4.4 h1:jQopwyaLsVGuwdxSiN4WkXjsEaFNPJ3V4lUj7eyEpzo= github.com/gonvenience/ytbx v1.4.4/go.mod h1:w37+MKCPcCMY/jpPNmEklD4xKqrOAVBO6kIWW2+uI6M= +github.com/google/certificate-transparency-go v1.1.4 h1:hCyXHDbtqlr/lMXU0D4WgbalXL0Zk4dSWWMbPV8VrqY= +github.com/google/certificate-transparency-go v1.1.4/go.mod h1:D6lvbfwckhNrbM9WVl1EVeMOyzC19mpIjMOI4nxBHtQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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= @@ -216,12 +304,15 @@ github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM= github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw= github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA= github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q= github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA= +github.com/gophercloud/gophercloud v1.6.0 h1:JwJN1bauRnWPba5ueWs9IluONHteXPWjjK+MvfM4krY= +github.com/gophercloud/gophercloud v1.6.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= @@ -240,12 +331,18 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= +github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hoisie/mustache v0.0.0-20160804235033-6375acf62c69 h1:umaj0TCQ9lWUUKy2DxAhEzPbwd0jnxiw1EI2z3FiILM= github.com/hoisie/mustache v0.0.0-20160804235033-6375acf62c69/go.mod h1:zdLK9ilQRSMjSeLKoZ4BqUfBT7jswTGF8zRlKEsiRXA= github.com/homeport/dyff v1.6.0 h1:AN+ikld0Fy+qx34YE7655b/bpWuxS6cL9k852pE2GUc= github.com/homeport/dyff v1.6.0/go.mod h1:FlAOFYzeKvxmU5nTrnG+qrlJVWpsFew7pt8L99p5q8k= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= +github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -268,6 +365,8 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm 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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kennygrant/sanitize v1.2.4 h1:gN25/otpP5vAsO2djbMhF/LQX6R7+O1TB4yv8NzpJ3o= @@ -277,19 +376,30 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +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= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kris-nova/logger v0.2.1 h1:hbZusgXXXTSd0rNAMBBe/8lhjxXkqWs0+nzjwewCI+E= +github.com/kris-nova/logger v0.2.1/go.mod h1:++9BgZujZd4v0ZTZCb5iPsaomXdZWyxotIAh1IiDm44= +github.com/kris-nova/novaarchive v0.0.0-20210219195539-c7c1cabb2577 h1:wDLPO65M4W4VRDq9kyPAqbg+10OAq6hUfnv6ORhBYOc= +github.com/kris-nova/novaarchive v0.0.0-20210219195539-c7c1cabb2577/go.mod h1:Q4IuuyWjHqEqrxx68v+NPB1iQgtR/jcuR7/sdcGsa8M= +github.com/kubicorn/kubicorn v0.0.0-20180829191017-06f6bce92acc h1:7jGjX/rZDjpMwz0kojvzWvRpOvUiR7L8e22QEr7RYes= +github.com/kubicorn/kubicorn v0.0.0-20180829191017-06f6bce92acc/go.mod h1:Z/PU7XQicaZV6QFTAvm8EaWyfNbAb4a76kmR4Am4KA8= github.com/kumahq/go-control-plane v0.13.1-kong-1 h1:y4VBsyImRrxfVA1/8Fk8QtDI18uo8upc0agVfg6x5qU= github.com/kumahq/go-control-plane v0.13.1-kong-1/go.mod h1:X45hY0mufo6Fd0KW3rqsGvQMw58jvjymeCzBU3mWyHw= github.com/kumahq/kuma v0.0.0-20241204051139-86593067f050 h1:LrjxWla20Qq3JRNGizl1EEA25agxuuQCvws0db7Thy0= github.com/kumahq/kuma v0.0.0-20241204051139-86593067f050/go.mod h1:NcmA/uycF3KPBxF10uyIxWnZeC+A/9DYF/2MVzRStg4= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= @@ -297,10 +407,18 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3 h1:BXxTozrOU8zgC5dkpn3J6NTRdoP+hjok/e+ACr4Hibk= github.com/mattn/go-ciede2000 v0.0.0-20170301095244-782e8c62fec3/go.mod h1:x1uk6vxTiVuNt6S5R2UYgdhpj3oKojXvOXauHZ7dEnI= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI= +github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= @@ -329,16 +447,33 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34= +github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= +github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852 h1:Yl0tPBa8QPjGmesFh1D0rDy+q1Twx6FyU7VWHi8wZbI= +github.com/oliveagle/jsonpath v0.0.0-20180606110733-2e52cf6e6852/go.mod h1:eqOVx5Vwu4gd2mmMZvVZsgIqNSaW3xxRThUJ0k/TPk4= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= 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.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU= github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk= +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.12.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= @@ -347,8 +482,12 @@ github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQ github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= +github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.13.6 h1:JFZT4XbOU7l77xGSpOdW+pwIMqP044IyjXX6FGyEKFo= +github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -364,13 +503,21 @@ github.com/prometheus/common v0.60.0 h1:+V9PAREWNvJMAuJ1x1BaWl9dewMW4YrHZQbx0sJN github.com/prometheus/common v0.60.0/go.mod h1:h0LYf1R1deLSKtD4Vdg8gy4RuOvENW2J/h19V5NADQw= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= +github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= +github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= +github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b h1:jUK33OXuZP/l6babJtnLo1qsGvq6G9so9KMflGAm4YA= +github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b/go.mod h1:8458kAagoME2+LN5//WxE71ysZ3B7r22fdgb7qVmXSY= +github.com/sanathkr/yaml v0.0.0-20170819201035-0056894fa522 h1:fOCp11H0yuyAt2wqlbJtbyPzSgaxHTv8uN1pMpkG1t8= +github.com/sanathkr/yaml v0.0.0-20170819201035-0056894fa522/go.mod h1:tQTYKOQgxoH3v6dEmdHiz4JG+nbxWwM5fgPQUpSZqVQ= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= @@ -383,6 +530,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slok/go-http-metrics v0.13.0 h1:lQDyJJx9wKhmbliyUsZ2l6peGnXRHjsjoqPt5VYzcP8= github.com/slok/go-http-metrics v0.13.0/go.mod h1:HIr7t/HbN2sJaunvnt9wKP9xoBBVZFo1/KiHU3b0w+4= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w= github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= @@ -400,6 +549,8 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ 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.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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= @@ -409,17 +560,35 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/texttheater/golang-levenshtein v1.0.1 h1:+cRNoVrfiwufQPhoMzB6N0Yf/Mqajr6t1lOv8GyGE2U= github.com/texttheater/golang-levenshtein v1.0.1/go.mod h1:PYAKrbF5sAiq9wd+H82hs7gNaen0CplQ9uvm6+enD/8= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= +github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.16 h1:MH0k6uJxdwdeWQTwhSO42Pwr4YLrNLwBtg1MRgTqPdQ= github.com/urfave/cli v1.22.16/go.mod h1:EeJR6BKodywf4zciqrdw6hpCPk68JO9z5LazXZMn5Po= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74 h1:JwtAtbp7r/7QSyGz8mKUbYJBg2+6Cd7OjM8o/GNOcVo= github.com/virtuald/go-ordered-json v0.0.0-20170621173500-b18e6e673d74/go.mod h1:RmMWU37GKR2s6pgrIEB4ixgpVCt/cf7dnJv3fuH1J1c= +github.com/weaveworks/eksctl v0.200.1-0.20250111135130-435cf341ad56 h1:qHlSl5gG2TcaDaGOe6cPf996q+wLyHnqc+fC812dNMU= +github.com/weaveworks/eksctl v0.200.1-0.20250111135130-435cf341ad56/go.mod h1:EUQ72BBzOrTsn/oD/y5uYBse9UTrn2L3VLVes4xE6Ys= +github.com/weaveworks/eksctl/goformation/v4 v4.0.0-20250111135130-435cf341ad56 h1:Zt/zWLPSBLW2vpIcqiSt1gFg3btVMzumhL9bDVoL3Bk= +github.com/weaveworks/eksctl/goformation/v4 v4.0.0-20250111135130-435cf341ad56/go.mod h1:Jy/NruPCtIR7GO8XjuQKZIxDNFBun3UfoPTSq2vNgNg= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/github.com/emicklei/go-restful/otelrestful v0.55.0 h1:cmalGDJPtKfkOhzvlX9ey9sVqKhLckBj8jSIp7EzmfQ= @@ -453,39 +622,77 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/W 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-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/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-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e h1:I88y4caeGeuDQxgdoFPUq097j7kNfw6uvuiNxUBfcBk= golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= 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/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191112182307-2180aed22343/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-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 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-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +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= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/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-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/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-20210112080510-489259a85091/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= golang.org/x/sys v0.28.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.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= 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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= @@ -493,7 +700,9 @@ 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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 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.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -512,6 +721,14 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 h1: google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA= google.golang.org/grpc v1.67.3 h1:OgPcDAFKHnH8X3O4WcO4XUc8GRDeKsKReqbQtiCj7N8= google.golang.org/grpc v1.67.3/go.mod h1:YGaHCc6Oap+FzBJTZLBzkGSYt/cvGPFTPxkn7QfSU8s= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +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.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -520,6 +737,7 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= @@ -527,7 +745,9 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -541,12 +761,20 @@ k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2S k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw= k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg= k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/cli-runtime v0.32.0 h1:dP+OZqs7zHPpGQMCGAhectbHU2SNCuZtIimRKTv2T1c= +k8s.io/cli-runtime v0.32.0/go.mod h1:Mai8ht2+esoDRK5hr861KRy6z0zHsSTYttNVJXgP3YQ= k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8= k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8= +k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU= +k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kops v1.28.4 h1:vMKtEmmSfv5SJc9yxoFA+o/gCzk6XGXRCJAOMoZdH8w= +k8s.io/kops v1.28.4/go.mod h1:qaPEwbWXvrbAO4si3nEyFiOZ2hlFC43kYf+wkQUh6q4= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y= k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4= +k8s.io/kubelet v0.29.1 h1:cso8Dk8dymkj8q+EvW/aCbIYU2aOkH27gho48tYza/8= +k8s.io/kubelet v0.29.1/go.mod h1:hTl/naFcCVG1Ku17fMgj/krbheBwBkf3gnFhaboMx7E= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro= k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= diff --git a/mk/run.mk b/mk/run.mk index 09954fa..4979d84 100644 --- a/mk/run.mk +++ b/mk/run.mk @@ -49,7 +49,7 @@ deploy-kubernetes: .PHONY: cleanup-kubernetes cleanup-kubernetes: $(eval ENV_NAME=$(shell kubectl --kubeconfig=$(TOP)/build/kubernetes/cluster.config config view -o jsonpath='{.clusters[0].name}')) - @if [[ "$(ENV_NAME)" != "" ]]; then \ + @if [ "$(ENV_NAME)" != "" ]; then \ $(TOP)/build/kuma-smoke kubernetes cleanup --env $(ENV_NAME) --env-platform $(SMOKE_ENV_TYPE) ; \ rm -f $(TOP)/build/kubernetes/cluster.config; \ fi diff --git a/pkg/cluster-providers/eks/aws-operations/eks.go b/pkg/cluster-providers/eks/aws-operations/eks.go new file mode 100644 index 0000000..318638c --- /dev/null +++ b/pkg/cluster-providers/eks/aws-operations/eks.go @@ -0,0 +1,458 @@ +package aws_operations + +import ( + "context" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + "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/eks" + "github.com/aws/aws-sdk-go-v2/service/eks/types" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/ami" + eksctlapi "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/authconfigmap" + eksiam "github.com/weaveworks/eksctl/pkg/iam" + "github.com/weaveworks/eksctl/pkg/nodebootstrap" + "k8s.io/client-go/kubernetes" + "os" + "time" +) + +const ( + DefaultNodeGroupName = "default-node-group" + DefaultKubernetesSvcCIDR = "172.20.0.0/16" + kubernetesTagFormat = "kubernetes.io/cluster/%s" + envKeyNodeSSHKeyName = "EKS_NODE_SSH_KEY" +) + +func CreateEKSClusterAll(ctx context.Context, cfg aws.Config, clusterName, + k8sMinorVersion, nodeMachineType string) error { + + ec2Client := ec2.NewFromConfig(cfg) + eksClient := eks.NewFromConfig(cfg) + iamClient := iam.NewFromConfig(cfg) + + clusterRoleArn, nodeRoleArn, err := createRoles(ctx, iamClient, clusterName) + if err != nil { + return errors.Wrap(err, "failed to create IAM roles") + } + subnetAvZones, err := getAvailabilityZones(ctx, ec2Client, cfg.Region) + if err != nil { + return errors.Wrapf(err, "failed to get availability zones in region %s", cfg.Region) + } + + vpcId, subnetIDs, err := createVPC(ctx, ec2Client, subnetAvZones) + if err != nil { + return errors.Wrap(err, "failed to create VPC") + } + + cpSgId, err := createControlPlaneSecurityGroup(ctx, ec2Client, vpcId, clusterName) + if err != nil { + return errors.Wrapf(err, "failed to create control plane security group in VPC %s", vpcId) + } + + _, err = createCluster(ctx, eksClient, clusterName, clusterRoleArn, k8sMinorVersion, cpSgId, subnetIDs) + if err != nil { + return errors.Wrapf(err, "failed to create EKS cluster %s", clusterName) + } + + activeCluster, err := waitForClusterActive(ctx, eksClient, clusterName) + if err != nil { + return errors.Wrapf(err, "failed while waiting for EKS cluster %s to become active", clusterName) + } + + sgId, err := createNodeSecurityGroup(ctx, ec2Client, vpcId, clusterName, activeCluster.ResourcesVpcConfig.SecurityGroupIds) + if err != nil { + return errors.Wrapf(err, "failed to create security groups") + } + + _, kubeCfg, err := ClientForCluster(ctx, cfg, clusterName) + if err != nil { + return errors.Wrapf(err, "failed to get kube client for cluster %s", clusterName) + } + + err = authorizeNodeGroup(kubeCfg, nodeRoleArn) + if err != nil { + return errors.Wrapf(err, "failed to authorize node group to access cluster %s", clusterName) + } + + amiId, err := resolveAMI(ctx, ec2Client, cfg.Region, k8sMinorVersion, nodeMachineType, eksctlapi.DefaultNodeImageFamily) + if err != nil { + return errors.Wrap(err, "failed to resolve AMI") + } + + clusterCfg := buildClusterConfig(clusterName, k8sMinorVersion, nodeMachineType, cfg.Region, amiId, subnetAvZones) + ng := clusterCfg.NodeGroups[0] + clusterCfg.VPC.ID = vpcId + ng.Subnets = subnetIDs + ng.SecurityGroups.AttachIDs = []string{sgId} + ng.IAM.InstanceRoleARN = nodeRoleArn + + err = clusterCfg.SetClusterState(activeCluster) + if err != nil { + return errors.Wrapf(err, "failed to create cluster state object for cluster %s", clusterName) + } + + err = createNodeGroup(ctx, eksClient, ec2Client, clusterCfg) + if err != nil { + return errors.Wrapf(err, "failed to create EKS node group for cluster %s", clusterName) + } + + return nil +} + +func DeleteEKSClusterAll(ctx context.Context, cfg aws.Config, clusterName string) error { + eksClient := eks.NewFromConfig(cfg) + ec2Client := ec2.NewFromConfig(cfg) + iamClient := iam.NewFromConfig(cfg) + + activeCluster, err := eksClient.DescribeCluster(ctx, &eks.DescribeClusterInput{ + Name: aws.String(clusterName), + }) + if err != nil { + return errors.Wrap(err, "failed to read cluster information") + } + + vpcID := activeCluster.Cluster.ResourcesVpcConfig.VpcId + ngRole, launchTemplateId, err := deleteNodeGroup(ctx, eksClient, clusterName) + if err != nil { + return err + } + if launchTemplateId != "" { + err = deleteNodeLaunchTemplate(ctx, ec2Client, launchTemplateId) + if err != nil { + return err + } + } + + err = deleteRoles(ctx, iamClient, []string{ngRole, *activeCluster.Cluster.RoleArn}) + if err != nil { + return err + } + + err = deleteCluster(ctx, eksClient, clusterName) + if err != nil { + return err + } + + return deleteVPC(ctx, ec2Client, *vpcID) +} + +func createCluster(ctx context.Context, eksClient *eks.Client, + clusterName, clusterRoleArn, version, cpSgId string, subnetIDs []string) (*types.Cluster, error) { + eksCreateInput := &eks.CreateClusterInput{ + Name: &clusterName, + RoleArn: &clusterRoleArn, + Version: aws.String(version), + + ResourcesVpcConfig: &types.VpcConfigRequest{ + EndpointPrivateAccess: aws.Bool(true), + EndpointPublicAccess: aws.Bool(true), + SubnetIds: subnetIDs, + SecurityGroupIds: []string{cpSgId}, + }, + KubernetesNetworkConfig: &types.KubernetesNetworkConfigRequest{ + ServiceIpv4Cidr: aws.String(DefaultKubernetesSvcCIDR), + }, + } + + clusterOutput, err := eksClient.CreateCluster(ctx, eksCreateInput) + if err != nil { + return nil, errors.Wrapf(err, "failed to create EKS cluster %s", clusterName) + } + return clusterOutput.Cluster, nil +} + +func buildClusterConfig(clusterName, minorVersion, nodeMachineType, region, amiId string, subnetAvZones []string) *eksctlapi.ClusterConfig { + clusterCfg := eksctlapi.NewClusterConfig() + + clusterCfg.Metadata.Name = clusterName + clusterCfg.Metadata.Region = region + clusterCfg.Metadata.Version = minorVersion + clusterCfg.KubernetesNetworkConfig.ServiceIPv4CIDR = DefaultKubernetesSvcCIDR + clusterCfg.Status = &eksctlapi.ClusterStatus{} + + ng := clusterCfg.NewNodeGroup() + ng.Name = DefaultNodeGroupName + ng.ContainerRuntime = aws.String(eksctlapi.ContainerRuntimeContainerD) + ng.AMIFamily = eksctlapi.DefaultNodeImageFamily + ng.AMI = amiId + ng.InstanceType = nodeMachineType + ng.AvailabilityZones = subnetAvZones + ng.ScalingConfig = &eksctlapi.ScalingConfig{ + DesiredCapacity: aws.Int(1), + MinSize: aws.Int(1), + MaxSize: aws.Int(1), + } + + nodeKeyName := os.Getenv(envKeyNodeSSHKeyName) + if nodeKeyName != "" { + ng.SSH.Allow = aws.Bool(true) + ng.SSH.PublicKeyName = aws.String(nodeKeyName) + } + + return clusterCfg +} + +func waitForClusterActive(ctx context.Context, eksClient *eks.Client, clusterName string) (*types.Cluster, error) { + childCtx, cancel := context.WithTimeout(ctx, 10*time.Minute) + defer cancel() + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + for { + select { + case <-childCtx.Done(): + return nil, childCtx.Err() + case <-ticker.C: + describeInput := &eks.DescribeClusterInput{ + Name: &clusterName, + } + resp, err := eksClient.DescribeCluster(ctx, describeInput) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("failed to describe EKS cluster %s", clusterName)) + } + + status := resp.Cluster.Status + if status == types.ClusterStatusActive { + return resp.Cluster, nil + } + } + } +} + +func authorizeNodeGroup(clientSet kubernetes.Interface, nodeRoleArn string) error { + acm, err := authconfigmap.NewFromClientSet(clientSet) + if err != nil { + return err + } + + nodeGroupRoles := authconfigmap.RoleNodeGroupGroups + + identity, err := eksiam.NewIdentity(nodeRoleArn, authconfigmap.RoleNodeGroupUsername, nodeGroupRoles) + if err != nil { + return err + } + + if err := acm.AddIdentity(identity); err != nil { + return errors.Wrap(err, "adding nodegroup to auth ConfigMap") + } + if err := acm.Save(); err != nil { + return errors.Wrap(err, "saving auth ConfigMap") + } + return nil +} + +func createNodeGroup(ctx context.Context, eksClient *eks.Client, ec2Client *ec2.Client, clusterCfg *eksctlapi.ClusterConfig) error { + nodeGroup := clusterCfg.NodeGroups[0] + launchTemplateId, err := createNodeLaunchTemplate(ctx, ec2Client, clusterCfg) + if err != nil { + return errors.Wrap(err, "failed to create launch template") + } + + input := &eks.CreateNodegroupInput{ + ClusterName: aws.String(clusterCfg.Metadata.Name), + NodegroupName: aws.String(nodeGroup.Name), + NodeRole: aws.String(nodeGroup.IAM.InstanceRoleARN), + Subnets: nodeGroup.Subnets, + ScalingConfig: &types.NodegroupScalingConfig{ + MinSize: aws.Int32(int32(aws.ToInt(nodeGroup.MinSize))), + MaxSize: aws.Int32(int32(aws.ToInt(nodeGroup.MaxSize))), + DesiredSize: aws.Int32(int32(aws.ToInt(nodeGroup.DesiredCapacity))), + }, + LaunchTemplate: &types.LaunchTemplateSpecification{ + Id: aws.String(launchTemplateId), + }, + } + + _, err = eksClient.CreateNodegroup(ctx, input) + if err != nil { + return err + } + + return waitForNodeGroupReady(ctx, eksClient, clusterCfg.Metadata.Name, nodeGroup.Name) +} + +func waitForNodeGroupReady(ctx context.Context, eksClient *eks.Client, clusterName, nodeGroupName string) error { + childCtx, cancel := context.WithTimeout(ctx, 10*time.Minute) + defer cancel() + ticker := time.NewTicker(10 * time.Second) + defer ticker.Stop() + + for { + select { + case <-childCtx.Done(): + return childCtx.Err() + case <-ticker.C: + describeInput := &eks.DescribeNodegroupInput{ + ClusterName: &clusterName, + NodegroupName: &nodeGroupName, + } + resp, err := eksClient.DescribeNodegroup(ctx, describeInput) + if err != nil { + return errors.Wrapf(err, "failed to describe node group %s", nodeGroupName) + } + + status := resp.Nodegroup.Status + if status == types.NodegroupStatusActive { + return nil + } + } + } +} + +func createNodeLaunchTemplate(ctx context.Context, ec2Client *ec2.Client, clusterCfg *eksctlapi.ClusterConfig) (string, error) { + nodeGroup := clusterCfg.NodeGroups[0] + bootstrap := nodebootstrap.NewAL2Bootstrapper(clusterCfg, nodeGroup, nodeGroup.ClusterDNS) + userdata, err := bootstrap.UserData() + if err != nil { + return "", errors.Wrap(err, "failed to generate instance bootstrap user data") + } + + input := &ec2.CreateLaunchTemplateInput{ + LaunchTemplateName: aws.String(fmt.Sprintf("%s-node-template", clusterCfg.Metadata.Name)), + LaunchTemplateData: &ec2Types.RequestLaunchTemplateData{ + ImageId: aws.String(nodeGroup.AMI), + InstanceType: ec2Types.InstanceType(nodeGroup.InstanceType), + SecurityGroupIds: nodeGroup.SecurityGroups.AttachIDs, + BlockDeviceMappings: []ec2Types.LaunchTemplateBlockDeviceMappingRequest{ + { + DeviceName: aws.String("/dev/xvda"), + Ebs: &ec2Types.LaunchTemplateEbsBlockDeviceRequest{ + VolumeSize: aws.Int32(int32(aws.ToInt(nodeGroup.VolumeSize))), + VolumeType: ec2Types.VolumeType(aws.ToString(nodeGroup.VolumeType)), + }, + }, + }, + UserData: aws.String(userdata), + TagSpecifications: []ec2Types.LaunchTemplateTagSpecificationRequest{ + { + ResourceType: ec2Types.ResourceTypeInstance, + Tags: []ec2Types.Tag{ + { + Key: aws.String(fmt.Sprintf(kubernetesTagFormat, clusterCfg.Metadata.Name)), + Value: aws.String("owned"), + }, + }, + }, + }, + }, + } + + if nodeGroup.SSH.PublicKeyName != nil { + input.LaunchTemplateData.KeyName = nodeGroup.SSH.PublicKeyName + } + + output, err := ec2Client.CreateLaunchTemplate(ctx, input) + if err != nil { + return "", errors.Wrap(err, "failed to create launch template") + } + + return *output.LaunchTemplate.LaunchTemplateId, nil +} + +func resolveAMI(ctx context.Context, ec2Client *ec2.Client, region, k8sMinorVersion, instanceType, amiFamily string) (string, error) { + resolver := ami.NewAutoResolver(ec2Client) + + id, err := resolver.Resolve(ctx, region, k8sMinorVersion, instanceType, amiFamily) + if err != nil { + return "", errors.Wrap(err, "unable to determine AMI to use") + } + return id, nil +} + +func deleteNodeGroup(ctx context.Context, eksClient *eks.Client, clusterName string) (string, string, error) { + var notFoundErr *types.ResourceNotFoundException + describeNGInput := &eks.DescribeNodegroupInput{ + ClusterName: aws.String(clusterName), + NodegroupName: aws.String(DefaultNodeGroupName), + } + ngInfo, err := eksClient.DescribeNodegroup(ctx, describeNGInput) + if err != nil { + if errors.As(err, ¬FoundErr) { + // the node group had already been deleted + return "", "", nil + } else { + return "", "", errors.Wrapf(err, "failed to describe node group %s of cluster %s", DefaultNodeGroupName, clusterName) + } + } + + nodeGroupInput := &eks.DeleteNodegroupInput{ + ClusterName: aws.String(clusterName), + NodegroupName: aws.String(DefaultNodeGroupName), + } + _, err = eksClient.DeleteNodegroup(ctx, nodeGroupInput) + if err != nil { + return "", "", err + } + + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return "", "", ctx.Err() + case <-ticker.C: + describeInput := &eks.DescribeNodegroupInput{ + ClusterName: aws.String(clusterName), + NodegroupName: aws.String(DefaultNodeGroupName), + } + _, err := eksClient.DescribeNodegroup(ctx, describeInput) + if err != nil { + if errors.As(err, ¬FoundErr) { + // the node group has already been deleted successfully + return aws.ToString(ngInfo.Nodegroup.NodeRole), aws.ToString(ngInfo.Nodegroup.LaunchTemplate.Id), nil + } else { + return "", "", errors.Wrap(err, fmt.Sprintf("failed to describe node group %s of cluster %s", DefaultNodeGroupName, clusterName)) + } + } + } + } +} + +func deleteNodeLaunchTemplate(ctx context.Context, ec2Client *ec2.Client, launchTemplateId string) error { + deleteLaunchTmplInput := &ec2.DeleteLaunchTemplateInput{ + LaunchTemplateId: aws.String(launchTemplateId), + } + _, err := ec2Client.DeleteLaunchTemplate(ctx, deleteLaunchTmplInput) + if err != nil { + return errors.Wrapf(err, "failed to delete node launch template %s", launchTemplateId) + } + return nil +} + +func deleteCluster(ctx context.Context, eksClient *eks.Client, clusterName string) error { + var notFoundErr *types.ResourceNotFoundException + clusterInput := &eks.DeleteClusterInput{ + Name: aws.String(clusterName), + } + _, err := eksClient.DeleteCluster(ctx, clusterInput) + if err != nil { + return err + } + + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-ticker.C: + describeInput := &eks.DescribeClusterInput{ + Name: aws.String(clusterName), + } + _, err := eksClient.DescribeCluster(ctx, describeInput) + if err != nil { + if errors.As(err, ¬FoundErr) { + // the cluster has already been deleted successfully + return nil + } else { + return errors.Wrap(err, fmt.Sprintf("failed to describe EKS cluster %s to check delete progress", clusterName)) + } + } + } + } +} diff --git a/pkg/cluster-providers/eks/aws-operations/iam.go b/pkg/cluster-providers/eks/aws-operations/iam.go new file mode 100644 index 0000000..c87e6fc --- /dev/null +++ b/pkg/cluster-providers/eks/aws-operations/iam.go @@ -0,0 +1,202 @@ +package aws_operations + +import ( + "context" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/iam" + "github.com/pkg/errors" + "strings" +) + +func createRoles(ctx context.Context, iamClient *iam.Client, namePrefix string) (string, string, error) { + clusterRoleArn, err := createRole(ctx, iamClient, + namePrefix+"-EksClusterRole", "Allows access to other AWS service resources that are required to operate clusters managed by EKS.", + []string{"arn:aws:iam::aws:policy/AmazonEKSClusterPolicy", + "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"}, + map[string]string{ + "CloudWatchMetricsPolicy": inlinePolicyCloudWatchMetrics, + "ELBPermissionsPolicy": inlinePoliciesELBPermissions, + }, trustedEntitiesEKS, + ) + if err != nil { + return "", "", errors.Wrap(err, "error creating the IAM role for the cluster to use") + } + + nodeRoleArn, err := createRole(ctx, iamClient, + namePrefix+"-NodeInstanceRole", "Allows EC2 instances to call AWS services on your behalf.", + []string{"arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy", + "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly", + "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy", + "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore", + }, nil, trustedEntitiesEC2, + ) + if err != nil { + return "", "", errors.Wrap(err, "error creating the IAM role for the nodegroup to use") + } + return clusterRoleArn, nodeRoleArn, nil +} + +func createRole(ctx context.Context, iamClient *iam.Client, + newRoleName string, newRoleDescription string, managedPolicyNames []string, inlinePolicies map[string]string, trustPolicy string) (string, error) { + input := &iam.CreateRoleInput{ + RoleName: aws.String(newRoleName), + Description: aws.String(newRoleDescription), + AssumeRolePolicyDocument: aws.String(trustPolicy), + } + + roleOutput, err := iamClient.CreateRole(ctx, input) + if err != nil { + return "", errors.Wrapf(err, "failed to create role %s", newRoleName) + } + + for name, policy := range inlinePolicies { + _, err := iamClient.PutRolePolicy(ctx, &iam.PutRolePolicyInput{ + RoleName: aws.String(newRoleName), + PolicyDocument: aws.String(policy), + PolicyName: aws.String(name), + }) + if err != nil { + return "", errors.Wrapf(err, "error adding inline policy %s to role %s", name, newRoleName) + } + } + + for _, policyName := range managedPolicyNames { + _, err := iamClient.AttachRolePolicy(ctx, &iam.AttachRolePolicyInput{ + RoleName: aws.String(newRoleName), + PolicyArn: aws.String(policyName), + }) + if err != nil { + return "", errors.Wrapf(err, "error attaching policy %s to role %s", policyName, newRoleName) + } + } + + return aws.ToString(roleOutput.Role.Arn), nil +} + +func deleteRoles(ctx context.Context, iamClient *iam.Client, roles []string) error { + const splitter = ":role/" + + for _, roleArn := range roles { + if roleArn == "" { + continue + } + indexOfPrefix := strings.Index(roleArn, splitter) + roleName := roleArn[indexOfPrefix+len(splitter):] + + err := detachManagedPolicies(ctx, iamClient, roleName) + if err != nil { + return err + } + + err = deleteInlinePolicies(ctx, iamClient, roleName) + if err != nil { + return err + } + + _, err = iamClient.DeleteRole(ctx, &iam.DeleteRoleInput{ + RoleName: aws.String(roleName), + }) + if err != nil { + return errors.Wrapf(err, "failed to delete IAM role %s", roleArn) + } + } + + return nil +} + +func detachManagedPolicies(ctx context.Context, client *iam.Client, roleName string) error { + listResp, err := client.ListAttachedRolePolicies(ctx, &iam.ListAttachedRolePoliciesInput{ + RoleName: aws.String(roleName), + }) + if err != nil { + return errors.Wrapf(err, "error listing managed policies in role %s", roleName) + } + + for _, policy := range listResp.AttachedPolicies { + _, err := client.DetachRolePolicy(ctx, &iam.DetachRolePolicyInput{ + RoleName: aws.String(roleName), + PolicyArn: policy.PolicyArn, + }) + if err != nil { + return errors.Wrapf(err, "error detaching policy %s from role %s", aws.ToString(policy.PolicyArn), roleName) + } + } + + return nil +} + +func deleteInlinePolicies(ctx context.Context, iamClient *iam.Client, roleName string) error { + listResp, err := iamClient.ListRolePolicies(ctx, &iam.ListRolePoliciesInput{ + RoleName: aws.String(roleName), + }) + if err != nil { + return errors.Wrapf(err, "error listing inline policies in role %s", roleName) + } + + for _, policyName := range listResp.PolicyNames { + _, err := iamClient.DeleteRolePolicy(ctx, &iam.DeleteRolePolicyInput{ + RoleName: aws.String(roleName), + PolicyName: aws.String(policyName), + }) + + if err != nil { + return errors.Wrapf(err, "error deleting inline policy %s from role %s", policyName, roleName) + } + } + + return nil +} + +const ( + trustedEntitiesEKS = `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "eks.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +}` + trustedEntitiesEC2 = `{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "ec2.amazonaws.com" + }, + "Action": "sts:AssumeRole" + } + ] +}` + + inlinePolicyCloudWatchMetrics = `{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "cloudwatch:PutMetricData" + ], + "Resource": "*", + "Effect": "Allow" + } + ] +}` + inlinePoliciesELBPermissions = `{ + "Version": "2012-10-17", + "Statement": [ + { + "Action": [ + "ec2:DescribeAccountAttributes", + "ec2:DescribeAddresses", + "ec2:DescribeInternetGateways" + ], + "Resource": "*", + "Effect": "Allow" + } + ] +}` +) diff --git a/pkg/cluster-providers/eks/aws-operations/kubeclient.go b/pkg/cluster-providers/eks/aws-operations/kubeclient.go new file mode 100644 index 0000000..396724e --- /dev/null +++ b/pkg/cluster-providers/eks/aws-operations/kubeclient.go @@ -0,0 +1,76 @@ +package aws_operations + +import ( + "context" + "encoding/base64" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/eks" + "github.com/aws/aws-sdk-go-v2/service/sts" + smithyhttp "github.com/aws/smithy-go/transport/http" + "github.com/pkg/errors" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" +) + +const ( + v1Prefix = "k8s-aws-v1" + clusterIDHeader = "x-k8s-aws-id" +) + +func ClientForCluster(ctx context.Context, awsCfg aws.Config, clusterName string) (*rest.Config, *kubernetes.Clientset, error) { + eksClient := eks.NewFromConfig(awsCfg) + stsClient := sts.NewFromConfig(awsCfg) + + // Fetch cluster details + describeInput := &eks.DescribeClusterInput{ + Name: &clusterName, + } + resp, err := eksClient.DescribeCluster(ctx, describeInput) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to describe EKS cluster") + } + + clusterInfo := resp.Cluster + bearerToken, err := generateBearerToken(ctx, stsClient, clusterName) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to generate bearer token") + } + + caData, err := base64.StdEncoding.DecodeString(*clusterInfo.CertificateAuthority.Data) + if err != nil { + return nil, nil, errors.Wrap(err, "failed to decode certificate authority data") + } + // caller should parse env name from the output (.clusters[0].cluster.name) + cfg := rest.Config{ + BearerToken: bearerToken, + Host: *clusterInfo.Endpoint, + TLSClientConfig: rest.TLSClientConfig{ + Insecure: false, + CAData: caData, + }, + } + k, err := kubernetes.NewForConfig(&cfg) + if err != nil { + return nil, nil, err + } + + return &cfg, k, nil +} + +func generateBearerToken(ctx context.Context, stsClient *sts.Client, clusterID string) (string, error) { + preSignClient := sts.NewPresignClient(stsClient) + preSignURLRequest, err := preSignClient.PresignGetCallerIdentity(ctx, &sts.GetCallerIdentityInput{}, func(presignOptions *sts.PresignOptions) { + presignOptions.ClientOptions = append(presignOptions.ClientOptions, func(stsOptions *sts.Options) { + stsOptions.APIOptions = append(stsOptions.APIOptions, smithyhttp.SetHeaderValue(clusterIDHeader, clusterID)) + // EKS does not accept a longer validity token while STS is able to generate a token with expiry with 7 days. + stsOptions.APIOptions = append(stsOptions.APIOptions, smithyhttp.SetHeaderValue("X-Amz-Expires", "900")) + }) + }) + if err != nil { + return "", err + } + + token := fmt.Sprintf("%s.%s", v1Prefix, base64.RawURLEncoding.EncodeToString([]byte(preSignURLRequest.URL))) + return token, nil +} diff --git a/pkg/cluster-providers/eks/aws-operations/network.go b/pkg/cluster-providers/eks/aws-operations/network.go new file mode 100644 index 0000000..aa07664 --- /dev/null +++ b/pkg/cluster-providers/eks/aws-operations/network.go @@ -0,0 +1,362 @@ +package aws_operations + +import ( + "context" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/pkg/errors" +) + +const ( + defaultVPCCIDR = "10.163.0.0/16" + defaultSubnetCIDR1 = "10.163.1.0/24" + defaultSubnetCIDR2 = "10.163.2.0/24" +) + +func getAvailabilityZones(ctx context.Context, ec2Client *ec2.Client, region string) ([]string, error) { + availabilityZonesOutput, err := ec2Client.DescribeAvailabilityZones(ctx, &ec2.DescribeAvailabilityZonesInput{}) + if err != nil { + return nil, errors.Wrap(err, "failed to describe availability zones") + } + var subnetAvZones []string + for _, az := range availabilityZonesOutput.AvailabilityZones { + if az.State == ec2Types.AvailabilityZoneStateAvailable && len(subnetAvZones) < 2 { + subnetAvZones = append(subnetAvZones, *az.ZoneName) + } + } + if len(subnetAvZones) < 2 { + return nil, errors.Wrapf(err, "there is no sufficient availability zones available in region %s", region) + } + return subnetAvZones, nil +} + +func createVPC(ctx context.Context, ec2Client *ec2.Client, subnetAvZones []string) (string, []string, error) { + vpcOutput, err := ec2Client.CreateVpc(ctx, &ec2.CreateVpcInput{ + CidrBlock: aws.String(defaultVPCCIDR), + }) + if err != nil { + return "", nil, errors.Wrap(err, "failed to create VPC") + } + + vpcID := *vpcOutput.Vpc.VpcId + _, err = ec2Client.ModifyVpcAttribute(context.TODO(), &ec2.ModifyVpcAttributeInput{ + VpcId: aws.String(vpcID), + EnableDnsSupport: &ec2Types.AttributeBooleanValue{ + Value: aws.Bool(true), + }, + }) + if err != nil { + return "", nil, errors.Wrapf(err, "failed to enable DNS support for VPC %s", vpcID) + } + _, err = ec2Client.ModifyVpcAttribute(context.TODO(), &ec2.ModifyVpcAttributeInput{ + VpcId: aws.String(vpcID), + EnableDnsHostnames: &ec2Types.AttributeBooleanValue{ + Value: aws.Bool(true), + }, + }) + if err != nil { + return "", nil, errors.Wrapf(err, "failed to enable DNS support for VPC %s", vpcID) + } + + igwOutput, err := ec2Client.CreateInternetGateway(ctx, &ec2.CreateInternetGatewayInput{}) + if err != nil { + return "", nil, errors.Wrap(err, "unable to create Internet Gateway") + } + _, err = ec2Client.AttachInternetGateway(ctx, &ec2.AttachInternetGatewayInput{ + InternetGatewayId: igwOutput.InternetGateway.InternetGatewayId, + VpcId: vpcOutput.Vpc.VpcId, + }) + if err != nil { + return "", nil, errors.Wrapf(err, "unable to add Internet Gateway %s within the VPC %s", *igwOutput.InternetGateway.InternetGatewayId, vpcID) + } + rtOutput, err := ec2Client.CreateRouteTable(ctx, &ec2.CreateRouteTableInput{ + VpcId: vpcOutput.Vpc.VpcId, + }) + if err != nil { + return "", nil, errors.Wrapf(err, "failed to create Route Table") + } + _, err = ec2Client.CreateRoute(ctx, &ec2.CreateRouteInput{ + RouteTableId: rtOutput.RouteTable.RouteTableId, + GatewayId: igwOutput.InternetGateway.InternetGatewayId, + DestinationCidrBlock: aws.String("0.0.0.0/0"), + }) + if err != nil { + return "", nil, errors.Wrapf(err, "failed to create default egress route for Route Table %s", + *rtOutput.RouteTable.RouteTableId) + } + + subnetId1, err := createSubnet(ctx, ec2Client, vpcID, defaultSubnetCIDR1, subnetAvZones[0], *rtOutput.RouteTable.RouteTableId) + if err != nil { + return "", nil, errors.Wrapf(err, "failed to create subnet within the VPC %s", vpcID) + } + subnetId2, err := createSubnet(ctx, ec2Client, vpcID, defaultSubnetCIDR2, subnetAvZones[1], *rtOutput.RouteTable.RouteTableId) + if err != nil { + return "", nil, errors.Wrapf(err, "failed to create subnet within the VPC %s", vpcID) + } + + subnetIDs := []string{subnetId1, subnetId2} + return vpcID, subnetIDs, nil +} + +func createSubnet(ctx context.Context, ec2Client *ec2.Client, vpcID, cidrBlock, availabilityZone, routeTableId string) (string, error) { + subnet1Output, err := ec2Client.CreateSubnet(ctx, &ec2.CreateSubnetInput{ + VpcId: aws.String(vpcID), + CidrBlock: aws.String(cidrBlock), + AvailabilityZone: aws.String(availabilityZone), + }) + if err != nil { + return "", errors.Wrapf(err, "failed to create subnet within the VPC %s", vpcID) + } + + subnetId := subnet1Output.Subnet.SubnetId + _, err = ec2Client.ModifySubnetAttribute(ctx, &ec2.ModifySubnetAttributeInput{ + SubnetId: subnetId, + MapPublicIpOnLaunch: &ec2Types.AttributeBooleanValue{Value: aws.Bool(true)}, + }) + if err != nil { + return "", errors.Wrapf(err, "unable to modify subnet %s to enable public IP assignment", *subnetId) + } + + if routeTableId != "" { + _, err = ec2Client.AssociateRouteTable(ctx, &ec2.AssociateRouteTableInput{ + RouteTableId: aws.String(routeTableId), + SubnetId: subnetId, + }) + if err != nil { + return "", errors.Wrapf(err, "failed to associate Route Table %s with subnet %s", routeTableId, *subnetId) + } + } + return *subnetId, nil +} + +func createControlPlaneSecurityGroup(ctx context.Context, ec2Client *ec2.Client, vpcId, clusterName string) (string, error) { + sg1Output, err := ec2Client.CreateSecurityGroup(ctx, &ec2.CreateSecurityGroupInput{ + GroupName: aws.String(fmt.Sprintf("%s-cp", clusterName)), + Description: aws.String("Allow communication between the control plane and worker nodes"), + VpcId: aws.String(vpcId), + TagSpecifications: []ec2Types.TagSpecification{ + { + ResourceType: ec2Types.ResourceTypeSecurityGroup, + Tags: []ec2Types.Tag{ + { + Key: aws.String(fmt.Sprintf(kubernetesTagFormat, clusterName)), + Value: aws.String("owned"), + }, + }, + }, + }, + }) + if err != nil { + return "", errors.Wrap(err, "failed to create security group") + } + return *sg1Output.GroupId, nil +} + +func createNodeSecurityGroup(ctx context.Context, ec2Client *ec2.Client, vpcId, clusterName string, cpDefaultSecurityGroupIds []string) (string, error) { + sgOutput, err := ec2Client.CreateSecurityGroup(ctx, &ec2.CreateSecurityGroupInput{ + GroupName: aws.String(fmt.Sprintf("%s-shared-by-all-nodes", clusterName)), + Description: aws.String("Allow communication between all nodes in the cluster"), + VpcId: aws.String(vpcId), + TagSpecifications: []ec2Types.TagSpecification{ + { + ResourceType: ec2Types.ResourceTypeSecurityGroup, + Tags: []ec2Types.Tag{ + { + Key: aws.String(fmt.Sprintf(kubernetesTagFormat, clusterName)), + Value: aws.String("owned"), + }, + }, + }, + }, + }) + if err != nil { + return "", errors.Wrap(err, "failed to create node security group") + } + + for _, sgId := range cpDefaultSecurityGroupIds { + _, err = ec2Client.AuthorizeSecurityGroupIngress(ctx, &ec2.AuthorizeSecurityGroupIngressInput{ + GroupId: sgOutput.GroupId, + IpPermissions: []ec2Types.IpPermission{ + { + IpProtocol: aws.String("-1"), + UserIdGroupPairs: []ec2Types.UserIdGroupPair{ + { + GroupId: aws.String(sgId), + }, + }, + }, + }, + }) + if err != nil { + return "", errors.Wrapf(err, "failed to authorize inbound traffic from control plane security group %s to node security group %s", + sgId, *sgOutput.GroupId) + } + + _, err = ec2Client.AuthorizeSecurityGroupIngress(ctx, &ec2.AuthorizeSecurityGroupIngressInput{ + GroupId: aws.String(sgId), + IpPermissions: []ec2Types.IpPermission{ + { + IpProtocol: aws.String("-1"), + UserIdGroupPairs: []ec2Types.UserIdGroupPair{ + { + GroupId: sgOutput.GroupId, + }, + }, + }, + }, + }) + if err != nil { + return "", errors.Wrapf(err, "failed to authorize inbound traffic from node security group %s to control plane security group %s", + *sgOutput.GroupId, sgId) + } + } + + return *sgOutput.GroupId, nil +} + +func deleteVPC(ctx context.Context, ec2Client *ec2.Client, vpcID string) error { + routeTablesOutput, err := ec2Client.DescribeRouteTables(ctx, &ec2.DescribeRouteTablesInput{ + Filters: []ec2Types.Filter{ + {Name: aws.String("vpc-id"), Values: []string{vpcID}}, + }, + }) + if err != nil { + return errors.Wrapf(err, "failed to list route tables in VPC %s", vpcID) + } + + for _, rt := range routeTablesOutput.RouteTables { + isMain := false + for _, assoc := range rt.Associations { + if assoc.Main != nil && *assoc.Main { + isMain = true + break + } + } + if isMain { + continue + } + + for _, assoc := range rt.Associations { + if assoc.RouteTableAssociationId != nil { + _, err := ec2Client.DisassociateRouteTable(ctx, &ec2.DisassociateRouteTableInput{ + AssociationId: assoc.RouteTableAssociationId, + }) + if err != nil { + return errors.Wrapf(err, "failed to disassociate route table association %s for route table %s", *assoc.RouteTableAssociationId, *rt.RouteTableId) + } + } + } + + _, err := ec2Client.DeleteRouteTable(ctx, &ec2.DeleteRouteTableInput{ + RouteTableId: rt.RouteTableId, + }) + if err != nil { + return errors.Wrapf(err, "failed to delete route table %s", *rt.RouteTableId) + } + } + + subnetsOutput, err := ec2Client.DescribeSubnets(ctx, &ec2.DescribeSubnetsInput{ + Filters: []ec2Types.Filter{ + {Name: aws.String("vpc-id"), Values: []string{vpcID}}, + }, + }) + if err != nil { + return errors.Wrapf(err, "failed to describe subnets in VPC %s", vpcID) + } + + for _, subnet := range subnetsOutput.Subnets { + _, err := ec2Client.DeleteSubnet(ctx, &ec2.DeleteSubnetInput{ + SubnetId: subnet.SubnetId, + }) + if err != nil { + return errors.Wrapf(err, "failed to delete subnet %s", *subnet.SubnetId) + } + } + + igwsOutput, err := ec2Client.DescribeInternetGateways(ctx, &ec2.DescribeInternetGatewaysInput{ + Filters: []ec2Types.Filter{ + {Name: aws.String("attachment.vpc-id"), Values: []string{vpcID}}, + }, + }) + if err != nil { + return errors.Wrapf(err, "failed to describe internet gateways in VPC %s", vpcID) + } + + for _, igw := range igwsOutput.InternetGateways { + _, err := ec2Client.DetachInternetGateway(ctx, &ec2.DetachInternetGatewayInput{ + InternetGatewayId: igw.InternetGatewayId, + VpcId: aws.String(vpcID), + }) + if err != nil { + return errors.Wrapf(err, "failed to detach internet gateway %s", *igw.InternetGatewayId) + } + + _, err = ec2Client.DeleteInternetGateway(ctx, &ec2.DeleteInternetGatewayInput{ + InternetGatewayId: igw.InternetGatewayId, + }) + if err != nil { + return errors.Wrapf(err, "failed to delete internet gateway %s", *igw.InternetGatewayId) + } + } + + sgOutput, err := ec2Client.DescribeSecurityGroups(ctx, &ec2.DescribeSecurityGroupsInput{ + Filters: []ec2Types.Filter{ + {Name: aws.String("vpc-id"), Values: []string{vpcID}}, + }, + }) + if err != nil { + return errors.Wrapf(err, "failed to describe security groups in VPC %s", vpcID) + } + + for _, sg := range sgOutput.SecurityGroups { + if sg.GroupName != nil && *sg.GroupName == "default" { + continue + } + + for _, ingress := range sg.IpPermissions { + _, err := ec2Client.RevokeSecurityGroupIngress(ctx, &ec2.RevokeSecurityGroupIngressInput{ + GroupId: sg.GroupId, + IpPermissions: []ec2Types.IpPermission{ingress}, + }) + if err != nil { + return errors.Wrapf(err, "failed to revoke a %s ingress rule on security group %s", + aws.ToString(ingress.IpProtocol), aws.ToString(sg.GroupId)) + } + } + + for _, egress := range sg.IpPermissionsEgress { + _, err := ec2Client.RevokeSecurityGroupEgress(ctx, &ec2.RevokeSecurityGroupEgressInput{ + GroupId: sg.GroupId, + IpPermissions: []ec2Types.IpPermission{egress}, + }) + if err != nil { + return errors.Wrapf(err, "failed to revoke a %s egress rule on security group %s", + aws.ToString(egress.IpProtocol), aws.ToString(sg.GroupId)) + } + } + } + + for _, sg := range sgOutput.SecurityGroups { + if sg.GroupName != nil && *sg.GroupName == "default" { + continue + } + + _, err := ec2Client.DeleteSecurityGroup(ctx, &ec2.DeleteSecurityGroupInput{ + GroupId: sg.GroupId, + }) + if err != nil { + return errors.Wrapf(err, "failed to delete security group %s", *sg.GroupId) + } + } + + _, err = ec2Client.DeleteVpc(ctx, &ec2.DeleteVpcInput{ + VpcId: aws.String(vpcID), + }) + if err != nil { + return errors.Wrapf(err, "failed to delete VPC %s", vpcID) + } + + return nil +} diff --git a/pkg/cluster-providers/eks/builder.go b/pkg/cluster-providers/eks/builder.go new file mode 100644 index 0000000..686efc5 --- /dev/null +++ b/pkg/cluster-providers/eks/builder.go @@ -0,0 +1,88 @@ +package eks + +import ( + "context" + "fmt" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/blang/semver/v4" + "github.com/google/uuid" + "github.com/kong/kubernetes-testing-framework/pkg/clusters" + "github.com/kumahq/kuma-smoke/pkg/cluster-providers/eks/aws-operations" + "github.com/pkg/errors" + "strings" +) + +// Builder generates clusters.Cluster objects backed by GKE given +// provided configuration options.DeleteVPC +type Builder struct { + Name string + + addons clusters.Addons + clusterVersion *semver.Version + nodeMachineType string +} + +const ( + defaultNodeMachineType = "c5.4xlarge" + defaultKubernetesVersion = "1.31.1" +) + +// NewBuilder provides a new *Builder object. +func NewBuilder() *Builder { + k8sVer := semver.MustParse(defaultKubernetesVersion) + return &Builder{ + Name: fmt.Sprintf("t-%s", uuid.NewString()), + nodeMachineType: defaultNodeMachineType, + addons: make(clusters.Addons), + clusterVersion: &k8sVer, + } +} + +// WithName indicates a custom name to use for the cluster. +func (b *Builder) WithName(name string) *Builder { + b.Name = name + return b +} + +// WithClusterVersion configures the Kubernetes cluster version for the Builder +// to use when building the GKE cluster. +func (b *Builder) WithClusterVersion(version semver.Version) *Builder { + b.clusterVersion = &version + return b +} + +func (b *Builder) WithNodeMachineType(machineType string) *Builder { + b.nodeMachineType = machineType + return b +} + +// Build creates and configures clients for an EKS-based Kubernetes clusters.Cluster. +func (b *Builder) Build(ctx context.Context) (clusters.Cluster, error) { + err := guardOnEnv() + if err != nil { + return nil, err + } + + cfg, err := config.LoadDefaultConfig(ctx) + if err != nil { + return nil, errors.Wrap(err, "failed to load AWS SDK config") + } + + err = aws_operations.CreateEKSClusterAll(ctx, cfg, b.Name, minorVersion(b.clusterVersion), b.nodeMachineType) + if err != nil { + return nil, err + } + + // EKS limits the maximum allowed validity of an STS token to 15min (900s) + return InitFromExisting(ctx, cfg, b.Name) + +} + +func minorVersion(v *semver.Version) string { + fullStr := v.String() + lastIndexOfDot := strings.LastIndex(fullStr, ".") + if lastIndexOfDot == -1 { + lastIndexOfDot = 1 + } + return fullStr[:lastIndexOfDot] +} diff --git a/pkg/cluster-providers/eks/cluster.go b/pkg/cluster-providers/eks/cluster.go new file mode 100644 index 0000000..e37150d --- /dev/null +++ b/pkg/cluster-providers/eks/cluster.go @@ -0,0 +1,231 @@ +package eks + +import ( + "context" + "errors" + "fmt" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/kumahq/kuma-smoke/pkg/cluster-providers/eks/aws-operations" + err_pkg "github.com/pkg/errors" + "os" + "os/exec" + "path/filepath" + "strings" + "sync" + + "github.com/blang/semver/v4" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + + "github.com/kong/kubernetes-testing-framework/pkg/clusters" +) + +// ----------------------------------------------------------------------------- +// EKS Cluster +// ----------------------------------------------------------------------------- + +// Cluster is a clusters.Cluster implementation backed by AWS Elastic Kubernetes Service (EKS) +type Cluster struct { + name string + client *kubernetes.Clientset + cfg *rest.Config + addons clusters.Addons + l *sync.RWMutex + ipFamily clusters.IPFamily +} + +// InitFromExisting provides a new clusters.Cluster backed by an existing EKS cluster, +// but allows some of the configuration to be filled in from the ENV instead of arguments. +func InitFromExisting(ctx context.Context, cfg aws.Config, name string) (*Cluster, error) { + restCfg, kubeCfg, err := aws_operations.ClientForCluster(ctx, cfg, name) + if err != nil { + return nil, err_pkg.Wrapf(err, "failed to get kube client for cluster %s", name) + } + return &Cluster{ + name: name, + client: kubeCfg, + cfg: restCfg, + addons: make(clusters.Addons), + l: &sync.RWMutex{}, + }, nil +} + +func guardOnEnv() error { + if os.Getenv(envAccessKeyId) == "" { + return errors.New(envAccessKeyId + " is not set") + } + if os.Getenv(envAccessKey) == "" { + return errors.New(envAccessKey + " is not set") + } + if os.Getenv(envRegion) == "" { + return errors.New(envRegion + " is not set") + } + return nil +} + +// ----------------------------------------------------------------------------- +// EKS Cluster - Cluster Implementation +// ----------------------------------------------------------------------------- + +func (c *Cluster) Name() string { + return c.name +} + +func (c *Cluster) Type() clusters.Type { + return eksClusterType +} + +func (c *Cluster) Version() (semver.Version, error) { + versionInfo, err := c.Client().ServerVersion() + if err != nil { + return semver.Version{}, err + } + return semver.Parse(strings.TrimPrefix(versionInfo.String(), "v")) +} + +func (c *Cluster) Cleanup(ctx context.Context) error { + c.l.Lock() + defer c.l.Unlock() + + err := guardOnEnv() + if err != nil { + return err + } + + cfg, err := config.LoadDefaultConfig(ctx) + if err != nil { + return err_pkg.Wrap(err, "failed to load AWS SDK config") + } + + return aws_operations.DeleteEKSClusterAll(ctx, cfg, c.Name()) +} + +func (c *Cluster) Client() *kubernetes.Clientset { + return c.client +} + +func (c *Cluster) Config() *rest.Config { + return c.cfg +} + +func (c *Cluster) GetAddon(name clusters.AddonName) (clusters.Addon, error) { + c.l.RLock() + defer c.l.RUnlock() + + for addonName, addon := range c.addons { + if addonName == name { + return addon, nil + } + } + + return nil, fmt.Errorf("addon %s not found", name) +} + +func (c *Cluster) ListAddons() []clusters.Addon { + c.l.RLock() + defer c.l.RUnlock() + + addonList := make([]clusters.Addon, 0, len(c.addons)) + for _, v := range c.addons { + addonList = append(addonList, v) + } + + return addonList +} + +func (c *Cluster) DeployAddon(ctx context.Context, addon clusters.Addon) error { + c.l.Lock() + if _, ok := c.addons[addon.Name()]; ok { + c.l.Unlock() + return fmt.Errorf("addon component %s is already loaded into cluster %s", addon.Name(), c.Name()) + } + c.addons[addon.Name()] = addon + c.l.Unlock() + + return addon.Deploy(ctx, c) +} + +func (c *Cluster) DeleteAddon(ctx context.Context, addon clusters.Addon) error { + c.l.Lock() + defer c.l.Unlock() + + if _, ok := c.addons[addon.Name()]; !ok { + return nil + } + + if err := addon.Delete(ctx, c); err != nil { + return err + } + + delete(c.addons, addon.Name()) + + return nil +} + +// DumpDiagnostics produces diagnostics data for the cluster at a given time. +// It uses the provided meta string to write to meta.txt file which will allow +// for diagnostics identification. +// It returns the path to directory containing all the diagnostic files and an error. +func (c *Cluster) DumpDiagnostics(ctx context.Context, meta string) (string, error) { + // Obtain a kubeconfig + kubeconfig, err := clusters.TempKubeconfig(c) + if err != nil { + return "", err + } + defer os.Remove(kubeconfig.Name()) + + // create a tempdir + outDir, err := os.MkdirTemp(os.TempDir(), clusters.DiagnosticOutDirectoryPrefix) + if err != nil { + return "", err + } + + // for each Pod, run kubectl logs + pods, err := c.Client().CoreV1().Pods("").List(ctx, metav1.ListOptions{}) + if err != nil { + return outDir, err + } + logsDir := filepath.Join(outDir, "pod_logs") + err = os.Mkdir(logsDir, 0o750) //nolint:mnd + if err != nil { + return outDir, err + } + failedPods := make(map[string]error) + for _, pod := range pods.Items { + podLogOut, err := os.Create(filepath.Join(logsDir, fmt.Sprintf("%s_%s", pod.Namespace, pod.Name))) + if err != nil { + failedPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = err + continue + } + cmd := exec.CommandContext(ctx, "kubectl", "--kubeconfig", kubeconfig.Name(), "logs", "--all-containers", "-n", pod.Namespace, pod.Name) //nolint:gosec + cmd.Stdout = podLogOut + if err := cmd.Run(); err != nil { + failedPods[fmt.Sprintf("%s/%s", pod.Namespace, pod.Name)] = err + continue + } + defer podLogOut.Close() + } + if len(failedPods) > 0 { + failedPodOut, err := os.Create(filepath.Join(outDir, "pod_logs_failures.txt")) + if err != nil { + return outDir, err + } + defer failedPodOut.Close() + for failed, reason := range failedPods { + _, err = failedPodOut.WriteString(fmt.Sprintf("%s: %v\n", failed, reason)) + if err != nil { + return outDir, err + } + } + } + + err = clusters.DumpDiagnostics(ctx, c, meta, outDir) + + return outDir, err +} + +func (c *Cluster) IPFamily() clusters.IPFamily { + return c.ipFamily +} diff --git a/pkg/cluster-providers/eks/init.go b/pkg/cluster-providers/eks/init.go new file mode 100644 index 0000000..99c6e13 --- /dev/null +++ b/pkg/cluster-providers/eks/init.go @@ -0,0 +1,52 @@ +package eks + +import ( + "context" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/kong/kubernetes-testing-framework/pkg/clusters" + "github.com/kris-nova/logger" + "github.com/kumahq/kuma-smoke/pkg/cluster-providers" + err_pkg "github.com/pkg/errors" + "github.com/spf13/cobra" + "io" +) + +const ( + envAccessKeyId = "AWS_ACCESS_KEY_ID" + envAccessKey = "AWS_SECRET_ACCESS_KEY" + envRegion = "AWS_REGION" + eksClusterType clusters.Type = "eks" +) + +type eksProvider struct{} + +func (eksProvider) ClusterProvider(_ *cobra.Command, envName string) (clusters.Builder, error) { + err := guardOnEnv() + if err != nil { + return nil, err + } + + eksBuilder := NewBuilder() + eksBuilder.Name = envName + + return eksBuilder, nil +} + +func (eksProvider) NewFromExisting(ctx context.Context, _ *cobra.Command, envName string) (clusters.Cluster, error) { + err := guardOnEnv() + if err != nil { + return nil, err + } + + cfg, err := config.LoadDefaultConfig(ctx) + if err != nil { + return nil, err_pkg.Wrap(err, "failed to load AWS SDK config") + } + return InitFromExisting(ctx, cfg, envName) +} + +func init() { + // By default, we don't log anything (until KTF support a logging mechanism) + logger.Writer = io.Discard + cluster_providers.Register("eks", eksProvider{}) +} diff --git a/pkg/utils/constants.go b/pkg/utils/constants.go index 70c382f..c809db4 100644 --- a/pkg/utils/constants.go +++ b/pkg/utils/constants.go @@ -4,5 +4,5 @@ import "time" var ( EnvironmentCreateTimeout = time.Minute * 30 - CleanupTimeout = time.Minute * 10 + CleanupTimeout = time.Minute * 20 ) diff --git a/pkg/utils/kubeconfig.go b/pkg/utils/kubeconfig.go index c6e32bb..bb2fb19 100644 --- a/pkg/utils/kubeconfig.go +++ b/pkg/utils/kubeconfig.go @@ -1,48 +1,20 @@ package utils import ( + "github.com/kong/kubernetes-testing-framework/pkg/utils/kubernetes/generators" "github.com/spf13/cobra" "io" "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" - clientcmdapi "k8s.io/client-go/tools/clientcmd/api" ) -func convertToClientCmdConfig(envName string, config *rest.Config) *clientcmdapi.Config { - // caller should parse env name from the output (.clusters[0].cluster.name) - return &clientcmdapi.Config{ - Clusters: map[string]*clientcmdapi.Cluster{ - envName: { - Server: config.Host, - CertificateAuthorityData: config.CAData, - TLSServerName: config.ServerName, - InsecureSkipTLSVerify: config.Insecure, - }, - }, - Contexts: map[string]*clientcmdapi.Context{ - envName: { - Cluster: envName, - AuthInfo: "default", - }, - }, - AuthInfos: map[string]*clientcmdapi.AuthInfo{ - "default": { - ClientKeyData: config.KeyData, - ClientCertificateData: config.CertData, - Token: config.BearerToken, - }, - }, - CurrentContext: envName, - } -} - func writeKubeconfigToFile(envName string, config *rest.Config, filename string) error { - kubeconfig := convertToClientCmdConfig(envName, config) + kubeconfig := generators.NewClientConfigForRestConfig(envName, config) return clientcmd.WriteToFile(*kubeconfig, filename) } func writeKubeconfigToOutput(envName string, config *rest.Config, writer io.Writer) error { - kubeconfig := convertToClientCmdConfig(envName, config) + kubeconfig := generators.NewClientConfigForRestConfig(envName, config) content, err := clientcmd.Write(*kubeconfig) if err != nil { return err