package provider
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-provider-scaffolding-framework/tidbcloud"
)
// Ensure provider defined types fully satisfy framework interfaces
var _ tfsdk.ResourceType = clusterResourceType{}
var _ tfsdk.Resource = clusterResource{}
var _ tfsdk.ResourceWithImportState = clusterResource{}
type clusterResourceType struct{}
func (t clusterResourceType) GetSchema(ctx context.Context) (tfsdk.Schema, diag.Diagnostics) {
return tfsdk.Schema{
// This description is used by the documentation generator and the language server.
MarkdownDescription: "Cluster resource",
Attributes: map[string]tfsdk.Attribute{
"project_id": {
MarkdownDescription: "The ID of the project",
Required: true,
Type: types.StringType,
},
"name": {
MarkdownDescription: "The name of the cluster",
Required: true,
Type: types.StringType,
},
"cluster_id": {
MarkdownDescription: "The ID of the cluster",
Computed: true,
Type: types.StringType,
PlanModifiers: tfsdk.AttributePlanModifiers{
tfsdk.UseStateForUnknown(),
},
},
"cluster_type": {
MarkdownDescription: "DEVELOPER: create a Developer Tier cluster \n DEDICATED:create a Dedicated Tier cluster",
Required: true,
Type: types.StringType,
},
"cloud_provider": {
MarkdownDescription: "AWS: the Amazon Web Services cloud provider \n GCP:the Google Cloud Platform cloud provider",
Required: true,
Type: types.StringType,
},
"region": {
MarkdownDescription: "the region value should match the cloud provider's region code",
Required: true,
Type: types.StringType,
},
"config": {
MarkdownDescription: "The configuration of the cluster",
Required: true,
Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{
"root_password": {
Required: true,
Type: types.StringType,
},
"port": {
Optional: true,
Type: types.Int64Type,
},
"components": {
Optional: true,
Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{
"tidb": {
Required: true,
Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{
"node_size": {
Required: true,
Type: types.StringType,
},
"node_quantity": {
Required: true,
Type: types.Int64Type,
},
}),
},
"tikv": {
Required: true,
Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{
"node_size": {
Required: true,
Type: types.StringType,
},
"storage_size_gib": {
Required: true,
Type: types.Int64Type,
},
"node_quantity": {
Required: true,
Type: types.Int64Type,
},
}),
},
"tiflash": {
Optional: true,
Attributes: tfsdk.SingleNestedAttributes(map[string]tfsdk.Attribute{
"node_size": {
Required: true,
Type: types.StringType,
},
"storage_size_gib": {
Required: true,
Type: types.Int64Type,
},
"node_quantity": {
Required: true,
Type: types.Int64Type,
},
}),
},
}),
},
"ip_access_list": {
Optional: true,
Attributes: tfsdk.ListNestedAttributes(map[string]tfsdk.Attribute{
"cidr": {
Required: true,
Type: types.StringType,
},
"description": {
Optional: true,
Type: types.StringType,
},
}),
},
}),
},
},
}, nil
}
func (t clusterResourceType) NewResource(ctx context.Context, in tfsdk.Provider) (tfsdk.Resource, diag.Diagnostics) {
provider, diags := convertProviderType(in)
return clusterResource{
provider: provider,
}, diags
}
type clusterResourceData struct {
clusterId types.String `tfsdk:"cluster_id"`
ProjectId types.String `tfsdk:"project_id"`
Name types.String `tfsdk:"name"`
ClusterType types.String `tfsdk:"cluster_type"`
CloudProvider types.String `tfsdk:"cloud_provider"`
Region types.String `tfsdk:"region"`
Config ClusterConfig `tfsdk:"config"`
}
type ClusterConfig struct {
RootPassword string `tfsdk:"root_password"`
Port int32 `tfsdk:"port"`
Components Components `tfsdk:"components"`
IPAccessList []IPAccess `tfsdk:"ip_access_list"`
}
type Components struct {
TiDB ComponentTiDB `tfsdk:"tidb"`
TiKV ComponentTiKV `tfsdk:"tikv"`
TiFlash ComponentTiFlash `tfsdk:"tiflash"`
}
type ComponentTiDB struct {
NodeSize string `tfsdk:"node_size"`
NodeQuantity int `tfsdk:"node_quantity"`
}
type ComponentTiKV struct {
NodeSize string `tfsdk:"node_size"`
StorageSizeGib int `tfsdk:"storage_size_gib"`
NodeQuantity int `tfsdk:"node_quantity"`
}
type ComponentTiFlash struct {
NodeSize string `tfsdk:"node_size"`
StorageSizeGib int32 `tfsdk:"storage_size_gib"`
NodeQuantity int32 `tfsdk:"node_quantity"`
}
type IPAccess struct {
CIDR string `tfsdk:"cidr"`
Description string `tfsdk:"description"`
}
type clusterResource struct {
provider provider
}
func (r clusterResource) Create(ctx context.Context, req tfsdk.CreateResourceRequest, resp *tfsdk.CreateResourceResponse) {
if !r.provider.configured {
resp.Diagnostics.AddError(
"Provider not configured",
"The provider hasn't been configured before apply, likely because it depends on an unknown value from another resource. This leads to weird stuff happening, so we'd prefer if you didn't do that. Thanks!",
)
return
}
var data clusterResourceData
diags := req.Config.Get(ctx, &data)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
// write logs using the tflog package
// see https://pkg.go.dev/github.com/hashicorp/terraform-plugin-log/tflog
// for more information
tflog.Trace(ctx, "created a resource")
// If applicable, this is a great opportunity to initialize any necessary
// provider client data and make a call using it.
createClusterResp, err := r.provider.client.CreateCluster(data.ProjectId.Value, convertToCreateClusterReq(data))
if err != nil {
resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to create cluster, got error: %s", err))
return
}
// save into the Terraform state.
data.clusterId = types.String{Value: fmt.Sprintf("%s", createClusterResp.ClusterID)}
diags = resp.State.Set(ctx, &data)
resp.Diagnostics.Append(diags...)
}
resource "tidbcloud_cluster" "cluster1" {
project_id = "1369847559691457392"
name = "cluster1"
cluster_type = "DEVELOPER"
cloud_provider = "AWS"
region = "us-east-1"
config = {
root_password = "Shiyuhang1."
port = 4000
components = {
tidb = {
node_size : "8C16G"
node_quantity : 2
}
tikv = {
node_size : "8C16G"
storage_size_gib : 1024,
node_quantity : 3
}
tiflash = {
node_size : "8C16G"
storage_size_gib : 1024,
node_quantity : 4
}
}
ip_access_list = [{
cidr = "0.0.0.0/0"
description = "all"
}
]
}
}