From c7646a955e5a100404f4603c6e64fe0e0b085d8f Mon Sep 17 00:00:00 2001
From: Mike Wang <52522981+mikechesterwang@users.noreply.github.com>
Date: Mon, 18 Mar 2024 11:06:59 +0800
Subject: [PATCH] feat: hide component id (#20)
* update
* feat: hide component id
* rm component type data sources
---
docs/data-sources/component_type.md | 28 --
docs/resources/cluster.md | 43 ++--
.../component_type/component_type.tf | 4 -
examples/resources/cluster/resource.tf | 53 ++--
internal/cloudsdk/fake/fake.go | 81 +++---
.../acc/data_source_component_type_test.go | 34 ---
.../provider/acc/resource_cluster_test.go | 52 ++--
.../provider/data_source_component_type.go | 194 --------------
internal/provider/provider.go | 4 +-
internal/provider/resource_cluster.go | 243 ++++++++++++------
10 files changed, 284 insertions(+), 452 deletions(-)
delete mode 100644 docs/data-sources/component_type.md
delete mode 100644 examples/data-sources/component_type/component_type.tf
delete mode 100644 internal/provider/acc/data_source_component_type_test.go
delete mode 100644 internal/provider/data_source_component_type.go
diff --git a/docs/data-sources/component_type.md b/docs/data-sources/component_type.md
deleted file mode 100644
index 28f45ab..0000000
--- a/docs/data-sources/component_type.md
+++ /dev/null
@@ -1,28 +0,0 @@
----
-# generated by https://github.com/hashicorp/terraform-plugin-docs
-page_title: "risingwavecloud_component_type Data Source - terraform-provider-risingwavecloud"
-subcategory: ""
-description: |-
- The type of the component of the RisingWave cluster
----
-
-# risingwavecloud_component_type (Data Source)
-
-The type of the component of the RisingWave cluster
-
-
-
-
-## Schema
-
-### Required
-
-- `component` (String) The component in a RisingWave cluster. Valid values are: `compute`, `compactor`, `frontend`, `meta`, `etcd`
-- `memory_gib` (Number) Memory size in GiB
-- `platform` (String)
-- `region` (String)
-- `vcpu` (Number) The number of the virtual CPU cores
-
-### Read-Only
-
-- `id` (String) The id of the RisingWave cluster. Valid values are
diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md
index 277e82a..59014c6 100644
--- a/docs/resources/cluster.md
+++ b/docs/resources/cluster.md
@@ -48,14 +48,15 @@ Optional:
Required:
-- `resource` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--compactor--resource))
+- `default_node_group` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--compactor--default_node_group))
-
-### Nested Schema for `spec.compactor.resource`
+
+### Nested Schema for `spec.compactor.default_node_group`
Required:
-- `id` (String) The component type ID of the node
+- `cpu` (String) The CPU of the node
+- `memory` (String) The memory size in of the node
Optional:
@@ -68,14 +69,15 @@ Optional:
Required:
-- `resource` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--compute--resource))
+- `default_node_group` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--compute--default_node_group))
-
-### Nested Schema for `spec.compute.resource`
+
+### Nested Schema for `spec.compute.default_node_group`
Required:
-- `id` (String) The component type ID of the node
+- `cpu` (String) The CPU of the node
+- `memory` (String) The memory size in of the node
Optional:
@@ -88,14 +90,15 @@ Optional:
Required:
-- `resource` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--frontend--resource))
+- `default_node_group` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--frontend--default_node_group))
-
-### Nested Schema for `spec.frontend.resource`
+
+### Nested Schema for `spec.frontend.default_node_group`
Required:
-- `id` (String) The component type ID of the node
+- `cpu` (String) The CPU of the node
+- `memory` (String) The memory size in of the node
Optional:
@@ -108,18 +111,19 @@ Optional:
Required:
-- `resource` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--meta--resource))
+- `default_node_group` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--meta--default_node_group))
Optional:
- `etcd_meta_store` (Attributes) (see [below for nested schema](#nestedatt--spec--meta--etcd_meta_store))
-
-### Nested Schema for `spec.meta.resource`
+
+### Nested Schema for `spec.meta.default_node_group`
Required:
-- `id` (String) The component type ID of the node
+- `cpu` (String) The CPU of the node
+- `memory` (String) The memory size in of the node
Optional:
@@ -131,18 +135,19 @@ Optional:
Required:
-- `resource` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--meta--etcd_meta_store--resource))
+- `default_node_group` (Attributes) The resource specification of the component (see [below for nested schema](#nestedatt--spec--meta--etcd_meta_store--default_node_group))
Optional:
- `etcd_config` (String) The environment variable list of the etcd configuration
-
+
### Nested Schema for `spec.meta.etcd_meta_store.etcd_config`
Required:
-- `id` (String) The component type ID of the node
+- `cpu` (String) The CPU of the node
+- `memory` (String) The memory size in of the node
Optional:
diff --git a/examples/data-sources/component_type/component_type.tf b/examples/data-sources/component_type/component_type.tf
deleted file mode 100644
index a8cd3f6..0000000
--- a/examples/data-sources/component_type/component_type.tf
+++ /dev/null
@@ -1,4 +0,0 @@
-data "risingwavecloud_component_type" "example" {
- vcpu = 2
- memory_gib = 4
-}
diff --git a/examples/resources/cluster/resource.tf b/examples/resources/cluster/resource.tf
index 06c12fd..3f04e1f 100644
--- a/examples/resources/cluster/resource.tf
+++ b/examples/resources/cluster/resource.tf
@@ -1,27 +1,42 @@
-resource "risingwavecloud_cluster" "example" {
- name = "dev"
- version = "v1.3.0"
- region = "us-east-2"
- resourcev1 = {
+resource "risingwavecloud_cluster" "my_cluster" {
+ region = "us-east-1"
+ name = "my_cluster"
+ version = "v1.8.0"
+ spec = {
compute = {
- type = "p-1c2g"
- replica = 1
+ default_node_group = {
+ cpu = "2"
+ memory = "8 GB"
+ replica = 1
+ }
}
compactor = {
- type = "p-2c4g"
- replica = 3
- },
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
+ replica = 1
+ }
+ }
frontend = {
- type = "p-1c1g"
- replica = 1
- },
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
+ replica = 1
+ }
+ }
meta = {
- type = "p-1c1g"
- replica = 1
- },
- etcd = {
- type = "p-1c1g"
- replica = 3
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
+ replica = 1
+ }
+ etcd_meta_store = {
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
+ replica = 1
+ }
+ }
}
}
}
diff --git a/internal/cloudsdk/fake/fake.go b/internal/cloudsdk/fake/fake.go
index 859bf74..fa472c6 100644
--- a/internal/cloudsdk/fake/fake.go
+++ b/internal/cloudsdk/fake/fake.go
@@ -185,31 +185,30 @@ func (acc *FakeCloudClient) CreateClusterAwait(ctx context.Context, region strin
return &cluster, nil
}
-func (acc *FakeCloudClient) GetTiers(ctx context.Context, _ string) ([]apigen_mgmt.Tier, error) {
- debugFuncCaller()
+var availableComponentTypes = []apigen_mgmt.AvailableComponentType{
+ {
+ Id: "p-1c4g",
+ Cpu: "1",
+ Memory: "4 GB",
+ Maximum: 3,
+ },
+ {
+ Id: "p-2c8g",
+ Cpu: "2",
+ Memory: "8 GB",
+ Maximum: 3,
+ },
+}
- nodes := []apigen_mgmt.AvailableComponentType{
- {
- Id: "p-1c4g",
- Cpu: "1",
- Memory: "4 GB",
- Maximum: 3,
- },
- {
- Id: "p-2c8g",
- Cpu: "2",
- Memory: "8 GB",
- Maximum: 3,
- },
- }
+func (acc *FakeCloudClient) GetTiers(ctx context.Context, _ string) ([]apigen_mgmt.Tier, error) {
return []apigen_mgmt.Tier{
{
Id: ptr.Ptr(apigen_mgmt.Standard),
- AvailableMetaNodes: nodes,
- AvailableComputeNodes: nodes,
- AvailableCompactorNodes: nodes,
- AvailableEtcdNodes: nodes,
- AvailableFrontendNodes: nodes,
+ AvailableMetaNodes: availableComponentTypes,
+ AvailableComputeNodes: availableComponentTypes,
+ AvailableCompactorNodes: availableComponentTypes,
+ AvailableEtcdNodes: availableComponentTypes,
+ AvailableFrontendNodes: availableComponentTypes,
AllowEnableComputeNodeFileCache: true,
MaximumEtcdSizeGiB: 20,
},
@@ -217,8 +216,6 @@ func (acc *FakeCloudClient) GetTiers(ctx context.Context, _ string) ([]apigen_mg
}
func (acc *FakeCloudClient) GetAvailableComponentTypes(ctx context.Context, region string, targetTier apigen_mgmt.TierId, component string) ([]apigen_mgmt.AvailableComponentType, error) {
- debugFuncCaller()
-
tiers, err := acc.GetTiers(ctx, region)
if err != nil {
return nil, err
@@ -315,26 +312,11 @@ func (acc *FakeCloudClient) UpdateEtcdConfigByNsIDAwait(ctx context.Context, nsI
func reqResouceToClusterResource(reqResource *apigen_mgmt.TenantResourceRequest) apigen_mgmt.TenantResource {
return apigen_mgmt.TenantResource{
Components: apigen_mgmt.TenantResourceComponents{
- Compute: &apigen_mgmt.ComponentResource{
- ComponentTypeId: reqResource.Components.Compute.ComponentTypeId,
- Replica: reqResource.Components.Compute.Replica,
- },
- Compactor: &apigen_mgmt.ComponentResource{
- ComponentTypeId: reqResource.Components.Compactor.ComponentTypeId,
- Replica: reqResource.Components.Compactor.Replica,
- },
- Frontend: &apigen_mgmt.ComponentResource{
- ComponentTypeId: reqResource.Components.Frontend.ComponentTypeId,
- Replica: reqResource.Components.Frontend.Replica,
- },
- Meta: &apigen_mgmt.ComponentResource{
- ComponentTypeId: reqResource.Components.Meta.ComponentTypeId,
- Replica: reqResource.Components.Meta.Replica,
- },
- Etcd: apigen_mgmt.ComponentResource{
- ComponentTypeId: reqResource.Components.Etcd.ComponentTypeId,
- Replica: reqResource.Components.Etcd.Replica,
- },
+ Compute: componentReqToComponent(reqResource.Components.Compute),
+ Compactor: componentReqToComponent(reqResource.Components.Compactor),
+ Frontend: componentReqToComponent(reqResource.Components.Frontend),
+ Meta: componentReqToComponent(reqResource.Components.Meta),
+ Etcd: *componentReqToComponent(&reqResource.Components.Etcd),
},
EnableComputeFileCache: reqResource.EnableComputeFileCache,
EtcdVolumeSizeGiB: reqResource.EtcdVolumeSizeGiB,
@@ -344,8 +326,15 @@ func reqResouceToClusterResource(reqResource *apigen_mgmt.TenantResourceRequest)
}
func componentReqToComponent(req *apigen_mgmt.ComponentResourceRequest) *apigen_mgmt.ComponentResource {
- return &apigen_mgmt.ComponentResource{
- ComponentTypeId: req.ComponentTypeId,
- Replica: req.Replica,
+ for _, c := range availableComponentTypes {
+ if c.Id == req.ComponentTypeId {
+ return &apigen_mgmt.ComponentResource{
+ ComponentTypeId: req.ComponentTypeId,
+ Replica: req.Replica,
+ Cpu: c.Cpu,
+ Memory: c.Memory,
+ }
+ }
}
+ return nil
}
diff --git a/internal/provider/acc/data_source_component_type_test.go b/internal/provider/acc/data_source_component_type_test.go
deleted file mode 100644
index 1fa303a..0000000
--- a/internal/provider/acc/data_source_component_type_test.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package provider
-
-import (
- "fmt"
- "testing"
-
- "github.com/hashicorp/terraform-plugin-testing/helper/resource"
-)
-
-func TestComponentTypeDataSource(t *testing.T) {
- resource.Test(t, resource.TestCase{
- PreCheck: func() { testAccPreCheck(t) },
- ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
- Steps: []resource.TestStep{
- // Read testing
- {
- Config: testComponentTypeDataSourceConfig("compute"),
- Check: resource.ComposeAggregateTestCheckFunc(
- resource.TestCheckResourceAttr("data.risingwavecloud_component_type.test", "id", "p-2c8g"),
- ),
- },
- },
- })
-}
-
-func testComponentTypeDataSourceConfig(component string) string {
- return fmt.Sprintf(`data "risingwavecloud_component_type" "test" {
- platform = "aws"
- region = "us-east-1"
- vcpu = 2
- memory_gib = 8
- component = "%s"
-}`, component)
-}
diff --git a/internal/provider/acc/resource_cluster_test.go b/internal/provider/acc/resource_cluster_test.go
index 0ab9329..31b6807 100644
--- a/internal/provider/acc/resource_cluster_test.go
+++ b/internal/provider/acc/resource_cluster_test.go
@@ -61,7 +61,7 @@ func TestClusterResource(t *testing.T) {
{
Config: testClusterResourceUpdateConfig("v1.6.0", clusterName),
Check: resource.ComposeAggregateTestCheckFunc(
- resource.TestCheckResourceAttr("risingwavecloud_cluster.test", "spec.compactor.resource.replica", "2"),
+ resource.TestCheckResourceAttr("risingwavecloud_cluster.test", "spec.compactor.default_node_group.replica", "2"),
resource.TestCheckResourceAttr("risingwavecloud_cluster.test", "spec.risingwave_config", "[server]\nheartbeat_interval_ms = 997\n"),
resource.TestCheckResourceAttr("risingwavecloud_cluster.test", "spec.meta.etcd_meta_store.etcd_config", "ETCD_MAX_REQUEST_BYTES: \"100000000\"\n"),
),
@@ -79,31 +79,36 @@ resource "risingwavecloud_cluster" "test" {
version = "%s"
spec = {
compute = {
- resource = {
- id = "p-2c8g"
+ default_node_group = {
+ cpu = "2"
+ memory = "8 GB"
replica = 1
}
}
compactor = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 1
}
}
frontend = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 1
}
}
meta = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 1
}
etcd_meta_store = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 1
}
}
@@ -122,31 +127,36 @@ resource "risingwavecloud_cluster" "test" {
version = "%s"
spec = {
compute = {
- resource = {
- id = "p-2c8g"
+ default_node_group = {
+ cpu = "2"
+ memory = "8 GB"
replica = 1
}
}
compactor = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 2
}
}
frontend = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 1
}
}
meta = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 1
}
etcd_meta_store = {
- resource = {
- id = "p-1c4g"
+ default_node_group = {
+ cpu = "1"
+ memory = "4 GB"
replica = 1
}
etcd_config = <<-EOT
diff --git a/internal/provider/data_source_component_type.go b/internal/provider/data_source_component_type.go
deleted file mode 100644
index 4c5af3f..0000000
--- a/internal/provider/data_source_component_type.go
+++ /dev/null
@@ -1,194 +0,0 @@
-package provider
-
-import (
- "context"
- "fmt"
-
- "github.com/hashicorp/terraform-plugin-framework/datasource"
- "github.com/hashicorp/terraform-plugin-framework/datasource/schema"
- "github.com/hashicorp/terraform-plugin-framework/types"
- "github.com/hashicorp/terraform-plugin-log/tflog"
- "github.com/risingwavelabs/terraform-provider-risingwavecloud/internal/cloudsdk"
-
- apigen_mgmt "github.com/risingwavelabs/terraform-provider-risingwavecloud/internal/cloudsdk/apigen/mgmt"
-)
-
-const (
- ComponentCompute = "compute"
- ComponentCompactor = "compactor"
- ComponentFrontend = "frontend"
- ComponentMeta = "meta"
- ComponentEtcd = "etcd"
-)
-
-var (
- ComponentMenu = fmt.Sprintf("`%s`, `%s`, `%s`, `%s`, `%s`",
- ComponentCompute,
- ComponentCompactor,
- ComponentFrontend,
- ComponentMeta,
- ComponentEtcd,
- )
-)
-
-var (
- DefaultTier = apigen_mgmt.Standard
-)
-
-// Ensure provider defined types fully satisfy framework interfaces.
-var _ datasource.DataSource = &ComponentTypeDataSource{}
-
-func NewComponentTypeDataSource() datasource.DataSource {
- return &ComponentTypeDataSource{}
-}
-
-type ComponentTypeDataSource struct {
- client cloudsdk.CloudClientInterface
-}
-
-type ComponentTypeDataSourceModel struct {
- Platform types.String `tfsdk:"platform"`
- Region types.String `tfsdk:"region"`
- Component types.String `tfsdk:"component"`
- VCPU types.Int64 `tfsdk:"vcpu"`
- MemoryGiB types.Int64 `tfsdk:"memory_gib"`
- ID types.String `tfsdk:"id"`
-}
-
-func (d *ComponentTypeDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
- resp.TypeName = req.ProviderTypeName + "_component_type"
-}
-
-func (d *ComponentTypeDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
- resp.Schema = schema.Schema{
- MarkdownDescription: "The type of the component of the RisingWave cluster",
- Attributes: map[string]schema.Attribute{
- "platform": schema.StringAttribute{
- Required: true,
- },
- "region": schema.StringAttribute{
- Required: true,
- },
- "vcpu": schema.Int64Attribute{
- MarkdownDescription: "The number of the virtual CPU cores",
- Required: true,
- },
- "memory_gib": schema.Int64Attribute{
- MarkdownDescription: "Memory size in GiB",
- Required: true,
- },
- "component": schema.StringAttribute{
- MarkdownDescription: fmt.Sprintf(
- "The component in a RisingWave cluster. Valid values are: %s", ComponentMenu,
- ),
- Required: true,
- },
- "id": schema.StringAttribute{
- MarkdownDescription: "The id of the RisingWave cluster. Valid values are",
- Computed: true,
- },
- },
- }
-}
-
-func (d *ComponentTypeDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
- // Prevent panic if the provider has not been configured.
- if req.ProviderData == nil {
- return
- }
-
- client, ok := req.ProviderData.(cloudsdk.CloudClientInterface)
-
- if !ok {
- resp.Diagnostics.AddError(
- "Unexpected Data Source Configure Type",
- fmt.Sprintf("Expected cloudsdk.AccountServiceClientInterface, got: %T. Please report this issue to the provider developers.", req.ProviderData),
- )
-
- return
- }
-
- d.client = client
-}
-
-func (d *ComponentTypeDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
- var data ComponentTypeDataSourceModel
-
- // Read Terraform configuration data into the model
- resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
-
- if resp.Diagnostics.HasError() {
- return
- }
-
- // If applicable, this is a great opportunity to initialize any necessary
- // provider client data and make a call using it.
- var (
- platform = data.Platform.ValueString()
- region = data.Region.ValueString()
- component = data.Component.ValueString()
- vCPU = data.VCPU.ValueInt64()
- memoryGiB = data.MemoryGiB.ValueInt64()
- tier = DefaultTier
- )
-
- if len(platform) == 0 {
- resp.Diagnostics.AddError(
- "Missing platform",
- "Platform is required to setup the provider.",
- )
- return
- }
-
- if len(region) == 0 {
- resp.Diagnostics.AddError(
- "Missing region",
- "Region is required to setup the provider.",
- )
- return
- }
-
- if len(component) == 0 {
- resp.Diagnostics.AddError(
- "Missing component",
- fmt.Sprintf("Component is required to setup the provider. Valid values are: %s", ComponentMenu),
- )
- return
- }
-
- availableComponentTypes, err := d.client.GetAvailableComponentTypes(ctx, region, tier, component)
- if err != nil {
- resp.Diagnostics.AddError(
- "Failed to get available component types",
- err.Error(),
- )
- return
- }
-
- ok := false
- for _, c := range availableComponentTypes {
- if fmt.Sprintf("%d", vCPU) == c.Cpu && fmt.Sprintf("%d GB", memoryGiB) == c.Memory {
- data.ID = types.StringValue(c.Id)
- ok = true
- break
- }
- }
-
- if !ok {
- resp.Diagnostics.AddError(
- "Cannot found the corresponding component type",
- fmt.Sprintf(
- "The component type %s with CPU %d cores and memory %d GB is not available for the tier %s",
- component, vCPU, memoryGiB, tier,
- ),
- )
- return
- }
-
- // Write logs using the tflog package
- // Documentation: https://terraform.io/plugin/log
- tflog.Trace(ctx, "read a data source")
-
- // Save data into Terraform state
- resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
-}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 6e0074a..19b640c 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -149,9 +149,7 @@ func (p *RisingWaveCloudProvider) Resources(ctx context.Context) []func() resour
}
func (p *RisingWaveCloudProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
- return []func() datasource.DataSource{
- NewComponentTypeDataSource,
- }
+ return []func() datasource.DataSource{}
}
func New(version string) func() provider.Provider {
diff --git a/internal/provider/resource_cluster.go b/internal/provider/resource_cluster.go
index 45d1f42..862631d 100644
--- a/internal/provider/resource_cluster.go
+++ b/internal/provider/resource_cluster.go
@@ -2,9 +2,10 @@ package provider
import (
"context"
- "errors"
"fmt"
+ "github.com/pkg/errors"
+
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
@@ -22,6 +23,7 @@ import (
)
var (
+ DefaultTier = apigen_mgmt.Standard
DefaultEnableComputeFileCache = true
DefaultComputeFileCacheSizeGB = 20
DefaultEtcdVolumeSizeGB = 10
@@ -39,55 +41,56 @@ type ClusterResource struct {
client cloudsdk.CloudClientInterface
}
-var resourceAttrTypes = map[string]attr.Type{
- "id": types.StringType,
+var defaultNodeGroup = map[string]attr.Type{
+ "cpu": types.StringType,
+ "memory": types.StringType,
"replica": types.Int64Type,
}
var componentAttrTypes = map[string]attr.Type{
- "resource": types.ObjectType{
- AttrTypes: resourceAttrTypes,
+ "default_node_group": types.ObjectType{
+ AttrTypes: defaultNodeGroup,
},
}
type EtcdMetaStoreModel struct {
- Resource types.Object `tfsdk:"resource"`
- EtcdConfig types.String `tfsdk:"etcd_config"`
+ DefaultNodeGroup types.Object `tfsdk:"default_node_group"`
+ EtcdConfig types.String `tfsdk:"etcd_config"`
}
var etcdMetaStoreAttrTypes = map[string]attr.Type{
- "resource": types.ObjectType{
- AttrTypes: resourceAttrTypes,
+ "default_node_group": types.ObjectType{
+ AttrTypes: defaultNodeGroup,
},
"etcd_config": types.StringType,
}
type ComputeSpecModel struct {
- Resource types.Object `tfsdk:"resource"`
+ DefaultNodeGroup types.Object `tfsdk:"default_node_group"`
}
var computeAttrTypes = componentAttrTypes
type CompactorSpecModel struct {
- Resource types.Object `tfsdk:"resource"`
+ DefaultNodeGroup types.Object `tfsdk:"default_node_group"`
}
var compactorAttrTypes = componentAttrTypes
type FrontendSpecModel struct {
- Resource types.Object `tfsdk:"resource"`
+ DefaultNodeGroup types.Object `tfsdk:"default_node_group"`
}
var frontendAttrTypes = componentAttrTypes
type MetaSpecModel struct {
- Resource types.Object `tfsdk:"resource"`
- EtcdMetaStore types.Object `tfsdk:"etcd_meta_store"`
+ DefaultNodeGroup types.Object `tfsdk:"default_node_group"`
+ EtcdMetaStore types.Object `tfsdk:"etcd_meta_store"`
}
var metaAttrTypes = map[string]attr.Type{
- "resource": types.ObjectType{
- AttrTypes: resourceAttrTypes,
+ "default_node_group": types.ObjectType{
+ AttrTypes: defaultNodeGroup,
},
"etcd_meta_store": types.ObjectType{
AttrTypes: etcdMetaStoreAttrTypes,
@@ -126,8 +129,9 @@ type ClusterModel struct {
Spec types.Object `tfsdk:"spec"`
}
-type ResourceModel struct {
- Id types.String `tfsdk:"id"`
+type NodeGroupModel struct {
+ CPU types.String `tfsdk:"cpu"`
+ Memory types.String `tfsdk:"memory"`
Replica types.Int64 `tfsdk:"replica"`
}
@@ -136,10 +140,14 @@ func (r *ClusterResource) Metadata(ctx context.Context, req resource.MetadataReq
}
func (r *ClusterResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
- resourceAttribute := schema.SingleNestedAttribute{
+ defauleNodeGroupAttribute := schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
- "id": schema.StringAttribute{
- MarkdownDescription: "The component type ID of the node",
+ "cpu": schema.StringAttribute{
+ MarkdownDescription: "The CPU of the node",
+ Required: true,
+ },
+ "memory": schema.StringAttribute{
+ MarkdownDescription: "The memory size in of the node",
Required: true,
},
"replica": schema.Int64Attribute{
@@ -177,28 +185,28 @@ func (r *ClusterResource) Schema(ctx context.Context, req resource.SchemaRequest
Attributes: map[string]schema.Attribute{
"compute": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
- "resource": resourceAttribute,
+ "default_node_group": defauleNodeGroupAttribute,
},
Required: true,
},
"compactor": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
- "resource": resourceAttribute,
+ "default_node_group": defauleNodeGroupAttribute,
},
Required: true,
},
"frontend": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
- "resource": resourceAttribute,
+ "default_node_group": defauleNodeGroupAttribute,
},
Required: true,
},
"meta": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
- "resource": resourceAttribute,
+ "default_node_group": defauleNodeGroupAttribute,
"etcd_meta_store": schema.SingleNestedAttribute{
Attributes: map[string]schema.Attribute{
- "resource": resourceAttribute,
+ "default_node_group": defauleNodeGroupAttribute,
"etcd_config": schema.StringAttribute{
MarkdownDescription: "The environment variable list of the etcd configuration",
Optional: true,
@@ -245,11 +253,75 @@ func (r *ClusterResource) Configure(ctx context.Context, req resource.ConfigureR
r.client = client
}
+func (r *ClusterResource) nodeGroupModelToComponentResource(
+ ctx context.Context, diags diag.Diagnostics, nodeGroup *NodeGroupModel, region string, tier apigen_mgmt.TierId, component string,
+) *apigen_mgmt.ComponentResource {
+
+ var (
+ reqCPU = nodeGroup.CPU.ValueString()
+ reqMem = nodeGroup.Memory.ValueString()
+ reqReplica = nodeGroup.Replica.ValueInt64()
+ )
+
+ availableTypes, err := r.client.GetAvailableComponentTypes(ctx, region, tier, component)
+ if err != nil {
+ diags.AddError(
+ "Failed to get available component types",
+ err.Error(),
+ )
+ return nil
+ }
+
+ var candidates []apigen_mgmt.AvailableComponentType
+ for _, availableType := range availableTypes {
+ if availableType.Cpu == reqCPU && availableType.Memory == reqMem {
+ candidates = append(candidates, availableType)
+ }
+ }
+
+ if len(candidates) == 0 {
+ var availableCfg []string
+ for _, availableType := range availableTypes {
+ availableCfg = append(availableCfg, fmt.Sprintf("(%s, %s)", availableType.Cpu, availableType.Memory))
+ }
+ errStr := "configuration (%s, %s) is not allowed for %s component in %s tier, available configurations are: %v"
+ diags.AddError(
+ "Invalid configuration",
+ fmt.Sprintf(errStr, reqCPU, reqMem, component, tier, availableCfg),
+ )
+ return nil
+ }
+
+ maximumReplica := 0
+ chosenType := apigen_mgmt.AvailableComponentType{}
+ for _, candidate := range candidates {
+ if candidate.Maximum > maximumReplica {
+ maximumReplica = candidate.Maximum
+ chosenType = candidate
+ }
+ }
+ if reqReplica > int64(maximumReplica) {
+ diags.AddError(
+ "Invalid replica",
+ fmt.Sprintf("requested replica is greater than maximum replica %d", maximumReplica),
+ )
+ return nil
+ }
+
+ return &apigen_mgmt.ComponentResource{
+ ComponentTypeId: chosenType.Id,
+ Replica: int(reqReplica),
+ Cpu: chosenType.Cpu,
+ Memory: chosenType.Memory,
+ }
+}
+
func clusterToDataModel(cluster *apigen_mgmt.Tenant, data *ClusterModel) {
data.Name = types.StringValue(cluster.TenantName)
data.Version = types.StringValue(cluster.ImageTag)
data.ID = types.StringValue(cluster.NsId.String())
data.Region = types.StringValue(cluster.Region)
+
data.Spec = types.ObjectValueMust(
clusterSpecAttrTypes,
map[string]attr.Value{
@@ -257,10 +329,11 @@ func clusterToDataModel(cluster *apigen_mgmt.Tenant, data *ClusterModel) {
"compute": types.ObjectValueMust(
computeAttrTypes,
map[string]attr.Value{
- "resource": types.ObjectValueMust(
- resourceAttrTypes,
+ "default_node_group": types.ObjectValueMust(
+ defaultNodeGroup,
map[string]attr.Value{
- "id": types.StringValue(cluster.Resources.Components.Compute.ComponentTypeId),
+ "cpu": types.StringValue(cluster.Resources.Components.Compute.Cpu),
+ "memory": types.StringValue(cluster.Resources.Components.Compute.Memory),
"replica": types.Int64Value(int64(cluster.Resources.Components.Compute.Replica)),
},
),
@@ -269,10 +342,11 @@ func clusterToDataModel(cluster *apigen_mgmt.Tenant, data *ClusterModel) {
"compactor": types.ObjectValueMust(
compactorAttrTypes,
map[string]attr.Value{
- "resource": types.ObjectValueMust(
- resourceAttrTypes,
+ "default_node_group": types.ObjectValueMust(
+ defaultNodeGroup,
map[string]attr.Value{
- "id": types.StringValue(cluster.Resources.Components.Compactor.ComponentTypeId),
+ "cpu": types.StringValue(cluster.Resources.Components.Compactor.Cpu),
+ "memory": types.StringValue(cluster.Resources.Components.Compactor.Memory),
"replica": types.Int64Value(int64(cluster.Resources.Components.Compactor.Replica)),
},
),
@@ -281,10 +355,11 @@ func clusterToDataModel(cluster *apigen_mgmt.Tenant, data *ClusterModel) {
"frontend": types.ObjectValueMust(
frontendAttrTypes,
map[string]attr.Value{
- "resource": types.ObjectValueMust(
- resourceAttrTypes,
+ "default_node_group": types.ObjectValueMust(
+ defaultNodeGroup,
map[string]attr.Value{
- "id": types.StringValue(cluster.Resources.Components.Frontend.ComponentTypeId),
+ "cpu": types.StringValue(cluster.Resources.Components.Frontend.Cpu),
+ "memory": types.StringValue(cluster.Resources.Components.Frontend.Memory),
"replica": types.Int64Value(int64(cluster.Resources.Components.Frontend.Replica)),
},
),
@@ -293,20 +368,22 @@ func clusterToDataModel(cluster *apigen_mgmt.Tenant, data *ClusterModel) {
"meta": types.ObjectValueMust(
metaAttrTypes,
map[string]attr.Value{
- "resource": types.ObjectValueMust(
- resourceAttrTypes,
+ "default_node_group": types.ObjectValueMust(
+ defaultNodeGroup,
map[string]attr.Value{
- "id": types.StringValue(cluster.Resources.Components.Meta.ComponentTypeId),
+ "cpu": types.StringValue(cluster.Resources.Components.Meta.Cpu),
+ "memory": types.StringValue(cluster.Resources.Components.Meta.Memory),
"replica": types.Int64Value(int64(cluster.Resources.Components.Meta.Replica)),
},
),
"etcd_meta_store": types.ObjectValueMust(
etcdMetaStoreAttrTypes,
map[string]attr.Value{
- "resource": types.ObjectValueMust(
- resourceAttrTypes,
+ "default_node_group": types.ObjectValueMust(
+ defaultNodeGroup,
map[string]attr.Value{
- "id": types.StringValue(cluster.Resources.Components.Etcd.ComponentTypeId),
+ "cpu": types.StringValue(cluster.Resources.Components.Etcd.Cpu),
+ "memory": types.StringValue(cluster.Resources.Components.Etcd.Memory),
"replica": types.Int64Value(int64(cluster.Resources.Components.Etcd.Replica)),
},
),
@@ -319,7 +396,7 @@ func clusterToDataModel(cluster *apigen_mgmt.Tenant, data *ClusterModel) {
)
}
-func dataModelToCluster(ctx context.Context, data *ClusterModel, cluster *apigen_mgmt.Tenant) diag.Diagnostics {
+func (r *ClusterResource) dataModelToCluster(ctx context.Context, data *ClusterModel, cluster *apigen_mgmt.Tenant) diag.Diagnostics {
diags := diag.Diagnostics{}
objectAsOptions := basetypes.ObjectAsOptions{
UnhandledUnknownAsEmpty: true,
@@ -327,19 +404,19 @@ func dataModelToCluster(ctx context.Context, data *ClusterModel, cluster *apigen
}
var (
- spec ClusterSpecModel
- compactorSpec CompactorSpecModel
- compactorResource ResourceModel
- computeSpec ComputeSpecModel
- computeResource ResourceModel
- frontendSpec FrontendSpecModel
- frontendResource ResourceModel
- metaSpec MetaSpecModel
- metaResource ResourceModel
-
- useEtcdMetaStore bool
- etcdMetaStore EtcdMetaStoreModel
- etcdResource ResourceModel
+ spec ClusterSpecModel
+ compactorSpec CompactorSpecModel
+ compactorDefaultNodeGroup NodeGroupModel
+ computeSpec ComputeSpecModel
+ computeDefaultNodeGroup NodeGroupModel
+ frontendSpec FrontendSpecModel
+ frontendDefaultNodeGroup NodeGroupModel
+ metaSpec MetaSpecModel
+ metaDefaultNodeGroup NodeGroupModel
+
+ useEtcdMetaStore bool
+ etcdMetaStore EtcdMetaStoreModel
+ etcdDefaultNodeGroup NodeGroupModel
)
tflog.Trace(ctx, "parsing spec")
@@ -347,25 +424,25 @@ func dataModelToCluster(ctx context.Context, data *ClusterModel, cluster *apigen
tflog.Trace(ctx, "parsing compactorSpec")
diags.Append(spec.CompactorSpec.As(ctx, &compactorSpec, objectAsOptions)...)
- diags.Append(compactorSpec.Resource.As(ctx, &compactorResource, objectAsOptions)...)
+ diags.Append(compactorSpec.DefaultNodeGroup.As(ctx, &compactorDefaultNodeGroup, objectAsOptions)...)
tflog.Trace(ctx, "parsing computeSpec")
diags.Append(spec.ComputeSpec.As(ctx, &computeSpec, objectAsOptions)...)
- diags.Append(computeSpec.Resource.As(ctx, &computeResource, objectAsOptions)...)
+ diags.Append(computeSpec.DefaultNodeGroup.As(ctx, &computeDefaultNodeGroup, objectAsOptions)...)
tflog.Trace(ctx, "parsing frontendSpec")
diags.Append(spec.FrontendSpec.As(ctx, &frontendSpec, objectAsOptions)...)
- diags.Append(frontendSpec.Resource.As(ctx, &frontendResource, objectAsOptions)...)
+ diags.Append(frontendSpec.DefaultNodeGroup.As(ctx, &frontendDefaultNodeGroup, objectAsOptions)...)
tflog.Trace(ctx, "parsing metaSpec")
diags.Append(spec.MetaSpec.As(ctx, &metaSpec, objectAsOptions)...)
- diags.Append(metaSpec.Resource.As(ctx, &metaResource, objectAsOptions)...)
+ diags.Append(metaSpec.DefaultNodeGroup.As(ctx, &metaDefaultNodeGroup, objectAsOptions)...)
if !metaSpec.EtcdMetaStore.IsNull() {
tflog.Trace(ctx, "parsing etcdMetaStore")
useEtcdMetaStore = true
diags.Append(metaSpec.EtcdMetaStore.As(ctx, &etcdMetaStore, objectAsOptions)...)
- diags.Append(etcdMetaStore.Resource.As(ctx, &etcdResource, objectAsOptions)...)
+ diags.Append(etcdMetaStore.DefaultNodeGroup.As(ctx, &etcdDefaultNodeGroup, objectAsOptions)...)
}
if !useEtcdMetaStore {
@@ -394,28 +471,24 @@ func dataModelToCluster(ctx context.Context, data *ClusterModel, cluster *apigen
cluster.RwConfig = spec.RisingWaveConfig.ValueString()
cluster.EtcdConfig = etcdMetaStore.EtcdConfig.ValueString()
cluster.Region = data.Region.ValueString()
+
+ computeResource := r.nodeGroupModelToComponentResource(ctx, diags, &computeDefaultNodeGroup, cluster.Region, cluster.Tier, "compute")
+ compactorResource := r.nodeGroupModelToComponentResource(ctx, diags, &compactorDefaultNodeGroup, cluster.Region, cluster.Tier, "compactor")
+ frontendResource := r.nodeGroupModelToComponentResource(ctx, diags, &frontendDefaultNodeGroup, cluster.Region, cluster.Tier, "frontend")
+ metaResource := r.nodeGroupModelToComponentResource(ctx, diags, &metaDefaultNodeGroup, cluster.Region, cluster.Tier, "meta")
+ etcdResuorce := r.nodeGroupModelToComponentResource(ctx, diags, &etcdDefaultNodeGroup, cluster.Region, cluster.Tier, "etcd")
+
+ if diags.HasError() {
+ return diags
+ }
+
cluster.Resources = apigen_mgmt.TenantResource{
Components: apigen_mgmt.TenantResourceComponents{
- Compactor: &apigen_mgmt.ComponentResource{
- ComponentTypeId: compactorResource.Id.ValueString(),
- Replica: int(compactorResource.Replica.ValueInt64()),
- },
- Compute: &apigen_mgmt.ComponentResource{
- ComponentTypeId: computeResource.Id.ValueString(),
- Replica: int(computeResource.Replica.ValueInt64()),
- },
- Frontend: &apigen_mgmt.ComponentResource{
- ComponentTypeId: frontendResource.Id.ValueString(),
- Replica: int(frontendResource.Replica.ValueInt64()),
- },
- Meta: &apigen_mgmt.ComponentResource{
- ComponentTypeId: metaResource.Id.ValueString(),
- Replica: int(metaResource.Replica.ValueInt64()),
- },
- Etcd: apigen_mgmt.ComponentResource{
- ComponentTypeId: etcdResource.Id.ValueString(),
- Replica: int(etcdResource.Replica.ValueInt64()),
- },
+ Compactor: compactorResource,
+ Compute: computeResource,
+ Frontend: frontendResource,
+ Meta: metaResource,
+ Etcd: *etcdResuorce,
},
ComputeFileCacheSizeGiB: DefaultComputeFileCacheSizeGB,
EnableComputeFileCache: DefaultEnableComputeFileCache,
@@ -447,7 +520,7 @@ func (r *ClusterResource) Create(ctx context.Context, req resource.CreateRequest
return
}
- resp.Diagnostics.Append(dataModelToCluster(ctx, &data, &cluster)...)
+ resp.Diagnostics.Append(r.dataModelToCluster(ctx, &data, &cluster)...)
if resp.Diagnostics.HasError() {
return
@@ -576,7 +649,9 @@ func (r *ClusterResource) Read(ctx context.Context, req resource.ReadRequest, re
}
func resourceEqual(a, b *apigen_mgmt.ComponentResource) bool {
- return a.ComponentTypeId == b.ComponentTypeId && a.Replica == b.Replica
+ return a.Cpu == b.Cpu &&
+ a.Memory == b.Memory &&
+ a.Replica == b.Replica
}
func (r *ClusterResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
@@ -608,7 +683,7 @@ func (r *ClusterResource) Update(ctx context.Context, req resource.UpdateRequest
var updated = apigen_mgmt.Tenant{}
- resp.Diagnostics.Append(dataModelToCluster(ctx, &data, &updated)...)
+ resp.Diagnostics.Append(r.dataModelToCluster(ctx, &data, &updated)...)
previous, err := r.client.GetClusterByNsID(ctx, nsID)
if err != nil {
@@ -657,7 +732,7 @@ func (r *ClusterResource) Update(ctx context.Context, req resource.UpdateRequest
if !resourceEqual(&previous.Resources.Components.Etcd, &updated.Resources.Components.Etcd) {
resp.Diagnostics.AddError(
"Cannot update immutable field",
- "Etcd resource cannot be changed",
+ fmt.Sprintf("Etcd resource cannot be changed, previous: %v, updated: %v", previous.Resources.Components.Etcd, updated.Resources.Components.Etcd),
)
}
if resp.Diagnostics.HasError() {