From b8e64abaf67a3319c819f40f1637b0500de46f68 Mon Sep 17 00:00:00 2001 From: Dean Date: Fri, 2 Jun 2023 13:41:43 +0200 Subject: [PATCH] Add Opensearch support (#147) * add opensearch * update helpers, add tests * update client * add examples * add project id validators + replace plan modifiers * Automated docs update --------- Co-authored-by: Dean Oren Co-authored-by: do87 --- .github/files/analyze-test-output/analyze.go | 3 + Makefile | 2 +- docs/data-sources/opensearch_credential.md | 70 ++++++++++++ docs/data-sources/opensearch_instance.md | 63 +++++++++++ docs/resources/kubernetes_cluster.md | 1 - docs/resources/opensearch_credential.md | 53 +++++++++ docs/resources/opensearch_instance.md | 64 +++++++++++ .../data-source.tf | 15 +++ .../data-source.tf | 9 ++ .../data-source.tf | 9 ++ .../data-source.tf | 4 + go.mod | 2 +- go.sum | 6 +- .../data-services/credential/actions.go | 16 ++- .../data-services/credential/data_source.go | 13 +++ .../credential/data_source_opensearch_test.go | 77 +++++++++++++ .../data-services/instance/actions.go | 2 +- .../data-services/instance/data_source.go | 13 +++ .../instance/data_source_opensearch_test.go | 70 ++++++++++++ .../data-sources/kubernetes/project/schema.go | 5 + .../data-services/credential/actions.go | 2 +- .../data-services/credential/helpers.go | 15 ++- .../data-services/credential/resource.go | 13 +++ .../credential/resource_opensearch_test.go | 89 +++++++++++++++ .../data-services/instance/actions.go | 10 +- .../data-services/instance/helpers.go | 8 +- .../data-services/instance/resource.go | 13 +++ .../instance/resource_opensearch_test.go | 104 ++++++++++++++++++ .../resources/kubernetes/cluster/schema.go | 28 +---- .../resources/kubernetes/project/schema.go | 3 + .../object-storage/project/schema.go | 8 ++ stackit/provider.go | 4 + 32 files changed, 742 insertions(+), 52 deletions(-) create mode 100644 docs/data-sources/opensearch_credential.md create mode 100644 docs/data-sources/opensearch_instance.md create mode 100644 docs/resources/opensearch_credential.md create mode 100644 docs/resources/opensearch_instance.md create mode 100644 examples/data-sources/stackit_opensearch_credential/data-source.tf create mode 100644 examples/data-sources/stackit_opensearch_instance/data-source.tf create mode 100644 examples/resources/stackit_opensearch_credential/data-source.tf create mode 100644 examples/resources/stackit_opensearch_instance/data-source.tf create mode 100644 stackit/internal/data-sources/data-services/credential/data_source_opensearch_test.go create mode 100644 stackit/internal/data-sources/data-services/instance/data_source_opensearch_test.go create mode 100644 stackit/internal/resources/data-services/credential/resource_opensearch_test.go create mode 100644 stackit/internal/resources/data-services/instance/resource_opensearch_test.go diff --git a/.github/files/analyze-test-output/analyze.go b/.github/files/analyze-test-output/analyze.go index 416ee6a7..61313451 100644 --- a/.github/files/analyze-test-output/analyze.go +++ b/.github/files/analyze-test-output/analyze.go @@ -112,6 +112,9 @@ func getDataServiceName(testName string) string { if strings.Contains(testName, "Postgres") { return "postgres-dsa" } + if strings.Contains(testName, "Opensearch") { + return "opensearch-dsa" + } if strings.Contains(testName, "RabbitMQ") { return "rabbitmq-dsa" } diff --git a/Makefile b/Makefile index 38462120..69a86336 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,7 @@ dummy: quality: @goreportcard-cli -v . -pre-commit: docs quality +pre-commit: quality @go run .github/files/generate-acceptance-tests/main.go @find docs -type f | sort | cat | md5 > .github/files/pre-commit-check/checksum @cat .github/workflows/acceptance_test.yml | md5 >> .github/files/pre-commit-check/checksum diff --git a/docs/data-sources/opensearch_credential.md b/docs/data-sources/opensearch_credential.md new file mode 100644 index 00000000..4ff6d8ce --- /dev/null +++ b/docs/data-sources/opensearch_credential.md @@ -0,0 +1,70 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "stackit_opensearch_credential Data Source - stackit" +subcategory: "" +description: |- + Manages Opensearch credentials + + -> Environment support + Productionhttps://opensearch.api.eu01.stackit.cloud + QAhttps://opensearch.api.eu01.qa.stackit.cloud + Devhttps://opensearch.api.eu01.dev.stackit.cloud + + By default, production is used.To set a custom URL, set an environment variable STACKITREDISBASEURL +--- + +# stackit_opensearch_credential (Data Source) + +Manages Opensearch credentials + +
+ +-> __Environment support__
+ + + +
Productionhttps://opensearch.api.eu01.stackit.cloud
QAhttps://opensearch.api.eu01.qa.stackit.cloud
Devhttps://opensearch.api.eu01.dev.stackit.cloud

+By default, production is used.
To set a custom URL, set an environment variable STACKIT_REDIS_BASEURL
+ +## Example Usage + +```terraform +resource "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} + +resource "stackit_opensearch_credential" "example" { + project_id = "example" + instance_id = stackit_opensearch_instance.example.id +} + +data "stackit_opensearch_credential" "example" { + id = stackit_opensearch_credential.example.id + project_id = "example" + instance_id = stackit_opensearch_instance.example.id +} +``` + + +## Schema + +### Required + +- `id` (String) Specifies the resource ID +- `instance_id` (String) Instance ID the credential belongs to +- `project_id` (String) Project ID the credential belongs to + +### Read-Only + +- `database_name` (String) Database name +- `host` (String) Credential host +- `hosts` (List of String) Credential hosts +- `password` (String, Sensitive) Credential password +- `port` (Number) Credential port +- `route_service_url` (String) Credential route_service_url +- `syslog_drain_url` (String) Credential syslog_drain_url +- `uri` (String) The instance URI +- `username` (String) Credential username + + diff --git a/docs/data-sources/opensearch_instance.md b/docs/data-sources/opensearch_instance.md new file mode 100644 index 00000000..eb922f6e --- /dev/null +++ b/docs/data-sources/opensearch_instance.md @@ -0,0 +1,63 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "stackit_opensearch_instance Data Source - stackit" +subcategory: "" +description: |- + Data source for Opensearch instances + + -> Environment support + Productionhttps://opensearch.api.eu01.stackit.cloud + QAhttps://opensearch.api.eu01.qa.stackit.cloud + Devhttps://opensearch.api.eu01.dev.stackit.cloud + + By default, production is used.To set a custom URL, set an environment variable STACKITREDISBASEURL +--- + +# stackit_opensearch_instance (Data Source) + +Data source for Opensearch instances + +
+ +-> __Environment support__
+ + + +
Productionhttps://opensearch.api.eu01.stackit.cloud
QAhttps://opensearch.api.eu01.qa.stackit.cloud
Devhttps://opensearch.api.eu01.dev.stackit.cloud

+By default, production is used.
To set a custom URL, set an environment variable STACKIT_REDIS_BASEURL
+ +## Example Usage + +```terraform +resource "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} + +data "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} +``` + + +## Schema + +### Required + +- `name` (String) Specifies the instance name. +- `project_id` (String) The project ID. + +### Read-Only + +- `acl` (List of String) Access Control rules to whitelist IP addresses +- `cf_guid` (String) Cloud Foundry GUID +- `cf_organization_guid` (String) Cloud Foundry Organization GUID +- `cf_space_guid` (String) Cloud Foundry Space GUID +- `dashboard_url` (String) Dashboard URL +- `id` (String) Specifies the resource ID +- `plan` (String) The RabbitMQ Plan +- `plan_id` (String) The selected plan ID +- `version` (String) RabbitMQ version + + diff --git a/docs/resources/kubernetes_cluster.md b/docs/resources/kubernetes_cluster.md index 12d11db6..6d49c4a8 100644 --- a/docs/resources/kubernetes_cluster.md +++ b/docs/resources/kubernetes_cluster.md @@ -60,7 +60,6 @@ resource "stackit_kubernetes_cluster" "example" { - `kubernetes_version` (String) Kubernetes version. Allowed Options are: `1.22`, `1.23`, `1.24`, or a full version including patch (not recommended). - `maintenance` (Attributes) A single maintenance block as defined below (see [below for nested schema](#nestedatt--maintenance)) - `node_pools` (Attributes List) One or more `node_pool` block as defined below (see [below for nested schema](#nestedatt--node_pools)) -- `project_id` (String, Deprecated) this attribure is deprecated. please remove it from your terraform config and use `kubernetes_project_id` instead - `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts)) ### Read-Only diff --git a/docs/resources/opensearch_credential.md b/docs/resources/opensearch_credential.md new file mode 100644 index 00000000..bf64c195 --- /dev/null +++ b/docs/resources/opensearch_credential.md @@ -0,0 +1,53 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "stackit_opensearch_credential Resource - stackit" +subcategory: "" +description: |- + Manages Opensearch credentials + + -> Environment support + Productionhttps://opensearch.api.eu01.stackit.cloud + QAhttps://opensearch.api.eu01.qa.stackit.cloud + Devhttps://opensearch.api.eu01.dev.stackit.cloud + + By default, production is used.To set a custom URL, set an environment variable STACKITREDISBASEURL +--- + +# stackit_opensearch_credential (Resource) + +Manages Opensearch credentials + +
+ +-> __Environment support__
+ + + +
Productionhttps://opensearch.api.eu01.stackit.cloud
QAhttps://opensearch.api.eu01.qa.stackit.cloud
Devhttps://opensearch.api.eu01.dev.stackit.cloud

+By default, production is used.
To set a custom URL, set an environment variable STACKIT_REDIS_BASEURL
+ + + + +## Schema + +### Required + +- `instance_id` (String) Instance ID the credential belongs to +- `project_id` (String) Project ID the credential belongs to + +### Read-Only + +- `database_name` (String) Database name +- `host` (String) Credential host +- `hosts` (List of String) Credential hosts +- `id` (String) Specifies the resource ID +- `password` (String, Sensitive) Credential password +- `port` (Number) Credential port +- `raw_response` (String, Sensitive) The full API response (as JSON string) +- `route_service_url` (String) Credential route_service_url +- `syslog_drain_url` (String) Credential syslog_drain_url +- `uri` (String) The instance URI +- `username` (String) Credential username + + diff --git a/docs/resources/opensearch_instance.md b/docs/resources/opensearch_instance.md new file mode 100644 index 00000000..23266be5 --- /dev/null +++ b/docs/resources/opensearch_instance.md @@ -0,0 +1,64 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "stackit_opensearch_instance Resource - stackit" +subcategory: "" +description: |- + Manages Opensearch instances + + -> Environment support + Productionhttps://opensearch.api.eu01.stackit.cloud + QAhttps://opensearch.api.eu01.qa.stackit.cloud + Devhttps://opensearch.api.eu01.dev.stackit.cloud + + By default, production is used.To set a custom URL, set an environment variable STACKITREDISBASEURL +--- + +# stackit_opensearch_instance (Resource) + +Manages Opensearch instances + +
+ +-> __Environment support__
+ + + +
Productionhttps://opensearch.api.eu01.stackit.cloud
QAhttps://opensearch.api.eu01.qa.stackit.cloud
Devhttps://opensearch.api.eu01.dev.stackit.cloud

+By default, production is used.
To set a custom URL, set an environment variable STACKIT_REDIS_BASEURL
+ + + + +## Schema + +### Required + +- `name` (String) Specifies the instance name. Changing this value requires the resource to be recreated. Changing this value requires the resource to be recreated. +- `project_id` (String) The project ID. + +### Optional + +- `acl` (List of String) Access Control rules to whitelist IP addresses +- `plan` (String) The Opensearch Plan. Default is `stackit-opensearch-1.4.10-single` +- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts)) +- `version` (String) Opensearch version. Default is 2 + +### Read-Only + +- `cf_guid` (String) Cloud Foundry GUID +- `cf_organization_guid` (String) Cloud Foundry Organization GUID +- `cf_space_guid` (String) Cloud Foundry Space GUID +- `dashboard_url` (String) Dashboard URL +- `id` (String) Specifies the resource ID +- `plan_id` (String) The selected plan ID + + +### Nested Schema for `timeouts` + +Optional: + +- `create` (String) +- `delete` (String) +- `update` (String) + + diff --git a/examples/data-sources/stackit_opensearch_credential/data-source.tf b/examples/data-sources/stackit_opensearch_credential/data-source.tf new file mode 100644 index 00000000..01afda14 --- /dev/null +++ b/examples/data-sources/stackit_opensearch_credential/data-source.tf @@ -0,0 +1,15 @@ +resource "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} + +resource "stackit_opensearch_credential" "example" { + project_id = "example" + instance_id = stackit_opensearch_instance.example.id +} + +data "stackit_opensearch_credential" "example" { + id = stackit_opensearch_credential.example.id + project_id = "example" + instance_id = stackit_opensearch_instance.example.id +} diff --git a/examples/data-sources/stackit_opensearch_instance/data-source.tf b/examples/data-sources/stackit_opensearch_instance/data-source.tf new file mode 100644 index 00000000..bc9a6f99 --- /dev/null +++ b/examples/data-sources/stackit_opensearch_instance/data-source.tf @@ -0,0 +1,9 @@ +resource "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} + +data "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} diff --git a/examples/resources/stackit_opensearch_credential/data-source.tf b/examples/resources/stackit_opensearch_credential/data-source.tf new file mode 100644 index 00000000..4d9bebd3 --- /dev/null +++ b/examples/resources/stackit_opensearch_credential/data-source.tf @@ -0,0 +1,9 @@ +resource "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} + +resource "stackit_opensearch_credential" "example" { + project_id = "example" + instance_id = stackit_opensearch_instance.example.id +} diff --git a/examples/resources/stackit_opensearch_instance/data-source.tf b/examples/resources/stackit_opensearch_instance/data-source.tf new file mode 100644 index 00000000..98a4d446 --- /dev/null +++ b/examples/resources/stackit_opensearch_instance/data-source.tf @@ -0,0 +1,4 @@ +resource "stackit_opensearch_instance" "example" { + name = "example" + project_id = "example" +} diff --git a/go.mod b/go.mod index 83d16544..78aa5e26 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/Masterminds/semver v1.5.0 - github.com/SchwarzIT/community-stackit-go-client v1.22.1 + github.com/SchwarzIT/community-stackit-go-client v1.23.2 github.com/hashicorp/terraform-plugin-framework v1.2.0 github.com/hashicorp/terraform-plugin-framework-timeouts v0.3.1 github.com/hashicorp/terraform-plugin-framework-validators v0.10.0 diff --git a/go.sum b/go.sum index bc378e85..90c87f44 100644 --- a/go.sum +++ b/go.sum @@ -11,10 +11,8 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= -github.com/SchwarzIT/community-stackit-go-client v1.22.0 h1:2/6xZQQRO2AZuj77euuY54GzU13EkHSAalGegB00Hc0= -github.com/SchwarzIT/community-stackit-go-client v1.22.0/go.mod h1:hlTfBNOKE1fokWE8g3KrI0AHo0SqzTKkS+LrIdhH8Qg= -github.com/SchwarzIT/community-stackit-go-client v1.22.1 h1:MdW7lzXvwfa5njfjnuIdkIeB5s4ZGQMHtZRaENG2E6I= -github.com/SchwarzIT/community-stackit-go-client v1.22.1/go.mod h1:hlTfBNOKE1fokWE8g3KrI0AHo0SqzTKkS+LrIdhH8Qg= +github.com/SchwarzIT/community-stackit-go-client v1.23.2 h1:xYoseJcPdIFYFFqSCL8e9+wHClKl3knVkHKv485nOfQ= +github.com/SchwarzIT/community-stackit-go-client v1.23.2/go.mod h1:hlTfBNOKE1fokWE8g3KrI0AHo0SqzTKkS+LrIdhH8Qg= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE= diff --git a/stackit/internal/data-sources/data-services/credential/actions.go b/stackit/internal/data-sources/data-services/credential/actions.go index b6f0dbbe..302c866b 100644 --- a/stackit/internal/data-sources/data-services/credential/actions.go +++ b/stackit/internal/data-sources/data-services/credential/actions.go @@ -19,7 +19,7 @@ func (d *DataSource) Read(ctx context.Context, req datasource.ReadRequest, resp return } - res, err := d.client.Credentials.Get(ctx, config.ProjectID.ValueString(), config.InstanceID.ValueString(), config.ID.ValueString()) + res, err := d.client.Credentials.GetCredentialByID(ctx, config.ProjectID.ValueString(), config.InstanceID.ValueString(), config.ID.ValueString()) if agg := validate.Response(res, err, "JSON200.Raw"); agg != nil { if validate.StatusEquals(res, http.StatusNotFound) { resp.State.RemoveResource(ctx) @@ -33,18 +33,24 @@ func (d *DataSource) Read(ctx context.Context, req datasource.ReadRequest, resp // set computed fields config.Host = types.StringValue(i.Raw.Credentials.Host) config.Hosts = types.ListNull(types.StringType) - if len(i.Raw.Credentials.Hosts) > 0 { + if i.Raw.Credentials.Hosts != nil && len(*i.Raw.Credentials.Hosts) > 0 { h := []attr.Value{} - for _, v := range i.Raw.Credentials.Hosts { + for _, v := range *i.Raw.Credentials.Hosts { h = append(h, types.StringValue(v)) } config.Hosts = types.ListValueMust(types.StringType, h) } - config.DatabaseName = types.StringValue(i.Raw.Credentials.Name) + config.DatabaseName = types.StringValue("") + if i.Raw.Credentials.Name != nil { + config.DatabaseName = types.StringValue(*i.Raw.Credentials.Name) + } config.Username = types.StringValue(i.Raw.Credentials.Username) config.Password = types.StringValue(i.Raw.Credentials.Password) - config.Port = types.Int64Value(int64(i.Raw.Credentials.Port)) + config.Port = types.Int64Value(0) + if i.Raw.Credentials.Port != nil { + config.Port = types.Int64Value(int64(*i.Raw.Credentials.Port)) + } config.SyslogDrainURL = types.StringValue(i.Raw.SyslogDrainUrl) config.RouteServiceURL = types.StringValue(i.Raw.RouteServiceUrl) config.URI = types.StringValue(i.Uri) diff --git a/stackit/internal/data-sources/data-services/credential/data_source.go b/stackit/internal/data-sources/data-services/credential/data_source.go index 24251da9..8fdfcce1 100644 --- a/stackit/internal/data-sources/data-services/credential/data_source.go +++ b/stackit/internal/data-sources/data-services/credential/data_source.go @@ -16,6 +16,7 @@ const ( ElasticSearch DataSourceService = "elasticsearch" LogMe DataSourceService = "logme" MariaDB DataSourceService = "mariadb" + Opensearch DataSourceService = "opensearch" Postgres DataSourceService = "postgres" Redis DataSourceService = "redis" RabbitMQ DataSourceService = "rabbitmq" @@ -29,6 +30,8 @@ func (s DataSourceService) Display() string { return "LogMe" case MariaDB: return "MariaDB" + case Opensearch: + return "Opensearch" case Postgres: return "Postgres" case Redis: @@ -63,6 +66,14 @@ func NewMariaDB() datasource.DataSource { } } +// NewOpensearch returns a new configured resource +func NewOpensearch() datasource.DataSource { + return &DataSource{ + service: Opensearch, + urls: dataservices.GetBaseURLs(dataservices.Opensearch), + } +} + // NewPostgres returns a new configured resource func NewPostgres() datasource.DataSource { return &DataSource{ @@ -126,6 +137,8 @@ func (d *DataSource) Configure(ctx context.Context, req datasource.ConfigureRequ d.client = c.LogMe case MariaDB: d.client = c.MariaDB + case Opensearch: + d.client = c.Opensearch case Postgres: d.client = c.PostgresDB case Redis: diff --git a/stackit/internal/data-sources/data-services/credential/data_source_opensearch_test.go b/stackit/internal/data-sources/data-services/credential/data_source_opensearch_test.go new file mode 100644 index 00000000..ee03434d --- /dev/null +++ b/stackit/internal/data-sources/data-services/credential/data_source_opensearch_test.go @@ -0,0 +1,77 @@ +package credential_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + + "github.com/SchwarzIT/terraform-provider-stackit/stackit" + "github.com/SchwarzIT/terraform-provider-stackit/stackit/internal/common" + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +const opensearch_cred_run_this_test = false + +func TestAcc_DataSourceOpensearchCredentialJob(t *testing.T) { + if !common.ShouldAccTestRun(opensearch_cred_run_this_test) { + t.Skip() + return + } + + name := "odjtest-" + acctest.RandStringFromCharSet(7, acctest.CharSetAlpha) + projectID := common.GetAcceptanceTestsProjectID() + + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "stackit": providerserver.NewProtocol6WithError(stackit.New("test")()), + }, + Steps: []resource.TestStep{ + // check minimal configuration + { + Config: configCredopensearch(projectID, name), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.stackit_opensearch_credential.example", "project_id", projectID), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "project_id", "data.stackit_opensearch_credential.example", "project_id"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "instance_id", "data.stackit_opensearch_credential.example", "instance_id"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "id", "data.stackit_opensearch_credential.example", "id"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "host", "data.stackit_opensearch_credential.example", "host"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "username", "data.stackit_opensearch_credential.example", "username"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "password", "data.stackit_opensearch_credential.example", "password"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "port", "data.stackit_opensearch_credential.example", "port"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "syslog_drain_url", "data.stackit_opensearch_credential.example", "syslog_drain_url"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "route_service_url", "data.stackit_opensearch_credential.example", "route_service_url"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_credential.example", "uri", "data.stackit_opensearch_credential.example", "uri"), + ), + }, + }, + }) +} + +func configCredopensearch(projectID, name string) string { + return fmt.Sprintf(` + resource "stackit_opensearch_instance" "example" { + name = "%s" + project_id = "%s" + } + + resource "stackit_opensearch_credential" "example" { + project_id = "%s" + instance_id = stackit_opensearch_instance.example.id + } + + data "stackit_opensearch_credential" "example" { + depends_on = [stackit_opensearch_credential.example] + project_id = "%s" + instance_id = stackit_opensearch_instance.example.id + id = stackit_opensearch_credential.example.id + } + `, + name, + projectID, + projectID, + projectID, + ) +} diff --git a/stackit/internal/data-sources/data-services/instance/actions.go b/stackit/internal/data-sources/data-services/instance/actions.go index 44d6367b..3136857b 100644 --- a/stackit/internal/data-sources/data-services/instance/actions.go +++ b/stackit/internal/data-sources/data-services/instance/actions.go @@ -51,7 +51,7 @@ func (d *DataSource) Read(ctx context.Context, req datasource.ReadRequest, resp // set found instance instance := list.Instances[found] - ores, err := d.client.Offerings.Get(ctx, config.ProjectID.ValueString()) + ores, err := d.client.Offerings.List(ctx, config.ProjectID.ValueString()) if agg := validate.Response(ores, err, "JSON200"); agg != nil { resp.Diagnostics.AddError("failed to get offerings", agg.Error()) return diff --git a/stackit/internal/data-sources/data-services/instance/data_source.go b/stackit/internal/data-sources/data-services/instance/data_source.go index 3e9ec531..7b6949d6 100644 --- a/stackit/internal/data-sources/data-services/instance/data_source.go +++ b/stackit/internal/data-sources/data-services/instance/data_source.go @@ -16,6 +16,7 @@ const ( ElasticSearch DataSourceService = "elasticsearch" LogMe DataSourceService = "logme" MariaDB DataSourceService = "mariadb" + Opensearch DataSourceService = "opensearch" Postgres DataSourceService = "postgres" Redis DataSourceService = "redis" RabbitMQ DataSourceService = "rabbitmq" @@ -29,6 +30,8 @@ func (s DataSourceService) Display() string { return "LogMe" case MariaDB: return "MariaDB" + case Opensearch: + return "Opensearch" case Postgres: return "Postgres" case Redis: @@ -63,6 +66,14 @@ func NewMariaDB() datasource.DataSource { } } +// NewOpensearch returns a new configured resource +func NewOpensearch() datasource.DataSource { + return &DataSource{ + service: Opensearch, + urls: dataservices.GetBaseURLs(dataservices.Opensearch), + } +} + // NewPostgres returns a new configured resource func NewPostgres() datasource.DataSource { return &DataSource{ @@ -126,6 +137,8 @@ func (d *DataSource) Configure(ctx context.Context, req datasource.ConfigureRequ d.client = c.LogMe case MariaDB: d.client = c.MariaDB + case Opensearch: + d.client = c.Opensearch case Postgres: d.client = c.PostgresDB case Redis: diff --git a/stackit/internal/data-sources/data-services/instance/data_source_opensearch_test.go b/stackit/internal/data-sources/data-services/instance/data_source_opensearch_test.go new file mode 100644 index 00000000..e7b0ec35 --- /dev/null +++ b/stackit/internal/data-sources/data-services/instance/data_source_opensearch_test.go @@ -0,0 +1,70 @@ +package instance_test + +import ( + "fmt" + "testing" + + "github.com/SchwarzIT/terraform-provider-stackit/stackit" + "github.com/SchwarzIT/terraform-provider-stackit/stackit/internal/common" + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +const opensearch_inst_run_this_test = true + +func TestAcc_DataSourceOpensearchInstanceJob(t *testing.T) { + if !common.ShouldAccTestRun(opensearch_inst_run_this_test) { + t.Skip() + return + } + + name := "odjtest-" + acctest.RandStringFromCharSet(7, acctest.CharSetAlpha) + + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "stackit": providerserver.NewProtocol6WithError(stackit.New("test")()), + }, + Steps: []resource.TestStep{ + // check minimal configuration + { + Config: configopensearch(name), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.stackit_opensearch_instance.example", "name", name), + resource.TestCheckResourceAttr("data.stackit_opensearch_instance.example", "project_id", common.GetAcceptanceTestsProjectID()), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "id", "data.stackit_opensearch_instance.example", "id"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "name", "data.stackit_opensearch_instance.example", "name"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "plan", "data.stackit_opensearch_instance.example", "plan"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "plan_id", "data.stackit_opensearch_instance.example", "plan_id"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "version", "data.stackit_opensearch_instance.example", "version"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "dashboard_url", "data.stackit_opensearch_instance.example", "dashboard_url"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "cf_guid", "data.stackit_opensearch_instance.example", "cf_guid"), + resource.TestCheckTypeSetElemAttrPair("stackit_opensearch_instance.example", "cf_space_guid", "data.stackit_opensearch_instance.example", "cf_space_guid"), + ), + }, + }, + }) +} + +func configopensearch(name string) string { + return fmt.Sprintf(` + resource "stackit_opensearch_instance" "example" { + name = "%s" + project_id = "%s" + } + + + data "stackit_opensearch_instance" "example" { + depends_on = [stackit_opensearch_instance.example] + name = "%s" + project_id = "%s" + } + + `, + name, + common.GetAcceptanceTestsProjectID(), + name, + common.GetAcceptanceTestsProjectID(), + ) +} diff --git a/stackit/internal/data-sources/kubernetes/project/schema.go b/stackit/internal/data-sources/kubernetes/project/schema.go index 3e4b8465..88cdeced 100644 --- a/stackit/internal/data-sources/kubernetes/project/schema.go +++ b/stackit/internal/data-sources/kubernetes/project/schema.go @@ -5,8 +5,10 @@ import ( "fmt" "github.com/SchwarzIT/terraform-provider-stackit/stackit/internal/common" + "github.com/SchwarzIT/terraform-provider-stackit/stackit/pkg/validate" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -30,6 +32,9 @@ func (d *DataSource) Schema(ctx context.Context, req datasource.SchemaRequest, r "project_id": schema.StringAttribute{ Description: "the project ID that SKE will be enabled in", Required: true, + Validators: []validator.String{ + validate.ProjectID(), + }, }, }, } diff --git a/stackit/internal/resources/data-services/credential/actions.go b/stackit/internal/resources/data-services/credential/actions.go index 296e6045..367d226f 100644 --- a/stackit/internal/resources/data-services/credential/actions.go +++ b/stackit/internal/resources/data-services/credential/actions.go @@ -61,7 +61,7 @@ func (r Resource) Read(ctx context.Context, req resource.ReadRequest, resp *reso } // read instance credential - res, err := r.client.Credentials.Get(ctx, cred.ProjectID.ValueString(), cred.InstanceID.ValueString(), cred.ID.ValueString()) + res, err := r.client.Credentials.GetCredentialByID(ctx, cred.ProjectID.ValueString(), cred.InstanceID.ValueString(), cred.ID.ValueString()) if agg := validate.Response(res, err, "JSON200"); agg != nil { if validate.StatusEquals(res, http.StatusNotFound) { resp.State.RemoveResource(ctx) diff --git a/stackit/internal/resources/data-services/credential/helpers.go b/stackit/internal/resources/data-services/credential/helpers.go index 0a22fa32..e1b72e3f 100644 --- a/stackit/internal/resources/data-services/credential/helpers.go +++ b/stackit/internal/resources/data-services/credential/helpers.go @@ -13,18 +13,23 @@ func (r Resource) applyClientResponse(ctx context.Context, c *Credential, cgr *c c.Host = types.StringValue(cgr.Raw.Credentials.Host) c.Hosts = types.ListNull(types.StringType) - if len(cgr.Raw.Credentials.Hosts) > 0 { + if cgr.Raw.Credentials.Hosts != nil && len(*cgr.Raw.Credentials.Hosts) > 0 { h := []attr.Value{} - for _, v := range cgr.Raw.Credentials.Hosts { + for _, v := range *cgr.Raw.Credentials.Hosts { h = append(h, types.StringValue(v)) } c.Hosts = types.ListValueMust(types.StringType, h) } - - c.DatabaseName = types.StringValue(cgr.Raw.Credentials.Name) + c.DatabaseName = types.StringValue("") + if cgr.Raw.Credentials.Name != nil { + c.DatabaseName = types.StringValue(*cgr.Raw.Credentials.Name) + } + c.Port = types.Int64Value(0) + if cgr.Raw.Credentials.Port != nil { + c.Port = types.Int64Value(int64(*cgr.Raw.Credentials.Port)) + } c.Username = types.StringValue(cgr.Raw.Credentials.Username) c.Password = types.StringValue(cgr.Raw.Credentials.Password) - c.Port = types.Int64Value(int64(cgr.Raw.Credentials.Port)) c.SyslogDrainURL = types.StringValue(cgr.Raw.SyslogDrainUrl) c.RouteServiceURL = types.StringValue(cgr.Raw.RouteServiceUrl) c.URI = types.StringValue(cgr.Uri) diff --git a/stackit/internal/resources/data-services/credential/resource.go b/stackit/internal/resources/data-services/credential/resource.go index 631eae4b..da546ce7 100644 --- a/stackit/internal/resources/data-services/credential/resource.go +++ b/stackit/internal/resources/data-services/credential/resource.go @@ -16,6 +16,7 @@ const ( ElasticSearch ResourceService = "elasticsearch" LogMe ResourceService = "logme" MariaDB ResourceService = "mariadb" + Opensearch ResourceService = "opensearch" Postgres ResourceService = "postgres" Redis ResourceService = "redis" RabbitMQ ResourceService = "rabbitmq" @@ -29,6 +30,8 @@ func (s ResourceService) Display() string { return "LogMe" case MariaDB: return "MariaDB" + case Opensearch: + return "Opensearch" case Postgres: return "Postgres" case Redis: @@ -87,6 +90,14 @@ func NewRabbitMQ() resource.Resource { } } +// NewOpensearch returns a new configured resource +func NewOpensearch() resource.Resource { + return &Resource{ + service: Opensearch, + urls: dataservices.GetBaseURLs(dataservices.Opensearch), + } +} + // Resource is the exported resource type Resource struct { client *dataservices.ClientWithResponses @@ -129,6 +140,8 @@ func (r *Resource) setClient(c *services.Services) { r.client = c.LogMe case MariaDB: r.client = c.MariaDB + case Opensearch: + r.client = c.Opensearch case Postgres: r.client = c.PostgresDB case Redis: diff --git a/stackit/internal/resources/data-services/credential/resource_opensearch_test.go b/stackit/internal/resources/data-services/credential/resource_opensearch_test.go new file mode 100644 index 00000000..db00f625 --- /dev/null +++ b/stackit/internal/resources/data-services/credential/resource_opensearch_test.go @@ -0,0 +1,89 @@ +package credential_test + +import ( + "errors" + "fmt" + "testing" + + "github.com/SchwarzIT/terraform-provider-stackit/stackit" + "github.com/SchwarzIT/terraform-provider-stackit/stackit/internal/common" + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +const opensearch_cred_run_this_test = true + +func TestAcc_ResourceOpensearchCredentialJob(t *testing.T) { + if !common.ShouldAccTestRun(opensearch_cred_run_this_test) { + t.Skip() + return + } + + name := "odjtest-" + acctest.RandStringFromCharSet(7, acctest.CharSetAlpha) + projectID := common.GetAcceptanceTestsProjectID() + + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "stackit": providerserver.NewProtocol6WithError(stackit.New("test")()), + }, + Steps: []resource.TestStep{ + // check minimal configuration + { + Config: configCredopensearch(projectID, name), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("stackit_opensearch_credential.example", "project_id", projectID), + resource.TestCheckResourceAttrSet("stackit_opensearch_credential.example", "instance_id"), + resource.TestCheckResourceAttrSet("stackit_opensearch_credential.example", "id"), + resource.TestCheckResourceAttrSet("stackit_opensearch_credential.example", "host"), + resource.TestCheckResourceAttrSet("stackit_opensearch_credential.example", "username"), + resource.TestCheckResourceAttrSet("stackit_opensearch_credential.example", "password"), + resource.TestCheckResourceAttrSet("stackit_opensearch_credential.example", "port"), + resource.TestCheckResourceAttrSet("stackit_opensearch_credential.example", "uri"), + ), + }, + // test import + { + ResourceName: "stackit_opensearch_credential.example", + ImportStateIdFunc: func(s *terraform.State) (string, error) { + r, ok := s.RootModule().Resources["stackit_opensearch_credential.example"] + if !ok { + return "", errors.New("couldn't find resource stackit_opensearch_instance.example") + } + id, ok := r.Primary.Attributes["id"] + if !ok { + return "", errors.New("couldn't find attribute id") + } + iid, ok := r.Primary.Attributes["instance_id"] + if !ok { + return "", errors.New("couldn't find attribute id") + } + + return fmt.Sprintf("%s,%s,%s", common.GetAcceptanceTestsProjectID(), iid, id), nil + }, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func configCredopensearch(project_id, name string) string { + return fmt.Sprintf(` + resource "stackit_opensearch_instance" "example" { + name = "%s" + project_id = "%s" + } + + resource "stackit_opensearch_credential" "example" { + project_id = "%s" + instance_id = stackit_opensearch_instance.example.id + } + `, + name, + project_id, + project_id, + ) +} diff --git a/stackit/internal/resources/data-services/instance/actions.go b/stackit/internal/resources/data-services/instance/actions.go index 1ce3d8b1..402552d4 100644 --- a/stackit/internal/resources/data-services/instance/actions.go +++ b/stackit/internal/resources/data-services/instance/actions.go @@ -42,8 +42,9 @@ func (r Resource) Create(ctx context.Context, req resource.CreateRequest, resp * } // handle creation - params := map[string]interface{}{ - "sgw_acl": strings.Join(acl, ","), + aclString := strings.Join(acl, ",") + params := instances.InstanceParameters{ + SgwAcl: &aclString, } body := instances.InstanceProvisionRequest{ InstanceName: plan.Name.ValueString(), @@ -168,8 +169,9 @@ func (r Resource) Update(ctx context.Context, req resource.UpdateRequest, resp * } // handle update - params := map[string]interface{}{ - "sgw_acl": strings.Join(acl, ","), + aclString := strings.Join(acl, ",") + params := instances.InstanceParameters{ + SgwAcl: &aclString, } body := instances.UpdateJSONRequestBody{ PlanID: plan.PlanID.ValueString(), diff --git a/stackit/internal/resources/data-services/instance/helpers.go b/stackit/internal/resources/data-services/instance/helpers.go index ce825096..28f42bb6 100644 --- a/stackit/internal/resources/data-services/instance/helpers.go +++ b/stackit/internal/resources/data-services/instance/helpers.go @@ -21,6 +21,8 @@ func (r Resource) getDefaultVersion() string { return "LogMe" case MariaDB: return "10.4" + case Opensearch: + return "2" case Postgres: return "11" case Redis: @@ -39,6 +41,8 @@ func (r Resource) getDefaultPlan() string { return "stackit-logme-single-small-non-ssl" case MariaDB: return "stackit-mariadb-single-small" + case Opensearch: + return "stackit-opensearch-1.4.10-single" case Postgres: return "stackit-postgresql-single-small" case Redis: @@ -54,7 +58,7 @@ func (r Resource) validate(ctx context.Context, data *Instance) error { return errors.New("at least 1 ip address must be specified for `acl`") } - res, err := r.client.Offerings.Get(ctx, data.ProjectID.ValueString()) + res, err := r.client.Offerings.List(ctx, data.ProjectID.ValueString()) if agg := validate.Response(res, err, "JSON200"); agg != nil { return agg } @@ -131,7 +135,7 @@ func (r Resource) getPlanAndVersion(ctx context.Context, projectID, instanceID s return "", "", agg } - res, err := r.client.Offerings.Get(ctx, projectID) + res, err := r.client.Offerings.List(ctx, projectID) if agg := validate.Response(res, err, "JSON200"); agg != nil { return "", "", agg } diff --git a/stackit/internal/resources/data-services/instance/resource.go b/stackit/internal/resources/data-services/instance/resource.go index f2f7b89f..427c0424 100644 --- a/stackit/internal/resources/data-services/instance/resource.go +++ b/stackit/internal/resources/data-services/instance/resource.go @@ -16,6 +16,7 @@ const ( ElasticSearch ResourceService = "elasticsearch" LogMe ResourceService = "logme" MariaDB ResourceService = "mariadb" + Opensearch ResourceService = "opensearch" Postgres ResourceService = "postgres" Redis ResourceService = "redis" RabbitMQ ResourceService = "rabbitmq" @@ -29,6 +30,8 @@ func (s ResourceService) Display() string { return "LogMe" case MariaDB: return "MariaDB" + case Opensearch: + return "Opensearch" case Postgres: return "Postgres" case Redis: @@ -87,6 +90,14 @@ func NewRabbitMQ() resource.Resource { } } +// NewOpensearch returns a new configured resource +func NewOpensearch() resource.Resource { + return &Resource{ + service: Opensearch, + urls: dataservices.GetBaseURLs(dataservices.Opensearch), + } +} + // Resource is the exported resource type Resource struct { client *dataservices.ClientWithResponses @@ -130,6 +141,8 @@ func (r *Resource) setClient(c *services.Services) { r.client = c.LogMe case MariaDB: r.client = c.MariaDB + case Opensearch: + r.client = c.Opensearch case Postgres: r.client = c.PostgresDB case Redis: diff --git a/stackit/internal/resources/data-services/instance/resource_opensearch_test.go b/stackit/internal/resources/data-services/instance/resource_opensearch_test.go new file mode 100644 index 00000000..337d2696 --- /dev/null +++ b/stackit/internal/resources/data-services/instance/resource_opensearch_test.go @@ -0,0 +1,104 @@ +package instance_test + +import ( + "errors" + "fmt" + "testing" + + "github.com/SchwarzIT/terraform-provider-stackit/stackit" + "github.com/SchwarzIT/terraform-provider-stackit/stackit/internal/common" + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +const opensearch_inst_run_this_test = false + +func TestAcc_ResourceOpensearchInstanceJob(t *testing.T) { + if !common.ShouldAccTestRun(opensearch_inst_run_this_test) { + t.Skip() + return + } + + name := "odjtest-" + acctest.RandStringFromCharSet(7, acctest.CharSetAlpha) + plan1 := "stackit-opensearch-1.4.10-single" + planID1 := "24615c29-99e8-4cc2-bcc3-ad7f45a5d46f" + plan2 := "stackit-opensearch-2.4.10-single" + planID2 := "f97a4935-0a77-4939-bfd1-33ba2e1f2b36" + version := "2" + + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "stackit": providerserver.NewProtocol6WithError(stackit.New("test")()), + }, + Steps: []resource.TestStep{ + // check minimal configuration + { + Config: configInstopensearch(name, plan1, version), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "name", name), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "project_id", common.GetAcceptanceTestsProjectID()), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "version", version), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "plan", plan1), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "plan_id", planID1), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "id"), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "dashboard_url"), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "cf_guid"), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "cf_space_guid"), + ), + }, + // check update plan + { + Config: configInstopensearch(name, plan2, version), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "name", name), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "project_id", common.GetAcceptanceTestsProjectID()), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "version", version), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "plan", plan2), + resource.TestCheckResourceAttr("stackit_opensearch_instance.example", "plan_id", planID2), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "id"), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "dashboard_url"), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "cf_guid"), + resource.TestCheckResourceAttrSet("stackit_opensearch_instance.example", "cf_space_guid"), + ), + }, + // test import + { + ResourceName: "stackit_opensearch_instance.example", + ImportStateIdFunc: func(s *terraform.State) (string, error) { + r, ok := s.RootModule().Resources["stackit_opensearch_instance.example"] + if !ok { + return "", errors.New("couldn't find resource stackit_opensearch_instance.example") + } + id, ok := r.Primary.Attributes["id"] + if !ok { + return "", errors.New("couldn't find attribute id") + } + + return fmt.Sprintf("%s,%s", common.GetAcceptanceTestsProjectID(), id), nil + }, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func configInstopensearch(name, plan, version string) string { + return fmt.Sprintf(` + resource "stackit_opensearch_instance" "example" { + name = "%s" + project_id = "%s" + version = "%s" + plan = "%s" + } + + `, + name, + common.GetAcceptanceTestsProjectID(), + version, + plan, + ) +} diff --git a/stackit/internal/resources/kubernetes/cluster/schema.go b/stackit/internal/resources/kubernetes/cluster/schema.go index 362feb63..22aea877 100644 --- a/stackit/internal/resources/kubernetes/cluster/schema.go +++ b/stackit/internal/resources/kubernetes/cluster/schema.go @@ -9,7 +9,6 @@ import ( "github.com/SchwarzIT/terraform-provider-stackit/stackit/internal/common" "github.com/SchwarzIT/terraform-provider-stackit/stackit/pkg/validate" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" - "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" @@ -111,14 +110,6 @@ func (r *Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp stringplanmodifier.RequiresReplace(), }, }, - "project_id": schema.StringAttribute{ - Description: "this attribure is deprecated. please remove it from your terraform config and use `kubernetes_project_id` instead", - Optional: true, - DeprecationMessage: "this attribure is deprecated. please remove it from your terraform config and use `kubernetes_project_id` instead", - Validators: []validator.String{ - validate.ProjectID(), - }, - }, "kubernetes_project_id": schema.StringAttribute{ Description: "The ID of a `stackit_kubernetes_project` resource", Required: true, @@ -126,24 +117,7 @@ func (r *Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp validate.ProjectID(), }, PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplaceIf(func(ctx context.Context, sr planmodifier.StringRequest, rrifr *stringplanmodifier.RequiresReplaceIfFuncResponse) { - if sr.StateValue.IsNull() || sr.StateValue.IsUnknown() { - var s *string - diags := sr.State.GetAttribute(ctx, path.Root("project_id"), &s) - rrifr.Diagnostics.Append(diags...) - if rrifr.Diagnostics.HasError() { - rrifr.RequiresReplace = true - return - } - if s != nil && *s == sr.ConfigValue.ValueString() { - rrifr.RequiresReplace = false - return - } - } else if sr.StateValue.ValueString() != sr.ConfigValue.ValueString() { - rrifr.RequiresReplace = true - return - } - }, "require modification if project ID has been modified", "require modification if project ID has been modified"), + stringplanmodifier.RequiresReplace(), }, }, "kubernetes_version": schema.StringAttribute{ diff --git a/stackit/internal/resources/kubernetes/project/schema.go b/stackit/internal/resources/kubernetes/project/schema.go index e224680e..1103e6de 100644 --- a/stackit/internal/resources/kubernetes/project/schema.go +++ b/stackit/internal/resources/kubernetes/project/schema.go @@ -45,6 +45,9 @@ func (r *Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp Validators: []validator.String{ validate.ProjectID(), }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, }, "timeouts": common.Timeouts(ctx, timeouts.Opts{ diff --git a/stackit/internal/resources/object-storage/project/schema.go b/stackit/internal/resources/object-storage/project/schema.go index c1bca0d6..be68cf24 100644 --- a/stackit/internal/resources/object-storage/project/schema.go +++ b/stackit/internal/resources/object-storage/project/schema.go @@ -5,10 +5,12 @@ import ( "fmt" "github.com/SchwarzIT/terraform-provider-stackit/stackit/internal/common" + "github.com/SchwarzIT/terraform-provider-stackit/stackit/pkg/validate" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -36,6 +38,12 @@ func (r *Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp "project_id": schema.StringAttribute{ Description: "the project ID that Object Storage will be enabled in", Required: true, + Validators: []validator.String{ + validate.ProjectID(), + }, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, }, }, } diff --git a/stackit/provider.go b/stackit/provider.go index a4992de9..f893441a 100644 --- a/stackit/provider.go +++ b/stackit/provider.go @@ -155,12 +155,14 @@ func (p *StackitProvider) Resources(_ context.Context) []func() resource.Resourc resourceDataServicesCredential.NewLogMe, resourceDataServicesCredential.NewMariaDB, resourceDataServicesCredential.NewPostgres, + resourceDataServicesCredential.NewOpensearch, resourceDataServicesCredential.NewRabbitMQ, resourceDataServicesCredential.NewRedis, resourceDataServicesInstance.NewElasticSearch, resourceDataServicesInstance.NewLogMe, resourceDataServicesInstance.NewMariaDB, resourceDataServicesInstance.NewPostgres, + resourceDataServicesInstance.NewOpensearch, resourceDataServicesInstance.NewRabbitMQ, resourceDataServicesInstance.NewRedis, resourceKubernetesCluster.New, @@ -185,12 +187,14 @@ func (p *StackitProvider) DataSources(context.Context) []func() datasource.DataS dataDataServicesCredential.NewElasticSearch, dataDataServicesCredential.NewLogMe, dataDataServicesCredential.NewMariaDB, + dataDataServicesCredential.NewOpensearch, dataDataServicesCredential.NewPostgres, dataDataServicesCredential.NewRabbitMQ, dataDataServicesCredential.NewRedis, dataDataServicesInstance.NewElasticSearch, dataDataServicesInstance.NewLogMe, dataDataServicesInstance.NewMariaDB, + dataDataServicesInstance.NewOpensearch, dataDataServicesInstance.NewPostgres, dataDataServicesInstance.NewRabbitMQ, dataDataServicesInstance.NewRedis,