diff --git a/acceptance/openstack/css/v1/change_cluser_name_test.go b/acceptance/openstack/css/v1/change_cluser_name_test.go new file mode 100644 index 000000000..a0ac36f6e --- /dev/null +++ b/acceptance/openstack/css/v1/change_cluser_name_test.go @@ -0,0 +1,25 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestChangeClusterNameWorkflow(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + opts := clusters.ChangeClusterNameOpts{ + DisplayName: tools.RandomString("changed-css-", 4), + } + err = clusters.ChangeClusterName(client, clusterID, opts) + th.AssertNoErr(t, err) +} diff --git a/acceptance/openstack/css/v1/change_password_test.go b/acceptance/openstack/css/v1/change_password_test.go new file mode 100644 index 000000000..27a93568f --- /dev/null +++ b/acceptance/openstack/css/v1/change_password_test.go @@ -0,0 +1,27 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestChangePasswordWorkflow(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + opts := clusters.ChangePasswordOpts{ + + NewPassword: tools.RandomString("newpass-css-", 4), + } + err = clusters.ChangePassword(client, clusterID, opts) + + th.AssertNoErr(t, err) +} diff --git a/acceptance/openstack/css/v1/cluster_add_nodes_test.go b/acceptance/openstack/css/v1/cluster_add_nodes_test.go new file mode 100644 index 000000000..ac147ff59 --- /dev/null +++ b/acceptance/openstack/css/v1/cluster_add_nodes_test.go @@ -0,0 +1,90 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/flavors" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestAddClusterClientNodes(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + nodeType := "ess-client" + nodeSize := 1 + volumeType := "HIGH" + + cluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + for _, instance := range cluster.Instances { + if instance.Type == nodeType { + t.Skip("Cluster already contains ess-client nodes.") + } + } + + Versions, err := flavors.List(client) + th.AssertNoErr(t, err) + filteredVersions := flavors.FilterVersions(Versions, flavors.FilterOpts{ + Version: cluster.Datastore.Version, + Type: nodeType, + }) + + _, err = clusters.AddClusterNodes(client, clusterID, nodeType, clusters.AddNodesOpts{ + Flavor: filteredVersions[0].Flavors[0].FlavorID, + NodeSize: nodeSize, + VolumeType: volumeType, + }) + th.AssertNoErr(t, err) + + timeout := 1200 + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) +} + +func TestAddClusterMasterNodes(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + nodeType := "ess-master" + nodeSize := 3 + volumeType := "HIGH" + + cluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + for _, instance := range cluster.Instances { + if instance.Type == nodeType { + t.Skip("Cluster already contains ess-master nodes.") + } + } + + Versions, err := flavors.List(client) + th.AssertNoErr(t, err) + filteredVersions := flavors.FilterVersions(Versions, flavors.FilterOpts{ + Version: cluster.Datastore.Version, + Type: nodeType, + }) + + _, err = clusters.AddClusterNodes(client, clusterID, nodeType, clusters.AddNodesOpts{ + Flavor: filteredVersions[0].Flavors[0].FlavorID, + NodeSize: nodeSize, + VolumeType: volumeType, + }) + th.AssertNoErr(t, err) + + timeout := 1200 + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) +} diff --git a/acceptance/openstack/css/v1/cluster_scale_in_test.go b/acceptance/openstack/css/v1/cluster_scale_in_test.go new file mode 100644 index 000000000..db030dfea --- /dev/null +++ b/acceptance/openstack/css/v1/cluster_scale_in_test.go @@ -0,0 +1,30 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestScaleInCluster(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + err = clusters.ScaleInCluster(client, clusterID, []clusters.ScaleInOpts{ + { + Type: "ess", + ReduceNodeNum: 1, + }, + }) + th.AssertNoErr(t, err) + + timeout := 1200 + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) +} diff --git a/acceptance/openstack/css/v1/cluster_update_flavor_test.go b/acceptance/openstack/css/v1/cluster_update_flavor_test.go new file mode 100644 index 000000000..320b4e787 --- /dev/null +++ b/acceptance/openstack/css/v1/cluster_update_flavor_test.go @@ -0,0 +1,113 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/flavors" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestUpdateClusterFlavor(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + cluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + var ( + currentFlavor string + newFlavorID string + instanceType string = "ess" + ) + + for _, instance := range cluster.Instances { + if instance.Type == instanceType { + currentFlavor = instance.SpecCode + break + } + } + + filterOpts := flavors.FilterOpts{ + Version: "7.10.2", + Type: instanceType, + } + + versions, err := flavors.List(client) + th.AssertNoErr(t, err) + + filteredVersions := flavors.FilterVersions(versions, filterOpts) + if filteredVersions[0].Flavors[0].Name != currentFlavor { + newFlavorID = filteredVersions[0].Flavors[0].FlavorID + } else { + newFlavorID = filteredVersions[0].Flavors[1].FlavorID + } + needCheckReplica := false + err = clusters.UpdateClusterFlavor(client, clusterID, clusters.ClusterFlavorOpts{ + NeedCheckReplica: &needCheckReplica, + NewFlavorID: newFlavorID, + }) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) +} + +func TestUpdateClusterNodeFlavor(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + cluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + var ( + currentFlavor string + newFlavorID string + instanceType string + ) + + for _, instance := range cluster.Instances { + if instance.Type == "ess-cold" || instance.Type == "ess-client" || instance.Type == "ess-master" { + currentFlavor = instance.SpecCode + instanceType = instance.Type + break + } + } + + if instanceType == "" { + t.Skip("There are no client, cold or master nodes to change the flavor.") + } + + filterOpts := flavors.FilterOpts{ + Version: "7.10.2", + Type: instanceType, + } + + versions, err := flavors.List(client) + th.AssertNoErr(t, err) + + filteredVersions := flavors.FilterVersions(versions, filterOpts) + if filteredVersions[0].Flavors[0].Name != currentFlavor { + newFlavorID = filteredVersions[0].Flavors[0].FlavorID + } else { + newFlavorID = filteredVersions[0].Flavors[1].FlavorID + } + + needCheckReplica := false + err = clusters.UpdateClusterFlavor(client, clusterID, clusters.ClusterFlavorOpts{ + NeedCheckReplica: &needCheckReplica, + NewFlavorID: newFlavorID, + NodeType: instanceType, + }) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) +} diff --git a/acceptance/openstack/css/v1/cluster_update_sg_test.go b/acceptance/openstack/css/v1/cluster_update_sg_test.go new file mode 100644 index 000000000..86f5028ae --- /dev/null +++ b/acceptance/openstack/css/v1/cluster_update_sg_test.go @@ -0,0 +1,27 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/openstack" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestUpdateSecurityGroup(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + sgID := openstack.DefaultSecurityGroup(t) + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + err = clusters.UpdateSecurityGroup(client, clusterID, clusters.SecurityGroupOpts{ + SecurityGroupID: sgID, + }) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) +} diff --git a/acceptance/openstack/css/v1/cluster_update_sm_test.go b/acceptance/openstack/css/v1/cluster_update_sm_test.go new file mode 100644 index 000000000..e577958ca --- /dev/null +++ b/acceptance/openstack/css/v1/cluster_update_sm_test.go @@ -0,0 +1,140 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/tools" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestUpdateSecurityModeEnableAll(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + cssCluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + adminPWD := tools.RandomString("newpass-css-", 4) + httpsEnable := cssCluster.HttpsEnabled + authEnable := cssCluster.AuthorityEnabled + + if httpsEnable == false && authEnable == false { + httpsEnable = !httpsEnable + authEnable = !authEnable + } else { + t.Skip("The HTTPS and the Authority is already enabled.") + } + + err = clusters.UpdateSecurityMode(client, clusterID, clusters.SecurityModeOpts{ + AuthorityEnabled: &authEnable, + AdminPassword: adminPWD, + HttpsEnabled: &httpsEnable, + }) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) + +} + +func TestUpdateSecurityModeDisableAll(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + cssCluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + httpsEnable := cssCluster.HttpsEnabled + authEnable := cssCluster.AuthorityEnabled + + if httpsEnable == true && authEnable == true { + httpsEnable = !httpsEnable + authEnable = !authEnable + } else { + t.Skip("The HTTPS and the Authority is already disabled.") + } + + err = clusters.UpdateSecurityMode(client, clusterID, clusters.SecurityModeOpts{ + AuthorityEnabled: &authEnable, + HttpsEnabled: &httpsEnable, + }) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) + +} + +func TestUpdateSecurityModeEnableHttps(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + cssCluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + adminPWD := tools.RandomString("newpass-css-", 4) + httpsEnable := cssCluster.HttpsEnabled + + if httpsEnable == false { + httpsEnable = !httpsEnable + } else { + t.Skip("HTTPS is already enabled.") + } + + var authEnable bool = true + + err = clusters.UpdateSecurityMode(client, clusterID, clusters.SecurityModeOpts{ + AuthorityEnabled: &authEnable, + AdminPassword: adminPWD, + HttpsEnabled: &httpsEnable, + }) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) + +} + +func TestUpdateSecurityModeEnableAuthority(t *testing.T) { + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + cssCluster, err := clusters.Get(client, clusterID) + th.AssertNoErr(t, err) + + adminPWD := tools.RandomString("newpass-css-", 4) + authEnable := cssCluster.AuthorityEnabled + + if authEnable == false { + authEnable = !authEnable + } else { + t.Skip("Authority is already enabled.") + } + + var httpsEnable bool = false + + err = clusters.UpdateSecurityMode(client, clusterID, clusters.SecurityModeOpts{ + AuthorityEnabled: &authEnable, + AdminPassword: adminPWD, + HttpsEnabled: &httpsEnable, + }) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, timeout)) + +} diff --git a/acceptance/openstack/css/v1/restart_cluster_test.go b/acceptance/openstack/css/v1/restart_cluster_test.go new file mode 100644 index 000000000..034655240 --- /dev/null +++ b/acceptance/openstack/css/v1/restart_cluster_test.go @@ -0,0 +1,24 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/clusters" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestRestartClusterWorkflow(t *testing.T) { + + clusterID := clients.EnvOS.GetEnv("CSS_CLUSTER_ID") + if clusterID == "" { + t.Skip("`CSS_CLUSTER_ID` must be defined") + } + client, err := clients.NewCssV1Client() + th.AssertNoErr(t, err) + + err = clusters.RestartCluster(client, clusterID) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, clusters.WaitForCluster(client, clusterID, 1200)) +} diff --git a/openstack/css/v1/clusters/AddClusterNodes.go b/openstack/css/v1/clusters/AddClusterNodes.go new file mode 100644 index 000000000..e8b32126b --- /dev/null +++ b/openstack/css/v1/clusters/AddClusterNodes.go @@ -0,0 +1,54 @@ +package clusters + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +// AddNodesOpts defines options to add master or client nodes . +type AddNodesOpts struct { + // NodeSize - Number of nodes. The value range is 1 to 32. + // If the node type is ess-master, the number of nodes must be an odd number in the range 3 to 10. + // If the node type is ess-client, the number of nodes must be in the range 1 to 32. + NodeSize int `json:"node_size" required:"true"` + // Flavor - Flavor ID. + Flavor string `json:"flavor_ref" required:"true"` + // Type of the volume. + // One of: + // - `COMMON`: Common I/O + // - `HIGH`: High I/O + // - `ULTRAHIGH`: Ultra-high I/O + VolumeType string `json:"volume_type" required:"true"` +} + +// AddClusterNodes function lets you add master and client nodes to a cluster. +func AddClusterNodes(client *golangsdk.ServiceClient, clusterID string, NodeType string, opts AddNodesOpts) (*AddNodesResponse, error) { + + b, err := build.RequestBody(opts, "type") + if err != nil { + return nil, err + } + + // POST /v1.0/{project_id}/clusters/{cluster_id}/type/{type}/independent + url := client.ServiceURL("clusters", clusterID, "type", NodeType, "independent") + + raw, err := client.Post(url, b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + }, + }) + if err != nil { + return nil, err + } + + var res AddNodesResponse + err = extract.IntoStructPtr(raw.Body, &res, "") + + return &res, err +} + +type AddNodesResponse struct { + ID string `json:"id"` +} diff --git a/openstack/css/v1/clusters/ChangeClusterName.go b/openstack/css/v1/clusters/ChangeClusterName.go new file mode 100644 index 000000000..a81a25a05 --- /dev/null +++ b/openstack/css/v1/clusters/ChangeClusterName.go @@ -0,0 +1,26 @@ +package clusters + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +type ChangeClusterNameOpts struct { + // DisplayName contains options for new name + // This object is passed to the snapshots.ChangeClusterName function. + DisplayName string `json:"displayName" required:"true"` +} + +// ChangeClusterName function is used to change the name of a cluster. +func ChangeClusterName(client *golangsdk.ServiceClient, clusterID string, opts ChangeClusterNameOpts) error { + // ChangeClusterName will change cluster name based on ChangeClusterNameOpts + b, err := build.RequestBody(opts, "") + if err != nil { + return err + } + + _, err = client.Post(client.ServiceURL("clusters", clusterID, "changename"), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + return err +} diff --git a/openstack/css/v1/clusters/ChangePassword.go b/openstack/css/v1/clusters/ChangePassword.go new file mode 100644 index 000000000..885aa044d --- /dev/null +++ b/openstack/css/v1/clusters/ChangePassword.go @@ -0,0 +1,26 @@ +package clusters + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +type ChangePasswordOpts struct { + // DisplayName contains options for new name + // This object is passed to the snapshots.ChangeClusterName function. + NewPassword string `json:"newpassword" required:"true"` +} + +// ChangePassword function is used to change the password of a cluster. +func ChangePassword(client *golangsdk.ServiceClient, clusterID string, opts ChangePasswordOpts) (err error) { + // ChangeClusterName will change cluster name based on ChangeClusterNameOpts + b, err := build.RequestBody(opts, "") + if err != nil { + return err + } + + _, err = client.Post(client.ServiceURL("clusters", clusterID, "password", "reset"), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + return +} diff --git a/openstack/css/v1/clusters/RestartCluster.go b/openstack/css/v1/clusters/RestartCluster.go new file mode 100644 index 000000000..2e671ffa4 --- /dev/null +++ b/openstack/css/v1/clusters/RestartCluster.go @@ -0,0 +1,11 @@ +package clusters + +import golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + +// RestartCluster function is used to restart a cluster. +func RestartCluster(client *golangsdk.ServiceClient, clusterID string) error { + _, err := client.Post(client.ServiceURL("clusters", clusterID, "restart"), nil, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + return err +} diff --git a/openstack/css/v1/clusters/ScaleInCluster.go b/openstack/css/v1/clusters/ScaleInCluster.go new file mode 100644 index 000000000..1fdf7a8ca --- /dev/null +++ b/openstack/css/v1/clusters/ScaleInCluster.go @@ -0,0 +1,51 @@ +package clusters + +import ( + "strings" + + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +// ScaleInOpts defines options for scaling in a cluster. +type ScaleInOpts struct { + // Type specifies the type of instance to be scaled in. + // Select at least one from `ess`, `ess-cold`, `ess-master`, and `ess-client`. + Type string `json:"type"` + // ReduceNodeNum is the number of nodes to be removed. + // After scaling in, there must be at least one node in each AZ under each node type. + // In a cross-AZ cluster, the difference between the number of nodes of the same type in different AZs cannot exceed 1. + // For a cluster with Master nodes, the number of removed master nodes in a scale-in must be fewer than half of the original master node count. + ReduceNodeNum int `json:"reducedNodeNum"` +} + +// ScaleInRequest is a wrapper to structure the "shrink" key in the JSON body. +type ScaleInRequest struct { + Shrink []ScaleInOpts `json:"shrink"` +} + +// ScaleInCluster scales in a cluster by removing specified nodes. +func ScaleInCluster(client *golangsdk.ServiceClient, clusterID string, opts []ScaleInOpts) error { + // Wrap opts in ScaleInRequest to match the required JSON structure. + request := ScaleInRequest{ + Shrink: opts, + } + + b, err := build.RequestBody(request, "") + if err != nil { + return err + } + + // POST /v1.0/extend/{project_id}/clusters/{cluster_id}/role/shrink + url := client.ServiceURL("clusters", clusterID, "role", "shrink") + convertedURL := strings.Replace(url, "v1.0", "v1.0/extend", 1) + + _, err = client.Post(convertedURL, b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + }, + }) + + return err +} diff --git a/openstack/css/v1/clusters/UpdateClusterFlavor.go b/openstack/css/v1/clusters/UpdateClusterFlavor.go new file mode 100644 index 000000000..325b75f4d --- /dev/null +++ b/openstack/css/v1/clusters/UpdateClusterFlavor.go @@ -0,0 +1,42 @@ +package clusters + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +type ClusterFlavorOpts struct { + // Indicates whether to verify replicas. + NeedCheckReplica *bool `json:"needCheckReplica,omitempty"` + // ID of the new flavor. + NewFlavorID string `json:"newFlavorId" required:"true"` + // Type of the cluster node to modify. + NodeType string `json:"-"` +} + +// UpdateClusterFlavor is used to modify the specifications of a cluster or specifications of a specified node type. +func UpdateClusterFlavor(client *golangsdk.ServiceClient, clusterID string, opts ClusterFlavorOpts) error { + // Construct the URL dynamically based on the optional NodeType. + + var url string + + if opts.NodeType != "" { + url = client.ServiceURL("clusters", clusterID, opts.NodeType, "flavor") + } else { + url = client.ServiceURL("clusters", clusterID, "flavor") + } + + b, err := build.RequestBody(opts, "") + if err != nil { + return err + } + + _, err = client.Post(url, b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + }, + }) + + return err +} diff --git a/openstack/css/v1/clusters/UpdateSecurityGroup.go b/openstack/css/v1/clusters/UpdateSecurityGroup.go new file mode 100644 index 000000000..2fa27ad94 --- /dev/null +++ b/openstack/css/v1/clusters/UpdateSecurityGroup.go @@ -0,0 +1,30 @@ +package clusters + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +type SecurityGroupOpts struct { + // Security group ID. + SecurityGroupID string `json:"security_group_ids" required:"true"` +} + +// UpdateSecurityGroup - change the security group of a cluster. +func UpdateSecurityGroup(client *golangsdk.ServiceClient, clusterID string, opts SecurityGroupOpts) error { + b, err := build.RequestBody(opts, "") + if err != nil { + return err + } + + url := client.ServiceURL("clusters", clusterID, "sg", "change") + + _, err = client.Post(url, b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + }, + }) + + return err +} diff --git a/openstack/css/v1/clusters/UpdateSecurityMode.go b/openstack/css/v1/clusters/UpdateSecurityMode.go new file mode 100644 index 000000000..3269560c8 --- /dev/null +++ b/openstack/css/v1/clusters/UpdateSecurityMode.go @@ -0,0 +1,34 @@ +package clusters + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" +) + +type SecurityModeOpts struct { + // Indicates whether to enable the security mode. + AuthorityEnabled *bool `json:"authorityEnable"` + // Cluster password. + AdminPassword string `json:"adminPwd"` + // Indicates whether to enable HTTPS. + HttpsEnabled *bool `json:"httpsEnable"` +} + +// UpdateSecurityMode - change the security mode of a cluster. +func UpdateSecurityMode(client *golangsdk.ServiceClient, clusterID string, opts SecurityModeOpts) error { + b, err := build.RequestBody(opts, "") + if err != nil { + return err + } + + url := client.ServiceURL("clusters", clusterID, "mode", "change") + + _, err = client.Post(url, b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + MoreHeaders: map[string]string{ + "Content-Type": "application/json", + }, + }) + + return err +} diff --git a/openstack/css/v1/clusters/util.go b/openstack/css/v1/clusters/util.go index e7285d474..10589aefe 100644 --- a/openstack/css/v1/clusters/util.go +++ b/openstack/css/v1/clusters/util.go @@ -54,3 +54,26 @@ func WaitForClusterToExtend(client *golangsdk.ServiceClient, id string, timeout return false, fmt.Errorf("unexpected cluster actions: %v; progress: %v", cluster.Actions, cluster.ActionProgress) }) } + +func WaitForCluster(client *golangsdk.ServiceClient, id string, timeout int) error { + return golangsdk.WaitFor(timeout, func() (bool, error) { + cluster, err := Get(client, id) + if err != nil { + if _, ok := err.(golangsdk.BaseError); ok { + return true, err + } + log.Printf("Error while waiting for cluster's status to change to active: %s", err) + return false, nil + } + + if len(cluster.Actions) == 0 { + return true, nil + } + + if len(cluster.Actions[0]) != 0 { + time.Sleep(30 * time.Second) + return false, nil + } + return false, fmt.Errorf("unexpected cluster actions: %v; progress: %v", cluster.Actions, cluster.ActionProgress) + }) +}