diff --git a/.github/actions/acc_test/README.md b/.github/actions/acc_test/README.md new file mode 100644 index 00000000..c3484cf2 --- /dev/null +++ b/.github/actions/acc_test/README.md @@ -0,0 +1 @@ +# acceptance test action diff --git a/.github/actions/acc_test/action.yaml b/.github/actions/acc_test/action.yaml new file mode 100644 index 00000000..828e1011 --- /dev/null +++ b/.github/actions/acc_test/action.yaml @@ -0,0 +1,114 @@ +name: Acceptance Testing +description: "Acceptance Testing pipeline" + +inputs: + go-version: + description: "go version to install" + default: '1.25' + required: true + + project_id: + description: "STACKIT project ID for tests" + required: true + + region: + description: "STACKIT region for tests" + default: 'eu01' + required: true + + service_account_json: + description: "STACKIT service account JSON file contents" + required: true + + test_file: + description: "testfile to run" + default: '' + +outputs: + random-number: + description: "Random number" + value: ${{ steps.random-number-generator.outputs.random-number }} + +runs: + using: "composite" + steps: + - name: Random Number Generator + id: random-number-generator + run: echo "random-number=$(echo $RANDOM)" >> $GITHUB_OUTPUT + shell: bash + + - name: Install needed tools + shell: bash + run: | + set -e + apt-get -y -qq update + apt-get -y -qq install jq python3 python3-pip python-is-python3 s3cmd git make wget + + - name: Setup JAVA + uses: actions/setup-java@v5 + with: + distribution: 'temurin' # See 'Supported distributions' for available options + java-version: '21' + + - name: Install Go ${{ inputs.go-version }} + uses: actions/setup-go@v6 + with: + go-version: ${{ inputs.go-version }} + check-latest: true + go-version-file: 'go.mod' + + - name: Install go tools + shell: bash + run: | + set -e + go mod download + go install golang.org/x/tools/cmd/goimports@latest + go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.7.2 + go install github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs@v0.24.0 + + - name: Prepare pkg_gen directory + shell: bash + run: | + go run cmd/main.go build -p + + - name: Run acceptance test file + if: ${{ inputs.test_file != '' }} + shell: bash + run: | + echo "Running acceptance tests for the terraform provider" + echo "${STACKIT_SERVICE_ACCOUNT_JSON}" > ~/.service_account.json + cd stackit + TF_ACC=1 \ + TF_ACC_PROJECT_ID=${TF_ACC_PROJECT_ID} \ + TF_ACC_REGION=${TF_ACC_REGION} \ + go test ${{ inputs.test_file }} -count=1 -timeout=30m + env: + STACKIT_SERVICE_ACCOUNT_JSON: ${{ inputs.service_account_json }} + TF_PROJECT_ID: ${{ inputs.project_id }} + TF_ACC_REGION: ${{ inputs.region }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN }} + # TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID }} + # TF_ACC_TEST_PROJECT_PARENT_UUID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_UUID }} + # TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_USER_EMAIL }} + + - name: Run acceptance tests + if: ${{ inputs.test_file == '' }} + shell: bash + run: | + echo "Running acceptance tests for the terraform provider" + echo "${STACKIT_SERVICE_ACCOUNT_JSON}" > ~/.service_account.json + cd stackit + TF_ACC=1 \ + TF_ACC_PROJECT_ID=${TF_ACC_PROJECT_ID} \ + TF_ACC_REGION=${TF_ACC_REGION} \ + go test ./... -count=1 -timeout=30m + env: + STACKIT_SERVICE_ACCOUNT_JSON: ${{ inputs.service_account_json }} + TF_PROJECT_ID: ${{ inputs.project_id }} + TF_ACC_REGION: ${{ inputs.region }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL }} + # TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN }} + # TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID }} + # TF_ACC_TEST_PROJECT_PARENT_UUID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_UUID }} + # TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_USER_EMAIL }} diff --git a/.github/actions/build/action.yaml b/.github/actions/build/action.yaml index fe544618..1fa83ee1 100644 --- a/.github/actions/build/action.yaml +++ b/.github/actions/build/action.yaml @@ -1,4 +1,3 @@ - name: Build description: "Build pipeline" inputs: diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index fbc3f339..186d2b42 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -106,7 +106,7 @@ jobs: needs: config steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Build uses: ./.github/actions/build @@ -150,7 +150,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Check GoReleaser uses: goreleaser/goreleaser-action@v6 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 254c40f2..7d7106ed 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -18,7 +18,7 @@ jobs: goreleaser: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 with: # Allow goreleaser to access older tag information. fetch-depth: 0 diff --git a/.github/workflows/renovate.yaml b/.github/workflows/renovate.yaml index 12454b9f..90adebe6 100644 --- a/.github/workflows/renovate.yaml +++ b/.github/workflows/renovate.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Self-hosted Renovate uses: renovatebot/github-action@v41.0.0 with: diff --git a/.github/workflows/tf-acc-test.yaml b/.github/workflows/tf-acc-test.yaml index a8e6a53f..3b4fb061 100644 --- a/.github/workflows/tf-acc-test.yaml +++ b/.github/workflows/tf-acc-test.yaml @@ -7,21 +7,17 @@ on: workflow_dispatch: jobs: - main: + acc_test: name: Acceptance Tests runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 - - name: Install project tools and dependencies - run: make project-tools - - name: Run tests - run: | - make test-acceptance-tf TF_ACC_PROJECT_ID=$${{ secrets.TF_ACC_PROJECT_ID }} TF_ACC_ORGANIZATION_ID=$${{ secrets.TF_ACC_ORGANIZATION_ID }} TF_ACC_REGION="eu01" - env: - STACKIT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_SERVICE_ACCOUNT_TOKEN }} - TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_EMAIL }} - TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN: ${{ secrets.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN }} - TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_CONTAINER_ID }} - TF_ACC_TEST_PROJECT_PARENT_UUID: ${{ secrets.TF_ACC_TEST_PROJECT_PARENT_UUID }} - TF_ACC_TEST_PROJECT_USER_EMAIL: ${{ secrets.TF_ACC_TEST_PROJECT_USER_EMAIL }} + uses: actions/checkout@v6 + + - name: Run Test + uses: ./.github/actions/acc_test + with: + go-version: ${{ env.GO_VERSION }} + project_id: ${{ vars.TEST_PROJECT_ID }} + region: 'eu01' + service_account_json: ${{ secrets.TF_ACC_SERVICE_ACCOUNT_JSON }} diff --git a/README.md b/README.md index 1da34359..018f615e 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@
-# STACKIT Terraform Provider +# STACKIT Terraform Provider (PRIVATE PREVIEW) -[![Go Report Card](https://goreportcard.com/badge/github.com/stackitcloud/terraform-provider-stackit)](https://goreportcard.com/report/github.com/stackitcloud/terraform-provider-stackit) [![GitHub Release](https://img.shields.io/github/v/release/stackitcloud/terraform-provider-stackit)](https://registry.terraform.io/providers/stackitcloud/stackit/latest) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/stackitcloud/terraform-provider-stackit) [![GitHub License](https://img.shields.io/github/license/stackitcloud/terraform-provider-stackit)](https://www.apache.org/licenses/LICENSE-2.0) +[![GitHub Release](https://img.shields.io/github/v/release/stackitcloud/terraform-provider-stackit)](https://registry.terraform.io/providers/stackitcloud/stackit/latest) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/stackitcloud/terraform-provider-stackit) [![GitHub License](https://img.shields.io/github/license/stackitcloud/terraform-provider-stackit)](https://www.apache.org/licenses/LICENSE-2.0) This project is the official [Terraform Provider](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs) for [STACKIT](https://www.stackit.de/en/), which allows you to manage STACKIT resources through Terraform. diff --git a/cmd/cmd/build/build.go b/cmd/cmd/build/build.go index a6e0acf9..f210b8d2 100644 --- a/cmd/cmd/build/build.go +++ b/cmd/cmd/build/build.go @@ -39,17 +39,15 @@ type version struct { } type Builder struct { - SkipClone bool - SkipCleanup bool + SkipClone bool + SkipCleanup bool + PackagesOnly bool } func (b *Builder) Build() error { slog.Info("Starting Builder") - - slog.Info(" ... Checking needed commands available") - err := checkCommands([]string{"tfplugingen-framework", "tfplugingen-openapi"}) - if err != nil { - return err + if b.PackagesOnly { + slog.Info(" >>> only generating pkg_gen <<<") } root, err := getRoot() @@ -61,13 +59,23 @@ func (b *Builder) Build() error { } slog.Info(" ... using root directory", "dir", *root) - if !b.SkipCleanup { - slog.Info("Cleaning up old generator directory") - err = os.RemoveAll(path.Join(*root, GEN_REPO_NAME)) + if !b.PackagesOnly { + slog.Info(" ... Checking needed commands available") + err := checkCommands([]string{"tfplugingen-framework", "tfplugingen-openapi"}) if err != nil { return err } + } + if !b.SkipCleanup { + slog.Info("Cleaning up old packages directory") + err = os.RemoveAll(path.Join(*root, "pkg_gen")) + if err != nil { + return err + } + } + + if !b.SkipCleanup && !b.PackagesOnly { slog.Info("Cleaning up old packages directory") err = os.RemoveAll(path.Join(*root, "pkg_gen")) if err != nil { @@ -211,24 +219,26 @@ func (b *Builder) Build() error { } } - slog.Info("Generating service boilerplate") - err = generateServiceFiles(*root, path.Join(*root, GEN_REPO_NAME)) - if err != nil { - return err - } + if !b.PackagesOnly { + slog.Info("Generating service boilerplate") + err = generateServiceFiles(*root, path.Join(*root, GEN_REPO_NAME)) + if err != nil { + return err + } - slog.Info("Copying all service files") - err = CopyDirectory( - path.Join(*root, "generated", "internal", "services"), - path.Join(*root, "stackit", "internal", "services"), - ) - if err != nil { - return err - } + slog.Info("Copying all service files") + err = CopyDirectory( + path.Join(*root, "generated", "internal", "services"), + path.Join(*root, "stackit", "internal", "services"), + ) + if err != nil { + return err + } - err = createBoilerplate(*root, path.Join(*root, "stackit", "internal", "services")) - if err != nil { - return err + err = createBoilerplate(*root, path.Join(*root, "stackit", "internal", "services")) + if err != nil { + return err + } } if !b.SkipCleanup { diff --git a/cmd/cmd/buildCmd.go b/cmd/cmd/buildCmd.go index 0a239215..8902132e 100644 --- a/cmd/cmd/buildCmd.go +++ b/cmd/cmd/buildCmd.go @@ -6,8 +6,9 @@ import ( ) var ( - skipCleanup bool - skipClone bool + skipCleanup bool + skipClone bool + packagesOnly bool ) var buildCmd = &cobra.Command{ @@ -16,8 +17,9 @@ var buildCmd = &cobra.Command{ Long: `...`, RunE: func(cmd *cobra.Command, args []string) error { b := build.Builder{ - SkipClone: skipClone, - SkipCleanup: skipCleanup, + SkipClone: skipClone, + SkipCleanup: skipCleanup, + PackagesOnly: packagesOnly, } return b.Build() }, @@ -30,4 +32,5 @@ func NewBuildCmd() *cobra.Command { func init() { // nolint: gochecknoinits buildCmd.Flags().BoolVarP(&skipCleanup, "skip-clean", "c", false, "Skip cleanup steps") buildCmd.Flags().BoolVarP(&skipClone, "skip-clone", "g", false, "Skip cloning from git") + buildCmd.Flags().BoolVarP(&packagesOnly, "packages-only", "p", false, "Only generate packages") } diff --git a/stackit/internal/services/postgresflexalpha/instance/resource_test.go b/stackit/internal/services/postgresflexalpha/instance/resource_test.go index 46d935a5..c84c1a5d 100644 --- a/stackit/internal/services/postgresflexalpha/instance/resource_test.go +++ b/stackit/internal/services/postgresflexalpha/instance/resource_test.go @@ -1,12 +1,233 @@ package postgresflexalpha import ( - "reflect" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "os" "testing" - "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/testutil" ) +var ( + validFlavor = "2.4" + kekKeyRingId = "" + kekKeyVersion = "" + kekKeySA = "" +) + +func testAccPreCheck(t *testing.T) { + // TODO: if needed ... +} + +//func TestAccResourceExample_parallel(t *testing.T) { +// t.Parallel() +// +// exData := resData{ +// Region: "eu01", +// ServiceAccountFilePath: sa_file, +// ProjectID: project_id, +// Name: acctest.RandomWithPrefix("tf-acc"), +// } +// +// resource.Test(t, resource.TestCase{ +// ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories, +// Steps: []resource.TestStep{ +// { +// Config: testAccResourceEncryptionExampleConfig(exData), +// Check: resource.TestCheckResourceAttrSet("example_resource.test", "id"), +// }, +// }, +// }) +//} + +type resData struct { + ServiceAccountFilePath string + ProjectID string + Region string + Name string + Flavor string + BackupSchedule string + RetentionDays uint32 +} + +func getExample() resData { + return resData{ + Region: testutil.Region, + ServiceAccountFilePath: testutil.ServiceAccountFile, + ProjectID: testutil.ProjectId, + Name: acctest.RandomWithPrefix("tf-acc"), + Flavor: "2.4", + BackupSchedule: "0 0 * * *", + RetentionDays: 33, + } +} + +func TestAccResourceExample_basic(t *testing.T) { + exData := getExample() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccResourceNoEncryptionExampleConfig(exData), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("example_resource.test", "name", exData.Name), + resource.TestCheckResourceAttrSet("example_resource.test", "id"), + ), + }, + //// Create and verify + //{ + // Config: testAccResourceNoEncryptionExampleConfig(exData), + // Check: resource.ComposeTestCheckFunc( + // resource.TestCheckResourceAttr("example_resource.test", "name", exData.Name), + // ), + //}, + //// Update and verify + //{ + // Config: testAccResourceNoEncryptionExampleConfig(exData), + // Check: resource.ComposeTestCheckFunc( + // resource.TestCheckResourceAttr("example_resource.test", "name", exData.Name), + // ), + //}, + // Import test + { + ResourceName: "example_resource.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccResourceNoEncryptionExampleConfig(data resData) string { + return fmt.Sprintf(` + +%[1]s + +resource "stackitprivatepreview_postgresflexalpha_instance" "test" { + project_id = %[2]q + name = %[3]q + backup_schedule = %[4]q + retention_days = %[5]d + flavor_id = %[6]q + replicas = 1 + storage = { + performance_class = "premium-perf2-stackit" + size = 10 + } + network = { + acl = ["0.0.0.0/0"] + access_scope = "PUBLIC" + } + version = 17 +} + +`, + testutil.PostgresFlexProviderConfig(data.ServiceAccountFilePath), + data.ProjectID, + data.Name, + data.BackupSchedule, + data.RetentionDays, + data.Flavor, + data.Name, + ) +} + +func testAccResourceEncryptionExampleConfig(data resData) string { + return fmt.Sprintf(` + +%[1]s + +resource "stackitprivatepreview_postgresflexalpha_instance" "test" { + project_id = %[2]q + name = %[3]q + backup_schedule = "0 0 * * *" + retention_days = 45 + flavor_id = "2.1" + replicas = 1 + storage = { + performance_class = "premium-perf2-stackit" + size = 10 + } + encryption = { + kek_key_id = "key01" + kek_key_ring_id = "key_ring_01" + kek_key_version = 1 + service_account = "service@account.email" + } + network = { + acl = ["0.0.0.0/0"] + access_scope = "PUBLIC" + } + version = 14 +} + +`, + testutil.PostgresFlexProviderConfig(data.ServiceAccountFilePath), + data.ProjectID, + data.Name, + ) +} + +func testCheckResourceExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("resource not found: %s", resourceName) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("resource ID not set") + } + + // Verify resource exists in the API + //client := testAccProvider.Meta().(*APIClient) + //_, err := client.GetResource(rs.Primary.ID) + //if err != nil { + // return fmt.Errorf("error fetching resource: %w", err) + //} + + return nil + } +} + +func setupMockServer() *httptest.Server { + mux := http.NewServeMux() + + mux.HandleFunc("/api/resources", func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodPost: + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(map[string]string{ + "id": "mock-id-123", + "name": "test-resource", + }) + case http.MethodGet: + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode([]map[string]string{}) + } + }) + + return httptest.NewServer(mux) +} + +func TestUnitResourceCreate(t *testing.T) { + server := setupMockServer() + defer server.Close() + + // Configure provider to use mock server URL + os.Setenv("API_ENDPOINT", server.URL) + + // Run unit tests against mock +} + // type postgresFlexClientMocked struct { // returnError bool // getFlavorsResp *postgresflex.GetFlavorsResponse @@ -20,21 +241,40 @@ import ( // return c.getFlavorsResp, nil // } -func TestNewInstanceResource(t *testing.T) { - tests := []struct { - name string - want resource.Resource - }{ - { - name: "create empty instance resource", - want: &instanceResource{}, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := NewInstanceResource(); !reflect.DeepEqual(got, tt.want) { - t.Errorf("NewInstanceResource() = %v, want %v", got, tt.want) - } - }) - } -} +//func TestNewInstanceResource(t *testing.T) { +// exData := resData{ +// Region: "eu01", +// ServiceAccountFilePath: sa_file, +// ProjectID: project_id, +// Name: "testRes", +// } +// resource.Test(t, resource.TestCase{ +// ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories, +// Steps: []resource.TestStep{ +// { +// Config: testAccResourceEncryptionExampleConfig(exData), +// Check: resource.ComposeAggregateTestCheckFunc( +// resource.TestCheckResourceAttr("example_resource.test", "name", exData.Name), +// resource.TestCheckResourceAttrSet("example_resource.test", "id"), +// ), +// }, +// }, +// }) +// +// //tests := []struct { +// // name string +// // want resource.Resource +// //}{ +// // { +// // name: "create empty instance resource", +// // want: &instanceResource{}, +// // }, +// //} +// //for _, tt := range tests { +// // t.Run(tt.name, func(t *testing.T) { +// // if got := NewInstanceResource(); !reflect.DeepEqual(got, tt.want) { +// // t.Errorf("NewInstanceResource() = %v, want %v", got, tt.want) +// // } +// // }) +// //} +//} diff --git a/stackit/internal/services/sqlserverflexbeta/database/datasource.go b/stackit/internal/services/sqlserverflexbeta/database/datasource.go index 4cc56ea2..bb6c3038 100644 --- a/stackit/internal/services/sqlserverflexbeta/database/datasource.go +++ b/stackit/internal/services/sqlserverflexbeta/database/datasource.go @@ -146,15 +146,11 @@ func (d *databaseDataSource) Read(ctx context.Context, req datasource.ReadReques data.Id = types.Int64Value(dbId) data.TfId = utils.BuildInternalTerraformId(projectId, region, instanceId, databaseName) data.Owner = types.StringValue(databaseResp.GetOwner()) - - // TODO: fill remaining fields - // data.CollationName = types.Sometype(apiResponse.GetCollationName()) - // data.CompatibilityLevel = types.Sometype(apiResponse.GetCompatibilityLevel()) - // data.DatabaseName = types.Sometype(apiResponse.GetDatabaseName()) - // data.Id = types.Sometype(apiResponse.GetId()) - // data.InstanceId = types.Sometype(apiResponse.GetInstanceId()) + data.CollationName = types.StringValue(databaseResp.GetCollationName()) + data.CompatibilityLevel = types.Int64Value(databaseResp.GetCompatibilityLevel()) + data.DatabaseName = types.StringValue(databaseResp.GetName()) + // data.InstanceId = types.StringValue(databaseResp.GetInstanceId()) // data.Name = types.Sometype(apiResponse.GetName()) - // data.Owner = types.Sometype(apiResponse.GetOwner()) // data.ProjectId = types.Sometype(apiResponse.GetProjectId()) // data.Region = types.Sometype(apiResponse.GetRegion()) diff --git a/stackit/internal/testutil/assert.go b/stackit/internal/testutil/assert.go new file mode 100644 index 00000000..80cb2104 --- /dev/null +++ b/stackit/internal/testutil/assert.go @@ -0,0 +1,11 @@ +package testutil + +import "testing" + +func Equal[V comparable](t *testing.T, got, expected V) { + t.Helper() + + if expected != got { + t.Errorf("assert equal failed:\ngot: %v \nexpected: %v", got, expected) + } +} diff --git a/stackit/internal/testutil/testutil.go b/stackit/internal/testutil/testutil.go index 1464c20d..b678efef 100644 --- a/stackit/internal/testutil/testutil.go +++ b/stackit/internal/testutil/testutil.go @@ -3,7 +3,6 @@ package testutil import ( - "encoding/json" "fmt" "os" "path/filepath" @@ -20,7 +19,8 @@ import ( const ( // Default location of credentials JSON - credentialsFilePath = ".stackit/credentials.json" //nolint:gosec // linter false positive + // credentialsFilePath = ".stackit/credentials.json" //nolint:gosec // linter false positive + serviceAccountFilePath = ".stackit/service_account.json" ) var ( @@ -52,6 +52,8 @@ var ( // ProjectId is the id of project used for tests ProjectId = os.Getenv("TF_ACC_PROJECT_ID") Region = os.Getenv("TF_ACC_REGION") + // ServiceAccountFile is the json file of the service account + ServiceAccountFile = os.Getenv("TF_ACC_SERVICE_ACCOUNT_FILE") // ServerId is the id of a server used for some tests ServerId = getenv("TF_ACC_SERVER_ID", "") // TestProjectParentContainerID is the container id of the parent resource under which projects are created as part of the resource-manager acceptance tests @@ -108,6 +110,7 @@ func ObservabilityProviderConfig() string { ObservabilityCustomEndpoint, ) } + func CdnProviderConfig() string { if CdnCustomEndpoint == "" { return ` @@ -316,8 +319,10 @@ func PostgresFlexProviderConfig(saFile string) string { } return fmt.Sprintf(` provider "stackitprivatepreview" { + service_account_key_path = "%s" postgresflex_custom_endpoint = "%s" }`, + saFile, PostgresFlexCustomEndpoint, ) } @@ -353,13 +358,13 @@ func RedisProviderConfig() string { } func ResourceManagerProviderConfig() string { - token := GetTestProjectServiceAccountToken("") + key := GetTestProjectServiceAccountJson("") if ResourceManagerCustomEndpoint == "" || AuthorizationCustomEndpoint == "" { return fmt.Sprintf(` provider "stackitprivatepreview" { - service_account_token = "%s" + service_account_key = "%s" }`, - token, + key, ) } return fmt.Sprintf(` @@ -370,7 +375,7 @@ func ResourceManagerProviderConfig() string { }`, ResourceManagerCustomEndpoint, AuthorizationCustomEndpoint, - token, + key, ) } @@ -389,17 +394,20 @@ func SecretsManagerProviderConfig() string { ) } -func SQLServerFlexProviderConfig() string { +func SQLServerFlexProviderConfig(saFile string) string { if SQLServerFlexCustomEndpoint == "" { - return ` + return fmt.Sprintf(` provider "stackitprivatepreview" { default_region = "eu01" - }` + service_account_key_path = "%s" + }`, saFile) } return fmt.Sprintf(` provider "stackitprivatepreview" { + service_account_key_path = "%s" sqlserverflex_custom_endpoint = "%s" }`, + saFile, SQLServerFlexCustomEndpoint, ) } @@ -531,7 +539,7 @@ func GetTestProjectServiceAccountJson(path string) string { var err error token, tokenSet := os.LookupEnv("TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_JSON") if !tokenSet || token == "" { - token, err = readTestTokenFromCredentialsFile(path) + token, err = readTestServiceAccountJsonFromFile(path) if err != nil { return "" } @@ -539,23 +547,53 @@ func GetTestProjectServiceAccountJson(path string) string { return token } -func GetTestProjectServiceAccountToken(path string) string { - var err error - token, tokenSet := os.LookupEnv("TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN") - if !tokenSet || token == "" { - token, err = readTestTokenFromCredentialsFile(path) - if err != nil { - return "" - } - } - return token -} +//func GetTestProjectServiceAccountToken(path string) string { +// var err error +// token, tokenSet := os.LookupEnv("TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN") +// if !tokenSet || token == "" { +// token, err = readTestTokenFromCredentialsFile(path) +// if err != nil { +// return "" +// } +// } +// return token +//} +// +//func readTestTokenFromCredentialsFile(path string) (string, error) { +// if path == "" { +// customPath, customPathSet := os.LookupEnv("STACKIT_CREDENTIALS_PATH") +// if !customPathSet || customPath == "" { +// path = credentialsFilePath +// home, err := os.UserHomeDir() +// if err != nil { +// return "", fmt.Errorf("getting home directory: %w", err) +// } +// path = filepath.Join(home, path) +// } else { +// path = customPath +// } +// } +// +// credentialsRaw, err := os.ReadFile(path) +// if err != nil { +// return "", fmt.Errorf("opening file: %w", err) +// } +// +// var credentials struct { +// TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN string `json:"TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN"` +// } +// err = json.Unmarshal(credentialsRaw, &credentials) +// if err != nil { +// return "", fmt.Errorf("unmarshalling credentials: %w", err) +// } +// return credentials.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN, nil +//} -func readTestTokenFromCredentialsFile(path string) (string, error) { +func readTestServiceAccountJsonFromFile(path string) (string, error) { if path == "" { - customPath, customPathSet := os.LookupEnv("STACKIT_CREDENTIALS_PATH") + customPath, customPathSet := os.LookupEnv("STACKIT_SERVICE_ACCOUNT_PATH") if !customPathSet || customPath == "" { - path = credentialsFilePath + path = serviceAccountFilePath home, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("getting home directory: %w", err) @@ -570,15 +608,7 @@ func readTestTokenFromCredentialsFile(path string) (string, error) { if err != nil { return "", fmt.Errorf("opening file: %w", err) } - - var credentials struct { - TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN string `json:"TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN"` - } - err = json.Unmarshal(credentialsRaw, &credentials) - if err != nil { - return "", fmt.Errorf("unmarshalling credentials: %w", err) - } - return credentials.TF_ACC_TEST_PROJECT_SERVICE_ACCOUNT_TOKEN, nil + return string(credentialsRaw), nil } func getenv(key, defaultValue string) string {