From 89e7b723fcc750234f488f83b39e89902eed6f28 Mon Sep 17 00:00:00 2001 From: Anton Sidelnikov <53078276+anton-sidelnikov@users.noreply.github.com> Date: Fri, 17 Jan 2025 15:29:24 +0100 Subject: [PATCH] CSS parameter configurations (#783) --- .../openstack/css/v1/configurations_test.go | 91 +++++++++++++++++++ .../css/v1/parameter-configuration/List.go | 50 ++++++++++ .../v1/parameter-configuration/ListTask.go | 37 ++++++++ .../css/v1/parameter-configuration/Modify.go | 44 +++++++++ 4 files changed, 222 insertions(+) create mode 100644 acceptance/openstack/css/v1/configurations_test.go create mode 100644 openstack/css/v1/parameter-configuration/List.go create mode 100644 openstack/css/v1/parameter-configuration/ListTask.go create mode 100644 openstack/css/v1/parameter-configuration/Modify.go diff --git a/acceptance/openstack/css/v1/configurations_test.go b/acceptance/openstack/css/v1/configurations_test.go new file mode 100644 index 000000000..9c2df5f16 --- /dev/null +++ b/acceptance/openstack/css/v1/configurations_test.go @@ -0,0 +1,91 @@ +package v1 + +import ( + "testing" + + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + pc "github.com/opentelekomcloud/gophertelekomcloud/openstack/css/v1/parameter-configuration" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestConfigurationsWorkflow(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) + + t.Logf("Attempting to MODIFY Parameter Configuration for cluster: %s", clusterID) + opts := pc.ModifyOpts{ + Edit: map[string]interface{}{ + "modify": map[string]interface{}{ + "elasticsearch.yml": map[string]interface{}{ + "http.cors.allow-credentials": true, + "http.cors.allow-headers": "X-Requested-With, Content-Type", + "thread_pool.force_merge.size": "5", + }, + }, + }, + } + _, err = pc.Modify(client, opts, clusterID) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, waitForState(client, clusterID, 30*60)) + + t.Cleanup(func() { + t.Logf("Attempting to DELETE Parameter Configuration for cluster: %s", clusterID) + resetOpts := pc.ModifyOpts{ + Edit: map[string]interface{}{ + "reset": map[string]interface{}{ + "elasticsearch.yml": map[string]interface{}{ + "http.cors.allow-credentials": "", + "http.cors.allow-origin": "", + "http.cors.max-age": "", + "http.cors.allow-headers": "", + "http.cors.enabled": "", + "http.cors.allow-methods": "", + "reindex.remote.whitelist": "", + "indices.queries.cache.size": "", + "thread_pool.force_merge.size": "", + }, + }, + }, + } + _, err = pc.Modify(client, resetOpts, clusterID) + th.AssertNoErr(t, err) + + th.AssertNoErr(t, waitForState(client, clusterID, 30*60)) + }) + + cfgs, err := pc.List(client, clusterID) + th.AssertNoErr(t, err) + for key, config := range cfgs.Templates { + if key == "http.cors.allow-headers" { + th.AssertEquals(t, "X-Requested-With, Content-Type", config.Value) + } + if key == "http.cors.allow-credentials" { + th.AssertEquals(t, "true", config.Value) + } + if key == "thread_pool.force_merge.size" { + th.AssertEquals(t, "5", config.Value) + } + } +} + +func waitForState(client *golangsdk.ServiceClient, id string, secs int) error { + return golangsdk.WaitFor(secs, func() (bool, error) { + cfgList, err := pc.ListTask(client, id) + if err != nil { + return false, err + } + for _, task := range cfgList { + if task.Status == "running" { + return false, nil + } + } + return true, nil + }) +} diff --git a/openstack/css/v1/parameter-configuration/List.go b/openstack/css/v1/parameter-configuration/List.go new file mode 100644 index 000000000..842d64057 --- /dev/null +++ b/openstack/css/v1/parameter-configuration/List.go @@ -0,0 +1,50 @@ +package parameter_configuration + +import ( + "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +func List(client *golangsdk.ServiceClient, clusterId string) (*Configurations, error) { + // GET /v1.0/{project_id}/clusters/{cluster_id}/ymls/template + raw, err := client.Get(client.ServiceURL("clusters", clusterId, "ymls", "template"), nil, nil) + if err != nil { + return nil, err + } + + var res Configurations + err = extract.Into(raw.Body, &res) + return &res, err +} + +type Configurations struct { + Templates map[string]Template `json:"configurations"` +} + +type Template struct { + // parameter ID + ID string `json:"id"` + // parameter name + Key string `json:"key"` + // parameter value + Value string `json:"value"` + // parameter default value. + DefaultValue string `json:"defaultValue"` + // parameter constraint + Regex string `json:"regex"` + // parameter type description + Type string `json:"type"` + // indicates whether a parameter can be modified. + // The value can be true (parameter value can be changed) and false (parameter value cannot be changed). + ModifyEnable string `json:"modifyEnable"` + // parameter value that can be changed + EnableValue string `json:"enableValue"` + // name of the file where parameters exist. The default value is elasticsearch.yml + FileName string `json:"fileName"` + // version information + Version string `json:"version"` + // parameter description + Description string `json:"descENG"` + // parameter function description + ModuleDescription string `json:"moduleDescENG"` +} diff --git a/openstack/css/v1/parameter-configuration/ListTask.go b/openstack/css/v1/parameter-configuration/ListTask.go new file mode 100644 index 000000000..99bfd423a --- /dev/null +++ b/openstack/css/v1/parameter-configuration/ListTask.go @@ -0,0 +1,37 @@ +package parameter_configuration + +import ( + "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +func ListTask(client *golangsdk.ServiceClient, clusterId string) ([]Task, error) { + // GET /v1.0/{project_id}/clusters/{cluster_id}/ymls/joblists + raw, err := client.Get(client.ServiceURL("clusters", clusterId, "ymls", "joblists"), nil, nil) + if err != nil { + return nil, err + } + + var res []Task + err = extract.IntoSlicePtr(raw.Body, &res, "configList") + return res, err +} + +type Task struct { + // Action ID + ID string `json:"id"` + // Cluster ID + ClusterId string `json:"clusterId"` + // Creation time. Format: Unix timestamp. + CreatedAt int64 `json:"createAt"` + // Task execution status. + // true: The operation is successful. + // false: The execution failed. + Status string `json:"status"` + // End time. If the creation has not been completed, the end time is null. Format: Unix timestamp. + FinishedAt int64 `json:"finishedAt"` + // History of parameter configuration modifications + History string `json:"modifyDeleteReset"` + // Returned error message. If the status is success, the value of this parameter is null. + ErrorMsg string `json:"failedMsg"` +} diff --git a/openstack/css/v1/parameter-configuration/Modify.go b/openstack/css/v1/parameter-configuration/Modify.go new file mode 100644 index 000000000..0079c6e01 --- /dev/null +++ b/openstack/css/v1/parameter-configuration/Modify.go @@ -0,0 +1,44 @@ +package parameter_configuration + +import ( + "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/build" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type ModifyOpts struct { + // Operations performed on parameter configurations. The value can be: + // modify + // delete + // reset + Edit map[string]interface{} `json:"edit" required:"true"` +} + +func Modify(client *golangsdk.ServiceClient, opts ModifyOpts, clusterID string) (*Config, error) { + b, err := build.RequestBody(opts, "") + if err != nil { + return nil, err + } + // POST /v1.0/{project_id}/clusters/{cluster_id}/ymls/update + raw, err := client.Post(client.ServiceURL("clusters", clusterID, "ymls", "update"), b, nil, &golangsdk.RequestOpts{ + OkCodes: []int{200}, + }) + if err != nil { + return nil, err + } + + var res Config + err = extract.Into(raw.Body, &res) + return &res, err +} + +type Config struct { + // Indicates whether the modification is successful. + // true: The modification is successful. + // false: The modification failed. + Acknowledged bool `json:"acknowledged"` + // Error message. If acknowledged is set to true, null is returned for this field. + ExternalMessage string `json:"externalMessage"` + // HTTP error information. The default value is null. + ErrorMsg string `json:"httpErrorResponse"` +}