diff --git a/docs/resources/postgresflexalpha_instance.md b/docs/resources/postgresflexalpha_instance.md
index 944425b5..60d4f2f4 100644
--- a/docs/resources/postgresflexalpha_instance.md
+++ b/docs/resources/postgresflexalpha_instance.md
@@ -44,13 +44,13 @@ import {
- `backup_schedule` (String)
- `encryption` (Attributes) The encryption block. (see [below for nested schema](#nestedatt--encryption))
-- `flavor` (Attributes) (see [below for nested schema](#nestedatt--flavor))
+- `flavor` (Attributes) The block that defines the flavor data. (see [below for nested schema](#nestedatt--flavor))
- `name` (String) Instance name.
-- `network` (Attributes) (see [below for nested schema](#nestedatt--network))
+- `network` (Attributes) The network block configuration. (see [below for nested schema](#nestedatt--network))
- `project_id` (String) STACKIT project ID to which the instance is associated.
- `replicas` (Number)
- `storage` (Attributes) (see [below for nested schema](#nestedatt--storage))
-- `version` (String)
+- `version` (String) The database version used.
### Optional
@@ -67,9 +67,9 @@ import {
Required:
- `key_id` (String) Key ID of the encryption key.
-- `key_version` (String)
-- `keyring_id` (String)
-- `service_account` (String)
+- `key_version` (String) Key version of the encryption key.
+- `keyring_id` (String) KeyRing ID of the encryption key.
+- `service_account` (String) The service account ID of the service account.
@@ -77,16 +77,17 @@ Required:
Required:
-- `cpu` (Number)
-- `ram` (Number)
+- `cpu` (Number) The CPU count of the flavor.
+- `ram` (Number) The RAM count of the flavor.
Optional:
-- `id` (String)
+- `id` (String) The ID of the flavor.
+- `node_type` (String) The node type of the flavor. (Single or Replicas)
Read-Only:
-- `description` (String)
+- `description` (String) The flavor detailed flavor name.
@@ -98,9 +99,9 @@ Required:
Optional:
-- `access_scope` (String)
-- `instance_address` (String)
-- `router_address` (String)
+- `access_scope` (String) The access scope. (Either SNA or PUBLIC)
+- `instance_address` (String) The returned instance address.
+- `router_address` (String) The returned router address.
@@ -108,5 +109,5 @@ Optional:
Required:
-- `class` (String)
-- `size` (Number)
+- `class` (String) The storage class used.
+- `size` (Number) The disk size of the storage.
diff --git a/sample/main.tf b/sample/main.tf
index 64cbbe25..8f791797 100644
--- a/sample/main.tf
+++ b/sample/main.tf
@@ -1,11 +1 @@
# see other files
-
-data "stackitprivatepreview_sqlserverflexalpha_instance" "existing" {
- project_id = var.project_id
- instance_id = "b31575e9-9dbd-4ff6-b341-82d89c34f14f"
- region = "eu01"
-}
-
-output "myinstance" {
- value = data.stackitprivatepreview_sqlserverflexalpha_instance.existing
-}
diff --git a/sample/postresql.tf b/sample/postresql.tf
index 39e50e7d..64f86884 100644
--- a/sample/postresql.tf
+++ b/sample/postresql.tf
@@ -6,7 +6,7 @@ resource "stackitprivatepreview_postgresflexalpha_instance" "ptlsdbsrv" {
cpu = 2
ram = 4
}
- replicas = 3
+ replicas = 1
storage = {
class = "premium-perf2-stackit"
size = 5
@@ -26,12 +26,12 @@ resource "stackitprivatepreview_postgresflexalpha_instance" "ptlsdbsrv" {
version = 14
}
-data "stackitprivatepreview_postgresflexalpha_instance" "datapsql" {
- project_id = var.project_id
- instance_id = "fdb6573e-2dea-4e1d-a638-9157cf90c3ba"
- region = "eu01"
-}
-
-output "sample_psqlinstance" {
- value = data.stackitprivatepreview_postgresflexalpha_instance.datapsql
-}
+# data "stackitprivatepreview_postgresflexalpha_instance" "datapsql" {
+# project_id = var.project_id
+# instance_id = "fdb6573e-2dea-4e1d-a638-9157cf90c3ba"
+# region = "eu01"
+# }
+#
+# output "sample_psqlinstance" {
+# value = data.stackitprivatepreview_postgresflexalpha_instance.datapsql
+# }
diff --git a/sample/sqlserver.tf b/sample/sqlserver.tf
index 3c33a221..a333c0cc 100644
--- a/sample/sqlserver.tf
+++ b/sample/sqlserver.tf
@@ -88,3 +88,13 @@ resource "stackitprivatepreview_sqlserverflexalpha_instance" "ptlsdbsqlsrv" {
# instance_id = var.instance_id
# region = "eu01"
# }
+
+# data "stackitprivatepreview_sqlserverflexalpha_instance" "existing" {
+# project_id = var.project_id
+# instance_id = "b31575e9-9dbd-4ff6-b341-82d89c34f14f"
+# region = "eu01"
+# }
+#
+# output "myinstance" {
+# value = data.stackitprivatepreview_sqlserverflexalpha_instance.existing
+# }
diff --git a/sample/user.tf b/sample/user.tf
index 2ebbb040..1671cc6d 100644
--- a/sample/user.tf
+++ b/sample/user.tf
@@ -1,12 +1,12 @@
data "stackitprivatepreview_postgresflexalpha_user" "example" {
project_id = stackitprivatepreview_postgresflexalpha_instance.ptlsdbsrv.project_id
- instance_id = stackitprivatepreview_postgresflexalpha_instance.ptlsdbsrv.id
+ instance_id = stackitprivatepreview_postgresflexalpha_instance.ptlsdbsrv.instance_id
user_id = 1
}
resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbuser" {
project_id = stackitprivatepreview_postgresflexalpha_instance.ptlsdbsrv.project_id
- instance_id = stackitprivatepreview_postgresflexalpha_instance.ptlsdbsrv.id
+ instance_id = stackitprivatepreview_postgresflexalpha_instance.ptlsdbsrv.instance_id
username = var.db_username
# roles = ["createdb", "login", "createrole"]
roles = ["createdb", "login"]
@@ -14,7 +14,7 @@ resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbuser" {
resource "stackitprivatepreview_sqlserverflexalpha_user" "ptlsdbuser" {
project_id = stackitprivatepreview_sqlserverflexalpha_instance.ptlsdbsqlsrv.project_id
- instance_id = stackitprivatepreview_sqlserverflexalpha_instance.ptlsdbsqlsrv.id
+ instance_id = stackitprivatepreview_sqlserverflexalpha_instance.ptlsdbsqlsrv.instance_id
username = var.db_username
roles = ["login"]
}
diff --git a/stackit/internal/services/postgresflexalpha/database/datasource.go b/stackit/internal/services/postgresflexalpha/database/datasource.go
index 3eecc35f..e1180c0f 100644
--- a/stackit/internal/services/postgresflexalpha/database/datasource.go
+++ b/stackit/internal/services/postgresflexalpha/database/datasource.go
@@ -127,7 +127,6 @@ func (r *databaseDataSource) Schema(_ context.Context, _ datasource.SchemaReques
// Read refreshes the Terraform state with the latest data.
func (r *databaseDataSource) Read(
ctx context.Context,
- // TODO - make it pointer
req datasource.ReadRequest,
resp *datasource.ReadResponse,
) { // nolint:gocritic // function signature required by Terraform
diff --git a/stackit/internal/services/postgresflexalpha/database/resource.go b/stackit/internal/services/postgresflexalpha/database/resource.go
index 983bb7c2..c75b7702 100644
--- a/stackit/internal/services/postgresflexalpha/database/resource.go
+++ b/stackit/internal/services/postgresflexalpha/database/resource.go
@@ -58,7 +58,6 @@ type databaseResource struct {
// Use the modifier to set the effective region in the current plan.
func (r *databaseResource) ModifyPlan(
ctx context.Context,
- // TODO - make it pointer
req resource.ModifyPlanRequest,
resp *resource.ModifyPlanResponse,
) { // nolint:gocritic // function signature required by Terraform
@@ -201,7 +200,6 @@ func (r *databaseResource) Schema(_ context.Context, _ resource.SchemaRequest, r
// Create creates the resource and sets the initial Terraform state.
func (r *databaseResource) Create(
ctx context.Context,
- // TODO - make it pointer
req resource.CreateRequest,
resp *resource.CreateResponse,
) { // nolint:gocritic // function signature required by Terraform
@@ -292,7 +290,6 @@ func (r *databaseResource) Create(
// Read refreshes the Terraform state with the latest data.
func (r *databaseResource) Read(
ctx context.Context,
- // TODO - make it pointer
req resource.ReadRequest,
resp *resource.ReadResponse,
) { // nolint:gocritic // function signature required by Terraform
diff --git a/stackit/internal/services/postgresflexalpha/flavor_test.go b/stackit/internal/services/postgresflexalpha/flavor_test.go
new file mode 100644
index 00000000..ecdedb8b
--- /dev/null
+++ b/stackit/internal/services/postgresflexalpha/flavor_test.go
@@ -0,0 +1,514 @@
+package postgresflex
+
+import (
+ "context"
+ "reflect"
+ "testing"
+
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+ "github.com/hashicorp/terraform-plugin-go/tftypes"
+)
+
+func TestFlavorType_Equal(t1 *testing.T) {
+ type fields struct {
+ ObjectType basetypes.ObjectType
+ }
+ type args struct {
+ o attr.Type
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t1.Run(tt.name, func(t1 *testing.T) {
+ t := FlavorType{
+ ObjectType: tt.fields.ObjectType,
+ }
+ if got := t.Equal(tt.args.o); got != tt.want {
+ t1.Errorf("Equal() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorType_String(t1 *testing.T) {
+ type fields struct {
+ ObjectType basetypes.ObjectType
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want string
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t1.Run(tt.name, func(t1 *testing.T) {
+ t := FlavorType{
+ ObjectType: tt.fields.ObjectType,
+ }
+ if got := t.String(); got != tt.want {
+ t1.Errorf("String() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorType_ValueFromObject(t1 *testing.T) {
+ type fields struct {
+ ObjectType basetypes.ObjectType
+ }
+ type args struct {
+ in0 context.Context
+ in basetypes.ObjectValue
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want basetypes.ObjectValuable
+ want1 diag.Diagnostics
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t1.Run(tt.name, func(t1 *testing.T) {
+ t := FlavorType{
+ ObjectType: tt.fields.ObjectType,
+ }
+ got, got1 := t.ValueFromObject(tt.args.in0, tt.args.in)
+ if !reflect.DeepEqual(got, tt.want) {
+ t1.Errorf("ValueFromObject() got = %v, want %v", got, tt.want)
+ }
+ if !reflect.DeepEqual(got1, tt.want1) {
+ t1.Errorf("ValueFromObject() got1 = %v, want %v", got1, tt.want1)
+ }
+ })
+ }
+}
+
+func TestFlavorType_ValueFromTerraform(t1 *testing.T) {
+ type fields struct {
+ ObjectType basetypes.ObjectType
+ }
+ type args struct {
+ ctx context.Context
+ in tftypes.Value
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want attr.Value
+ wantErr bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t1.Run(tt.name, func(t1 *testing.T) {
+ t := FlavorType{
+ ObjectType: tt.fields.ObjectType,
+ }
+ got, err := t.ValueFromTerraform(tt.args.ctx, tt.args.in)
+ if (err != nil) != tt.wantErr {
+ t1.Errorf("ValueFromTerraform() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t1.Errorf("ValueFromTerraform() got = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorType_ValueType(t1 *testing.T) {
+ type fields struct {
+ ObjectType basetypes.ObjectType
+ }
+ type args struct {
+ in0 context.Context
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want attr.Value
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t1.Run(tt.name, func(t1 *testing.T) {
+ t := FlavorType{
+ ObjectType: tt.fields.ObjectType,
+ }
+ if got := t.ValueType(tt.args.in0); !reflect.DeepEqual(got, tt.want) {
+ t1.Errorf("ValueType() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_AttributeTypes(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ type args struct {
+ in0 context.Context
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want map[string]attr.Type
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ if got := v.AttributeTypes(tt.args.in0); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("AttributeTypes() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_Equal(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ type args struct {
+ o attr.Value
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ if got := v.Equal(tt.args.o); got != tt.want {
+ t.Errorf("Equal() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_IsNull(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ if got := v.IsNull(); got != tt.want {
+ t.Errorf("IsNull() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_IsUnknown(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ if got := v.IsUnknown(); got != tt.want {
+ t.Errorf("IsUnknown() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_String(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ tests := []struct {
+ name string
+ fields fields
+ want string
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ if got := v.String(); got != tt.want {
+ t.Errorf("String() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_ToObjectValue(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ type args struct {
+ in0 context.Context
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want basetypes.ObjectValue
+ want1 diag.Diagnostics
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ got, got1 := v.ToObjectValue(tt.args.in0)
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("ToObjectValue() got = %v, want %v", got, tt.want)
+ }
+ if !reflect.DeepEqual(got1, tt.want1) {
+ t.Errorf("ToObjectValue() got1 = %v, want %v", got1, tt.want1)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_ToTerraformValue(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ type args struct {
+ ctx context.Context
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want tftypes.Value
+ wantErr bool
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ got, err := v.ToTerraformValue(tt.args.ctx)
+ if (err != nil) != tt.wantErr {
+ t.Errorf("ToTerraformValue() error = %v, wantErr %v", err, tt.wantErr)
+ return
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("ToTerraformValue() got = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestFlavorValue_Type(t *testing.T) {
+ type fields struct {
+ Cpu basetypes.Int64Value
+ Description basetypes.StringValue
+ Id basetypes.StringValue
+ Ram basetypes.Int64Value
+ state attr.ValueState
+ }
+ type args struct {
+ ctx context.Context
+ }
+ tests := []struct {
+ name string
+ fields fields
+ args args
+ want attr.Type
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ v := FlavorValue{
+ Cpu: tt.fields.Cpu,
+ Description: tt.fields.Description,
+ Id: tt.fields.Id,
+ Ram: tt.fields.Ram,
+ state: tt.fields.state,
+ }
+ if got := v.Type(tt.args.ctx); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("Type() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestNewFlavorValue(t *testing.T) {
+ type args struct {
+ attributeTypes map[string]attr.Type
+ attributes map[string]attr.Value
+ }
+ tests := []struct {
+ name string
+ args args
+ want FlavorValue
+ want1 diag.Diagnostics
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ got, got1 := NewFlavorValue(tt.args.attributeTypes, tt.args.attributes)
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewFlavorValue() got = %v, want %v", got, tt.want)
+ }
+ if !reflect.DeepEqual(got1, tt.want1) {
+ t.Errorf("NewFlavorValue() got1 = %v, want %v", got1, tt.want1)
+ }
+ })
+ }
+}
+
+func TestNewFlavorValueMust(t *testing.T) {
+ type args struct {
+ attributeTypes map[string]attr.Type
+ attributes map[string]attr.Value
+ }
+ tests := []struct {
+ name string
+ args args
+ want FlavorValue
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := NewFlavorValueMust(tt.args.attributeTypes, tt.args.attributes); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewFlavorValueMust() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestNewFlavorValueNull(t *testing.T) {
+ tests := []struct {
+ name string
+ want FlavorValue
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := NewFlavorValueNull(); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewFlavorValueNull() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
+
+func TestNewFlavorValueUnknown(t *testing.T) {
+ tests := []struct {
+ name string
+ want FlavorValue
+ }{
+ // TODO: Add test cases.
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := NewFlavorValueUnknown(); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewFlavorValueUnknown() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/stackit/internal/services/postgresflexalpha/instance/functions.go b/stackit/internal/services/postgresflexalpha/instance/functions.go
index abb2288e..7fd976e9 100644
--- a/stackit/internal/services/postgresflexalpha/instance/functions.go
+++ b/stackit/internal/services/postgresflexalpha/instance/functions.go
@@ -101,7 +101,7 @@ func mapFields(
}
var flavorValues map[string]attr.Value
- if instance.FlavorId == nil {
+ if instance.FlavorId == nil || *instance.FlavorId == "" {
return fmt.Errorf("instance has no flavor id")
}
if !flavor.Id.IsUnknown() && !flavor.Id.IsNull() {
@@ -110,12 +110,28 @@ func mapFields(
}
}
if model.Flavor.IsNull() || model.Flavor.IsUnknown() {
+ var nodeType string
+ if flavor.NodeType.IsUnknown() || flavor.NodeType.IsNull() {
+ if instance.Replicas == nil {
+ return fmt.Errorf("instance has no replicas setting")
+ }
+ switch *instance.Replicas {
+ case 1:
+ nodeType = "Single"
+ case 3:
+ nodeType = "Replicas"
+ default:
+ return fmt.Errorf("could not determine replicas settings")
+ }
+ } else {
+ nodeType = flavor.NodeType.ValueString()
+ }
flavorValues = map[string]attr.Value{
"id": flavor.Id,
"description": flavor.Description,
"cpu": flavor.CPU,
"ram": flavor.RAM,
- "node_type": flavor.NodeType,
+ "node_type": types.StringValue(nodeType),
}
} else {
flavorValues = model.Flavor.Attributes()
@@ -143,6 +159,11 @@ func mapFields(
return fmt.Errorf("creating storage: %w", core.DiagsToError(diags))
}
+ if instance.Replicas == nil {
+ diags.AddError("error mapping fields", "replicas is nil")
+ return fmt.Errorf("replicas is nil")
+ }
+
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, instanceId)
model.InstanceId = types.StringValue(instanceId)
model.Name = types.StringPointerValue(instance.Name)
@@ -159,7 +180,13 @@ func mapFields(
return nil
}
-func toCreatePayload(model *Model, flavor *flavorModel, storage *storageModel, enc *encryptionModel, net *networkModel) (*postgresflex.CreateInstanceRequestPayload, error) {
+func toCreatePayload(
+ model *Model,
+ flavor *flavorModel,
+ storage *storageModel,
+ enc *encryptionModel,
+ net *networkModel,
+) (*postgresflex.CreateInstanceRequestPayload, error) {
if model == nil {
return nil, fmt.Errorf("nil model")
}
@@ -170,10 +197,13 @@ func toCreatePayload(model *Model, flavor *flavorModel, storage *storageModel, e
return nil, fmt.Errorf("nil storage")
}
- if model.Replicas.ValueInt64() > math.MaxInt32 {
- return nil, fmt.Errorf("replica count too big: %d", model.Replicas.ValueInt64())
+ var replVal int32
+ if !model.Replicas.IsNull() && !model.Replicas.IsUnknown() {
+ if model.Replicas.ValueInt64() > math.MaxInt32 {
+ return nil, fmt.Errorf("replica count too big: %d", model.Replicas.ValueInt64())
+ }
+ replVal = int32(model.Replicas.ValueInt64()) // nolint:gosec // check is performed above
}
- replVal := int32(model.Replicas.ValueInt64()) // nolint:gosec // check is performed above
storagePayload := &postgresflex.CreateInstanceRequestPayloadGetStorageArgType{
PerformanceClass: conversion.StringValueToPointer(storage.Class),
@@ -197,6 +227,10 @@ func toCreatePayload(model *Model, flavor *flavorModel, storage *storageModel, e
}
}
+ if len(aclElements) < 1 {
+ return nil, fmt.Errorf("no acl elements found")
+ }
+
networkPayload := &postgresflex.CreateInstanceRequestPayloadGetNetworkArgType{}
if net != nil {
networkPayload = &postgresflex.CreateInstanceRequestPayloadGetNetworkArgType{
@@ -205,6 +239,19 @@ func toCreatePayload(model *Model, flavor *flavorModel, storage *storageModel, e
}
}
+ if model.Replicas.IsNull() || model.Replicas.IsUnknown() {
+ if !flavor.NodeType.IsNull() && !flavor.NodeType.IsUnknown() {
+ switch strings.ToLower(flavor.NodeType.ValueString()) {
+ case "single":
+ replVal = int32(1)
+ case "replica":
+ replVal = int32(3)
+ default:
+ return nil, fmt.Errorf("flavor has invalid replica attribute")
+ }
+ }
+ }
+
return &postgresflex.CreateInstanceRequestPayload{
BackupSchedule: conversion.StringValueToPointer(model.BackupSchedule),
FlavorId: conversion.StringValueToPointer(flavor.Id),
@@ -259,10 +306,22 @@ func loadFlavorId(ctx context.Context, client postgresflexClient, model *Model,
if ram == nil {
return fmt.Errorf("nil RAM")
}
+
nodeType := conversion.StringValueToPointer(flavor.NodeType)
if nodeType == nil {
- return fmt.Errorf("nil NodeType")
+ if model.Replicas.IsNull() || model.Replicas.IsUnknown() {
+ return fmt.Errorf("nil NodeType")
+ }
+ switch model.Replicas.ValueInt64() {
+ case 1:
+ nodeType = conversion.StringValueToPointer(types.StringValue("Single"))
+ case 3:
+ nodeType = conversion.StringValueToPointer(types.StringValue("Replicas"))
+ default:
+ return fmt.Errorf("unknown Replicas value: %d", model.Replicas.ValueInt64())
+ }
}
+
storageClass := conversion.StringValueToPointer(storage.Class)
if storageClass == nil {
return fmt.Errorf("nil StorageClass")
diff --git a/stackit/internal/services/postgresflexalpha/instance/models.go b/stackit/internal/services/postgresflexalpha/instance/models.go
new file mode 100644
index 00000000..1e550135
--- /dev/null
+++ b/stackit/internal/services/postgresflexalpha/instance/models.go
@@ -0,0 +1,80 @@
+package postgresflexalpha
+
+import (
+ "github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
+)
+
+type Model struct {
+ Id types.String `tfsdk:"id"` // needed by TF
+ InstanceId types.String `tfsdk:"instance_id"`
+ ProjectId types.String `tfsdk:"project_id"`
+ Name types.String `tfsdk:"name"`
+ BackupSchedule types.String `tfsdk:"backup_schedule"`
+ Flavor types.Object `tfsdk:"flavor"`
+ Replicas types.Int64 `tfsdk:"replicas"`
+ Storage types.Object `tfsdk:"storage"`
+ Version types.String `tfsdk:"version"`
+ Region types.String `tfsdk:"region"`
+ Encryption types.Object `tfsdk:"encryption"`
+ Network types.Object `tfsdk:"network"`
+}
+
+type encryptionModel struct {
+ KeyRingId types.String `tfsdk:"keyring_id"`
+ KeyId types.String `tfsdk:"key_id"`
+ KeyVersion types.String `tfsdk:"key_version"`
+ ServiceAccount types.String `tfsdk:"service_account"`
+}
+
+var encryptionTypes = map[string]attr.Type{
+ "keyring_id": basetypes.StringType{},
+ "key_id": basetypes.StringType{},
+ "key_version": basetypes.StringType{},
+ "service_account": basetypes.StringType{},
+}
+
+type networkModel struct {
+ ACL types.List `tfsdk:"acl"`
+ AccessScope types.String `tfsdk:"access_scope"`
+ InstanceAddress types.String `tfsdk:"instance_address"`
+ RouterAddress types.String `tfsdk:"router_address"`
+}
+
+var networkTypes = map[string]attr.Type{
+ "acl": basetypes.ListType{ElemType: types.StringType},
+ "access_scope": basetypes.StringType{},
+ "instance_address": basetypes.StringType{},
+ "router_address": basetypes.StringType{},
+}
+
+// Struct corresponding to Model.Flavor
+type flavorModel struct {
+ Id types.String `tfsdk:"id"`
+ Description types.String `tfsdk:"description"`
+ CPU types.Int64 `tfsdk:"cpu"`
+ RAM types.Int64 `tfsdk:"ram"`
+ NodeType types.String `tfsdk:"node_type"`
+}
+
+// Types corresponding to flavorModel
+var flavorTypes = map[string]attr.Type{
+ "id": basetypes.StringType{},
+ "description": basetypes.StringType{},
+ "cpu": basetypes.Int64Type{},
+ "ram": basetypes.Int64Type{},
+ "node_type": basetypes.StringType{},
+}
+
+// Struct corresponding to Model.Storage
+type storageModel struct {
+ Class types.String `tfsdk:"class"`
+ Size types.Int64 `tfsdk:"size"`
+}
+
+// Types corresponding to storageModel
+var storageTypes = map[string]attr.Type{
+ "class": basetypes.StringType{},
+ "size": basetypes.Int64Type{},
+}
diff --git a/stackit/internal/services/postgresflexalpha/instance/resource.go b/stackit/internal/services/postgresflexalpha/instance/resource.go
index 7d5f4ccb..1340bd07 100644
--- a/stackit/internal/services/postgresflexalpha/instance/resource.go
+++ b/stackit/internal/services/postgresflexalpha/instance/resource.go
@@ -8,6 +8,7 @@ import (
"strings"
"time"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
"github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha/wait"
postgresflexUtils "github.com/mhenselin/terraform-provider-stackitprivatepreview/stackit/internal/services/postgresflexalpha/utils"
@@ -35,85 +36,13 @@ import (
// Ensure the implementation satisfies the expected interfaces.
var (
- _ resource.Resource = &instanceResource{}
- _ resource.ResourceWithConfigure = &instanceResource{}
- _ resource.ResourceWithImportState = &instanceResource{}
- _ resource.ResourceWithModifyPlan = &instanceResource{}
+ _ resource.Resource = &instanceResource{}
+ _ resource.ResourceWithConfigure = &instanceResource{}
+ _ resource.ResourceWithImportState = &instanceResource{}
+ _ resource.ResourceWithModifyPlan = &instanceResource{}
+ _ resource.ResourceWithValidateConfig = &instanceResource{}
)
-type Model struct {
- Id types.String `tfsdk:"id"` // needed by TF
- InstanceId types.String `tfsdk:"instance_id"`
- ProjectId types.String `tfsdk:"project_id"`
- Name types.String `tfsdk:"name"`
- BackupSchedule types.String `tfsdk:"backup_schedule"`
- Flavor types.Object `tfsdk:"flavor"`
- Replicas types.Int64 `tfsdk:"replicas"`
- Storage types.Object `tfsdk:"storage"`
- Version types.String `tfsdk:"version"`
- Region types.String `tfsdk:"region"`
- Encryption types.Object `tfsdk:"encryption"`
- Network types.Object `tfsdk:"network"`
-}
-
-type encryptionModel struct {
- KeyRingId types.String `tfsdk:"keyring_id"`
- KeyId types.String `tfsdk:"key_id"`
- KeyVersion types.String `tfsdk:"key_version"`
- ServiceAccount types.String `tfsdk:"service_account"`
-}
-
-var encryptionTypes = map[string]attr.Type{
- "keyring_id": basetypes.StringType{},
- "key_id": basetypes.StringType{},
- "key_version": basetypes.StringType{},
- "service_account": basetypes.StringType{},
-}
-
-type networkModel struct {
- ACL types.List `tfsdk:"acl"`
- AccessScope types.String `tfsdk:"access_scope"`
- InstanceAddress types.String `tfsdk:"instance_address"`
- RouterAddress types.String `tfsdk:"router_address"`
-}
-
-var networkTypes = map[string]attr.Type{
- "acl": basetypes.ListType{ElemType: types.StringType},
- "access_scope": basetypes.StringType{},
- "instance_address": basetypes.StringType{},
- "router_address": basetypes.StringType{},
-}
-
-// Struct corresponding to Model.Flavor
-type flavorModel struct {
- Id types.String `tfsdk:"id"`
- Description types.String `tfsdk:"description"`
- CPU types.Int64 `tfsdk:"cpu"`
- RAM types.Int64 `tfsdk:"ram"`
- NodeType types.String `tfsdk:"node_type"`
-}
-
-// Types corresponding to flavorModel
-var flavorTypes = map[string]attr.Type{
- "id": basetypes.StringType{},
- "description": basetypes.StringType{},
- "cpu": basetypes.Int64Type{},
- "ram": basetypes.Int64Type{},
- "node_type": basetypes.StringType{},
-}
-
-// Struct corresponding to Model.Storage
-type storageModel struct {
- Class types.String `tfsdk:"class"`
- Size types.Int64 `tfsdk:"size"`
-}
-
-// Types corresponding to storageModel
-var storageTypes = map[string]attr.Type{
- "class": basetypes.StringType{},
- "size": basetypes.Int64Type{},
-}
-
// NewInstanceResource is a helper function to simplify the provider implementation.
func NewInstanceResource() resource.Resource {
return &instanceResource{}
@@ -125,6 +54,24 @@ type instanceResource struct {
providerData core.ProviderData
}
+func (r *instanceResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) {
+ var data Model
+ resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ if data.Replicas.IsNull() || data.Replicas.IsUnknown() {
+ resp.Diagnostics.AddAttributeWarning(
+ path.Root("replicas"),
+ "Missing Attribute Configuration",
+ "Expected replicas to be configured. "+
+ "The resource may return unexpected results.",
+ )
+ }
+}
+
// ModifyPlan implements resource.ResourceWithModifyPlan.
// Use the modifier to set the effective region in the current plan.
func (r *instanceResource) ModifyPlan(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) { // nolint:gocritic // function signature required by Terraform
@@ -179,18 +126,35 @@ func (r *instanceResource) Configure(ctx context.Context, req resource.Configure
// Schema defines the schema for the resource.
func (r *instanceResource) Schema(_ context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
descriptions := map[string]string{
- "backup_schedule": "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
- "main": "Postgres Flex instance resource schema. Must have a `region` specified in the provider configuration.",
- "id": "Terraform's internal resource ID. It is structured as \"`project_id`,`region`,`instance_id`\".",
- "instance_id": "ID of the PostgresFlex instance.",
- "project_id": "STACKIT project ID to which the instance is associated.",
- "name": "Instance name.",
- "acl": "The Access Control List (ACL) for the PostgresFlex instance.",
- "region": "The resource region. If not defined, the provider region is used.",
- "encryption": "The encryption block.",
- "key_id": "Key ID of the encryption key.",
+ "main": "Postgres Flex instance resource schema. Must have a `region` specified in the provider configuration.",
+ "id": "Terraform's internal resource ID. It is structured as \"`project_id`,`region`,`instance_id`\".",
+ "instance_id": "ID of the PostgresFlex instance.",
+ "project_id": "STACKIT project ID to which the instance is associated.",
+ "name": "Instance name.",
+ "backup_schedule": "The schedule for on what time and how often the database backup will be created. The schedule is written as a cron schedule.",
+ "flavor": "The block that defines the flavor data.",
+ "flavor_id": "The ID of the flavor.",
+ "flavor_description": "The flavor detailed flavor name.",
+ "flavor_cpu": "The CPU count of the flavor.",
+ "flavor_ram": "The RAM count of the flavor.",
+ "flavor_node_type": "The node type of the flavor. (Single or Replicas)",
+ "replicas": "The number of replicas.",
+ "storage": "The block of the storage configuration.",
+ "storage_class": "The storage class used.",
+ "storage_size": "The disk size of the storage.",
+ "region": "The resource region. If not defined, the provider region is used.",
+ "version": "The database version used.",
+ "encryption": "The encryption block.",
+ "keyring_id": "KeyRing ID of the encryption key.",
+ "key_id": "Key ID of the encryption key.",
+ "key_version": "Key version of the encryption key.",
+ "service_account": "The service account ID of the service account.",
+ "network": "The network block configuration.",
+ "access_scope": "The access scope. (Either SNA or PUBLIC)",
+ "acl": "The Access Control List (ACL) for the PostgresFlex instance.",
+ "instance_address": "The returned instance address.",
+ "router_address": "The returned router address.",
}
- // TODO @mhenselin - do the rest
resp.Schema = schema.Schema{
Description: descriptions["main"],
@@ -240,44 +204,64 @@ func (r *instanceResource) Schema(_ context.Context, req resource.SchemaRequest,
Required: true,
},
"flavor": schema.SingleNestedAttribute{
- Required: true,
+ Required: true,
+ Description: descriptions["flavor"],
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
- Computed: true,
- Optional: true,
+ Description: descriptions["flavor_id"],
+ Computed: true,
+ Optional: true,
PlanModifiers: []planmodifier.String{
UseStateForUnknownIfFlavorUnchanged(req),
stringplanmodifier.RequiresReplace(),
},
},
"description": schema.StringAttribute{
- Computed: true,
+ Computed: true,
+ Description: descriptions["flavor_description"],
PlanModifiers: []planmodifier.String{
UseStateForUnknownIfFlavorUnchanged(req),
},
},
"cpu": schema.Int64Attribute{
- Required: true,
+ Description: descriptions["flavor_cpu"],
+ Required: true,
},
"ram": schema.Int64Attribute{
- Required: true,
+ Description: descriptions["flavor_ram"],
+ Required: true,
+ },
+ "node_type": schema.StringAttribute{
+ Description: descriptions["flavor_node_type"],
+ Computed: true,
+ Optional: true,
+ PlanModifiers: []planmodifier.String{
+ // TODO @mhenselin anschauen
+ UseStateForUnknownIfFlavorUnchanged(req),
+ stringplanmodifier.RequiresReplace(),
+ },
},
},
},
"replicas": schema.Int64Attribute{
Required: true,
+ PlanModifiers: []planmodifier.Int64{
+ int64planmodifier.RequiresReplace(),
+ },
},
"storage": schema.SingleNestedAttribute{
Required: true,
Attributes: map[string]schema.Attribute{
"class": schema.StringAttribute{
- Required: true,
+ Required: true,
+ Description: descriptions["storage_class"],
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
"size": schema.Int64Attribute{
- Required: true,
+ Description: descriptions["storage_size"],
+ Required: true,
// PlanModifiers: []planmodifier.Int64{
// TODO - req replace if new size smaller than state size
// int64planmodifier.RequiresReplaceIf(),
@@ -286,7 +270,8 @@ func (r *instanceResource) Schema(_ context.Context, req resource.SchemaRequest,
},
},
"version": schema.StringAttribute{
- Required: true,
+ Description: descriptions["version"],
+ Required: true,
},
"region": schema.StringAttribute{
Optional: true,
@@ -399,7 +384,11 @@ func (r *instanceResource) Schema(_ context.Context, req resource.SchemaRequest,
}
// Create creates the resource and sets the initial Terraform state.
-func (r *instanceResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // nolint:gocritic // function signature required by Terraform
+func (r *instanceResource) Create(
+ ctx context.Context,
+ req resource.CreateRequest,
+ resp *resource.CreateResponse,
+) { // nolint:gocritic // function signature required by Terraform
// Retrieve values from plan
var model Model
diags := req.Plan.Get(ctx, &model)
diff --git a/stackit/internal/services/postgresflexalpha/instance/resource_test.go b/stackit/internal/services/postgresflexalpha/instance/resource_test.go
index 17747a2f..47d334d2 100644
--- a/stackit/internal/services/postgresflexalpha/instance/resource_test.go
+++ b/stackit/internal/services/postgresflexalpha/instance/resource_test.go
@@ -2,10 +2,12 @@ package postgresflexalpha
import (
"context"
+ "reflect"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/attr"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/types"
postgresflex "github.com/mhenselin/terraform-provider-stackitprivatepreview/pkg/postgresflexalpha"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
@@ -25,7 +27,6 @@ import (
// }
func TestMapFields(t *testing.T) {
- t.Skip("Skipping - needs refactoring")
const testRegion = "region"
tests := []struct {
description string
@@ -40,16 +41,26 @@ func TestMapFields(t *testing.T) {
isValid bool
}{
{
- "default_values",
+ "default_values does exactly mean what?",
Model{
InstanceId: types.StringValue("iid"),
ProjectId: types.StringValue("pid"),
+ Replicas: types.Int64Value(1),
+ },
+ &postgresflex.GetInstanceResponse{
+ FlavorId: utils.Ptr("flavor_id"),
+ Replicas: postgresflex.GetInstanceResponseGetReplicasAttributeType(utils.Ptr(int32(1))),
+ },
+ &flavorModel{
+ NodeType: types.StringValue("Single"),
},
- &postgresflex.GetInstanceResponse{},
- &flavorModel{},
&storageModel{},
&encryptionModel{},
- &networkModel{},
+ &networkModel{
+ ACL: types.ListValueMust(types.StringType, []attr.Value{
+ types.StringValue("0.0.0.0/0"),
+ }),
+ },
testRegion,
Model{
Id: types.StringValue("pid,region,iid"),
@@ -63,202 +74,96 @@ func TestMapFields(t *testing.T) {
"description": types.StringNull(),
"cpu": types.Int64Null(),
"ram": types.Int64Null(),
- "node_type": types.StringNull(),
+ "node_type": types.StringValue("Single"),
+ }),
+ Replicas: types.Int64Value(1),
+ Encryption: types.ObjectValueMust(encryptionTypes, map[string]attr.Value{
+ "keyring_id": types.StringNull(),
+ "key_id": types.StringNull(),
+ "key_version": types.StringNull(),
+ "service_account": types.StringNull(),
}),
- Replicas: types.Int64Null(),
Storage: types.ObjectValueMust(storageTypes, map[string]attr.Value{
"class": types.StringNull(),
"size": types.Int64Null(),
}),
+ Network: types.ObjectValueMust(networkTypes, map[string]attr.Value{
+ "acl": types.ListValueMust(types.StringType, []attr.Value{
+ types.StringValue("0.0.0.0/0"),
+ }),
+ "access_scope": types.StringNull(),
+ "instance_address": types.StringNull(),
+ "router_address": types.StringNull(),
+ }),
Version: types.StringNull(),
Region: types.StringValue(testRegion),
},
true,
},
- {
- "simple_values",
- Model{
- InstanceId: types.StringValue("iid"),
- ProjectId: types.StringValue("pid"),
- },
- &postgresflex.GetInstanceResponse{
- // Acl: &[]string{
- // "ip1",
- // "ip2",
- // "",
- // },
- BackupSchedule: utils.Ptr("schedule"),
- // Flavor: &postgresflex.Flavor{
- // Cpu: utils.Ptr(int64(12)),
- // Description: utils.Ptr("description"),
- // Id: utils.Ptr("flavor_id"),
- // Ram: utils.Ptr(int64(34)),
- // },
- Id: utils.Ptr("iid"),
- Name: utils.Ptr("name"),
- Replicas: postgresflex.GetInstanceResponseGetReplicasAttributeType(utils.Ptr(int32(56))),
- Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr("status")),
- Storage: &postgresflex.Storage{
- PerformanceClass: utils.Ptr("class"),
- Size: utils.Ptr(int64(78)),
- },
- Version: utils.Ptr("version"),
- },
- &flavorModel{},
- &storageModel{},
- &encryptionModel{},
- &networkModel{},
- testRegion,
- Model{
- Id: types.StringValue("pid,region,iid"),
- InstanceId: types.StringValue("iid"),
- ProjectId: types.StringValue("pid"),
- Name: types.StringValue("name"),
- // ACL: types.ListValueMust(types.StringType, []attr.Value{
- // types.StringValue("ip1"),
- // types.StringValue("ip2"),
- // types.StringValue(""),
- // }),
- BackupSchedule: types.StringValue("schedule"),
- Flavor: types.ObjectValueMust(flavorTypes, map[string]attr.Value{
- "id": types.StringValue("flavor_id"),
- "description": types.StringValue("description"),
- "cpu": types.Int64Value(12),
- "ram": types.Int64Value(34),
- }),
- Replicas: types.Int64Value(56),
- Storage: types.ObjectValueMust(storageTypes, map[string]attr.Value{
- "class": types.StringValue("class"),
- "size": types.Int64Value(78),
- }),
- Version: types.StringValue("version"),
- Region: types.StringValue(testRegion),
- },
- true,
- },
- {
- "simple_values_no_flavor_and_storage",
- Model{
- InstanceId: types.StringValue("iid"),
- ProjectId: types.StringValue("pid"),
- },
- &postgresflex.GetInstanceResponse{
- // Acl: &[]string{
- // "ip1",
- // "ip2",
- // "",
- // },
- BackupSchedule: utils.Ptr("schedule"),
- FlavorId: nil,
- Id: utils.Ptr("iid"),
- Name: utils.Ptr("name"),
- Replicas: postgresflex.GetInstanceResponseGetReplicasAttributeType(utils.Ptr(int32(56))),
- Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr("status")),
- Storage: nil,
- Version: utils.Ptr("version"),
- },
- &flavorModel{
- CPU: types.Int64Value(12),
- RAM: types.Int64Value(34),
- },
- &storageModel{
- Class: types.StringValue("class"),
- Size: types.Int64Value(78),
- },
- &encryptionModel{},
- &networkModel{},
- testRegion,
- Model{
- Id: types.StringValue("pid,region,iid"),
- InstanceId: types.StringValue("iid"),
- ProjectId: types.StringValue("pid"),
- Name: types.StringValue("name"),
- // ACL: types.ListValueMust(types.StringType, []attr.Value{
- // types.StringValue("ip1"),
- // types.StringValue("ip2"),
- // types.StringValue(""),
- // }),
- BackupSchedule: types.StringValue("schedule"),
- Flavor: types.ObjectValueMust(flavorTypes, map[string]attr.Value{
- "id": types.StringNull(),
- "description": types.StringNull(),
- "cpu": types.Int64Value(12),
- "ram": types.Int64Value(34),
- }),
- Replicas: types.Int64Value(56),
- Storage: types.ObjectValueMust(storageTypes, map[string]attr.Value{
- "class": types.StringValue("class"),
- "size": types.Int64Value(78),
- }),
- Version: types.StringValue("version"),
- Region: types.StringValue(testRegion),
- },
- true,
- },
- {
- "acl_unordered",
- Model{
- InstanceId: types.StringValue("iid"),
- ProjectId: types.StringValue("pid"),
- // ACL: types.ListValueMust(types.StringType, []attr.Value{
- // types.StringValue("ip2"),
- // types.StringValue(""),
- // types.StringValue("ip1"),
- // }),
- },
- &postgresflex.GetInstanceResponse{
- // Acl: &[]string{
- // "",
- // "ip1",
- // "ip2",
- // },
- BackupSchedule: utils.Ptr("schedule"),
- FlavorId: nil,
- Id: utils.Ptr("iid"),
- Name: utils.Ptr("name"),
- Replicas: postgresflex.GetInstanceResponseGetReplicasAttributeType(utils.Ptr(int32(56))),
- Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr("status")),
- Storage: nil,
- Version: utils.Ptr("version"),
- },
- &flavorModel{
- CPU: types.Int64Value(12),
- RAM: types.Int64Value(34),
- },
- &storageModel{
- Class: types.StringValue("class"),
- Size: types.Int64Value(78),
- },
- &encryptionModel{},
- &networkModel{},
- testRegion,
- Model{
- Id: types.StringValue("pid,region,iid"),
- InstanceId: types.StringValue("iid"),
- ProjectId: types.StringValue("pid"),
- Name: types.StringValue("name"),
- // ACL: types.ListValueMust(types.StringType, []attr.Value{
- // types.StringValue("ip2"),
- // types.StringValue(""),
- // types.StringValue("ip1"),
- // }),
- BackupSchedule: types.StringValue("schedule"),
- Flavor: types.ObjectValueMust(flavorTypes, map[string]attr.Value{
- "id": types.StringNull(),
- "description": types.StringNull(),
- "cpu": types.Int64Value(12),
- "ram": types.Int64Value(34),
- }),
- Replicas: types.Int64Value(56),
- Storage: types.ObjectValueMust(storageTypes, map[string]attr.Value{
- "class": types.StringValue("class"),
- "size": types.Int64Value(78),
- }),
- Version: types.StringValue("version"),
- Region: types.StringValue(testRegion),
- },
- true,
- },
+ // {
+ // "acl_unordered",
+ // Model{
+ // InstanceId: types.StringValue("iid"),
+ // ProjectId: types.StringValue("pid"),
+ // // ACL: types.ListValueMust(types.StringType, []attr.Value{
+ // // types.StringValue("ip2"),
+ // // types.StringValue(""),
+ // // types.StringValue("ip1"),
+ // // }),
+ // },
+ // &postgresflex.GetInstanceResponse{
+ // // Acl: &[]string{
+ // // "",
+ // // "ip1",
+ // // "ip2",
+ // // },
+ // BackupSchedule: utils.Ptr("schedule"),
+ // FlavorId: nil,
+ // Id: utils.Ptr("iid"),
+ // Name: utils.Ptr("name"),
+ // Replicas: postgresflex.GetInstanceResponseGetReplicasAttributeType(utils.Ptr(int32(56))),
+ // Status: postgresflex.GetInstanceResponseGetStatusAttributeType(utils.Ptr("status")),
+ // Storage: nil,
+ // Version: utils.Ptr("version"),
+ // },
+ // &flavorModel{
+ // CPU: types.Int64Value(12),
+ // RAM: types.Int64Value(34),
+ // },
+ // &storageModel{
+ // Class: types.StringValue("class"),
+ // Size: types.Int64Value(78),
+ // },
+ // &encryptionModel{},
+ // &networkModel{},
+ // testRegion,
+ // Model{
+ // Id: types.StringValue("pid,region,iid"),
+ // InstanceId: types.StringValue("iid"),
+ // ProjectId: types.StringValue("pid"),
+ // Name: types.StringValue("name"),
+ // // ACL: types.ListValueMust(types.StringType, []attr.Value{
+ // // types.StringValue("ip2"),
+ // // types.StringValue(""),
+ // // types.StringValue("ip1"),
+ // // }),
+ // BackupSchedule: types.StringValue("schedule"),
+ // Flavor: types.ObjectValueMust(flavorTypes, map[string]attr.Value{
+ // "id": types.StringNull(),
+ // "description": types.StringNull(),
+ // "cpu": types.Int64Value(12),
+ // "ram": types.Int64Value(34),
+ // }),
+ // Replicas: types.Int64Value(56),
+ // Storage: types.ObjectValueMust(storageTypes, map[string]attr.Value{
+ // "class": types.StringValue("class"),
+ // "size": types.Int64Value(78),
+ // }),
+ // Version: types.StringValue("version"),
+ // Region: types.StringValue(testRegion),
+ // },
+ // true,
+ // },
{
"nil_response",
Model{
@@ -300,7 +205,7 @@ func TestMapFields(t *testing.T) {
t.Fatalf("Should not have failed: %v", err)
}
if tt.isValid {
- diff := cmp.Diff(tt.state, tt.expected)
+ diff := cmp.Diff(tt.expected, tt.state)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
@@ -310,7 +215,6 @@ func TestMapFields(t *testing.T) {
}
func TestToCreatePayload(t *testing.T) {
- t.Skip("Skipping - needs refactoring")
tests := []struct {
description string
input *Model
@@ -324,89 +228,50 @@ func TestToCreatePayload(t *testing.T) {
}{
{
"default_values",
- &Model{},
+ &Model{
+ Replicas: types.Int64Value(1),
+ },
[]string{},
&flavorModel{},
&storageModel{},
&encryptionModel{},
- &networkModel{},
+ &networkModel{
+ ACL: types.ListValueMust(types.StringType, []attr.Value{
+ types.StringValue("0.0.0.0/0"),
+ }),
+ },
+ &postgresflex.CreateInstanceRequestPayload{
+ Storage: postgresflex.CreateInstanceRequestPayloadGetStorageAttributeType(&postgresflex.Storage{}),
+ Encryption: &postgresflex.InstanceEncryption{},
+ Network: &postgresflex.InstanceNetwork{
+ Acl: &[]string{"0.0.0.0/0"},
+ },
+ Replicas: postgresflex.CreateInstanceRequestPayloadGetReplicasAttributeType(utils.Ptr(int32(1))),
+ },
+ true,
+ },
+ {
+ "use flavor node_type instead of replicas",
+ &Model{},
+ []string{},
+ &flavorModel{
+ NodeType: types.StringValue("Single"),
+ },
+ &storageModel{},
+ &encryptionModel{},
+ &networkModel{
+ ACL: types.ListValueMust(types.StringType, []attr.Value{
+ types.StringValue("0.0.0.0/0"),
+ }),
+ },
&postgresflex.CreateInstanceRequestPayload{
//Acl: &[]string{},
- Storage: postgresflex.CreateInstanceRequestPayloadGetStorageAttributeType(&postgresflex.Storage{}),
- },
- true,
- },
- {
- "simple_values",
- &Model{
- BackupSchedule: types.StringValue("schedule"),
- Name: types.StringValue("name"),
- Replicas: types.Int64Value(12),
- Version: types.StringValue("version"),
- },
- []string{
- "ip_1",
- "ip_2",
- },
- &flavorModel{
- Id: types.StringValue("flavor_id"),
- },
- &storageModel{
- Class: types.StringValue("class"),
- Size: types.Int64Value(34),
- },
- &encryptionModel{},
- &networkModel{},
- &postgresflex.CreateInstanceRequestPayload{
- // Acl: &[]string{
- // "ip_1",
- // "ip_2",
- // },
- BackupSchedule: utils.Ptr("schedule"),
- FlavorId: utils.Ptr("flavor_id"),
- Name: utils.Ptr("name"),
- Replicas: postgresflex.CreateInstanceRequestPayloadGetReplicasAttributeType(utils.Ptr(int32(56))),
- Storage: postgresflex.CreateInstanceRequestPayloadGetStorageAttributeType(&postgresflex.Storage{
- PerformanceClass: utils.Ptr("class"),
- Size: utils.Ptr(int64(34)),
- }),
- Version: utils.Ptr("version"),
- },
- true,
- },
- {
- " ^^1null_fields_and_int_conversions",
- &Model{
- BackupSchedule: types.StringNull(),
- Name: types.StringNull(),
- Replicas: types.Int64Value(2123456789),
- Version: types.StringNull(),
- },
- []string{
- "",
- },
- &flavorModel{
- Id: types.StringNull(),
- },
- &storageModel{
- Class: types.StringNull(),
- Size: types.Int64Null(),
- },
- &encryptionModel{},
- &networkModel{},
- &postgresflex.CreateInstanceRequestPayload{
- // Acl: &[]string{
- // "",
- // },
- BackupSchedule: nil,
- FlavorId: nil,
- Name: nil,
- Replicas: postgresflex.CreateInstanceRequestPayloadGetReplicasAttributeType(utils.Ptr(int32(2123456789))),
- Storage: postgresflex.CreateInstanceRequestPayloadGetStorageAttributeType(&postgresflex.Storage{
- PerformanceClass: nil,
- Size: nil,
- }),
- Version: nil,
+ Storage: postgresflex.CreateInstanceRequestPayloadGetStorageAttributeType(&postgresflex.Storage{}),
+ Encryption: &postgresflex.InstanceEncryption{},
+ Network: &postgresflex.InstanceNetwork{
+ Acl: &[]string{"0.0.0.0/0"},
+ },
+ Replicas: postgresflex.CreateInstanceRequestPayloadGetReplicasAttributeType(utils.Ptr(int32(1))),
},
true,
},
@@ -465,7 +330,7 @@ func TestToCreatePayload(t *testing.T) {
t.Fatalf("Should not have failed: %v", err)
}
if tt.isValid {
- diff := cmp.Diff(output, tt.expected)
+ diff := cmp.Diff(tt.expected, output)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
@@ -780,3 +645,22 @@ func TestToCreatePayload(t *testing.T) {
// })
// }
// }
+
+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)
+ }
+ })
+ }
+}