diff --git a/acceptance/openstack/ces/v1/alarms_test.go b/acceptance/openstack/ces/v1/alarms_test.go new file mode 100644 index 000000000..514e74078 --- /dev/null +++ b/acceptance/openstack/ces/v1/alarms_test.go @@ -0,0 +1,61 @@ +package v1 + +import ( + "testing" + + "github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients" + "github.com/opentelekomcloud/gophertelekomcloud/openstack/ces/v1/alarms" + th "github.com/opentelekomcloud/gophertelekomcloud/testhelper" +) + +func TestAlarms(t *testing.T) { + client, err := clients.NewCesV1Client() + th.AssertNoErr(t, err) + + alarmsRes, err := alarms.ListAlarms(client, alarms.ListAlarmsOpts{ + Limit: 10, + Order: "desc", + }) + + th.AssertNoErr(t, err) + th.AssertEquals(t, alarmsRes.MetaData.Count <= 10, true) + + f := false + newAlarm, err := alarms.CreateAlarm(client, alarms.CreateAlarmOpts{ + AlarmName: "alarm-acc-test", + Metric: alarms.MetricForAlarm{ + Namespace: "SYS.VPC", + MetricName: "upstream_bandwidth", + Dimensions: []alarms.MetricsDimension{ + { + Name: "bandwidth_id", + Value: "026c495c-fake-test-8b11-a113ba530d11", + }, + }, + }, + Condition: alarms.Condition{ + ComparisonOperator: ">=", + Count: 3, + Filter: "average", + Period: 300, + Value: 4000000, + }, + AlarmEnabled: &f, + AlarmActionEnabled: &f, + }) + th.AssertNoErr(t, err) + + t.Cleanup(func() { + err = alarms.DeleteAlarm(client, newAlarm) + th.AssertNoErr(t, err) + }) + + err = alarms.UpdateAlarmAction(client, newAlarm, alarms.ModifyAlarmActionRequest{ + AlarmEnabled: true, + }) + th.AssertNoErr(t, err) + + showAlarm, err := alarms.ShowAlarm(client, newAlarm) + th.AssertNoErr(t, err) + th.AssertEquals(t, showAlarm[0].AlarmEnabled, true) +} diff --git a/openstack/ces/v1/alarms/create_alarm.go b/openstack/ces/v1/alarms/create_alarm.go new file mode 100644 index 000000000..a392d07aa --- /dev/null +++ b/openstack/ces/v1/alarms/create_alarm.go @@ -0,0 +1,62 @@ +package alarms + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type CreateAlarmOpts struct { + // Specifies the alarm rule name. + // Enter 1 to 128 characters. Only letters, digits, underscores (_), and hyphens (-) are allowed. + AlarmName string `json:"alarm_name"` + // Provides supplementary information about the alarm rule. Enter 0 to 256 characters. + AlarmDescription string `json:"alarm_description,omitempty"` + // Specifies the alarm metric. + Metric MetricForAlarm `json:"metric"` + // Specifies the alarm triggering condition. + Condition Condition `json:"condition"` + // Specifies whether to enable the alarm. + AlarmEnabled *bool `json:"alarm_enabled,omitempty"` + // Specifies whether to enable the action to be triggered by an alarm. The default value is true. + AlarmActionEnabled *bool `json:"alarm_action_enabled,omitempty"` + // Specifies the alarm severity. Possible values are 1, 2 (default), 3 and 4, + // indicating critical, major, minor, and informational, respectively. + AlarmLevel int `json:"alarm_level,omitempty"` + // Specifies the action to be triggered by an alarm. + AlarmActions []AlarmActions `json:"alarm_actions,omitempty"` + // Specifies the action to be triggered after the alarm is cleared. + OkActions []AlarmActions `json:"ok_actions,omitempty"` +} + +type MetricForAlarm struct { + // Specifies the namespace of a service. + // The value must be in the service.item format and can contain 3 to 32 characters. + // service and item each must start with a letter and contain only letters, digits, and underscores (_). + Namespace string `json:"namespace"` + // Specifies the metric name. + // Start with a letter. Enter 1 to 64 characters. Only letters, digits, and underscores (_) are allowed. + MetricName string `json:"metric_name"` + // Specifies the list of metric dimensions. + Dimensions []MetricsDimension `json:"dimensions,omitempty"` + // Specifies the resource group ID selected during the alarm rule creation. + ResourceGroupId string `json:"resource_group_id,omitempty"` +} + +func CreateAlarm(client *golangsdk.ServiceClient, opts CreateAlarmOpts) (string, error) { + reqBody, err := golangsdk.BuildRequestBody(opts, "") + if err != nil { + return "", err + } + + // POST /V1.0/{project_id}/alarms + raw, err := client.Post(client.ServiceURL("alarms"), reqBody, nil, nil) + if err != nil { + return "", err + } + + var s struct { + AlarmId string `json:"alarm_id"` + } + err = extract.Into(raw.Body, &s) + return s.AlarmId, err +} diff --git a/openstack/ces/v1/alarms/delete_alarm.go b/openstack/ces/v1/alarms/delete_alarm.go new file mode 100644 index 000000000..d361d83d6 --- /dev/null +++ b/openstack/ces/v1/alarms/delete_alarm.go @@ -0,0 +1,9 @@ +package alarms + +import golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + +func DeleteAlarm(client *golangsdk.ServiceClient, id string) (err error) { + // DELETE /V1.0/{project_id}/alarms/{alarm_id} + _, err = client.Delete(client.ServiceURL("alarms", id), nil) + return +} diff --git a/openstack/ces/v1/alarms/list_alarms.go b/openstack/ces/v1/alarms/list_alarms.go new file mode 100644 index 000000000..46891fb44 --- /dev/null +++ b/openstack/ces/v1/alarms/list_alarms.go @@ -0,0 +1,36 @@ +package alarms + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +type ListAlarmsOpts struct { + // The value ranges from 1 to 100, and is 100 by default. + // This parameter is used to limit the number of query results. + Limit int `q:"limit"` + // Specifies the result sorting method, which is sorted by timestamp. + // The default value is desc. + // asc: The query results are displayed in the ascending order. + // desc: The query results are displayed in the descending order. + Order string `q:"order"` + // Specifies the first queried alarm to be displayed on a page. + Start string `q:"start"` +} + +func ListAlarms(client *golangsdk.ServiceClient, opts ListAlarmsOpts) (*ListAlarmsResponse, error) { + query, err := golangsdk.BuildQueryString(opts) + if err != nil { + return nil, err + } + + // GET /V1.0/{project_id}/alarms + raw, err := client.Get(client.ServiceURL("alarms")+query.String(), nil, nil) + if err != nil { + return nil, err + } + + var s ListAlarmsResponse + err = extract.Into(raw.Body, &s) + return &s, err +} diff --git a/openstack/ces/v1/alarms/results.go b/openstack/ces/v1/alarms/results.go new file mode 100644 index 000000000..afb52f303 --- /dev/null +++ b/openstack/ces/v1/alarms/results.go @@ -0,0 +1,88 @@ +package alarms + +type ListAlarmsResponse struct { + MetricAlarms []MetricAlarms `json:"metric_alarms,omitempty"` + MetaData MetaData `json:"meta_data,omitempty"` +} + +type MetaData struct { + Count int `json:"count"` + Total int `json:"total"` + Marker string `json:"marker"` +} + +type MetricAlarms struct { + // Specifies the alarm rule name. + AlarmName string `json:"alarm_name"` + // Provides supplementary information about the alarm rule. + AlarmDescription string `json:"alarm_description,omitempty"` + // Specifies the alarm metric. + Metric MetricForAlarm `json:"metric"` + // Specifies the alarm triggering condition. + Condition Condition `json:"condition"` + // Specifies whether to enable the alarm rule. + AlarmEnabled bool `json:"alarm_enabled,omitempty"` + // Specifies the alarm severity. Possible values are 1, 2, 3 and 4, indicating critical, major, minor, and informational, respectively. + AlarmLevel int `json:"alarm_level,omitempty"` + // Specifies whether to enable the action to be triggered by an alarm. + AlarmActionEnabled bool `json:"alarm_action_enabled,omitempty"` + // Specifies the action to be triggered by an alarm. + AlarmActions []AlarmActions `json:"alarm_actions,omitempty"` + // Specifies the action to be triggered after the alarm is cleared. + OkActions []AlarmActions `json:"ok_actions,omitempty"` + // Specifies the alarm rule ID. + AlarmId string `json:"alarm_id"` + // Specifies when the alarm status changed. The value is a UNIX timestamp and the unit is ms. + UpdateTime int64 `json:"update_time"` + // Specifies the alarm status. The value can be: + // + // ok: The alarm status is normal. + // alarm: An alarm is generated. + // insufficient_data: The required data is insufficient. + AlarmState string `json:"alarm_state"` +} + +type MetricsDimension struct { + // Specifies the dimension. For example, the ECS dimension is instance_id. + Name string `json:"name"` + // Specifies the dimension value, for example, an ECS ID. + Value string `json:"value"` +} + +type Condition struct { + // Specifies the operator of alarm thresholds. Possible values are >, =, <, >=, and <=. + ComparisonOperator string `json:"comparison_operator"` + // Specifies the number of consecutive occurrence times that the alarm policy was met. + // The value ranges from 1 to 5. + Count int `json:"count"` + // Specifies the data rollup method. The following methods are supported: + // + // average: Cloud Eye calculates the average value of metric data within a rollup period. + // max: Cloud Eye calculates the maximum value of metric data within a rollup period. + // min: Cloud Eye calculates the minimum value of metric data within a rollup period. + // sum: Cloud Eye calculates the sum of metric data within a rollup period. + // variance: Cloud Eye calculates the variance value of metric data within a rollup period. + Filter string `json:"filter"` + // Specifies the interval (seconds) for checking whether the configured alarm rules are met. + Period int `json:"period"` + // Specifies the data unit. Enter up to 32 characters. + Unit string `json:"unit,omitempty"` + // Specifies the alarm threshold. The value ranges from 0 to Number. MAX_VALUE (1.7976931348623157e+108). + // + // For detailed thresholds, see the value range of each metric in the appendix. + // For example, you can set ECS cpu_util in Services Interconnected with Cloud Eye to 80. + Value float64 `json:"value"` +} + +type AlarmActions struct { + // Specifies the alarm notification type. + // notification: indicates that a notification will be sent. + // autoscaling: indicates that a scaling action will be triggered. + Type string `json:"type"` + // Specifies the list of objects to be notified if the alarm status changes. + // You can configure up to 5 object IDs. You can obtain the topicUrn value from SMN in the following format: + // urn:smn:([a-z]|[A-Z]|[0-9]|\-){1,32}:([a-z]|[A-Z]|[0-9]){32}:([a-z]|[A-Z]|[0-9]|\-|\_){1,256}. + // If you set type to notification, you must specify notificationList. + // If you set type to autoscaling, you must set notificationList to []. + NotificationList []string `json:"notificationList"` +} diff --git a/openstack/ces/v1/alarms/show_alarm.go b/openstack/ces/v1/alarms/show_alarm.go new file mode 100644 index 000000000..ca677cc49 --- /dev/null +++ b/openstack/ces/v1/alarms/show_alarm.go @@ -0,0 +1,18 @@ +package alarms + +import ( + golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + "github.com/opentelekomcloud/gophertelekomcloud/internal/extract" +) + +func ShowAlarm(client *golangsdk.ServiceClient, id string) ([]MetricAlarms, error) { + // GET /V1.0/{project_id}/alarms/{alarm_id} + raw, err := client.Get(client.ServiceURL("alarms", id), nil, nil) + if err != nil { + return nil, err + } + + var res []MetricAlarms + err = extract.IntoSlicePtr(raw.Body, &res, "metric_alarms") + return res, err +} diff --git a/openstack/ces/v1/alarms/update_alarm_action.go b/openstack/ces/v1/alarms/update_alarm_action.go new file mode 100644 index 000000000..d2ff6f18b --- /dev/null +++ b/openstack/ces/v1/alarms/update_alarm_action.go @@ -0,0 +1,21 @@ +package alarms + +import golangsdk "github.com/opentelekomcloud/gophertelekomcloud" + +type ModifyAlarmActionRequest struct { + // Specifies whether the alarm rule is enabled. + AlarmEnabled bool `json:"alarm_enabled"` +} + +func UpdateAlarmAction(client *golangsdk.ServiceClient, id string, req ModifyAlarmActionRequest) (err error) { + reqBody, err := golangsdk.BuildRequestBody(req, "") + if err != nil { + return + } + + // PUT /V1.0/{project_id}/alarms/{alarm_id}/action + _, err = client.Put(client.ServiceURL("alarms", id, "action"), reqBody, nil, &golangsdk.RequestOpts{ + OkCodes: []int{204}, + }) + return +} diff --git a/openstack/cloudeyeservice/alarmrule/requests.go b/openstack/cloudeyeservice/alarmrule/requests.go deleted file mode 100644 index f043008f9..000000000 --- a/openstack/cloudeyeservice/alarmrule/requests.go +++ /dev/null @@ -1,103 +0,0 @@ -package alarmrule - -import ( - "log" - - "github.com/opentelekomcloud/gophertelekomcloud" -) - -type CreateOptsBuilder interface { - ToAlarmRuleCreateMap() (map[string]interface{}, error) -} - -type DimensionOpts struct { - Name string `json:"name" required:"true"` - Value string `json:"value" required:"true"` -} - -type MetricOpts struct { - Namespace string `json:"namespace" required:"true"` - MetricName string `json:"metric_name" required:"true"` - Dimensions []DimensionOpts `json:"dimensions" required:"true"` -} - -type ConditionOpts struct { - Period int `json:"period" required:"true"` - SuppressDuration int `json:"suppress_duration,omitempty"` - Filter string `json:"filter" required:"true"` - ComparisonOperator string `json:"comparison_operator" required:"true"` - // The Value ranges from 0 to MAX_VALUE - Value int `json:"value"` - Unit string `json:"unit,omitempty"` - Count int `json:"count" required:"true"` -} - -type ActionOpts struct { - Type string `json:"type" required:"true"` - NotificationList []string `json:"notificationList" required:"true"` -} - -type CreateOpts struct { - AlarmName string `json:"alarm_name" required:"true"` - AlarmDescription string `json:"alarm_description,omitempty"` - AlarmType string `json:"alarm_type,omitempty"` - AlarmLevel int `json:"alarm_level,omitempty"` - Metric MetricOpts `json:"metric" required:"true"` - Condition ConditionOpts `json:"condition" required:"true"` - AlarmActions []ActionOpts `json:"alarm_actions,omitempty"` - InsufficientdataActions []ActionOpts `json:"insufficientdata_actions,omitempty"` - OkActions []ActionOpts `json:"ok_actions,omitempty"` - AlarmEnabled bool `json:"alarm_enabled"` - AlarmActionEnabled bool `json:"alarm_action_enabled"` -} - -func (opts CreateOpts) ToAlarmRuleCreateMap() (map[string]interface{}, error) { - return golangsdk.BuildRequestBody(opts, "") -} - -func Create(c *golangsdk.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { - b, err := opts.ToAlarmRuleCreateMap() - if err != nil { - r.Err = err - return - } - log.Printf("[DEBUG] create AlarmRule url:%q, body=%#v, opt=%#v", rootURL(c), b, opts) - reqOpt := &golangsdk.RequestOpts{OkCodes: []int{201}} - _, r.Err = c.Post(rootURL(c), b, &r.Body, reqOpt) - return -} - -func Get(c *golangsdk.ServiceClient, id string) (r GetResult) { - _, r.Err = c.Get(resourceURL(c, id), &r.Body, nil) - return -} - -type UpdateOptsBuilder interface { - ToAlarmRuleUpdateMap() (map[string]interface{}, error) -} - -type UpdateOpts struct { - AlarmEnabled bool `json:"alarm_enabled"` -} - -func (opts UpdateOpts) ToAlarmRuleUpdateMap() (map[string]interface{}, error) { - return golangsdk.BuildRequestBody(opts, "") -} - -func Update(c *golangsdk.ServiceClient, id string, opts UpdateOpts) (r UpdateResult) { - b, err := opts.ToAlarmRuleUpdateMap() - if err != nil { - r.Err = err - return - } - _, r.Err = c.Put(actionURL(c, id), b, nil, &golangsdk.RequestOpts{ - OkCodes: []int{204}, - }) - return -} - -func Delete(c *golangsdk.ServiceClient, id string) (r DeleteResult) { - reqOpt := &golangsdk.RequestOpts{OkCodes: []int{204}} - _, r.Err = c.Delete(resourceURL(c, id), reqOpt) - return -} diff --git a/openstack/cloudeyeservice/alarmrule/results.go b/openstack/cloudeyeservice/alarmrule/results.go deleted file mode 100644 index f77684e94..000000000 --- a/openstack/cloudeyeservice/alarmrule/results.go +++ /dev/null @@ -1,89 +0,0 @@ -package alarmrule - -import ( - "fmt" - - "github.com/opentelekomcloud/gophertelekomcloud" -) - -type CreateResponse struct { - AlarmID string `json:"alarm_id"` -} - -type CreateResult struct { - golangsdk.Result -} - -func (c CreateResult) Extract() (*CreateResponse, error) { - r := &CreateResponse{} - return r, c.ExtractInto(r) -} - -type DimensionInfo struct { - Name string `json:"name"` - Value string `json:"value"` -} - -type MetricInfo struct { - Namespace string `json:"namespace"` - MetricName string `json:"metric_name"` - Dimensions []DimensionInfo `json:"dimensions"` -} - -type ConditionInfo struct { - Period int `json:"period"` - SuppressDuration int `json:"suppress_duration,omitempty"` - Filter string `json:"filter"` - ComparisonOperator string `json:"comparison_operator"` - Value int `json:"value"` - Unit string `json:"unit"` - Count int `json:"count"` -} - -type ActionInfo struct { - Type string `json:"type"` - NotificationList []string `json:"notificationList"` -} - -type AlarmRule struct { - AlarmName string `json:"alarm_name"` - AlarmID string `json:"alarm_id"` - AlarmDescription string `json:"alarm_description"` - AlarmType string `json:"alarm_type"` - AlarmLevel int `json:"alarm_level"` - Metric MetricInfo `json:"metric"` - Condition ConditionInfo `json:"condition"` - AlarmActions []ActionInfo `json:"alarm_actions"` - InsufficientdataActions []ActionInfo `json:"insufficientdata_actions"` - OkActions []ActionInfo `json:"ok_actions"` - AlarmEnabled bool `json:"alarm_enabled"` - AlarmActionEnabled bool `json:"alarm_action_enabled"` - UpdateTime int64 `json:"update_time"` - AlarmState string `json:"alarm_state"` -} - -type GetResult struct { - golangsdk.Result -} - -func (g GetResult) Extract() (*AlarmRule, error) { - var r struct { - MetricAlarms []AlarmRule `json:"metric_alarms"` - } - err := g.ExtractInto(&r) - if err != nil { - return nil, err - } - if len(r.MetricAlarms) != 1 { - return nil, fmt.Errorf("get %d alarm rules", len(r.MetricAlarms)) - } - return &(r.MetricAlarms[0]), nil -} - -type UpdateResult struct { - golangsdk.ErrResult -} - -type DeleteResult struct { - golangsdk.ErrResult -} diff --git a/openstack/cloudeyeservice/alarmrule/urls.go b/openstack/cloudeyeservice/alarmrule/urls.go deleted file mode 100644 index e3f4dbf52..000000000 --- a/openstack/cloudeyeservice/alarmrule/urls.go +++ /dev/null @@ -1,19 +0,0 @@ -package alarmrule - -import "github.com/opentelekomcloud/gophertelekomcloud" - -const ( - rootPath = "alarms" -) - -func rootURL(c *golangsdk.ServiceClient) string { - return c.ServiceURL(rootPath) -} - -func resourceURL(c *golangsdk.ServiceClient, id string) string { - return c.ServiceURL(rootPath, id) -} - -func actionURL(c *golangsdk.ServiceClient, id string) string { - return c.ServiceURL(rootPath, id, "action") -}