From a48e2ecd04610b313845ba75dc2e973b6cd5e68e Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Mon, 6 May 2024 09:42:36 +0800 Subject: [PATCH 1/7] add dotfile Signed-off-by: Liang Huang --- .tool-versions | 1 + 1 file changed, 1 insertion(+) create mode 100644 .tool-versions diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..0e6ce87 --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +golang 1.21.9 From 3aff95730bdfc640ed2976b05c40b044d15fb545 Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Wed, 8 May 2024 11:05:39 +0800 Subject: [PATCH 2/7] enhance(client): add test cases Signed-off-by: Liang Huang --- client/cluster.go | 18 +- client/cluster_test.go | 295 ++++++++++++++++++ client/error.go | 8 + client/project_test.go | 105 ++----- client/provider.go | 22 ++ client/provider_test.go | 43 +++ client/region.go | 35 +++ client/region_test.go | 57 ++++ client/testdata/TestClient_Cluster.json | 4 + .../TestClient_Cluster/CreateCluster.json | 4 + .../TestClient_Cluster/DeleteCluster.json | 4 + .../TestClient_Cluster/DescribeCluster.json | 4 + .../duplicately_create_cluster.json | 4 + .../TestClient_Cluster/scale_up_cluster.json | 4 + .../ListCloudProviders.json | 4 + .../ListCloudRegions_via_aws.json | 4 + .../ListCloudRegions_via_azure.json | 4 + .../ListCloudRegions_via_gcp.json | 4 + .../TestClient_ListProject/ListProjects.json | 4 + .../get_project_list_with_wrong_api_key.json | 4 + .../TestClient_ServerlessCluster.json | 4 + .../DeleteCluster.json | 4 + .../DescribeCluster.json | 4 + .../create_serverless_cluster.json | 4 + .../duplicately_create_cluster.json | 4 + client/util_test.go | 149 +++++++++ client/zilliz.go | 265 ++++++++++------ client/zilliz_test.go | 96 ++++-- 28 files changed, 966 insertions(+), 195 deletions(-) create mode 100644 client/provider.go create mode 100644 client/provider_test.go create mode 100644 client/region.go create mode 100644 client/region_test.go create mode 100644 client/testdata/TestClient_Cluster.json create mode 100644 client/testdata/TestClient_Cluster/CreateCluster.json create mode 100644 client/testdata/TestClient_Cluster/DeleteCluster.json create mode 100644 client/testdata/TestClient_Cluster/DescribeCluster.json create mode 100644 client/testdata/TestClient_Cluster/duplicately_create_cluster.json create mode 100644 client/testdata/TestClient_Cluster/scale_up_cluster.json create mode 100644 client/testdata/TestClient_ListCloudProviders/ListCloudProviders.json create mode 100644 client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_aws.json create mode 100644 client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_azure.json create mode 100644 client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_gcp.json create mode 100644 client/testdata/TestClient_ListProject/ListProjects.json create mode 100644 client/testdata/TestClient_ListProject/get_project_list_with_wrong_api_key.json create mode 100644 client/testdata/TestClient_ServerlessCluster.json create mode 100644 client/testdata/TestClient_ServerlessCluster/DeleteCluster.json create mode 100644 client/testdata/TestClient_ServerlessCluster/DescribeCluster.json create mode 100644 client/testdata/TestClient_ServerlessCluster/create_serverless_cluster.json create mode 100644 client/testdata/TestClient_ServerlessCluster/duplicately_create_cluster.json create mode 100644 client/util_test.go diff --git a/client/cluster.go b/client/cluster.go index f270a2e..c293334 100644 --- a/client/cluster.go +++ b/client/cluster.go @@ -1,5 +1,14 @@ package client +type Plan string + +var ( + FreePlan Plan = "Free" + ServerlessPlan Plan = "Serverless" + StandardPlan Plan = "Standard" + EnterprisePlan Plan = "Enterprise" +) + type ModifyClusterParams struct { CuSize int `json:"cuSize"` } @@ -41,6 +50,7 @@ type Cluster struct { Description string `json:"description"` RegionId string `json:"regionId"` ClusterType string `json:"clusterType"` + Plan Plan `json:"plan"` CuSize int64 `json:"cuSize"` Status string `json:"status"` ConnectAddress string `json:"connectAddress"` @@ -61,16 +71,19 @@ func (c *Client) DescribeCluster(clusterId string) (Cluster, error) { } type CreateClusterParams struct { - Plan string `json:"plan"` + Plan Plan `json:"plan"` ClusterName string `json:"clusterName"` CUSize int `json:"cuSize"` CUType string `json:"cuType"` ProjectId string `json:"projectId"` + RegionId string } type CreateServerlessClusterParams struct { ClusterName string `json:"clusterName"` ProjectId string `json:"projectId"` + Plan Plan `json:"plan,omitempty"` + RegionId string } type CreateClusterResponse struct { @@ -81,6 +94,9 @@ type CreateClusterResponse struct { } func (c *Client) CreateCluster(params CreateClusterParams) (*CreateClusterResponse, error) { + if params.RegionId == "" && c.RegionId == "" { + return nil, errRegionIdRequired + } var clusterResponse zillizResponse[CreateClusterResponse] err := c.do("POST", "clusters/create", params, &clusterResponse) return &clusterResponse.Data, err diff --git a/client/cluster_test.go b/client/cluster_test.go index da13c8e..d81047f 100644 --- a/client/cluster_test.go +++ b/client/cluster_test.go @@ -1 +1,296 @@ package client + +import ( + "context" + "errors" + "testing" + "time" +) + +func TestClient_Cluster(t *testing.T) { + var clusterId string + var projectID string + if update { + pollInterval = 60 + } + + checkPlan := func(plan string) func(resp *Cluster) bool { + return func(resp *Cluster) bool { + return resp.Plan == Plan(plan) + } + } + + checkCUSize := func(cuSize int64) func(resp *Cluster) bool { + return func(resp *Cluster) bool { + return resp.CuSize == cuSize + } + } + + checkClusterType := func(clusterType string) func(resp *Cluster) bool { + return func(resp *Cluster) bool { + return resp.ClusterType == clusterType + } + } + + c, teardown := zillizClient[Clusters](t) + defer teardown() + + getProject := func() string { + + projects, err := c.ListProjects() + if err != nil { + t.Fatalf("failed to list projects: %v", err) + } + + var want string = "Default Project" + + if len(projects) == 0 || projects[0].ProjectName != want { + t.Errorf("want = %s, got = %v", want, projects) + } + + return projects[0].ProjectId + } + + projectID = getProject() + params := CreateClusterParams{ + ProjectId: projectID, + Plan: "Standard", + ClusterName: "a-standard-type-cluster", + CUSize: 1, + CUType: "Performance-optimized", + } + + t.Run("CreateCluster", func(t *testing.T) { + c, teardown := zillizClient[Clusters](t) + defer teardown() + + resp, err := c.CreateCluster(params) + if err != nil { + t.Fatalf("failed to create cluster: %v", err) + } + + if resp.ClusterId == "" { + t.Fatalf("failed to create cluster: %v", resp) + } + + clusterId = resp.ClusterId + }) + + t.Run("duplicately create cluster", func(t *testing.T) { + + c, teardown := zillizClient[Clusters](t) + defer teardown() + _, err := c.CreateCluster(params) + + var e = Error{ + Code: 80010, + } + + if !errors.Is(err, e) { + t.Fatalf("want = %v, but got = %v", e, err) + } + + }) + + t.Run("DescribeCluster", func(t *testing.T) { + + c, teardown := zillizClient[Clusters](t) + defer teardown() + // checkfn:=make([]func(resp *Cluster) bool,0) + checkfn := []func(resp *Cluster) bool{ + checkPlan("Standard"), + checkCUSize(1), + checkClusterType("Performance-optimized"), + } + + ctx, cancelfn := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancelfn() + got := pollClusterStatus(ctx, t, c, clusterId, "RUNNING", pollInterval) + + for _, fn := range checkfn { + if !fn(got) { + t.Errorf("check failed") + } + } + + }) + + t.Run("scale up cluster", func(t *testing.T) { + c, teardown := zillizClient[Clusters](t) + defer teardown() + checkfn := []func(resp *Cluster) bool{ + checkCUSize(2), + } + _, err := c.ModifyCluster(clusterId, &ModifyClusterParams{ + + CuSize: 2, + }) + if err != nil { + t.Fatalf("failed to describe cluster: %v", err) + } + + ctx, cancelfn := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancelfn() + got := pollClusterStatus(ctx, t, c, clusterId, "RUNNING", pollInterval) + for _, fn := range checkfn { + if !fn(got) { + t.Errorf("check failed") + } + } + + }) + + t.Run("DeleteCluster", func(t *testing.T) { + + c, teardown := zillizClient[Clusters](t) + defer teardown() + got, err := c.DropCluster(clusterId) + if err != nil { + t.Fatalf("failed to delete cluster: %v", err) + } + + if got == nil || *got != clusterId { + t.Fatalf("want = %s, got = %v", clusterId, got) + } + }) +} + +func TestClient_ServerlessCluster(t *testing.T) { + var clusterId string + var projectID string + if update { + pollInterval = 60 + } + + checkClusterId := func(clusterId string) func(resp *Cluster) bool { + return func(resp *Cluster) bool { + return resp.ClusterId == clusterId + } + } + + c, teardown := zillizClient[Clusters](t) + defer teardown() + + getProject := func() string { + + projects, err := c.ListProjects() + if err != nil { + t.Fatalf("failed to list projects: %v", err) + } + + var want string = "Default Project" + + if len(projects) == 0 || projects[0].ProjectName != want { + t.Errorf("want = %s, got = %v", want, projects) + } + + return projects[0].ProjectId + } + + projectID = getProject() + params := CreateServerlessClusterParams{ + ProjectId: projectID, + ClusterName: "a-starter-type-cluster", + } + + t.Run("create serverless cluster", func(t *testing.T) { + c, teardown := zillizClient[Clusters](t) + defer teardown() + + resp, err := c.CreateServerlessCluster(params) + if err != nil { + t.Fatalf("failed to create cluster: %v", err) + } + + if resp.ClusterId == "" { + t.Fatalf("failed to create cluster: %v", resp) + } + + clusterId = resp.ClusterId + }) + + t.Run("duplicately create cluster", func(t *testing.T) { + + c, teardown := zillizClient[Clusters](t) + defer teardown() + + _, err := c.CreateServerlessCluster(params) + var e = Error{ + Code: 80010, + } + + if !errors.Is(err, e) { + t.Fatalf("want = %v, but got = %v", e, err) + } + + }) + + t.Run("DescribeCluster", func(t *testing.T) { + + c, teardown := zillizClient[Clusters](t) + defer teardown() + // checkfn:=make([]func(resp *Cluster) bool,0) + checkfn := []func(resp *Cluster) bool{ + checkClusterId(clusterId), + } + + ctx, cancelfn := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancelfn() + got := pollClusterStatus(ctx, t, c, clusterId, "RUNNING", pollInterval) + + for _, fn := range checkfn { + if !fn(got) { + t.Errorf("check failed") + } + } + + }) + + t.Run("DeleteCluster", func(t *testing.T) { + + c, teardown := zillizClient[Clusters](t) + defer teardown() + got, err := c.DropCluster(clusterId) + if err != nil { + t.Fatalf("failed to delete cluster: %v", err) + } + + if got == nil || *got != clusterId { + t.Fatalf("want = %s, got = %v", clusterId, got) + } + }) +} + +func pollClusterStatus(ctx context.Context, t *testing.T, c *Client, clusterId string, status string, pollingInterval int) *Cluster { + + var ( + got Cluster + err error + ) + interval := time.Duration(pollingInterval) * time.Second + // ctx, _ := context.WithTimeout(ctx, 5*time.Minute) + + for { + select { + case <-ctx.Done(): + t.Fatalf("timeout") + return nil + + case <-time.After(interval): + t.Logf("[%s] polling cluster status...", time.Now().Format("2006-01-02 15:04:05")) + + got, err = c.DescribeCluster(clusterId) + if err != nil { + t.Fatalf("failed to describe cluster: %v", err) + } + + switch got.Status { + case status: + return &got + default: + continue + } + } + + } +} diff --git a/client/error.go b/client/error.go index f34f43e..4418147 100644 --- a/client/error.go +++ b/client/error.go @@ -12,3 +12,11 @@ type Error struct { func (err Error) Error() string { return fmt.Sprintf("code:%d,Message:%s", err.Code, err.Message) } + +func (err Error) Is(target error) bool { + t, ok := target.(Error) + if !ok { + return false + } + return t.Code == err.Code +} diff --git a/client/project_test.go b/client/project_test.go index fed58ae..45cd980 100644 --- a/client/project_test.go +++ b/client/project_test.go @@ -1,90 +1,49 @@ package client import ( - "flag" + "errors" "testing" ) -var ( - apiKey string -) +func TestClient_ListProject(t *testing.T) { -func init() { - flag.StringVar(&apiKey, "key", "", "Your TEST secret key for the zilliz cloud API. If present, integration tests will be run using this key.") -} + t.Run("ListProjects", func(t *testing.T) { + c, teardown := zillizClient[[]Project](t) + defer teardown() -func TestClient_ListProjects(t *testing.T) { - if apiKey == "" { - t.Skip("No API key provided") - } + got, err := c.ListProjects() + if err != nil { + t.Fatalf("failed to list projects: %v", err) + } - type checkFn func(*testing.T, []Project, error) - check := func(fns ...checkFn) []checkFn { return fns } + var want string = "Default Project" - hasNoErr := func() checkFn { - return func(t *testing.T, _ []Project, err error) { - if err != nil { - t.Fatalf("err = %v; want nil", err) - } + if len(got) == 0 || got[0].ProjectName != want { + t.Errorf("want = %s, got = %v", want, got) } - } - hasErrCode := func(code int) checkFn { - return func(t *testing.T, _ []Project, err error) { - se, ok := err.(Error) - if !ok { - t.Fatalf("err isn't a Error") - } - if se.Code != code { - t.Errorf("err.Code = %d; want %d", se.Code, code) - } - } - } + }) - hasProject := func(Name string) checkFn { - return func(t *testing.T, p []Project, err error) { - for _, project := range p { - if project.ProjectName == Name { - return - } - } - t.Errorf("project not found: %s", Name) + t.Run("get project list with wrong api key", func(t *testing.T) { + var tmp string + if apiKey != "" { + tmp = apiKey } - } + defer func() { + apiKey = tmp + }() - type fields struct { - CloudRegionId string - apiKey string - } - tests := []struct { - name string - fields fields - checks []checkFn - }{ - { - "postive 1", - fields{CloudRegionId: "gcp-us-west1", apiKey: apiKey}, - check( - hasNoErr(), - hasProject("Default Project")), - }, - { - "none exist region", - fields{CloudRegionId: "gcp-us-west1", apiKey: "fake"}, - check(hasErrCode(80001)), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := NewClient( - tt.fields.apiKey, - tt.fields.CloudRegionId, - ) + apiKey = "gibberish_api_key" + c, teardown := zillizClient[[]Project](t) + defer teardown() + + _, err := c.ListProjects() + var apierr = Error{ + Code: 80001, + } + if !errors.Is(err, apierr) { + t.Errorf("want = %v, got = %v", apierr, err) + } + }) - got, err := c.ListProjects() - for _, check := range tt.checks { - check(t, got, err) - } - }) - } } diff --git a/client/provider.go b/client/provider.go new file mode 100644 index 0000000..b069986 --- /dev/null +++ b/client/provider.go @@ -0,0 +1,22 @@ +package client + +type CloudId string + +var ( + AWS CloudId = "aws" + Azure CloudId = "azure" + GCP CloudId = "gcp" + AliCloud CloudId = "ali" + TencentCloud CloudId = "tc" +) + +type CloudProvider struct { + CloudId CloudId `json:"cloudId"` + Description string `json:"description"` +} + +func (c *Client) ListCloudProviders() ([]CloudProvider, error) { + var cloudProviders zillizResponse[[]CloudProvider] + err := c.do("GET", "clouds", nil, &cloudProviders) + return cloudProviders.Data, err +} diff --git a/client/provider_test.go b/client/provider_test.go new file mode 100644 index 0000000..94181a8 --- /dev/null +++ b/client/provider_test.go @@ -0,0 +1,43 @@ +package client + +import ( + "testing" +) + +func TestClient_ListCloudProviders(t *testing.T) { + + t.Run("ListCloudProviders", func(t *testing.T) { + + checkFn := make(map[string]func(cloudProviders []CloudProvider) bool, 0) + + has := func(cloudId string) func(cloudProviders []CloudProvider) bool { + return func(cloudProviders []CloudProvider) bool { + for _, cp := range cloudProviders { + if string(cp.CloudId) == cloudId { + return true + } + } + return false + } + } + + checkFn["aws"] = has("aws") + checkFn["azure"] = has("azure") + checkFn["gcp"] = has("gcp") + + c, teardown := zillizClient[[]CloudProvider](t) + defer teardown() + + got, err := c.ListCloudProviders() + if err != nil { + t.Fatalf("failed to ListCloudProviders: %v", err) + } + + for k, fn := range checkFn { + if !fn(got) { + t.Errorf("has %s failed", k) + } + } + + }) +} diff --git a/client/region.go b/client/region.go new file mode 100644 index 0000000..3bf88b6 --- /dev/null +++ b/client/region.go @@ -0,0 +1,35 @@ +package client + +import ( + "fmt" + "strings" +) + +type CloudRegion struct { + ApiBaseUrl string `json:"apiBaseUrl"` + CloudId string `json:"cloudId"` + RegionId string `json:"regionId"` +} + +func (c *Client) ListCloudRegions(cloudId string) ([]CloudRegion, error) { + var cloudRegions zillizResponse[[]CloudRegion] + err := c.do("GET", "regions?cloudId="+cloudId, nil, &cloudRegions) + return cloudRegions.Data, err +} + +func BaseUrlFrom(cloudRegionId string) string { + tokens := strings.Split(cloudRegionId, "-") + + cloudId := tokens[0] + template := globalApiTemplateUrl + + switch CloudId(cloudId) { + case AliCloud, TencentCloud: + template = cnApiTemplateUrl + default: + // aws, gcp, azure, unknown will use global apiTemplateUrl + + } + + return fmt.Sprintf(template, cloudRegionId) +} diff --git a/client/region_test.go b/client/region_test.go new file mode 100644 index 0000000..85ae343 --- /dev/null +++ b/client/region_test.go @@ -0,0 +1,57 @@ +package client + +import ( + "testing" +) + +func TestClient_BaseUrlFromCloudRegion(t *testing.T) { + testCases := []struct { + cloudRegionId string + want string + }{ + {"aws-us-east-2", "https://controller.api.aws-us-east-2.zillizcloud.com/v1/"}, + {"aws-us-east-1", "https://controller.api.aws-us-east-1.zillizcloud.com/v1/"}, + {"az-eastus", "https://controller.api.az-eastus.zillizcloud.com/v1/"}, + {"ali-cn-beijing", "https://controller.api.ali-cn-beijing.cloud.zilliz.com.cn/v1/"}, + {"tc-ap-shanghai", "https://controller.api.tc-ap-shanghai.cloud.zilliz.com.cn/v1/"}, + {"unknown-eastus", "https://controller.api.unknown-eastus.zillizcloud.com/v1/"}, + {"unknown", "https://controller.api.unknown.zillizcloud.com/v1/"}, + } + + for _, tc := range testCases { + t.Run(tc.cloudRegionId, func(t *testing.T) { + got := BaseUrlFrom(tc.cloudRegionId) + if got != tc.want { + t.Errorf("want = %s, got = %s", tc.want, got) + } + }) + } + +} + +func TestClient_ListCloudRegions(t *testing.T) { + testCases := []struct { + cloudId CloudId + notWant int + }{ + {GCP, 0}, + {AWS, 0}, + {Azure, 0}, + } + + for _, tc := range testCases { + t.Run("ListCloudRegions via "+string(tc.cloudId), func(t *testing.T) { + c, teardown := zillizClient[[]CloudRegion](t) + defer teardown() + + got, err := c.ListCloudRegions(string(tc.cloudId)) + if err != nil { + t.Fatalf("failed to ListCloudRegions: %v", err) + } + + if len(got) == tc.notWant { + t.Errorf("want > %d, got = %v", tc.notWant, got) + } + }) + } +} diff --git a/client/testdata/TestClient_Cluster.json b/client/testdata/TestClient_Cluster.json new file mode 100644 index 0000000..64352e4 --- /dev/null +++ b/client/testdata/TestClient_Cluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOlt7ImNyZWF0ZVRpbWVNaWxsaSI6MTcxNDg5MjE3NTAwMCwiaW5zdGFuY2VDb3VudCI6MCwicHJvamVjdElkIjoicHJvai00NDg3NTgwZmNmZTJjOGE0MzkxNjg2IiwicHJvamVjdE5hbWUiOiJEZWZhdWx0IFByb2plY3QifV19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_Cluster/CreateCluster.json b/client/testdata/TestClient_Cluster/CreateCluster.json new file mode 100644 index 0000000..892e773 --- /dev/null +++ b/client/testdata/TestClient_Cluster/CreateCluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOnsiY2x1c3RlcklkIjoiaW4wMS04NTBhMjRlY2UxNGQ4NzIiLCJ1c2VybmFtZSI6ImRiX2FkbWluIiwicGFzc3dvcmQiOiJGeTAubTY5bUdhbkMpLlRRIiwicHJvbXB0IjoiU3VibWlzc2lvbiBzdWNjZXNzZnVsLCBDbHVzdGVyIGlzIGJlaW5nIGNyZWF0ZWQsIFlvdSBjYW4gdXNlIHRoZSBEZXNjcmliZUNsdXN0ZXIgaW50ZXJmYWNlIHRvIG9idGFpbiB0aGUgY3JlYXRpb24gcHJvZ3Jlc3MgYW5kIHRoZSBzdGF0dXMgb2YgdGhlIENsdXN0ZXIuIFdoZW4gdGhlIENsdXN0ZXIgc3RhdHVzIGlzIFJVTk5JTkcsIHlvdSBjYW4gYWNjZXNzIHlvdXIgdmVjdG9yIGRhdGFiYXNlIHVzaW5nIHRoZSBTREsgd2l0aCB0aGUgYWRtaW4gYWNjb3VudCBhbmQgdGhlIGluaXRpYWxpemF0aW9uIHBhc3N3b3JkIHlvdSBwcm92aWRlZC4ifX0K" +} \ No newline at end of file diff --git a/client/testdata/TestClient_Cluster/DeleteCluster.json b/client/testdata/TestClient_Cluster/DeleteCluster.json new file mode 100644 index 0000000..0030ebd --- /dev/null +++ b/client/testdata/TestClient_Cluster/DeleteCluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOnsiY2x1c3RlcklkIjoiaW4wMS04NTBhMjRlY2UxNGQ4NzIiLCJwcm9tcHQiOiJUaGUgQ2x1c3RlciBoYXMgYmVlbiBkZWxldGVkLiBJZiB5b3UgYmVsaWV2ZSB0aGlzIHdhcyBhIG1pc3Rha2UsIHlvdSBjYW4gcmVzdG9yZSB0aGUgQ2x1c3RlciBmcm9tIHRoZSByZWN5Y2xlIGJpbiB3aXRoaW4gMzAgZGF5cyAodGhpcyBub3QgaW5jbHVkZSBzZXJ2ZXJsZXNzKS4ifX0K" +} \ No newline at end of file diff --git a/client/testdata/TestClient_Cluster/DescribeCluster.json b/client/testdata/TestClient_Cluster/DescribeCluster.json new file mode 100644 index 0000000..69a8dbd --- /dev/null +++ b/client/testdata/TestClient_Cluster/DescribeCluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOnsiY2x1c3RlcklkIjoiaW4wMS04NTBhMjRlY2UxNGQ4NzIiLCJjbHVzdGVyTmFtZSI6ImEtc3RhbmRhcmQtdHlwZS1jbHVzdGVyIiwiZGVzY3JpcHRpb24iOiJwcmUgY3JlYXRlIGluc3RhbmNlIiwicmVnaW9uSWQiOiJnY3AtdXMtd2VzdDEiLCJjbHVzdGVyVHlwZSI6IlBlcmZvcm1hbmNlLW9wdGltaXplZCIsInBsYW4iOiJTdGFuZGFyZCIsImN1U2l6ZSI6MSwic3RhdHVzIjoiUlVOTklORyIsImNvbm5lY3RBZGRyZXNzIjoiaHR0cHM6Ly9pbjAxLTg1MGEyNGVjZTE0ZDg3Mi5nY3AtdXMtd2VzdDEudmVjdG9yZGIuemlsbGl6Y2xvdWQuY29tOjQ0MyIsInByaXZhdGVMaW5rQWRkcmVzcyI6IiIsImNyZWF0ZVRpbWUiOiIyMDI0LTA1LTA2VDA1OjUyOjA2WiIsInN0b3JhZ2VTaXplIjowLCJzbmFwc2hvdE51bWJlciI6MCwiY3JlYXRlUHJvZ3Jlc3MiOjEwMCwicHJvamVjdElkIjoicHJvai00NDg3NTgwZmNmZTJjOGE0MzkxNjg2In19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_Cluster/duplicately_create_cluster.json b/client/testdata/TestClient_Cluster/duplicately_create_cluster.json new file mode 100644 index 0000000..61c6643 --- /dev/null +++ b/client/testdata/TestClient_Cluster/duplicately_create_cluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjo4MDAxMCwibWVzc2FnZSI6IkR1cGxpY2F0ZWQgQ2x1c3Rlck5hbWUuIFlvdSBoYXZlIGFscmVhZHkgY3JlYXRlZCBhbiBleGlzdCBDbHVzdGVyIHdpdGggdGhlIHNhbWUgbmFtZS4gVG8gYXZvaWQgY29tcGxleGl0eSBpbiBtYW5hZ2VtZW50LCBwbGVhc2UgbW9kaWZ5IHRoZSBuYW1lIGFuZCBjcmVhdGUgYSBuZXcgb25lLiJ9Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_Cluster/scale_up_cluster.json b/client/testdata/TestClient_Cluster/scale_up_cluster.json new file mode 100644 index 0000000..b296aea --- /dev/null +++ b/client/testdata/TestClient_Cluster/scale_up_cluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOnsiY2x1c3RlcklkIjoiaW4wMS04NTBhMjRlY2UxNGQ4NzIiLCJjbHVzdGVyTmFtZSI6ImEtc3RhbmRhcmQtdHlwZS1jbHVzdGVyIiwiZGVzY3JpcHRpb24iOiJwcmUgY3JlYXRlIGluc3RhbmNlIiwicmVnaW9uSWQiOiJnY3AtdXMtd2VzdDEiLCJjbHVzdGVyVHlwZSI6IlBlcmZvcm1hbmNlLW9wdGltaXplZCIsInBsYW4iOiJTdGFuZGFyZCIsImN1U2l6ZSI6Miwic3RhdHVzIjoiUlVOTklORyIsImNvbm5lY3RBZGRyZXNzIjoiaHR0cHM6Ly9pbjAxLTg1MGEyNGVjZTE0ZDg3Mi5nY3AtdXMtd2VzdDEudmVjdG9yZGIuemlsbGl6Y2xvdWQuY29tOjQ0MyIsInByaXZhdGVMaW5rQWRkcmVzcyI6IiIsImNyZWF0ZVRpbWUiOiIyMDI0LTA1LTA2VDA1OjUyOjA2WiIsInN0b3JhZ2VTaXplIjowLCJzbmFwc2hvdE51bWJlciI6MCwiY3JlYXRlUHJvZ3Jlc3MiOjEwMCwicHJvamVjdElkIjoicHJvai00NDg3NTgwZmNmZTJjOGE0MzkxNjg2In19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ListCloudProviders/ListCloudProviders.json b/client/testdata/TestClient_ListCloudProviders/ListCloudProviders.json new file mode 100644 index 0000000..b1fe1b1 --- /dev/null +++ b/client/testdata/TestClient_ListCloudProviders/ListCloudProviders.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOlt7ImNsb3VkSWQiOiJhd3MiLCJkZXNjcmlwdGlvbiI6ImFtYXpvbiBhd3MifSx7ImNsb3VkSWQiOiJnY3AiLCJkZXNjcmlwdGlvbiI6Imdvb2dsZSBjbG91ZCJ9LHsiY2xvdWRJZCI6ImF6dXJlIiwiZGVzY3JpcHRpb24iOiJhenVyZSJ9XX0K" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_aws.json b/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_aws.json new file mode 100644 index 0000000..4a644d4 --- /dev/null +++ b/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_aws.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOlt7ImFwaUJhc2VVcmwiOiJodHRwczovL2FwaS5hd3MtdXMtd2VzdC0yLnppbGxpemNsb3VkLmNvbSIsImNsb3VkSWQiOiJhd3MiLCJyZWdpb25JZCI6ImF3cy11cy13ZXN0LTIifSx7ImFwaUJhc2VVcmwiOiJodHRwczovL2FwaS5hd3MtdXMtZWFzdC0yLnppbGxpemNsb3VkLmNvbSIsImNsb3VkSWQiOiJhd3MiLCJyZWdpb25JZCI6ImF3cy11cy1lYXN0LTIifSx7ImFwaUJhc2VVcmwiOiJodHRwczovL2FwaS5hd3MtYXAtc291dGhlYXN0LTEuemlsbGl6Y2xvdWQuY29tIiwiY2xvdWRJZCI6ImF3cyIsInJlZ2lvbklkIjoiYXdzLWFwLXNvdXRoZWFzdC0xIn0seyJhcGlCYXNlVXJsIjoiaHR0cHM6Ly9hcGkuYXdzLXVzLWVhc3QtMS56aWxsaXpjbG91ZC5jb20iLCJjbG91ZElkIjoiYXdzIiwicmVnaW9uSWQiOiJhd3MtdXMtZWFzdC0xIn0seyJhcGlCYXNlVXJsIjoiaHR0cHM6Ly9hcGkuYXdzLWV1LWNlbnRyYWwtMS56aWxsaXpjbG91ZC5jb20iLCJjbG91ZElkIjoiYXdzIiwicmVnaW9uSWQiOiJhd3MtZXUtY2VudHJhbC0xIn1dfQo=" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_azure.json b/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_azure.json new file mode 100644 index 0000000..6d41b0e --- /dev/null +++ b/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_azure.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOlt7ImFwaUJhc2VVcmwiOiJodHRwczovL2FwaS5hei1lYXN0dXMuemlsbGl6Y2xvdWQuY29tIiwiY2xvdWRJZCI6ImF6dXJlIiwicmVnaW9uSWQiOiJhei1lYXN0dXMifSx7ImFwaUJhc2VVcmwiOiJodHRwczovL2FwaS5hei1nZXJtYW55d2VzdGNlbnRyYWwuemlsbGl6Y2xvdWQuY29tIiwiY2xvdWRJZCI6ImF6dXJlIiwicmVnaW9uSWQiOiJhei1nZXJtYW55d2VzdGNlbnRyYWwifV19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_gcp.json b/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_gcp.json new file mode 100644 index 0000000..0693385 --- /dev/null +++ b/client/testdata/TestClient_ListCloudRegions/ListCloudRegions_via_gcp.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOlt7ImFwaUJhc2VVcmwiOiJodHRwczovL2FwaS5nY3AtdXMtd2VzdDEuemlsbGl6Y2xvdWQuY29tIiwiY2xvdWRJZCI6ImdjcCIsInJlZ2lvbklkIjoiZ2NwLXVzLXdlc3QxIn0seyJhcGlCYXNlVXJsIjoiaHR0cHM6Ly9hcGkuZ2NwLWFzaWEtc291dGhlYXN0MS56aWxsaXpjbG91ZC5jb20iLCJjbG91ZElkIjoiZ2NwIiwicmVnaW9uSWQiOiJnY3AtYXNpYS1zb3V0aGVhc3QxIn0seyJhcGlCYXNlVXJsIjoiaHR0cHM6Ly9hcGkuZ2NwLXVzLWVhc3Q0LnppbGxpemNsb3VkLmNvbSIsImNsb3VkSWQiOiJnY3AiLCJyZWdpb25JZCI6ImdjcC11cy1lYXN0NCJ9LHsiYXBpQmFzZVVybCI6Imh0dHBzOi8vYXBpLmdjcC1ldXJvcGUtd2VzdDMuemlsbGl6Y2xvdWQuY29tIiwiY2xvdWRJZCI6ImdjcCIsInJlZ2lvbklkIjoiZ2NwLWV1cm9wZS13ZXN0MyJ9XX0K" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ListProject/ListProjects.json b/client/testdata/TestClient_ListProject/ListProjects.json new file mode 100644 index 0000000..64352e4 --- /dev/null +++ b/client/testdata/TestClient_ListProject/ListProjects.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOlt7ImNyZWF0ZVRpbWVNaWxsaSI6MTcxNDg5MjE3NTAwMCwiaW5zdGFuY2VDb3VudCI6MCwicHJvamVjdElkIjoicHJvai00NDg3NTgwZmNmZTJjOGE0MzkxNjg2IiwicHJvamVjdE5hbWUiOiJEZWZhdWx0IFByb2plY3QifV19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ListProject/get_project_list_with_wrong_api_key.json b/client/testdata/TestClient_ListProject/get_project_list_with_wrong_api_key.json new file mode 100644 index 0000000..f537853 --- /dev/null +++ b/client/testdata/TestClient_ListProject/get_project_list_with_wrong_api_key.json @@ -0,0 +1,4 @@ +{ + "status_code": 401, + "body": "eyJjb2RlIjo4MDAwMSwibWVzc2FnZSI6IkludmFsaWQgdG9rZW46IFlvdXIgdG9rZW4gaXMgbm90IHZhbGlkLiBQbGVhc2UgZG91YmxlLWNoZWNrIHlvdXIgcmVxdWVzdCBwYXJhbWV0ZXJzIGFuZCBlbnN1cmUgdGhhdCB5b3UgaGF2ZSBwcm92aWRlZCBhIHZhbGlkIHRva2VuLiJ9Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ServerlessCluster.json b/client/testdata/TestClient_ServerlessCluster.json new file mode 100644 index 0000000..64352e4 --- /dev/null +++ b/client/testdata/TestClient_ServerlessCluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOlt7ImNyZWF0ZVRpbWVNaWxsaSI6MTcxNDg5MjE3NTAwMCwiaW5zdGFuY2VDb3VudCI6MCwicHJvamVjdElkIjoicHJvai00NDg3NTgwZmNmZTJjOGE0MzkxNjg2IiwicHJvamVjdE5hbWUiOiJEZWZhdWx0IFByb2plY3QifV19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ServerlessCluster/DeleteCluster.json b/client/testdata/TestClient_ServerlessCluster/DeleteCluster.json new file mode 100644 index 0000000..60cf8e7 --- /dev/null +++ b/client/testdata/TestClient_ServerlessCluster/DeleteCluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOnsiY2x1c3RlcklkIjoiaW4wMy1kZWFmZjA3N2JkM2ZjMDciLCJwcm9tcHQiOiJUaGUgQ2x1c3RlciBoYXMgYmVlbiBkZWxldGVkLiBJZiB5b3UgYmVsaWV2ZSB0aGlzIHdhcyBhIG1pc3Rha2UsIHlvdSBjYW4gcmVzdG9yZSB0aGUgQ2x1c3RlciBmcm9tIHRoZSByZWN5Y2xlIGJpbiB3aXRoaW4gMzAgZGF5cyAodGhpcyBub3QgaW5jbHVkZSBzZXJ2ZXJsZXNzKS4ifX0K" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ServerlessCluster/DescribeCluster.json b/client/testdata/TestClient_ServerlessCluster/DescribeCluster.json new file mode 100644 index 0000000..3e339d8 --- /dev/null +++ b/client/testdata/TestClient_ServerlessCluster/DescribeCluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOnsiY2x1c3RlcklkIjoiaW4wMy1kZWFmZjA3N2JkM2ZjMDciLCJjbHVzdGVyTmFtZSI6ImEtc3RhcnRlci10eXBlLWNsdXN0ZXIiLCJkZXNjcmlwdGlvbiI6IiIsInJlZ2lvbklkIjoiZ2NwLXVzLXdlc3QxIiwiY2x1c3RlclR5cGUiOiIiLCJwbGFuIjoiRnJlZSIsImN1U2l6ZSI6MCwic3RhdHVzIjoiUlVOTklORyIsImNvbm5lY3RBZGRyZXNzIjoiaHR0cHM6Ly9pbjAzLWRlYWZmMDc3YmQzZmMwNy5hcGkuZ2NwLXVzLXdlc3QxLnppbGxpemNsb3VkLmNvbSIsInByaXZhdGVMaW5rQWRkcmVzcyI6IiIsImNyZWF0ZVRpbWUiOiIyMDI0LTA1LTA2VDA5OjE5OjUxWiIsInN0b3JhZ2VTaXplIjowLCJzbmFwc2hvdE51bWJlciI6MCwiY3JlYXRlUHJvZ3Jlc3MiOjEwMCwicHJvamVjdElkIjoicHJvai00NDg3NTgwZmNmZTJjOGE0MzkxNjg2In19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ServerlessCluster/create_serverless_cluster.json b/client/testdata/TestClient_ServerlessCluster/create_serverless_cluster.json new file mode 100644 index 0000000..479d718 --- /dev/null +++ b/client/testdata/TestClient_ServerlessCluster/create_serverless_cluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjoyMDAsImRhdGEiOnsiY2x1c3RlcklkIjoiaW4wMy1kZWFmZjA3N2JkM2ZjMDciLCJ1c2VybmFtZSI6ImRiX2RlYWZmMDc3YmQzZmMwNyIsInBhc3N3b3JkIjoiSms4JkFYN2s3eEQtTzshUiIsInByb21wdCI6IlN1Ym1pc3Npb24gc3VjY2Vzc2Z1bCwgQ2x1c3RlciBpcyBiZWluZyBjcmVhdGVkLCBZb3UgY2FuIHVzZSB0aGUgRGVzY3JpYmVDbHVzdGVyIGludGVyZmFjZSB0byBvYnRhaW4gdGhlIGNyZWF0aW9uIHByb2dyZXNzIGFuZCB0aGUgc3RhdHVzIG9mIHRoZSBDbHVzdGVyLiBXaGVuIHRoZSBDbHVzdGVyIHN0YXR1cyBpcyBSVU5OSU5HLCB5b3UgY2FuIGFjY2VzcyB5b3VyIHZlY3RvciBkYXRhYmFzZSB1c2luZyB0aGUgU0RLIHdpdGggdGhlIGFkbWluIGFjY291bnQgYW5kIHRoZSBpbml0aWFsaXphdGlvbiBwYXNzd29yZCB5b3UgcHJvdmlkZWQuIn19Cg==" +} \ No newline at end of file diff --git a/client/testdata/TestClient_ServerlessCluster/duplicately_create_cluster.json b/client/testdata/TestClient_ServerlessCluster/duplicately_create_cluster.json new file mode 100644 index 0000000..61c6643 --- /dev/null +++ b/client/testdata/TestClient_ServerlessCluster/duplicately_create_cluster.json @@ -0,0 +1,4 @@ +{ + "status_code": 200, + "body": "eyJjb2RlIjo4MDAxMCwibWVzc2FnZSI6IkR1cGxpY2F0ZWQgQ2x1c3Rlck5hbWUuIFlvdSBoYXZlIGFscmVhZHkgY3JlYXRlZCBhbiBleGlzdCBDbHVzdGVyIHdpdGggdGhlIHNhbWUgbmFtZS4gVG8gYXZvaWQgY29tcGxleGl0eSBpbiBtYW5hZ2VtZW50LCBwbGVhc2UgbW9kaWZ5IHRoZSBuYW1lIGFuZCBjcmVhdGUgYSBuZXcgb25lLiJ9Cg==" +} \ No newline at end of file diff --git a/client/util_test.go b/client/util_test.go new file mode 100644 index 0000000..2de59b3 --- /dev/null +++ b/client/util_test.go @@ -0,0 +1,149 @@ +package client + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "io" + "net/http" + "net/http/httptest" + "os" + "path/filepath" + "testing" +) + +var ( + apiKey string + update bool + pollInterval int +) + +func init() { + flag.StringVar(&apiKey, "key", "", "Your TEST secret key for the zilliz cloud API. If present, integration tests will be run using this key.") + flag.BoolVar(&update, "update", false, "Set this flag to update the responses used in local tests. This requires that the key flag is set so that we can interact with the zilliz cloud API.") + // flag.IntVar(&pollInterval, "poll-interval", 60, "The interval in seconds to poll the zilliz cloud API for the status of a resource.") +} + +func zillizClient[T any](t *testing.T) (*Client, func()) { + tearDowns := make([]func(), 0) + options := make([]Option, 0) + key := "gibberish_key" + + // when apiKey is empty, we need to create a test server, read the response from the file, and return the response + if apiKey == "" { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + data := readResponse[T](t) + w.WriteHeader(data.StatusCode) + _, err := w.Write(data.Body) + if err != nil { + t.Fatalf("failed to write response body: %v", err) + } + }) + server := httptest.NewServer(mux) + + tearDowns = append(tearDowns, server.Close) + + options = append(options, WithBaseUrl(server.URL)) + } else { + key = apiKey + } + + client := &recorderClient{t: t} + options = append(options, + WithApiKey(key), + WithCloudRegionId("gcp-us-west1"), + WithHTTPClient(client)) + c, err := NewClient( + options..., + ) + + if err != nil { + t.Fatalf("failed to create client: %v", err) + } + + if apiKey != "" && update { + tearDowns = append(tearDowns, func() { + recordResponse(t, client.responses) + }) + } + + return c, func() { + for _, fn := range tearDowns { + fn() + } + } +} + +func responsePath(t *testing.T) string { + return filepath.Join("testdata", filepath.FromSlash(fmt.Sprintf("%s.json", t.Name()))) +} +func recordResponse(t *testing.T, resp any) { + path := responsePath(t) + err := os.MkdirAll(filepath.Dir(path), 0700) + if err != nil { + t.Fatalf("failed to create the response dir: %s. err = %v", filepath.Dir(path), err) + } + f, err := os.Create(path) + if err != nil { + t.Fatalf("failed to create the response file: %s. err = %v", path, err) + } + defer f.Close() + jsonBytes, err := json.MarshalIndent(resp, "", " ") + if err != nil { + t.Fatalf("failed to marshal JSON for response file: %s. err = %v", path, err) + } + _, err = f.Write(jsonBytes) + if err != nil { + t.Fatalf("failed to write json bytes for response file: %s. err = %v", path, err) + } +} + +func readResponse[T any](t *testing.T) response { + var resp response + path := responsePath(t) + f, err := os.Open(path) + if err != nil { + t.Fatalf("failed to open the response file: %s. err = %v", path, err) + } + defer f.Close() + jsonBytes, err := io.ReadAll(f) + if err != nil { + t.Fatalf("failed to read the response file: %s. err = %v", path, err) + } + err = json.Unmarshal(jsonBytes, &resp) + if err != nil { + t.Fatalf("failed to json unmarshal the response file: %s. err = %v", path, err) + } + return resp +} + +type response struct { + StatusCode int `json:"status_code"` + Body []byte `json:"body"` +} + +type recorderClient struct { + t *testing.T + responses response +} + +func (rc *recorderClient) Do(req *http.Request) (*http.Response, error) { + httpClient := &http.Client{} + res, err := httpClient.Do(req) + if err != nil { + rc.t.Fatalf("http request failed. err = %v", err) + } + defer res.Body.Close() + body, err := io.ReadAll(res.Body) + if err != nil { + rc.t.Fatalf("failed to read the response body. err = %v", err) + } + rc.responses = response{ + StatusCode: res.StatusCode, + Body: body, + } + res.Body = io.NopCloser(bytes.NewReader(body)) + return res, err +} diff --git a/client/zilliz.go b/client/zilliz.go index b644b6d..1db5fb9 100644 --- a/client/zilliz.go +++ b/client/zilliz.go @@ -7,80 +7,206 @@ import ( "io" "net/http" "net/url" - "path" - "time" ) const ( - apiTemplateUrl string = "https://controller.api.%s.zillizcloud.com/v1/" + globalApiTemplateUrl string = "https://controller.api.%s.zillizcloud.com/v1/" + cnApiTemplateUrl string = "https://controller.api.%s.cloud.zilliz.com.cn/v1/" ) +type HttpClient interface { + Do(*http.Request) (*http.Response, error) +} + type Client struct { - CloudRegionId string - HTTPClient *http.Client - baseUrl string - apiKey string - userAgent string + apiKey string + RegionId string + baseUrl string + userAgent string + HttpClient HttpClient } -// NewClient - creates new Pinecone client. -func NewClient(apiKey string, cloudRegionId string) *Client { - c := &Client{ - CloudRegionId: cloudRegionId, - HTTPClient: &http.Client{Timeout: 30 * time.Second}, - baseUrl: apiTemplateUrl, - apiKey: apiKey, - userAgent: "zilliztech/terraform-provider-zillizcloud", +var ( + errApiKeyRequired = fmt.Errorf("ApiKey is required") + errRegionIdRequired = fmt.Errorf("RegionId is required") +) + +func checkCloudRegionId(c *Client) func() error { + return func() error { + if c.RegionId == "" { + return errRegionIdRequired + } + return nil } - return c } -type zillizResponse[T any] struct { - Code int `json:"code"` - Data T `json:"data"` - Message string `json:"message"` +func checkApiKey(c *Client) func() error { + return func() error { + if c.apiKey == "" { + return errApiKeyRequired + } + return nil + } } -type ZillizAPIError struct { - Code int `json:"code"` - Message string `json:"message"` +func (client *Client) Clone(opts ...Option) (*Client, error) { + clone := func(c Client) *Client { + return &c + } + + c := clone(*client) + + for _, opt := range opts { + opt(c) + } + + applyOverride(c) + + if err := validate(c); err != nil { + return nil, err + } + + return c, nil } -func (r *ZillizAPIError) Error() string { - return fmt.Sprintf("error, code: %d, message: %s", r.Code, r.Message) +func validate(c *Client) error { + checkFns := []func() error{ + checkCloudRegionId(c), + checkApiKey(c), + } + for _, fn := range checkFns { + if err := fn(); err != nil { + return err + } + } + return nil } -type zillizPage struct { - Count int `json:"count"` - CurrentPage int `json:"currentPage"` - PageSize int `json:"pageSize"` +func applyOverride(c *Client) { + overrides := []Option{ + OverrideBaseUrl(), + } + for _, opt := range overrides { + opt(c) + } +} + +func applyDefaults(c *Client) { + defaultOptions := []Option{ + WithDefaultClient(), + WithDefaultRegion(), + WithDefaultBaseUrl(), + WithDefaultUserAgent(), + } + for _, opt := range defaultOptions { + opt(c) + } +} + +func NewClient(opts ...Option) (*Client, error) { + + // create a new client with options + c := new(Client) + for _, opt := range opts { + opt(c) + } + + applyDefaults(c) + + if err := validate(c); err != nil { + return nil, err + } + + return c, nil +} + +type Option func(*Client) + +func WithHTTPClient(client HttpClient) Option { + return func(c *Client) { + c.HttpClient = client + } +} + +func WithBaseUrl(baseUrl string) Option { + return func(c *Client) { + c.baseUrl = baseUrl + } +} + +func WithUserAgent(userAgent string) Option { + return func(c *Client) { + c.userAgent = userAgent + } } -type CloudProvider struct { - CloudId string `json:"cloudId"` - Description string `json:"description"` +func WithCloudRegionId(cloudRegionId string) Option { + return func(c *Client) { + c.RegionId = cloudRegionId + } } -func (c *Client) ListCloudProviders() ([]CloudProvider, error) { - var cloudProviders zillizResponse[[]CloudProvider] - err := c.do("GET", "clouds", nil, &cloudProviders) - return cloudProviders.Data, err +func WithApiKey(apiKey string) Option { + return func(c *Client) { + c.apiKey = apiKey + } } -type CloudRegion struct { - ApiBaseUrl string `json:"apiBaseUrl"` - CloudId string `json:"cloudId"` - RegionId string `json:"regionId"` +func WithDefaultBaseUrl() Option { + return func(c *Client) { + if c.baseUrl == "" && c.RegionId != "" { + c.baseUrl = BaseUrlFrom(c.RegionId) + } + } } -func (c *Client) ListCloudRegions(cloudId string) ([]CloudRegion, error) { - var cloudRegions zillizResponse[[]CloudRegion] - err := c.do("GET", "regions?cloudId="+cloudId, nil, &cloudRegions) - return cloudRegions.Data, err +func OverrideBaseUrl() Option { + return func(c *Client) { + if c.RegionId != "" { + c.baseUrl = BaseUrlFrom(c.RegionId) + } + } + +} + +func WithDefaultClient() Option { + return func(c *Client) { + if c.HttpClient == nil { + c.HttpClient = &http.Client{} + } + } +} + +func WithDefaultRegion() Option { + return func(c *Client) { + if c.RegionId == "" { + c.RegionId = "gcp-us-west1" + } + } +} + +func WithDefaultUserAgent() Option { + return func(c *Client) { + if c.userAgent == "" { + c.userAgent = "zilliztech/terraform-provider-zillizcloud" + } + } +} + +type zillizResponse[T any] struct { + Error + Data T `json:"data"` +} + +type zillizPage struct { + Count int `json:"count"` + CurrentPage int `json:"currentPage"` + PageSize int `json:"pageSize"` } func (c *Client) do(method string, path string, body interface{}, result interface{}) error { - u, err := c.buildURL(path) + + u, err := c.url(path) if err != nil { return err } @@ -115,7 +241,7 @@ func (c *Client) newRequest(method string, u *url.URL, body interface{}) (*http. } func (c *Client) doRequest(req *http.Request, v any) error { - res, err := c.HTTPClient.Do(req) + res, err := c.HttpClient.Do(req) if err != nil { return err } @@ -134,7 +260,6 @@ func parseError(body io.Reader) error { b, err := io.ReadAll(body) if err != nil { return err - } var e Error err = json.Unmarshal(b, &e) @@ -154,53 +279,15 @@ func decodeResponse(body io.Reader, v any) error { return err } - var apierr ZillizAPIError + var apierr Error err = json.Unmarshal(b, &apierr) if err == nil && apierr.Code != 200 { return &apierr } err = json.Unmarshal(b, v) return err - // return json.NewDecoder(body).Decode(v) -} - -func (c *Client) buildURL(endpointPath string) (*url.URL, error) { - u, err := url.Parse(endpointPath) - if err != nil { - return nil, err - } - sBaseUrl := c.baseUrl - if c.CloudRegionId != "" { - sBaseUrl = fmt.Sprintf(apiTemplateUrl, c.CloudRegionId) - } - baseUrl, err := url.Parse(sBaseUrl) - if err != nil { - return nil, err - } - u.Path = path.Join(baseUrl.Path, u.Path) - return baseUrl.ResolveReference(u), err -} - -func (c *Client) handleHTTPErrorResp(resp *http.Response) error { - data, err := io.ReadAll(resp.Body) - if err != nil { - return err - } - reqErr := &HTTPError{ - StatusCode: resp.StatusCode, - Status: resp.Status, - Message: string(data), - } - return reqErr -} - -// HTTPError provides informations about generic HTTP errors. -type HTTPError struct { - StatusCode int - Status string - Message string } -func (e HTTPError) Error() string { - return fmt.Sprintf("error, status code: %d, message: %s", e.StatusCode, e.Message) +func (c *Client) url(path string) (*url.URL, error) { + return url.Parse(fmt.Sprintf("%s/%s", c.baseUrl, path)) } diff --git a/client/zilliz_test.go b/client/zilliz_test.go index a3bc128..e67953e 100644 --- a/client/zilliz_test.go +++ b/client/zilliz_test.go @@ -1,47 +1,79 @@ package client import ( - "net/http" - "reflect" "testing" ) -func TestClient_CreateCluster(t *testing.T) { - type fields struct { - CloudRegionId string - HTTPClient *http.Client - baseUrl string - apiKey string - userAgent string +func TestClone(t *testing.T) { + origin, err := NewClient(WithCloudRegionId("gibberish_id"), WithApiKey("giberishkey")) + if err != nil { + t.Errorf("got %v, want nil", err) } - type args struct { - params CreateClusterParams + client, err := origin.Clone(WithCloudRegionId("aws-west2")) + if err != nil { + t.Errorf("got %v, want nil", err) } - tests := []struct { + + expected := "https://controller.api.aws-west2.zillizcloud.com/v1/" + if client.baseUrl != expected { + t.Errorf("got %s, want %s", client.baseUrl, expected) + } + +} + +func TestNewClient(t *testing.T) { + type expect struct { + baseUrl string + err error + } + + testCases := []struct { name string - fields fields - args args - want *CreateClusterResponse - wantErr bool + options []Option + expect expect }{ - // TODO: Add test cases. + { + name: "Valid options", + options: []Option{ + WithCloudRegionId("gibberish_id"), + WithApiKey("gibberish_key"), + }, + expect: expect{ + baseUrl: "https://controller.api.gibberish_id.zillizcloud.com/v1/", + err: nil, + }, + }, + { + name: "Missing API key", + options: []Option{ + WithCloudRegionId("id"), + }, + expect: expect{ + err: errApiKeyRequired, + }, + }, + { + name: "Missing cloud region ID", + options: []Option{ + WithApiKey("key"), + }, + expect: expect{ + baseUrl: "https://controller.api.gcp-us-west1.zillizcloud.com/v1/", + err: nil, + }, + }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &Client{ - CloudRegionId: tt.fields.CloudRegionId, - HTTPClient: tt.fields.HTTPClient, - baseUrl: tt.fields.baseUrl, - apiKey: tt.fields.apiKey, - userAgent: tt.fields.userAgent, - } - got, err := c.CreateCluster(tt.args.params) - if (err != nil) != tt.wantErr { - t.Errorf("Client.CreateCluster() error = %v, wantErr %v", err, tt.wantErr) - return + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + c, err := NewClient(tc.options...) + _ = c + if err != tc.expect.err { + t.Errorf("got = %v, want %v", err, tc.expect.err) } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Client.CreateCluster() = %v, want %v", got, tt.want) + + if c != nil && c.baseUrl != tc.expect.baseUrl { + t.Errorf("got = %s, want %s", c.baseUrl, tc.expect.baseUrl) } }) } From c9e400ed47c00c46dbd9f16991072b7d75e7583b Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Wed, 8 May 2024 11:06:55 +0800 Subject: [PATCH 3/7] enhance: update provider Signed-off-by: Liang Huang update provider Signed-off-by: Liang Huang --- .../provider/cloud_providers_data_source.go | 4 +- .../provider/cloud_regions_data_source.go | 6 +- internal/provider/cluster_resource.go | 79 ++++++++++++++++--- internal/provider/projects_data_source.go | 1 - internal/provider/provider.go | 28 +++++-- 5 files changed, 92 insertions(+), 26 deletions(-) diff --git a/internal/provider/cloud_providers_data_source.go b/internal/provider/cloud_providers_data_source.go index 78f154b..e2420a6 100644 --- a/internal/provider/cloud_providers_data_source.go +++ b/internal/provider/cloud_providers_data_source.go @@ -69,7 +69,7 @@ func (d *CloudProvidersDataSource) Schema(ctx context.Context, req datasource.Sc } func (d *CloudProvidersDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { - // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { return } @@ -106,7 +106,7 @@ func (d *CloudProvidersDataSource) Read(ctx context.Context, req datasource.Read } for _, cp := range cloudProviders { - state.CloudProviders = append(state.CloudProviders, CloudProviderItem{CloudId: types.StringValue(cp.CloudId), Description: types.StringValue(cp.Description)}) + state.CloudProviders = append(state.CloudProviders, CloudProviderItem{CloudId: types.StringValue(string(cp.CloudId)), Description: types.StringValue(cp.Description)}) } diags := resp.State.Set(ctx, &state) diff --git a/internal/provider/cloud_regions_data_source.go b/internal/provider/cloud_regions_data_source.go index 3f2de36..3c93ecd 100644 --- a/internal/provider/cloud_regions_data_source.go +++ b/internal/provider/cloud_regions_data_source.go @@ -35,12 +35,12 @@ type CloudRegionItem struct { // CloudRegionsDataSourceModel describes the data source data model. type CloudRegionsDataSourceModel struct { - CloudRegions []CloudRegionItem `tfsdk:"cloud_regions"` + CloudRegions []CloudRegionItem `tfsdk:"items"` CloudId types.String `tfsdk:"cloud_id"` } func (d *CloudRegionsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { - resp.TypeName = req.ProviderTypeName + "_cloud_regions" + resp.TypeName = req.ProviderTypeName + "_regions" } func (d *CloudRegionsDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { @@ -49,7 +49,7 @@ func (d *CloudRegionsDataSource) Schema(ctx context.Context, req datasource.Sche MarkdownDescription: "Cloud Regions data source", Attributes: map[string]schema.Attribute{ - "cloud_regions": schema.ListNestedAttribute{ + "items": schema.ListNestedAttribute{ MarkdownDescription: "List of Cloud Regions", Computed: true, NestedObject: schema.NestedAttributeObject{ diff --git a/internal/provider/cluster_resource.go b/internal/provider/cluster_resource.go index 51cb392..fc5c220 100644 --- a/internal/provider/cluster_resource.go +++ b/internal/provider/cluster_resource.go @@ -48,7 +48,7 @@ func (r *ClusterResource) Metadata(ctx context.Context, req resource.MetadataReq func (r *ClusterResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - MarkdownDescription: "Cluster resource. If 'plan', 'cu_size' and 'cu-type' are not specified, then a serverless cluster is created.", + MarkdownDescription: "Cluster resource. If 'plan', 'cu_size' and 'cu_type' are not specified, then a free cluster is created.", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ MarkdownDescription: "Cluster identifier", @@ -96,7 +96,7 @@ func (r *ClusterResource) Schema(ctx context.Context, req resource.SchemaRequest }, }, "cu_type": schema.StringAttribute{ - MarkdownDescription: "The type of the CU used for the Zilliz Cloud cluster to be created. Available options are Performance-optimized, Capacity-optimized, and Cost-optimized. This parameter defaults to Performance-optimized. The value defaults to Performance-optimized.", + MarkdownDescription: "The type of the CU used for the Zilliz Cloud cluster to be created. A compute unit (CU) is the physical resource unit for cluster deployment. Different CU types comprise varying combinations of CPU, memory, and storage. Available options are Performance-optimized, Capacity-optimized, and Cost-optimized. This parameter defaults to Performance-optimized. The value defaults to Performance-optimized.", Optional: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), @@ -127,6 +127,7 @@ func (r *ClusterResource) Schema(ctx context.Context, req resource.SchemaRequest }, "region_id": schema.StringAttribute{ MarkdownDescription: "The ID of the region where the cluster exists.", + Optional: true, Computed: true, }, "cluster_type": schema.StringAttribute{ @@ -186,6 +187,16 @@ func (r *ClusterResource) Configure(ctx context.Context, req resource.ConfigureR r.client = client } +func CloneClient(client *zilliz.Client, data *ClusterResourceModel) (*zilliz.Client, error) { + var id = client.RegionId + + if data.RegionId.ValueString() != "" { + id = data.RegionId.ValueString() + } + + return client.Clone(zilliz.WithCloudRegionId(id)) +} + func (r *ClusterResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { var data ClusterResourceModel resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) @@ -193,17 +204,45 @@ func (r *ClusterResource) Create(ctx context.Context, req resource.CreateRequest return } + checkPlan := func(data ClusterResourceModel) (bool, error) { + + if data.Plan.IsNull() { + return true, nil + } + + switch zilliz.Plan(data.Plan.ValueString()) { + case zilliz.StandardPlan, zilliz.EnterprisePlan, zilliz.FreePlan, zilliz.ServerlessPlan: + return true, nil + default: + return false, fmt.Errorf("Invalid plan: %s", data.Plan.ValueString()) + } + + } + + if _, err := checkPlan(data); err != nil { + resp.Diagnostics.AddError("Invalid plan", err.Error()) + return + } + var response *zilliz.CreateClusterResponse var err error - if data.Plan.IsNull() && data.CuSize.IsUnknown() && data.CuType.IsNull() { - response, err = r.client.CreateServerlessCluster(zilliz.CreateServerlessClusterParams{ + client, err := CloneClient(r.client, &data) + if err != nil { + resp.Diagnostics.AddError("client error", err.Error()) + return + } + + if (data.Plan.IsNull() || zilliz.Plan(data.Plan.ValueString()) == zilliz.FreePlan) && data.CuSize.IsUnknown() && data.CuType.IsNull() { + + response, err = client.CreateServerlessCluster(zilliz.CreateServerlessClusterParams{ + // Plan: zilliz.Plan(data.Plan.ValueString()), ClusterName: data.ClusterName.ValueString(), ProjectId: data.ProjectId.ValueString(), }) } else { - response, err = r.client.CreateCluster(zilliz.CreateClusterParams{ - Plan: data.Plan.ValueString(), + response, err = client.CreateCluster(zilliz.CreateClusterParams{ + Plan: zilliz.Plan(data.Plan.ValueString()), ClusterName: data.ClusterName.ValueString(), CUSize: int(data.CuSize.ValueInt64()), CUType: data.CuType.ValueString(), @@ -229,12 +268,12 @@ func (r *ClusterResource) Create(ctx context.Context, req resource.CreateRequest return } - resp.Diagnostics.Append(data.waitForStatus(ctx, createTimeout, r.client, "RUNNING")...) + resp.Diagnostics.Append(data.waitForStatus(ctx, createTimeout, client, "RUNNING")...) if resp.Diagnostics.HasError() { return } - resp.Diagnostics.Append(data.refresh(r.client)...) + resp.Diagnostics.Append(data.refresh(client)...) resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } @@ -245,7 +284,12 @@ func (r *ClusterResource) Read(ctx context.Context, req resource.ReadRequest, re return } - resp.Diagnostics.Append(data.refresh(r.client)...) + client, err := CloneClient(r.client, &data) + if err != nil { + resp.Diagnostics.AddError("client error", err.Error()) + return + } + resp.Diagnostics.Append(data.refresh(client)...) resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } @@ -265,8 +309,13 @@ func (r *ClusterResource) Update(ctx context.Context, req resource.UpdateRequest return } + client, err := CloneClient(r.client, &state) + if err != nil { + resp.Diagnostics.AddError("client error", err.Error()) + return + } // Only support changes of cuSize - all other attributes are set to ForceNew - _, err := r.client.ModifyCluster(state.ClusterId.ValueString(), &zilliz.ModifyClusterParams{ + _, err = client.ModifyCluster(state.ClusterId.ValueString(), &zilliz.ModifyClusterParams{ CuSize: int(plan.CuSize.ValueInt64()), }) if err != nil { @@ -283,7 +332,7 @@ func (r *ClusterResource) Update(ctx context.Context, req resource.UpdateRequest return } - resp.Diagnostics.Append(state.waitForStatus(ctx, updateTimeout, r.client, "RUNNING")...) + resp.Diagnostics.Append(state.waitForStatus(ctx, updateTimeout, client, "RUNNING")...) if resp.Diagnostics.HasError() { return } @@ -300,7 +349,12 @@ func (r *ClusterResource) Delete(ctx context.Context, req resource.DeleteRequest return } - _, err := r.client.DropCluster(data.ClusterId.ValueString()) + client, err := CloneClient(r.client, &data) + if err != nil { + resp.Diagnostics.AddError("client error", err.Error()) + return + } + _, err = client.DropCluster(data.ClusterId.ValueString()) if err != nil { resp.Diagnostics.AddError("Failed to drop cluster", err.Error()) return @@ -334,6 +388,7 @@ type ClusterResourceModel struct { func (data *ClusterResourceModel) refresh(client *zilliz.Client) diag.Diagnostics { var diags diag.Diagnostics + var err error c, err := client.DescribeCluster(data.ClusterId.ValueString()) if err != nil { diff --git a/internal/provider/projects_data_source.go b/internal/provider/projects_data_source.go index 7d641ca..54cf20f 100644 --- a/internal/provider/projects_data_source.go +++ b/internal/provider/projects_data_source.go @@ -127,7 +127,6 @@ func (d *ProjectDataSource) Read(ctx context.Context, req datasource.ReadRequest state.InstanceCount = types.Int64Value(p.InstanceCount) state.CreatedAt = types.Int64Value(p.CreateTimeMilli) - // Set state diags := resp.State.Set(ctx, &state) resp.Diagnostics.Append(diags...) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index d3574ae..87dec3d 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/provider/schema" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-log/tflog" zilliz "github.com/zilliztech/terraform-provider-zillizcloud/client" ) @@ -28,12 +29,12 @@ type ZillizProvider struct { // zillizProviderModel describes the provider data model. type zillizProviderModel struct { - ApiKey types.String `tfsdk:"api_key"` - CloudRegionId types.String `tfsdk:"cloud_region_id"` + ApiKey types.String `tfsdk:"api_key"` + RegionId types.String `tfsdk:"region_id"` } func (p *ZillizProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { - resp.TypeName = "zilliz" + resp.TypeName = "zillizcloud" resp.Version = p.version } @@ -41,19 +42,22 @@ func (p *ZillizProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "api_key": schema.StringAttribute{ - MarkdownDescription: "Zilliz API Key", + MarkdownDescription: "Zilliz Cloud API Key", Optional: true, Sensitive: true, }, - "cloud_region_id": schema.StringAttribute{ + "region_id": schema.StringAttribute{ MarkdownDescription: "Zilliz Cloud Region Id", - Required: true, + Optional: true, }, }, } } func (p *ZillizProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) { + + tflog.Info(ctx, "Configuring client...") + var data zillizProviderModel resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) @@ -64,11 +68,19 @@ func (p *ZillizProvider) Configure(ctx context.Context, req provider.ConfigureRe // Default to environment variables, but override // with Terraform configuration value if set. - apiKey := os.Getenv("ZILLIZ_API_KEY") + apiKey := os.Getenv("ZILLIZCLOUD_API_KEY") if !data.ApiKey.IsNull() { apiKey = data.ApiKey.ValueString() } - client := zilliz.NewClient(apiKey, data.CloudRegionId.ValueString()) + + client, err := zilliz.NewClient( + zilliz.WithApiKey(apiKey), + zilliz.WithCloudRegionId(data.RegionId.ValueString()), + ) + if err != nil { + resp.Diagnostics.AddError("failed to create client: %v", err.Error()) + return + } // Zilliz client for data sources and resources resp.DataSourceData = client From 0aa2865de9446aa0fcb582095b0f9ff7b7211587 Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Wed, 8 May 2024 11:07:21 +0800 Subject: [PATCH 4/7] chore: update Signed-off-by: Liang Huang --- GNUmakefile | 6 ++++++ go.mod | 4 ++-- main.go | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 7771cd6..59d6b6b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -4,3 +4,9 @@ default: testacc .PHONY: testacc testacc: TF_ACC=1 go test ./... -v $(TESTARGS) -timeout 120m + +unit-test: + go test ./... -v + +install: + sudo go install -v ./... diff --git a/go.mod b/go.mod index d310a50..9724c91 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/hashicorp/terraform-plugin-framework v1.6.0 github.com/hashicorp/terraform-plugin-framework-timeouts v0.4.1 github.com/hashicorp/terraform-plugin-framework-validators v0.12.0 - github.com/hashicorp/terraform-plugin-go v0.22.0 + github.com/hashicorp/terraform-plugin-log v0.9.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.30.0 ) @@ -36,7 +36,7 @@ require ( github.com/hashicorp/hc-install v0.6.2 // indirect github.com/hashicorp/terraform-exec v0.20.0 // indirect github.com/hashicorp/terraform-json v0.21.0 // indirect - github.com/hashicorp/terraform-plugin-log v0.9.0 // indirect + github.com/hashicorp/terraform-plugin-go v0.22.0 // indirect github.com/hashicorp/terraform-registry-address v0.2.3 // indirect github.com/hashicorp/terraform-svchost v0.1.1 // indirect github.com/hashicorp/yamux v0.1.1 // indirect diff --git a/main.go b/main.go index acb5cec..c523954 100644 --- a/main.go +++ b/main.go @@ -20,7 +20,7 @@ import ( // Run the docs generation tool, check its repository for more information on how it works and how docs // can be customized. -//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate -provider-name scaffolding +//go:generate go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs generate -provider-name zillizcloud var ( // these will be set by the goreleaser configuration From e222def906ac530ed3267b109b6cd802d7215eb1 Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Wed, 8 May 2024 11:07:39 +0800 Subject: [PATCH 5/7] chore(examples): update Signed-off-by: Liang Huang --- .../zilliz_cloud_providers/data-source.tf | 18 --------- .../zilliz_cloud_regions/data-source.tf | 37 ------------------- .../zilliz_cluster/data-source.tf | 21 ----------- .../zilliz_clusters/data-source.tf | 18 --------- .../zilliz_projects/data-source.tf | 28 -------------- .../data-source.tf | 16 ++++++++ .../zillizcloud_cluster/data-source.tf | 20 ++++++++++ .../zillizcloud_clusters/data-source.tf | 16 ++++++++ .../zillizcloud_projects/data-source.tf | 26 +++++++++++++ .../zillizcloud_regions/data-source.tf | 35 ++++++++++++++++++ examples/provider/provider.tf | 6 +-- examples/resources/zilliz_cluster/resource.tf | 28 -------------- .../resources/zillizcloud_cluster/resource.tf | 28 ++++++++++++++ 13 files changed, 143 insertions(+), 154 deletions(-) delete mode 100644 examples/data-sources/zilliz_cloud_providers/data-source.tf delete mode 100644 examples/data-sources/zilliz_cloud_regions/data-source.tf delete mode 100644 examples/data-sources/zilliz_cluster/data-source.tf delete mode 100644 examples/data-sources/zilliz_clusters/data-source.tf delete mode 100644 examples/data-sources/zilliz_projects/data-source.tf create mode 100644 examples/data-sources/zillizcloud_cloud_providers/data-source.tf create mode 100644 examples/data-sources/zillizcloud_cluster/data-source.tf create mode 100644 examples/data-sources/zillizcloud_clusters/data-source.tf create mode 100644 examples/data-sources/zillizcloud_projects/data-source.tf create mode 100644 examples/data-sources/zillizcloud_regions/data-source.tf delete mode 100644 examples/resources/zilliz_cluster/resource.tf create mode 100644 examples/resources/zillizcloud_cluster/resource.tf diff --git a/examples/data-sources/zilliz_cloud_providers/data-source.tf b/examples/data-sources/zilliz_cloud_providers/data-source.tf deleted file mode 100644 index 383d479..0000000 --- a/examples/data-sources/zilliz_cloud_providers/data-source.tf +++ /dev/null @@ -1,18 +0,0 @@ -terraform { - required_providers { - zilliz = { - source = "zilliztech/zillizcloud" - } - } -} - -provider "zilliz" { - api_key = "fake-api-key" - cloud_region_id = "gcp-us-west1" -} - -data "zilliz_cloud_providers" "example" {} - -output "ouput" { - value = data.zilliz_cloud_providers.example.cloud_providers -} diff --git a/examples/data-sources/zilliz_cloud_regions/data-source.tf b/examples/data-sources/zilliz_cloud_regions/data-source.tf deleted file mode 100644 index 1a405b8..0000000 --- a/examples/data-sources/zilliz_cloud_regions/data-source.tf +++ /dev/null @@ -1,37 +0,0 @@ -terraform { - required_providers { - zilliz = { - source = "zilliztech/zillizcloud" - } - } -} - -provider "zilliz" { - api_key = "fake-api-key" - cloud_region_id = "gcp-us-west1" -} - -data "zilliz_cloud_regions" "region01" { - cloud_id = "aws" -} - -data "zilliz_cloud_regions" "region02" { - cloud_id = "gcp" -} - -data "zilliz_cloud_regions" "region03" { - cloud_id = "azure" -} - -output "aws_ouput" { - value = data.zilliz_cloud_regions.region01.cloud_regions -} - - -output "gcp_ouput" { - value = data.zilliz_cloud_regions.region02.cloud_regions -} - -output "azure_ouput" { - value = data.zilliz_cloud_regions.region03.cloud_regions -} diff --git a/examples/data-sources/zilliz_cluster/data-source.tf b/examples/data-sources/zilliz_cluster/data-source.tf deleted file mode 100644 index 70df127..0000000 --- a/examples/data-sources/zilliz_cluster/data-source.tf +++ /dev/null @@ -1,21 +0,0 @@ -terraform { - required_providers { - zilliz = { - source = "zilliztech/zillizcloud" - } - } -} - -provider "zilliz" { - api_key = "fake-api-key" - cloud_region_id = "gcp-us-west1" -} - - -data "zilliz_cluster" "test" { - id = "in03-bd4013ae76exxx" -} - -output "output" { - value = data.zilliz_cluster.test -} diff --git a/examples/data-sources/zilliz_clusters/data-source.tf b/examples/data-sources/zilliz_clusters/data-source.tf deleted file mode 100644 index 9c7f194..0000000 --- a/examples/data-sources/zilliz_clusters/data-source.tf +++ /dev/null @@ -1,18 +0,0 @@ -terraform { - required_providers { - zilliz = { - source = "zilliztech/zillizcloud" - } - } -} - -provider "zilliz" { - api_key = "fake-api-key" - cloud_region_id = "gcp-us-west1" -} - -data "zilliz_clusters" "example" {} - -output "clusters" { - value = data.zilliz_clusters.example.clusters -} diff --git a/examples/data-sources/zilliz_projects/data-source.tf b/examples/data-sources/zilliz_projects/data-source.tf deleted file mode 100644 index 3367a5b..0000000 --- a/examples/data-sources/zilliz_projects/data-source.tf +++ /dev/null @@ -1,28 +0,0 @@ -terraform { - required_providers { - zilliz = { - source = "zilliztech/zillizcloud" - } - } -} - -provider "zilliz" { - api_key = "fake-api-key" - cloud_region_id = "gcp-us-west1" -} - -// default project -data "zilliz_project" "example01" {} - -// specific project -data "zilliz_project" "example02" { - name = "payments" -} - -output "output_01" { - value = data.zilliz_project.example01 -} - -output "output_02" { - value = data.zilliz_project.example02 -} diff --git a/examples/data-sources/zillizcloud_cloud_providers/data-source.tf b/examples/data-sources/zillizcloud_cloud_providers/data-source.tf new file mode 100644 index 0000000..f6444c6 --- /dev/null +++ b/examples/data-sources/zillizcloud_cloud_providers/data-source.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_cloud_providers" "example" {} + +output "ouput" { + value = data.zillizcloud_cloud_providers.example.cloud_providers +} diff --git a/examples/data-sources/zillizcloud_cluster/data-source.tf b/examples/data-sources/zillizcloud_cluster/data-source.tf new file mode 100644 index 0000000..2df4210 --- /dev/null +++ b/examples/data-sources/zillizcloud_cluster/data-source.tf @@ -0,0 +1,20 @@ +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { + region_id = "gcp-us-west1" +} + + +data "zillizcloud_cluster" "test" { + id = "in03-bd4013ae76exxx" +} + +output "output" { + value = data.zillizcloud_cluster.test +} diff --git a/examples/data-sources/zillizcloud_clusters/data-source.tf b/examples/data-sources/zillizcloud_clusters/data-source.tf new file mode 100644 index 0000000..292b4fc --- /dev/null +++ b/examples/data-sources/zillizcloud_clusters/data-source.tf @@ -0,0 +1,16 @@ +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_clusters" "example" {} + +output "clusters" { + value = data.zillizcloud_clusters.example.clusters +} diff --git a/examples/data-sources/zillizcloud_projects/data-source.tf b/examples/data-sources/zillizcloud_projects/data-source.tf new file mode 100644 index 0000000..ad605bf --- /dev/null +++ b/examples/data-sources/zillizcloud_projects/data-source.tf @@ -0,0 +1,26 @@ +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +// default project +data "zillizcloud_project" "example01" {} + +// specific project +data "zillizcloud_project" "example02" { + name = "payments" +} + +output "output_01" { + value = data.zillizcloud_project.example01 +} + +output "output_02" { + value = data.zillizcloud_project.example02 +} diff --git a/examples/data-sources/zillizcloud_regions/data-source.tf b/examples/data-sources/zillizcloud_regions/data-source.tf new file mode 100644 index 0000000..001e995 --- /dev/null +++ b/examples/data-sources/zillizcloud_regions/data-source.tf @@ -0,0 +1,35 @@ +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_regions" "aws_region" { + cloud_id = "aws" +} + +data "zillizcloud_regions" "gcp_region" { + cloud_id = "gcp" +} + +data "zillizcloud_regions" "azure_region" { + cloud_id = "azure" +} + +output "aws_ouput" { + value = data.zillizcloud_regions.aws_region.items +} + + +output "gcp_ouput" { + value = data.zillizcloud_regions.gcp_region.items +} + +output "azure_ouput" { + value = data.zillizcloud_regions.azure_region.items +} diff --git a/examples/provider/provider.tf b/examples/provider/provider.tf index 82c9c2e..71e248e 100644 --- a/examples/provider/provider.tf +++ b/examples/provider/provider.tf @@ -1,12 +1,10 @@ terraform { required_providers { - zilliz = { + zillizcloud = { source = "zilliztech/zillizcloud" } } } -provider "zilliz" { - api_key = "fake-api-key" - cloud_region_id = "gcp-us-west1" +provider "zillizcloud" { } diff --git a/examples/resources/zilliz_cluster/resource.tf b/examples/resources/zilliz_cluster/resource.tf deleted file mode 100644 index a369d5d..0000000 --- a/examples/resources/zilliz_cluster/resource.tf +++ /dev/null @@ -1,28 +0,0 @@ -terraform { - required_providers { - zilliz = { - source = "zilliztech/zillizcloud" - } - } -} - -provider "zilliz" { - api_key = "fake-api-key" - cloud_region_id = "gcp-us-west1" -} - -data "zilliz_project" "default" { -} - -resource "zilliz_cluster" "standard_plan_cluster" { - plan = "Standard" - cluster_name = "Cluster-01" - cu_size = "1" - cu_type = "Performance-optimized" - project_id = data.zilliz_project.default.id -} - -resource "zilliz_cluster" "serverless_cluster" { - cluster_name = "Cluster-02" - project_id = data.zilliz_project.default.id -} diff --git a/examples/resources/zillizcloud_cluster/resource.tf b/examples/resources/zillizcloud_cluster/resource.tf new file mode 100644 index 0000000..c3de90d --- /dev/null +++ b/examples/resources/zillizcloud_cluster/resource.tf @@ -0,0 +1,28 @@ +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_project" "default" { +} + +resource "zillizcloud_cluster" "starter_cluster" { + cluster_name = "Cluster-01" + project_id = data.zillizcloud_project.default.id +} + +resource "zillizcloud_cluster" "standard_plan_cluster" { + cluster_name = "Cluster-02" + region_id = "aws-us-east-2" + plan = "Standard" + cu_size = "1" + cu_type = "Performance-optimized" + project_id = data.zillizcloud_project.default.id +} + From 3dbffa33adc29158f7efa2ec762fde6daa64bf7f Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Wed, 8 May 2024 15:18:20 +0800 Subject: [PATCH 6/7] update makefile Signed-off-by: Liang Huang --- GNUmakefile | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/GNUmakefile b/GNUmakefile index 59d6b6b..3a7d62a 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -10,3 +10,9 @@ unit-test: install: sudo go install -v ./... + +doc: + go generate ./... + +lint: + golangci-lint run From 5376de070b1d8914092bfaff37c067be6d654c34 Mon Sep 17 00:00:00 2001 From: Liang Huang Date: Wed, 8 May 2024 15:19:08 +0800 Subject: [PATCH 7/7] chore(doc): update Signed-off-by: Liang Huang --- docs/data-sources/cloud_providers.md | 47 ++++++++++++++++ docs/data-sources/cluster.md | 55 +++++++++++++++++++ docs/data-sources/clusters.md | 56 +++++++++++++++++++ docs/data-sources/example.md | 30 ----------- docs/data-sources/project.md | 26 +++++++++ docs/data-sources/regions.md | 71 ++++++++++++++++++++++++ docs/functions/example.md | 26 --------- docs/index.md | 18 +++++-- docs/resources/cluster.md | 80 ++++++++++++++++++++++++++++ docs/resources/example.md | 31 ----------- 10 files changed, 348 insertions(+), 92 deletions(-) create mode 100644 docs/data-sources/cloud_providers.md create mode 100644 docs/data-sources/cluster.md create mode 100644 docs/data-sources/clusters.md delete mode 100644 docs/data-sources/example.md create mode 100644 docs/data-sources/project.md create mode 100644 docs/data-sources/regions.md delete mode 100644 docs/functions/example.md create mode 100644 docs/resources/cluster.md delete mode 100644 docs/resources/example.md diff --git a/docs/data-sources/cloud_providers.md b/docs/data-sources/cloud_providers.md new file mode 100644 index 0000000..9591dca --- /dev/null +++ b/docs/data-sources/cloud_providers.md @@ -0,0 +1,47 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "zillizcloud_cloud_providers Data Source - zillizcloud" +subcategory: "" +description: |- + Cloud Providers data source +--- + +# zillizcloud_cloud_providers (Data Source) + +Cloud Providers data source + +## Example Usage + +```terraform +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_cloud_providers" "example" {} + +output "ouput" { + value = data.zillizcloud_cloud_providers.example.cloud_providers +} +``` + + +## Schema + +### Read-Only + +- `cloud_providers` (Attributes List) List of Cloud Providers (see [below for nested schema](#nestedatt--cloud_providers)) + + +### Nested Schema for `cloud_providers` + +Read-Only: + +- `cloud_id` (String) Cloud Provider Identifier +- `description` (String) Cloud Provider Description diff --git a/docs/data-sources/cluster.md b/docs/data-sources/cluster.md new file mode 100644 index 0000000..1c0d45f --- /dev/null +++ b/docs/data-sources/cluster.md @@ -0,0 +1,55 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "zillizcloud_cluster Data Source - zillizcloud" +subcategory: "" +description: |- + Cluster data source +--- + +# zillizcloud_cluster (Data Source) + +Cluster data source + +## Example Usage + +```terraform +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { + region_id = "gcp-us-west1" +} + + +data "zillizcloud_cluster" "test" { + id = "in03-bd4013ae76exxx" +} + +output "output" { + value = data.zillizcloud_cluster.test +} +``` + + +## Schema + +### Required + +- `id` (String) The ID of the cluster. + +### Read-Only + +- `cluster_name` (String) The name of the cluster. +- `cluster_type` (String) The type of CU associated with the cluster. Possible values are Performance-optimized and Capacity-optimized. +- `connect_address` (String) The public endpoint of the cluster. You can connect to the cluster using this endpoint from the public network. +- `create_time` (String) The time at which the cluster has been created. +- `cu_size` (Number) The size of the CU associated with the cluster. +- `description` (String) An optional description about the cluster. +- `private_link_address` (String) The private endpoint of the cluster. You can set up a private link to allow your VPS in the same cloud region to access your cluster. +- `region_id` (String) The ID of the region where the cluster exists. +- `status` (String) The current status of the cluster. Possible values are INITIALIZING, RUNNING, SUSPENDING, and RESUMING. diff --git a/docs/data-sources/clusters.md b/docs/data-sources/clusters.md new file mode 100644 index 0000000..eff07af --- /dev/null +++ b/docs/data-sources/clusters.md @@ -0,0 +1,56 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "zillizcloud_clusters Data Source - zillizcloud" +subcategory: "" +description: |- + Cluster data source +--- + +# zillizcloud_clusters (Data Source) + +Cluster data source + +## Example Usage + +```terraform +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_clusters" "example" {} + +output "clusters" { + value = data.zillizcloud_clusters.example.clusters +} +``` + + +## Schema + +### Read-Only + +- `clusters` (Attributes List) List of Clusters (see [below for nested schema](#nestedatt--clusters)) +- `id` (String) Clusters identifier + + +### Nested Schema for `clusters` + +Read-Only: + +- `cluster_name` (String) The name of the cluster. +- `cluster_type` (String) The type of CU associated with the cluster. Possible values are Performance-optimized and Capacity-optimized. +- `connect_address` (String) The public endpoint of the cluster. You can connect to the cluster using this endpoint from the public network. +- `create_time` (String) The time at which the cluster has been created. +- `cu_size` (Number) The size of the CU associated with the cluster. +- `description` (String) An optional description about the cluster. +- `id` (String) The ID of the cluster. +- `private_link_address` (String) The private endpoint of the cluster. You can set up a private link to allow your VPS in the same cloud region to access your cluster. +- `region_id` (String) The ID of the region where the cluster exists. +- `status` (String) The current status of the cluster. Possible values are INITIALIZING, RUNNING, SUSPENDING, and RESUMING. diff --git a/docs/data-sources/example.md b/docs/data-sources/example.md deleted file mode 100644 index b19c8a0..0000000 --- a/docs/data-sources/example.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "scaffolding_example Data Source - scaffolding" -subcategory: "" -description: |- - Example data source ---- - -# scaffolding_example (Data Source) - -Example data source - -## Example Usage - -```terraform -data "scaffolding_example" "example" { - configurable_attribute = "some-value" -} -``` - - -## Schema - -### Optional - -- `configurable_attribute` (String) Example configurable attribute - -### Read-Only - -- `id` (String) Example identifier diff --git a/docs/data-sources/project.md b/docs/data-sources/project.md new file mode 100644 index 0000000..4a512f1 --- /dev/null +++ b/docs/data-sources/project.md @@ -0,0 +1,26 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "zillizcloud_project Data Source - zillizcloud" +subcategory: "" +description: |- + +--- + +# zillizcloud_project (Data Source) + + + + + + +## Schema + +### Optional + +- `name` (String) Project Name + +### Read-Only + +- `created_at` (Number) Created At +- `id` (String) Project Identifier +- `instance_count` (Number) Instance Count diff --git a/docs/data-sources/regions.md b/docs/data-sources/regions.md new file mode 100644 index 0000000..6d4ac5a --- /dev/null +++ b/docs/data-sources/regions.md @@ -0,0 +1,71 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "zillizcloud_regions Data Source - zillizcloud" +subcategory: "" +description: |- + Cloud Regions data source +--- + +# zillizcloud_regions (Data Source) + +Cloud Regions data source + +## Example Usage + +```terraform +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_regions" "aws_region" { + cloud_id = "aws" +} + +data "zillizcloud_regions" "gcp_region" { + cloud_id = "gcp" +} + +data "zillizcloud_regions" "azure_region" { + cloud_id = "azure" +} + +output "aws_ouput" { + value = data.zillizcloud_regions.aws_region.items +} + + +output "gcp_ouput" { + value = data.zillizcloud_regions.gcp_region.items +} + +output "azure_ouput" { + value = data.zillizcloud_regions.azure_region.items +} +``` + + +## Schema + +### Required + +- `cloud_id` (String) Cloud ID + +### Read-Only + +- `items` (Attributes List) List of Cloud Regions (see [below for nested schema](#nestedatt--items)) + + +### Nested Schema for `items` + +Read-Only: + +- `api_base_url` (String) Cloud Region API Base URL +- `cloud_id` (String) Cloud Region Identifier +- `region_id` (String) Cloud Region Id diff --git a/docs/functions/example.md b/docs/functions/example.md deleted file mode 100644 index c65087d..0000000 --- a/docs/functions/example.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "example function - scaffolding" -subcategory: "" -description: |- - Example function ---- - -# function: example - -Echoes given argument as result - - - -## Signature - - -```text -example(input string) string -``` - -## Arguments - - -1. `input` (String) String to echo - diff --git a/docs/index.md b/docs/index.md index 7458d6d..0732399 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,20 +1,27 @@ --- # generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "scaffolding Provider" +page_title: "zillizcloud Provider" subcategory: "" description: |- --- -# scaffolding Provider +# zillizcloud Provider ## Example Usage ```terraform -provider "scaffolding" { - # example configuration here +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { } ``` @@ -23,4 +30,5 @@ provider "scaffolding" { ### Optional -- `endpoint` (String) Example provider attribute +- `api_key` (String, Sensitive) Zilliz Cloud API Key +- `region_id` (String) Zilliz Cloud Region Id diff --git a/docs/resources/cluster.md b/docs/resources/cluster.md new file mode 100644 index 0000000..f489c35 --- /dev/null +++ b/docs/resources/cluster.md @@ -0,0 +1,80 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "zillizcloud_cluster Resource - zillizcloud" +subcategory: "" +description: |- + Cluster resource. If 'plan', 'cusize' and 'cutype' are not specified, then a free cluster is created. +--- + +# zillizcloud_cluster (Resource) + +Cluster resource. If 'plan', 'cu_size' and 'cu_type' are not specified, then a free cluster is created. + +## Example Usage + +```terraform +terraform { + required_providers { + zillizcloud = { + source = "zilliztech/zillizcloud" + } + } +} + +provider "zillizcloud" { +} + +data "zillizcloud_project" "default" { +} + +resource "zillizcloud_cluster" "starter_cluster" { + cluster_name = "Cluster-01" + project_id = data.zillizcloud_project.default.id +} + +resource "zillizcloud_cluster" "standard_plan_cluster" { + cluster_name = "Cluster-02" + region_id = "aws-us-east-2" + plan = "Standard" + cu_size = "1" + cu_type = "Performance-optimized" + project_id = data.zillizcloud_project.default.id +} +``` + + +## Schema + +### Required + +- `cluster_name` (String) The name of the cluster to be created. It is a string of no more than 32 characters. +- `project_id` (String) The ID of the project where the cluster is to be created. + +### Optional + +- `cu_size` (Number) The size of the CU to be used for the created cluster. It is an integer from 1 to 256. +- `cu_type` (String) The type of the CU used for the Zilliz Cloud cluster to be created. A compute unit (CU) is the physical resource unit for cluster deployment. Different CU types comprise varying combinations of CPU, memory, and storage. Available options are Performance-optimized, Capacity-optimized, and Cost-optimized. This parameter defaults to Performance-optimized. The value defaults to Performance-optimized. +- `plan` (String) The plan tier of the Zilliz Cloud service. Available options are Standard and Enterprise. +- `region_id` (String) The ID of the region where the cluster exists. +- `timeouts` (Block, Optional) (see [below for nested schema](#nestedblock--timeouts)) + +### Read-Only + +- `cluster_type` (String) The type of CU associated with the cluster. Possible values are Performance-optimized and Capacity-optimized. +- `connect_address` (String) The public endpoint of the cluster. You can connect to the cluster using this endpoint from the public network. +- `create_time` (String) The time at which the cluster has been created. +- `description` (String) An optional description about the cluster. +- `id` (String) Cluster identifier +- `password` (String, Sensitive) The password of the cluster user generated by default. It will not be displayed again, so note it down and securely store it. +- `private_link_address` (String) The private endpoint of the cluster. You can set up a private link to allow your VPS in the same cloud region to access your cluster. +- `prompt` (String) The statement indicating that this operation succeeds. +- `status` (String) The current status of the cluster. Possible values are INITIALIZING, RUNNING, SUSPENDING, and RESUMING. +- `username` (String) The name of the cluster user generated by default. + + +### Nested Schema for `timeouts` + +Optional: + +- `create` (String) Timeout defaults to 5 mins. Accepts a string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). +- `update` (String) Timeout defaults to 5 mins. Accepts a string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). diff --git a/docs/resources/example.md b/docs/resources/example.md deleted file mode 100644 index 5f3d5ca..0000000 --- a/docs/resources/example.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "scaffolding_example Resource - scaffolding" -subcategory: "" -description: |- - Example resource ---- - -# scaffolding_example (Resource) - -Example resource - -## Example Usage - -```terraform -resource "scaffolding_example" "example" { - configurable_attribute = "some-value" -} -``` - - -## Schema - -### Optional - -- `configurable_attribute` (String) Example configurable attribute -- `defaulted` (String) Example configurable attribute with default value - -### Read-Only - -- `id` (String) Example identifier