diff --git a/acceptance/openstack/gaussdb/v3/db_test.go b/acceptance/openstack/gaussdb/v3/db_test.go index 8c001ce10..7aeefdbf4 100644 --- a/acceptance/openstack/gaussdb/v3/db_test.go +++ b/acceptance/openstack/gaussdb/v3/db_test.go @@ -46,6 +46,7 @@ func TestGaussDBLifecycle(t *testing.T) { SlaveCount: pointerto.Int(1), SecurityGroupId: openstack.DefaultSecurityGroup(t), }) + th.AssertNoErr(t, err) id := ins.Instance.Id t.Cleanup(func() { @@ -100,7 +101,7 @@ func TestGaussDBLifecycle(t *testing.T) { getInstance, err = instance.GetInstance(client, ins.Instance.Id) th.AssertNoErr(t, err) - th.AssertEquals(t, getInstance.Name, name) + th.AssertEquals(t, getInstance.Name, nameOpts.Name) } diff --git a/acceptance/openstack/gaussdb/v3/proxy_test.go b/acceptance/openstack/gaussdb/v3/proxy_test.go new file mode 100644 index 000000000..49a0ee99c --- /dev/null +++ b/acceptance/openstack/gaussdb/v3/proxy_test.go @@ -0,0 +1,112 @@ +package v3 + +import ( + "os" + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/openstack" + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/common/pointerto" + v3 "github.com/opentelekomcloud/gophertelekomcloud/openstack/gaussdb/v3" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/gaussdb/v3/instance" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/gaussdb/v3/proxy" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestGaussDBProxyLifecycle(t *testing.T) { + if os.Getenv("RUN_GAUSS") == "" { + t.Skip("long test") + } + client, err := clients.NewGaussDBClient() + th.AssertNoErr(t, err) + createOpts := openstack.GetCloudServerCreateOpts(t) + + name := tools.RandomString("gaussdb-test-", 5) + + ins, err := instance.CreateInstance(client, instance.CreateInstanceOpts{ + Region: "eu-de", + Name: name, + AvailabilityZoneMode: "multi", + MasterAvailabilityZone: "eu-de-01", + Datastore: instance.Datastore{ + Type: "gaussdb-mysql", + Version: "8.0", + }, + Mode: "Cluster", + FlavorRef: "gaussdb.mysql.large.x86.4", + VpcId: createOpts.VpcId, + SubnetId: createOpts.Nics[0].SubnetId, + Password: "gaussdb1!-test", + SlaveCount: pointerto.Int(1), + SecurityGroupId: openstack.DefaultSecurityGroup(t), + }) + th.AssertNoErr(t, err) + id := ins.Instance.Id + + t.Cleanup(func() { + _, err = instance.DeleteInstance(client, ins.Instance.Id) + th.AssertNoErr(t, err) + }) + th.AssertNoErr(t, err) + _, err = v3.WaitForGaussJob(client, ins.JobId, 600) + th.AssertNoErr(t, err) + + t.Logf("Attempting to list GaussDB proxy flavors") + flavors, err := proxy.ListFlavors(client, id) + th.AssertNoErr(t, err) + + tools.PrintResource(t, flavors) + + t.Logf("Attempting to enable GaussDB proxy") + jobId, err := proxy.EnableProxy(client, proxy.EnableProxyOpts{ + InstanceID: id, + NodeNum: 1, + FlavorRef: flavors[0].ProxyFlavors[0].SpecCode, + }) + th.AssertNoErr(t, err) + _, err = v3.WaitForGaussJob(client, jobId, 600) + th.AssertNoErr(t, err) + + t.Logf("Attempting to list proxy instances") + + proxyNode, err := proxy.ListProxyInstances(client, proxy.ListProxyInstancesOpts{}) + th.AssertNoErr(t, err) + + tools.PrintResource(t, proxyNode) + + t.Logf("Attempting to enlarge proxy") + + jobId, err = proxy.EnlargeProxy(client, proxy.EnlargeProxyOpts{ + InstanceID: id, + NodeNum: 2, + }) + th.AssertNoErr(t, err) + _, err = v3.WaitForGaussJob(client, jobId, 600) + th.AssertNoErr(t, err) + + t.Logf("Attempting to change proxy flavor") + + jobId, err = proxy.ChangeFlavor(client, proxy.ChangeFlavorOpts{ + InstanceID: id, + ProxyID: proxyNode.ProxyList[0].Proxy.Nodes[0].ID, + FlavorRef: flavors[0].ProxyFlavors[1].SpecCode, + }) + + th.AssertNoErr(t, err) + _, err = v3.WaitForGaussJob(client, jobId, 600) + th.AssertNoErr(t, err) + + t.Logf("Attempting to disable proxy flavor") + jobId, err = proxy.Disable(client, proxy.DisableProxyOpts{ + InstanceID: id, + ProxyIDs: &[]string{ + proxyNode.ProxyList[0].Proxy.Nodes[0].ID, + proxyNode.ProxyList[0].Proxy.Nodes[1].ID, + }, + }) + + th.AssertNoErr(t, err) + _, err = v3.WaitForGaussJob(client, jobId, 600) + th.AssertNoErr(t, err) +} diff --git a/openstack/client.go b/openstack/client.go index bdf076e3a..96c42b48d 100644 --- a/openstack/client.go +++ b/openstack/client.go @@ -955,7 +955,7 @@ func NewTMSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*gol } func NewGaussDBV3(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) { - sc, err := initCommonServiceClient(client, eo, "gaussdb", "mysql/v3") + sc, err := initCommonServiceClient(client, eo, "gaussdb-mysql", "v3") return sc, err } diff --git a/openstack/gaussdb/v3/instance/CreateInstance.go b/openstack/gaussdb/v3/instance/CreateInstance.go index e97fddcaa..a0bc90c4c 100644 --- a/openstack/gaussdb/v3/instance/CreateInstance.go +++ b/openstack/gaussdb/v3/instance/CreateInstance.go @@ -54,9 +54,6 @@ type CreateInstanceOpts struct { MasterAvailabilityZone string `json:"master_availability_zone,omitempty"` // Number of created read replicas. The value ranges from 1 to 9. An instance contains up to 15 read replicas. SlaveCount *int `json:"slave_count"` - // Volume information. - // Missing in documentation - Volume *MysqlVolume `json:"volume,omitempty"` // Tag list. Instances are created based on tag keys and values. // {key} indicates the tag key. It must be unique and cannot be empty. // {value} indicates the tag value, which can be empty. To create instances with multiple tag keys and values, @@ -66,12 +63,6 @@ type CreateInstanceOpts struct { DedicatedResourceId string `json:"dedicated_resource_id,omitempty"` } -type MysqlVolume struct { - // Storage space. The default value is 40 in GB. - // The value ranges from 40 GB to 128,000 GB and must be a multiple of 10. - Size string `json:"size"` -} - type MysqlTags struct { // Tag key. The value can contain up to 36 unicode characters. The value cannot be an empty string, a space, or left blank. // Only uppercase letters, lowercase letters, digits, hyphens (-), and underscores (_) are allowed. diff --git a/openstack/gaussdb/v3/proxy/AssignWeight.go b/openstack/gaussdb/v3/proxy/AssignWeight.go new file mode 100644 index 000000000..70f05d477 --- /dev/null +++ b/openstack/gaussdb/v3/proxy/AssignWeight.go @@ -0,0 +1,35 @@ +package proxy + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type AssignWeightOpts struct { + InstanceID string `json:"-"` + ProxyID string `json:"-"` + MasterWeight *int `json:"flavor_ref,omitempty"` + ReadonlyNodes *[]ReadonlyNode `json:"readonly_nodes,omitempty"` +} + +type ReadonlyNode struct { + ID string `json:"id"` + Weight *int `json:"weight"` +} + +func AssignWeight(client *golangsdk.ServiceClient, opts AssignWeightOpts) (string, error) { + b, err := build.RequestBody(opts, "") + if err != nil { + return "", err + } + + raw, err := client.Put(client.ServiceURL("instances", opts.InstanceID, "proxy", opts.ProxyID, "weight"), b, nil, nil) + if err != nil { + return "", err + } + + var res JobId + err = extract.Into(raw.Body, &res) + return res.JobId, err +} diff --git a/openstack/gaussdb/v3/proxy/ChangeFlavor.go b/openstack/gaussdb/v3/proxy/ChangeFlavor.go new file mode 100644 index 000000000..92bdabc83 --- /dev/null +++ b/openstack/gaussdb/v3/proxy/ChangeFlavor.go @@ -0,0 +1,29 @@ +package proxy + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type ChangeFlavorOpts struct { + InstanceID string `json:"-"` + ProxyID string `json:"-"` + FlavorRef string `json:"flavor_ref" required:"true"` +} + +func ChangeFlavor(client *golangsdk.ServiceClient, opts ChangeFlavorOpts) (string, error) { + b, err := build.RequestBody(opts, "") + if err != nil { + return "", err + } + + raw, err := client.Put(client.ServiceURL("instances", opts.InstanceID, "proxy", opts.ProxyID, "flavor"), b, nil, nil) + if err != nil { + return "", err + } + + var res JobId + err = extract.Into(raw.Body, &res) + return res.JobId, err +} diff --git a/openstack/gaussdb/v3/proxy/Disable.go b/openstack/gaussdb/v3/proxy/Disable.go new file mode 100644 index 000000000..db242a359 --- /dev/null +++ b/openstack/gaussdb/v3/proxy/Disable.go @@ -0,0 +1,31 @@ +package proxy + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type DisableProxyOpts struct { + InstanceID string `json:"-"` + ProxyIDs *[]string `json:"proxy_ids,omitempty"` +} + +func Disable(client *golangsdk.ServiceClient, opts DisableProxyOpts) (string, error) { + b, err := build.RequestBody(opts, "") + if err != nil { + return "", err + } + + raw, err := client.DeleteWithBody(client.ServiceURL("instances", opts.InstanceID, "proxy"), b, &golangsdk.RequestOpts{ + OkCodes: []int{200, 202}, + MoreHeaders: map[string]string{"Content-Type": "application/json"}, + }) + if err != nil { + return "", err + } + + var res JobId + err = extract.Into(raw.Body, &res) + return res.JobId, err +} diff --git a/openstack/gaussdb/v3/proxy/Enable.go b/openstack/gaussdb/v3/proxy/Enable.go new file mode 100644 index 000000000..ec70280ca --- /dev/null +++ b/openstack/gaussdb/v3/proxy/Enable.go @@ -0,0 +1,41 @@ +package proxy + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type EnableProxyOpts struct { + InstanceID string `json:"-"` + FlavorRef string `json:"flavor_ref" required:"true"` + NodeNum int `json:"node_num" required:"true"` + ProxyName string `json:"proxy_name,omitempty"` + ProxyMode string `json:"proxy_mode,omitempty"` + NodesReadWeight []NodeWeight `json:"nodes_read_weight,omitempty"` +} + +type NodeWeight struct { + ID string `json:"id"` + Weight int `json:"weight"` +} + +func EnableProxy(client *golangsdk.ServiceClient, opts EnableProxyOpts) (string, error) { + b, err := build.RequestBody(opts, "") + if err != nil { + return "", err + } + + raw, err := client.Post(client.ServiceURL("instances", opts.InstanceID, "proxy"), b, nil, nil) + if err != nil { + return "", err + } + + var res JobId + err = extract.Into(raw.Body, &res) + return res.JobId, err +} + +type JobId struct { + JobId string `json:"job_id"` +} diff --git a/openstack/gaussdb/v3/proxy/Enlarge.go b/openstack/gaussdb/v3/proxy/Enlarge.go new file mode 100644 index 000000000..81194190e --- /dev/null +++ b/openstack/gaussdb/v3/proxy/Enlarge.go @@ -0,0 +1,29 @@ +package proxy + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type EnlargeProxyOpts struct { + InstanceID string `json:"-"` + NodeNum int `json:"node_num" required:"true"` + ProxyID string `json:"proxy_id,omitempty"` +} + +func EnlargeProxy(client *golangsdk.ServiceClient, opts EnlargeProxyOpts) (string, error) { + b, err := build.RequestBody(opts, "") + if err != nil { + return "", err + } + + raw, err := client.Post(client.ServiceURL("instances", opts.InstanceID, "proxy", "enlarge"), b, nil, nil) + if err != nil { + return "", err + } + + var res JobId + err = extract.Into(raw.Body, &res) + return res.JobId, err +} diff --git a/openstack/gaussdb/v3/proxy/ListFlavors.go b/openstack/gaussdb/v3/proxy/ListFlavors.go new file mode 100644 index 000000000..e6e7e8180 --- /dev/null +++ b/openstack/gaussdb/v3/proxy/ListFlavors.go @@ -0,0 +1,30 @@ +package proxy + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +func ListFlavors(client *golangsdk.ServiceClient, instanceID string) ([]ProxyFlavor, error) { + raw, err := client.Get(client.ServiceURL("instances", instanceID, "proxy", "flavors"), nil, nil) + if err != nil { + return nil, err + } + + var res []ProxyFlavor + err = extract.IntoSlicePtr(raw.Body, &res, "proxy_flavor_groups") + return res, err +} + +type ProxyFlavor struct { + GroupType string `json:"group_type"` + ProxyFlavors []MysqlFlavor `json:"proxy_flavors"` +} + +type MysqlFlavor struct { + Vcpus string `json:"vcpus"` + Ram string `json:"ram"` + DbType string `json:"db_type"` + ID string `json:"id"` + SpecCode string `json:"spec_code"` +} diff --git a/openstack/gaussdb/v3/proxy/ListProxyInstances.go b/openstack/gaussdb/v3/proxy/ListProxyInstances.go new file mode 100644 index 000000000..6876c37c8 --- /dev/null +++ b/openstack/gaussdb/v3/proxy/ListProxyInstances.go @@ -0,0 +1,78 @@ +package proxy + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type ListProxyInstancesOpts struct { + InstanceID string `json:"-"` + Limit int `q:"limit"` + Offset int `q:"offset"` +} + +func ListProxyInstances(client *golangsdk.ServiceClient, opts ListProxyInstancesOpts) (*ListProxyInstanceResponse, error) { + url, err := golangsdk.NewURLBuilder().WithEndpoints("instances", opts.InstanceID, "proxies").WithQueryParams(&opts).Build() + if err != nil { + return nil, err + } + + raw, err := client.Get(client.ServiceURL(url.String()), nil, nil) + if err != nil { + return nil, err + } + + var res ListProxyInstanceResponse + err = extract.Into(raw.Body, &res) + return &res, err +} + +type ListProxyInstanceResponse struct { + ProxyList []MysqlProxyResponse `json:"proxy_list"` +} + +type MysqlProxyResponse struct { + Proxy *MysqlProxy `json:"proxy"` + MasterNode *MysqlProxyNodeV3 `json:"master_node"` + ReadonlyNodes []MysqlProxyNodeV3 `json:"readonly_nodes"` +} + +type MysqlProxy struct { + PoolID string `json:"pool_id"` + Status string `json:"status"` + Address string `json:"address"` + Port int `json:"port"` + PoolStatus string `json:"pool_status"` + DelayThresholdInSeconds int `json:"delay_threshold_in_seconds"` + ElbVIP string `json:"elb_vip"` + EIP string `json:"eip"` + Vcpus string `json:"vcpus"` + Ram string `json:"ram"` + NodeNum int `json:"node_num"` + Mode string `json:"mode"` + Nodes []MysqlProxyNode `json:"nodes"` + TransactionSplit string `json:"transaction_split"` +} + +type MysqlProxyNode struct { + ID string `json:"id"` + Status string `json:"status"` + Name string `json:"name"` + Role string `json:"role"` + AzCode string `json:"az_code"` + FrozenFlag int `json:"frozen_flag"` +} + +type MysqlProxyNodeV3 struct { + ID string `json:"id"` + InstanceId string `json:"instance_id"` + Status string `json:"status"` + Name string `json:"name"` + Weight int `json:"weight"` + AvailabilityZone *MysqlProxyAvailable `json:"availability_zone"` +} + +type MysqlProxyAvailable struct { + Code string `json:"code"` + Description string `json:"description"` +}