diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 12aac3d..4bb3fd8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ on: env: # Common versions - GO_VERSION: '1.21' + GO_VERSION: '1.22' GOLANGCI_VERSION: 'v1.54.0' DOCKER_BUILDX_VERSION: 'v0.8.2' @@ -170,6 +170,49 @@ jobs: flags: unittests file: _output/tests/linux_amd64/coverage.txt + integration-tests: + runs-on: ubuntu-22.04 + needs: detect-noop + if: needs.detect-noop.outputs.noop != 'true' + + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: true + + - name: Fetch History + run: git fetch --prune --unshallow + + - name: Setup Go + uses: actions/setup-go@v2 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Find the Go Build Cache + id: go + run: echo "::set-output name=cache::$(make go.cachedir)" + + - name: Cache the Go Build Cache + uses: actions/cache@v2 + with: + path: ${{ steps.go.outputs.cache }} + key: ${{ runner.os }}-build-unit-tests-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-build-unit-tests- + + - name: Cache Go Dependencies + uses: actions/cache@v2 + with: + path: .work/pkg + key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-pkg- + + - name: Vendor Dependencies + run: make vendor vendor.check + + - name: Run Integration Tests + run: make -j2 test-integration + local-deploy: runs-on: ubuntu-22.04 needs: detect-noop diff --git a/.vscode/launch.json b/.vscode/launch.json index c61e1e3..eb6bb1b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -23,6 +23,20 @@ }, // "showLog": true, // "trace": "verbose", - } + }, + { + "name": "Integration Tests", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/tests/integration/suite_test.go", + "env": { + "KUBECONFIG": "", + "KUBEBUILDER_ASSETS": "/Users/tylergillson/spectrocloud/repos/oss/spectrocloud/provider-palette/.cache/tools/darwin_arm64/k8s/1.30.0-darwin-arm64", + "TERRAFORM_VERSION": "1.3.3", + "TERRAFORM_PROVIDER_VERSION": "0.19.2", + // "TF_REATTACH_PROVIDERS": "{\"registry.terraform.io/spectrocloud/spectrocloud\":{\"Protocol\":\"grpc\",\"ProtocolVersion\":5,\"Pid\":5045,\"Test\":true,\"Addr\":{\"Network\":\"unix\",\"String\":\"/var/folders/w1/sm7f2fb959j2xkxln196ksj40000gn/T/plugin2100568909\"}}}", + }, + }, ] } \ No newline at end of file diff --git a/Makefile b/Makefile index 11d5213..589581a 100644 --- a/Makefile +++ b/Makefile @@ -158,6 +158,25 @@ run: go.build @# To see other arguments that can be provided, run the command with --help instead UPBOUND_CONTEXT="local" $(GO_OUT_DIR)/provider --debug +# =================== +# Integration Testing + +test-integration: init-envtest ## Run integration tests + @mkdir -p $(GO_TEST_OUTPUT) || $(FAIL) + KUBEBUILDER_ASSETS=${KUBEBUILDER_ASSETS} go test -v -timeout 10m \ + -covermode=atomic -coverpkg=./... -coverprofile=$(GO_TEST_OUTPUT)/integration.out ./tests/... + +init-envtest: setup-envtest + $(TOOLS_HOST_DIR)/setup-envtest use --bin-dir $(TOOLS_HOST_DIR) $(ENVTEST_VERSION) +KUBEBUILDER_ASSETS = $(shell $(TOOLS_HOST_DIR)/setup-envtest use -p path --bin-dir $(TOOLS_HOST_DIR) $(ENVTEST_VERSION)) + +setup-envtest: +ifeq ("$(wildcard $(TOOLS_HOST_DIR)/setup-envtest)", "") + go get sigs.k8s.io/controller-runtime/tools/setup-envtest + GOBIN=$(TOOLS_HOST_DIR) go install sigs.k8s.io/controller-runtime/tools/setup-envtest +endif +SETUP_ENVTEST=$(TOOLS_HOST_DIR)/setup-envtest + # ==================================================================================== # End to End Testing CROSSPLANE_NAMESPACE = upbound-system diff --git a/cmd/provider/main.go b/cmd/provider/main.go index c883349..0472eec 100644 --- a/cmd/provider/main.go +++ b/cmd/provider/main.go @@ -4,118 +4,8 @@ Copyright 2021 Upbound Inc. package main -import ( - "context" - "os" - "path/filepath" - "time" - - xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" - xpcontroller "github.com/crossplane/crossplane-runtime/pkg/controller" - "github.com/crossplane/crossplane-runtime/pkg/feature" - "github.com/crossplane/crossplane-runtime/pkg/logging" - "github.com/crossplane/crossplane-runtime/pkg/ratelimiter" - "github.com/crossplane/crossplane-runtime/pkg/resource" - tjcontroller "github.com/crossplane/upjet/pkg/controller" - "github.com/crossplane/upjet/pkg/terraform" - "github.com/go-logr/logr" - "gopkg.in/alecthomas/kingpin.v2" - kerrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/tools/leaderelection/resourcelock" - ctrl "sigs.k8s.io/controller-runtime" - ctrllog "sigs.k8s.io/controller-runtime/pkg/log" - "sigs.k8s.io/controller-runtime/pkg/log/zap" - - "github.com/crossplane-contrib/provider-palette/apis" - "github.com/crossplane-contrib/provider-palette/apis/v1alpha1" - "github.com/crossplane-contrib/provider-palette/config" - "github.com/crossplane-contrib/provider-palette/internal/clients" - "github.com/crossplane-contrib/provider-palette/internal/controller" - "github.com/crossplane-contrib/provider-palette/internal/features" -) +import "github.com/crossplane-contrib/provider-palette/cmd/provider/run" func main() { - var ( - app = kingpin.New(filepath.Base(os.Args[0]), "Terraform based Crossplane provider for Palette").DefaultEnvars() - debug = app.Flag("debug", "Run with debug logging.").Short('d').Bool() - leaderElection = app.Flag("leader-election", "Use leader election for the controller manager.").Short('l').Default("false").OverrideDefaultFromEnvar("LEADER_ELECTION").Bool() - terraformVersion = app.Flag("terraform-version", "Terraform version.").Required().Envar("TERRAFORM_VERSION").String() - providerSource = app.Flag("terraform-provider-source", "Terraform provider source.").Required().Envar("TERRAFORM_PROVIDER_SOURCE").String() - providerVersion = app.Flag("terraform-provider-version", "Terraform provider version.").Required().Envar("TERRAFORM_PROVIDER_VERSION").String() - maxReconcileRate = app.Flag("max-reconcile-rate", "The global maximum rate per second at which resources may checked for drift from the desired state.").Default("10").Int() - - namespace = app.Flag("namespace", "Namespace used to set as default scope in default secret store config.").Default("crossplane-system").Envar("POD_NAMESPACE").String() - enableExternalSecretStores = app.Flag("enable-external-secret-stores", "Enable support for ExternalSecretStores.").Default("false").Envar("ENABLE_EXTERNAL_SECRET_STORES").Bool() - enableManagementPolicies = app.Flag("enable-management-policies", "Enable support for Management Policies.").Default("false").Envar("ENABLE_MANAGEMENT_POLICIES").Bool() - ) - - kingpin.MustParse(app.Parse(os.Args[1:])) - - zl := zap.New(zap.UseDevMode(*debug)) - log := logging.NewLogrLogger(zl.WithName("provider-palette")) - if *debug { - // The controller-runtime runs with a no-op logger by default. It is - // *very* verbose even at info level, so we only provide it a real - // logger when we're running in debug mode. - ctrl.SetLogger(zl) - } else { - ctrl.SetLogger(logr.New(ctrllog.NullLogSink{})) - } - - log.Debug("Starting") - - cfg, err := ctrl.GetConfig() - kingpin.FatalIfError(err, "Cannot get API server rest config") - - mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - LeaderElection: *leaderElection, - LeaderElectionID: "crossplane-leader-election-provider-palette", - LeaderElectionResourceLock: resourcelock.LeasesResourceLock, - LeaseDuration: func() *time.Duration { d := 60 * time.Second; return &d }(), - RenewDeadline: func() *time.Duration { d := 50 * time.Second; return &d }(), - }) - kingpin.FatalIfError(err, "Cannot create controller manager") - kingpin.FatalIfError(apis.AddToScheme(mgr.GetScheme()), "Cannot add Palette APIs to scheme") - o := tjcontroller.Options{ - Options: xpcontroller.Options{ - Logger: log, - GlobalRateLimiter: ratelimiter.NewGlobal(*maxReconcileRate), - PollInterval: 1 * time.Minute, - MaxConcurrentReconciles: 1, - Features: &feature.Flags{}, - }, - Provider: config.GetProvider(), - // use the following WorkspaceStoreOption to enable the shared gRPC mode - // terraform.WithProviderRunner(terraform.NewSharedProvider(log, os.Getenv("TERRAFORM_NATIVE_PROVIDER_PATH"), terraform.WithNativeProviderArgs("-debuggable"))) - WorkspaceStore: terraform.NewWorkspaceStore(log), - SetupFn: clients.TerraformSetupBuilder(*terraformVersion, *providerSource, *providerVersion), - } - - if *enableManagementPolicies { - o.Features.Enable(features.EnableBetaManagementPolicies) - log.Info("Beta feature enabled", "flag", features.EnableBetaManagementPolicies) - } - - if *enableExternalSecretStores { - o.SecretStoreConfigGVK = &v1alpha1.StoreConfigGroupVersionKind - log.Info("Alpha feature enabled", "flag", features.EnableAlphaExternalSecretStores) - - // Ensure default store config exists. - kingpin.FatalIfError(resource.Ignore(kerrors.IsAlreadyExists, mgr.GetClient().Create(context.Background(), &v1alpha1.StoreConfig{ - ObjectMeta: metav1.ObjectMeta{ - Name: "default", - }, - Spec: v1alpha1.StoreConfigSpec{ - // NOTE(turkenh): We only set required spec and expect optional - // ones to properly be initialized with CRD level default values. - SecretStoreConfig: xpv1.SecretStoreConfig{ - DefaultScope: *namespace, - }, - }, - })), "cannot create default store config") - } - - kingpin.FatalIfError(controller.Setup(mgr, o), "Cannot setup Palette controllers") - kingpin.FatalIfError(mgr.Start(ctrl.SetupSignalHandler()), "Cannot start controller manager") + run.Run() } diff --git a/cmd/provider/run/run.go b/cmd/provider/run/run.go new file mode 100644 index 0000000..1002004 --- /dev/null +++ b/cmd/provider/run/run.go @@ -0,0 +1,125 @@ +package run + +import ( + "context" + "os" + "path/filepath" + "time" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + xpcontroller "github.com/crossplane/crossplane-runtime/pkg/controller" + "github.com/crossplane/crossplane-runtime/pkg/feature" + "github.com/crossplane/crossplane-runtime/pkg/logging" + "github.com/crossplane/crossplane-runtime/pkg/ratelimiter" + "github.com/crossplane/crossplane-runtime/pkg/resource" + tjcontroller "github.com/crossplane/upjet/pkg/controller" + "github.com/crossplane/upjet/pkg/terraform" + "github.com/go-logr/logr" + "gopkg.in/alecthomas/kingpin.v2" + kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/leaderelection/resourcelock" + ctrl "sigs.k8s.io/controller-runtime" + ctrllog "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/crossplane-contrib/provider-palette/apis" + "github.com/crossplane-contrib/provider-palette/apis/v1alpha1" + "github.com/crossplane-contrib/provider-palette/config" + "github.com/crossplane-contrib/provider-palette/internal/clients" + "github.com/crossplane-contrib/provider-palette/internal/controller" + "github.com/crossplane-contrib/provider-palette/internal/features" +) + +var cancel context.CancelFunc + +func Run() { + var ( + app = kingpin.New(filepath.Base(os.Args[0]), "Terraform based Crossplane provider for Palette").DefaultEnvars() + debug = app.Flag("debug", "Run with debug logging.").Short('d').Bool() + leaderElection = app.Flag("leader-election", "Use leader election for the controller manager.").Short('l').Default("false").OverrideDefaultFromEnvar("LEADER_ELECTION").Bool() + terraformVersion = app.Flag("terraform-version", "Terraform version.").Required().Envar("TERRAFORM_VERSION").String() + providerSource = app.Flag("terraform-provider-source", "Terraform provider source.").Required().Envar("TERRAFORM_PROVIDER_SOURCE").String() + providerVersion = app.Flag("terraform-provider-version", "Terraform provider version.").Required().Envar("TERRAFORM_PROVIDER_VERSION").String() + maxReconcileRate = app.Flag("max-reconcile-rate", "The global maximum rate per second at which resources may checked for drift from the desired state.").Default("10").Int() + + namespace = app.Flag("namespace", "Namespace used to set as default scope in default secret store config.").Default("crossplane-system").Envar("POD_NAMESPACE").String() + enableExternalSecretStores = app.Flag("enable-external-secret-stores", "Enable support for ExternalSecretStores.").Default("false").Envar("ENABLE_EXTERNAL_SECRET_STORES").Bool() + enableManagementPolicies = app.Flag("enable-management-policies", "Enable support for Management Policies.").Default("false").Envar("ENABLE_MANAGEMENT_POLICIES").Bool() + ) + + kingpin.MustParse(app.Parse(os.Args[1:])) + + zl := zap.New(zap.UseDevMode(*debug)) + log := logging.NewLogrLogger(zl.WithName("provider-palette")) + if *debug { + // The controller-runtime runs with a no-op logger by default. It is + // *very* verbose even at info level, so we only provide it a real + // logger when we're running in debug mode. + ctrl.SetLogger(zl) + } else { + ctrl.SetLogger(logr.New(ctrllog.NullLogSink{})) + } + + log.Debug("Starting") + + cfg, err := ctrl.GetConfig() + kingpin.FatalIfError(err, "Cannot get API server rest config") + + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + LeaderElection: *leaderElection, + LeaderElectionID: "crossplane-leader-election-provider-palette", + LeaderElectionResourceLock: resourcelock.LeasesResourceLock, + LeaseDuration: func() *time.Duration { d := 60 * time.Second; return &d }(), + RenewDeadline: func() *time.Duration { d := 50 * time.Second; return &d }(), + }) + kingpin.FatalIfError(err, "Cannot create controller manager") + kingpin.FatalIfError(apis.AddToScheme(mgr.GetScheme()), "Cannot add Palette APIs to scheme") + o := tjcontroller.Options{ + Options: xpcontroller.Options{ + Logger: log, + GlobalRateLimiter: ratelimiter.NewGlobal(*maxReconcileRate), + PollInterval: 1 * time.Minute, + MaxConcurrentReconciles: 1, + Features: &feature.Flags{}, + }, + Provider: config.GetProvider(), + // use the following WorkspaceStoreOption to enable the shared gRPC mode + // terraform.WithProviderRunner(terraform.NewSharedProvider(log, os.Getenv("TERRAFORM_NATIVE_PROVIDER_PATH"), terraform.WithNativeProviderArgs("-debuggable"))) + WorkspaceStore: terraform.NewWorkspaceStore(log), + SetupFn: clients.TerraformSetupBuilder(*terraformVersion, *providerSource, *providerVersion), + } + + if *enableManagementPolicies { + o.Features.Enable(features.EnableBetaManagementPolicies) + log.Info("Beta feature enabled", "flag", features.EnableBetaManagementPolicies) + } + + if *enableExternalSecretStores { + o.SecretStoreConfigGVK = &v1alpha1.StoreConfigGroupVersionKind + log.Info("Alpha feature enabled", "flag", features.EnableAlphaExternalSecretStores) + + // Ensure default store config exists. + kingpin.FatalIfError(resource.Ignore(kerrors.IsAlreadyExists, mgr.GetClient().Create(context.Background(), &v1alpha1.StoreConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + Spec: v1alpha1.StoreConfigSpec{ + // NOTE(turkenh): We only set required spec and expect optional + // ones to properly be initialized with CRD level default values. + SecretStoreConfig: xpv1.SecretStoreConfig{ + DefaultScope: *namespace, + }, + }, + })), "cannot create default store config") + } + + kingpin.FatalIfError(controller.Setup(mgr, o), "Cannot setup Palette controllers") + ctx := ctrl.SetupSignalHandler() + ctx, cancel = context.WithCancel(ctx) + kingpin.FatalIfError(mgr.Start(ctx), "Cannot start controller manager") +} + +func Cancel() { + cancel() +} diff --git a/go.mod b/go.mod index d460de1..f6d32e8 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/crossplane-contrib/provider-palette -go 1.21 +go 1.22.0 -toolchain go1.21.7 +toolchain go1.22.2 require ( dario.cat/mergo v1.0.0 @@ -10,9 +10,13 @@ require ( github.com/crossplane/crossplane-tools v0.0.0-20230925130601-628280f8bf79 github.com/crossplane/upjet v1.3.0 github.com/go-logr/logr v1.4.1 + github.com/gorilla/mux v1.8.1 + github.com/onsi/ginkgo/v2 v2.17.3 + github.com/onsi/gomega v1.33.1 github.com/pkg/errors v0.9.1 gopkg.in/alecthomas/kingpin.v2 v2.2.6 - k8s.io/apimachinery v0.29.1 + k8s.io/api v0.29.1 + k8s.io/apimachinery v0.30.0 k8s.io/client-go v0.29.1 sigs.k8s.io/controller-runtime v0.17.0 sigs.k8s.io/controller-tools v0.14.0 @@ -40,14 +44,16 @@ require ( github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gobuffalo/flect v1.0.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.6.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect github.com/google/uuid v1.4.0 // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect @@ -101,27 +107,27 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect - golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.23.0 // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/net v0.24.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect - golang.org/x/sys v0.18.0 // indirect - golang.org/x/term v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.17.0 // indirect + golang.org/x/tools v0.20.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect google.golang.org/grpc v1.61.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.29.1 // indirect k8s.io/apiextensions-apiserver v0.29.1 // indirect k8s.io/component-base v0.29.1 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/klog/v2 v2.120.1 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect diff --git a/go.sum b/go.sum index 7febb99..d015bc4 100644 --- a/go.sum +++ b/go.sum @@ -52,7 +52,6 @@ github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= 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/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= @@ -63,8 +62,8 @@ github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2Kv github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +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/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= @@ -82,8 +81,8 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 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.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/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/google/addlicense v0.0.0-20210428195630-6d92264d7170/go.mod h1:EMjYTRimagHs1FwlIqKyX3wAM0u3rA+McvlIIWmSamA= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= @@ -96,10 +95,12 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8= -github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= +github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 h1:1/D3zfFHttUKaCaGKZ/dR2roBXv0vKbSCnssIldfQdI= github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320/go.mod h1:EiZBMaudVLy8fmjf9Npq1dq9RalhveqZG5w/yz3mHWs= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= @@ -197,10 +198,10 @@ github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= 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.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/ginkgo/v2 v2.17.3 h1:oJcvKpIb7/8uLpDDtnQuf18xVnwKp8DTD7DQ6gTd/MU= +github.com/onsi/ginkgo/v2 v2.17.3/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -280,8 +281,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180811021610-c39426892332/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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= @@ -293,8 +294,8 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -303,8 +304,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -324,12 +325,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.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.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= -golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= 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= @@ -347,8 +348,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -365,8 +366,8 @@ google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -388,16 +389,16 @@ k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw= k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ= k8s.io/apiextensions-apiserver v0.29.1 h1:S9xOtyk9M3Sk1tIpQMu9wXHm5O2MX6Y1kIpPMimZBZw= k8s.io/apiextensions-apiserver v0.29.1/go.mod h1:zZECpujY5yTW58co8V2EQR4BD6A9pktVgHhvc0uLfeU= -k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc= -k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= +k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= +k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A= k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks= k8s.io/component-base v0.29.1 h1:MUimqJPCRnnHsskTTjKD+IC1EHBbRCVyi37IoFBrkYw= k8s.io/component-base v0.29.1/go.mod h1:fP9GFjxYrLERq1GcWWZAE3bqbNcDKDytn2srWuHTtKc= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= +k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= sigs.k8s.io/controller-runtime v0.17.0 h1:fjJQf8Ukya+VjogLO6/bNX9HE6Y2xpsO5+fyS26ur/s= diff --git a/internal/clients/palette.go b/internal/clients/palette.go index e43ac2f..5b97b27 100644 --- a/internal/clients/palette.go +++ b/internal/clients/palette.go @@ -31,6 +31,7 @@ const ( keyAPIEndpoint = "host" keyAPIKey = "api_key" keyProjectName = "project_name" + keyInsecure = "ignore_insecure_tls_error" // Palette credentials environment variable names @@ -77,13 +78,10 @@ func TerraformSetupBuilder(version, providerSource, providerVersion string) terr ps.Configuration = map[string]interface{}{ keyAPIEndpoint: paletteCreds[keyAPIEndpoint], keyProjectName: paletteCreds[keyProjectName], + keyAPIKey: paletteCreds[keyAPIKey], } - - if v, ok := paletteCreds[keyProjectName]; ok { - ps.Configuration[keyProjectName] = v - } - if v, ok := paletteCreds[keyAPIKey]; ok { - ps.Configuration[keyAPIKey] = v + if v, ok := paletteCreds[keyInsecure]; ok { + ps.Configuration[keyInsecure] = v } // set environment variables for sensitive provider configuration diff --git a/internal/utils/ptr.go b/internal/utils/ptr.go new file mode 100644 index 0000000..9c03643 --- /dev/null +++ b/internal/utils/ptr.go @@ -0,0 +1,5 @@ +package utils + +func Ptr[T any](x T) *T { + return &x +} diff --git a/tests/integration/cloudaccount_test.go b/tests/integration/cloudaccount_test.go new file mode 100644 index 0000000..957f6f5 --- /dev/null +++ b/tests/integration/cloudaccount_test.go @@ -0,0 +1,57 @@ +package integration + +import ( + v1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + logf "sigs.k8s.io/controller-runtime/pkg/log" + + cloudaccountv1alpha1 "github.com/crossplane-contrib/provider-palette/apis/cloudaccount/v1alpha1" + "github.com/crossplane-contrib/provider-palette/internal/utils" +) + +var _ = Describe("Cloud Account Tests", Ordered, func() { + + Describe("Creating an AWS cloud account", func() { + It("should succeed", func() { + awsCloudAccount := &cloudaccountv1alpha1.Aws{ + ObjectMeta: metav1.ObjectMeta{ + Name: "aws-cloud-account", + Namespace: "default", + }, + Spec: cloudaccountv1alpha1.AwsSpec{ + ResourceSpec: v1.ResourceSpec{ + ProviderConfigReference: &v1.Reference{ + Name: "provider-palette-config", + }, + }, + ForProvider: cloudaccountv1alpha1.AwsParameters{ + Type: utils.Ptr("secret"), + }, + }, + } + + err := kclient.Create(tc, awsCloudAccount) + Expect(err).ShouldNot(HaveOccurred()) + + Eventually(func() bool { + if err := kclient.Get(tc, keyFromObj(awsCloudAccount), awsCloudAccount); err != nil { + return false + } + if len(awsCloudAccount.Status.Conditions) == 0 { + return false + } + for _, c := range awsCloudAccount.Status.Conditions { + logf.Log.Info("AWSCloudAccount Condition", "Type", c.Type, "Status", c.Status, "Reason", c.Reason) + if c.Status != corev1.ConditionTrue { + return false + } + } + logf.Log.Info("AWSCloudAccount created successfully") + return true + }, timeout, interval).Should(BeTrue(), "failed to create AWS cloud account") + }) + }) +}) diff --git a/tests/integration/routes/cloudaccount.go b/tests/integration/routes/cloudaccount.go new file mode 100644 index 0000000..4dc5c66 --- /dev/null +++ b/tests/integration/routes/cloudaccount.go @@ -0,0 +1,59 @@ +package routes + +import ( + "net/http" + + "github.com/gorilla/mux" +) + +func RegisterCloudAccount(router *mux.Router) { + + // create + router.Handle("/v1/cloudaccounts/aws", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch r.Method { + case http.MethodPost: + w.WriteHeader(http.StatusCreated) + _, _ = w.Write([]byte(`{"uid": "1"}`)) + default: + w.WriteHeader(http.StatusMethodNotAllowed) + } + })) + + // get + router.Handle("/v1/cloudaccounts/aws/{uid}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + switch r.Method { + case http.MethodGet: + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(` + { + "apiVersion": "v1", + "kind": "AwsCloudAccount", + "metadata": { + "name": "aws-cloud-account", + "annotations": { + "scope": "project" + }, + "uid": "1" + }, + "spec": { + "credentialType": "secret", + "accessKey": "fake-access-key", + "partition": "aws" + }, + "status": { + "state": "active" + } + }`)) + default: + w.WriteHeader(http.StatusMethodNotAllowed) + } + })) + + // validate + router.Handle("/v1/clouds/aws/account/validate", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusNoContent) + })) +} diff --git a/tests/integration/routes/project.go b/tests/integration/routes/project.go new file mode 100644 index 0000000..2797934 --- /dev/null +++ b/tests/integration/routes/project.go @@ -0,0 +1,33 @@ +package routes + +import ( + "net/http" + + "github.com/gorilla/mux" +) + +func RegisterProject(router *mux.Router) { + + // list + router.Handle("/v1/dashboard/projects/metadata", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(` + { + "items": [ + { + "metadata": { + "name": "Default", + "uid": "1" + } + }, + { + "metadata": { + "name": "TestProject", + "uid": "2" + } + } + ] + }`)) + })) +} diff --git a/tests/integration/suite_test.go b/tests/integration/suite_test.go new file mode 100644 index 0000000..13c47c6 --- /dev/null +++ b/tests/integration/suite_test.go @@ -0,0 +1,186 @@ +package integration + +import ( + "context" + "fmt" + "net/http/httptest" + "os" + "path/filepath" + "testing" + "time" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/gorilla/mux" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + "github.com/crossplane-contrib/provider-palette/apis" + "github.com/crossplane-contrib/provider-palette/apis/v1beta1" + "github.com/crossplane-contrib/provider-palette/cmd/provider/run" + "github.com/crossplane-contrib/provider-palette/internal/utils" + "github.com/crossplane-contrib/provider-palette/tests/integration/routes" +) + +const ( + timeout = time.Second * 300 + interval = time.Millisecond * 250 +) + +var ( + kclient client.Client + cancel context.CancelFunc + tc context.Context + te *envtest.Environment + ts *httptest.Server +) + +func TestFunctionality(t *testing.T) { + RegisterFailHandler(Fail) + + // Ensure verbose log output + suiteConfig, reporterConfig := GinkgoConfiguration() + reporterConfig.FullTrace = true + reporterConfig.Verbose = true + + RunSpecs(t, "Integration Test Suite", suiteConfig, reporterConfig) +} + +var _ = BeforeSuite(func() { + tc = context.Background() + tc, cancel = context.WithCancel(tc) + + // Start a mock server for the Palette API + router := mux.NewRouter() + routes.RegisterProject(router) + routes.RegisterCloudAccount(router) + ts = httptest.NewTLSServer(router) + + // Start the test environment + te = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "package", "crds")}, + ErrorIfCRDPathMissing: true, + } + if kcfg := os.Getenv("KUBECONFIG"); kcfg != "" { + te.UseExistingCluster = utils.Ptr(true) + } + + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + cfg, err := te.Start() + Expect(err).ShouldNot(HaveOccurred()) + + scheme := scheme.Scheme + Expect(apis.AddToScheme(scheme)).To(Succeed()) + + kclient, err = client.New(cfg, client.Options{Scheme: scheme}) + Expect(err).ShouldNot(HaveOccurred()) + + // Generate, save, and configure kubeconfig so in-cluster client lookups succeed + kubeconfigPath, err := kubeconfigFromRestConfig(cfg) + Expect(err).ShouldNot(HaveOccurred()) + + os.Setenv("KUBECONFIG", kubeconfigPath) + logf.Log.Info("Kubeconfig", "path", kubeconfigPath) + + initResources() + + go func() { + defer GinkgoRecover() + os.Args = initProviderArgs() + run.Run() + }() +}) + +var _ = AfterSuite(func() { + By("tearing down the provider") + run.Cancel() + + By("tearing down the mock server") + ts.Close() + + By("tearing down the test environment") + cancel() + err := te.Stop() + Expect(err).ShouldNot(HaveOccurred(), "failed to tear down the test environment") +}) + +// initProviderArgs initializes the arguments required to run provider-palette in test mode. +func initProviderArgs() []string { + v := os.Getenv("TERRAFORM_VERSION") + if v == "" { + Fail("TERRAFORM_VERSION environment variable must be set") + } + pv := os.Getenv("TERRAFORM_PROVIDER_VERSION") + if v == "" { + Fail("TERRAFORM_PROVIDER_VERSION environment variable must be set") + } + return []string{ + "run", + "--debug", + fmt.Sprintf("--terraform-version=%s", v), + fmt.Sprintf("--terraform-provider-version=%s", pv), + "--terraform-provider-source=spectrocloud/spectrocloud", + } +} + +// initResources creates namespace, secret, and provider config resources +// required for provider-palette to function in test mode. +func initResources() { + ns := &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "crossplane-system", + }, + } + err := kclient.Create(tc, ns) + Expect(err).ShouldNot(HaveOccurred()) + + s := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "palette-creds", + Namespace: "crossplane-system", + }, + StringData: map[string]string{ + "credentials": fmt.Sprintf(`{ + "api_key": "dummy", + "project_name": "Default", + "host": "%s", + "ignore_insecure_tls_error": "true" + }`, + // Configure provider-palette to use the mock Palette server + ts.Listener.Addr().String(), + ), + }, + } + err = kclient.Create(tc, s) + Expect(err).ShouldNot(HaveOccurred()) + + pc := &v1beta1.ProviderConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "provider-palette-config", + Namespace: "crossplane-system", + }, + Spec: v1beta1.ProviderConfigSpec{ + Credentials: v1beta1.ProviderCredentials{ + Source: xpv1.CredentialsSource("Secret"), + CommonCredentialSelectors: xpv1.CommonCredentialSelectors{ + SecretRef: &xpv1.SecretKeySelector{ + SecretReference: xpv1.SecretReference{ + Name: "palette-creds", + Namespace: "crossplane-system", + }, + Key: "credentials", + }, + }, + }, + }, + } + err = kclient.Create(tc, pc) + Expect(err).ShouldNot(HaveOccurred()) +} diff --git a/tests/integration/utils.go b/tests/integration/utils.go new file mode 100644 index 0000000..b9bd8fc --- /dev/null +++ b/tests/integration/utils.go @@ -0,0 +1,52 @@ +package integration + +import ( + "os" + + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func keyFromObj(obj client.Object) types.NamespacedName { + return types.NamespacedName{ + Name: obj.GetName(), + Namespace: obj.GetNamespace(), + } +} + +func kubeconfigFromRestConfig(restConfig *rest.Config) (string, error) { + clusters := make(map[string]*clientcmdapi.Cluster) + clusters["default-cluster"] = &clientcmdapi.Cluster{ + Server: restConfig.Host, + CertificateAuthorityData: restConfig.CAData, + } + contexts := make(map[string]*clientcmdapi.Context) + contexts["default-context"] = &clientcmdapi.Context{ + Cluster: "default-cluster", + AuthInfo: "default-user", + } + authinfos := make(map[string]*clientcmdapi.AuthInfo) + authinfos["default-user"] = &clientcmdapi.AuthInfo{ + ClientCertificateData: restConfig.CertData, + ClientKeyData: restConfig.KeyData, + } + clientConfig := clientcmdapi.Config{ + Kind: "Config", + APIVersion: "v1", + Clusters: clusters, + Contexts: contexts, + CurrentContext: "default-context", + AuthInfos: authinfos, + } + kubeConfigFile, err := os.CreateTemp("", "kubeconfig") + if err != nil { + return "", err + } + if err := clientcmd.WriteToFile(clientConfig, kubeConfigFile.Name()); err != nil { + return "", err + } + return kubeConfigFile.Name(), nil +}