diff --git a/.generator/schemas/v1/openapi.yaml b/.generator/schemas/v1/openapi.yaml index e4c94965900..4fc8dbe3785 100644 --- a/.generator/schemas/v1/openapi.yaml +++ b/.generator/schemas/v1/openapi.yaml @@ -7255,6 +7255,12 @@ components: Monitor: description: Object describing a monitor. properties: + assets: + description: The list of monitor assets tied to a monitor, which represents + key links for users to take action on monitor alerts (for example, runbooks). + items: + $ref: '#/components/schemas/MonitorAsset' + type: array created: description: Timestamp of the monitor creation. format: date-time @@ -7338,6 +7344,52 @@ components: - type - query type: object + MonitorAsset: + description: 'Represents key links tied to a monitor to help users take action + on alerts. + + This feature is in Preview and only available to users with the feature enabled.' + properties: + category: + $ref: '#/components/schemas/MonitorAssetCategory' + name: + description: Name for the monitor asset + example: Monitor Runbook + type: string + resource_key: + description: Represents the identifier of the internal Datadog resource + that this asset represents. IDs in this field should be passed in as strings. + example: '12345' + type: string + resource_type: + $ref: '#/components/schemas/MonitorAssetResourceType' + url: + description: URL link for the asset. For links with an internal resource + type set, this should be the relative path to where the Datadog domain + is appended internally. For external links, this should be the full URL + path. + example: /notebooks/12345 + type: string + required: + - name + - url + - category + type: object + MonitorAssetCategory: + description: Indicates the type of asset this entity represents on a monitor. + enum: + - runbook + example: runbook + type: string + x-enum-varnames: + - RUNBOOK + MonitorAssetResourceType: + description: Type of internal Datadog resource associated with a monitor asset. + enum: + - notebook + type: string + x-enum-varnames: + - NOTEBOOK MonitorDeviceID: description: ID of the device the Synthetics monitor is running on. Same as `SyntheticsDeviceID`. @@ -8452,6 +8504,13 @@ components: MonitorUpdateRequest: description: Object describing a monitor update request. properties: + assets: + description: The list of monitor assets tied to a monitor, which represents + key links for users to take action on monitor alerts (for example, runbooks). + items: + $ref: '#/components/schemas/MonitorAsset' + nullable: true + type: array created: description: Timestamp of the monitor creation. format: date-time @@ -31584,6 +31643,13 @@ paths: required: false schema: type: boolean + - description: If this argument is set to `true`, the returned data includes + all assets tied to this monitor. + in: query + name: with_assets + required: false + schema: + type: boolean responses: '200': content: diff --git a/api/datadogV1/api_monitors.go b/api/datadogV1/api_monitors.go index fef2e230acb..4347056157e 100644 --- a/api/datadogV1/api_monitors.go +++ b/api/datadogV1/api_monitors.go @@ -512,6 +512,7 @@ func (a *MonitorsApi) DeleteMonitor(ctx _context.Context, monitorId int64, o ... type GetMonitorOptionalParameters struct { GroupStates *string WithDowntimes *bool + WithAssets *bool } // NewGetMonitorOptionalParameters creates an empty struct for parameters. @@ -532,6 +533,12 @@ func (r *GetMonitorOptionalParameters) WithWithDowntimes(withDowntimes bool) *Ge return r } +// WithWithAssets sets the corresponding parameter name and returns the struct. +func (r *GetMonitorOptionalParameters) WithWithAssets(withAssets bool) *GetMonitorOptionalParameters { + r.WithAssets = &withAssets + return r +} + // GetMonitor Get a monitor's details. // Get details about the specified monitor from your organization. func (a *MonitorsApi) GetMonitor(ctx _context.Context, monitorId int64, o ...GetMonitorOptionalParameters) (Monitor, *_nethttp.Response, error) { @@ -566,6 +573,9 @@ func (a *MonitorsApi) GetMonitor(ctx _context.Context, monitorId int64, o ...Get if optionalParams.WithDowntimes != nil { localVarQueryParams.Add("with_downtimes", datadog.ParameterToString(*optionalParams.WithDowntimes, "")) } + if optionalParams.WithAssets != nil { + localVarQueryParams.Add("with_assets", datadog.ParameterToString(*optionalParams.WithAssets, "")) + } localVarHeaderParams["Accept"] = "application/json" if a.Client.Cfg.DelegatedTokenConfig != nil { diff --git a/api/datadogV1/model_monitor.go b/api/datadogV1/model_monitor.go index 5ffd06751b3..3c613ced6ed 100644 --- a/api/datadogV1/model_monitor.go +++ b/api/datadogV1/model_monitor.go @@ -13,6 +13,8 @@ import ( // Monitor Object describing a monitor. type Monitor struct { + // The list of monitor assets tied to a monitor, which represents key links for users to take action on monitor alerts (for example, runbooks). + Assets []MonitorAsset `json:"assets,omitempty"` // Timestamp of the monitor creation. Created *time.Time `json:"created,omitempty"` // Object describing the creator of the shared element. @@ -82,6 +84,34 @@ func NewMonitorWithDefaults() *Monitor { return &this } +// GetAssets returns the Assets field value if set, zero value otherwise. +func (o *Monitor) GetAssets() []MonitorAsset { + if o == nil || o.Assets == nil { + var ret []MonitorAsset + return ret + } + return o.Assets +} + +// GetAssetsOk returns a tuple with the Assets field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Monitor) GetAssetsOk() (*[]MonitorAsset, bool) { + if o == nil || o.Assets == nil { + return nil, false + } + return &o.Assets, true +} + +// HasAssets returns a boolean if a field has been set. +func (o *Monitor) HasAssets() bool { + return o != nil && o.Assets != nil +} + +// SetAssets gets a reference to the given []MonitorAsset and assigns it to the Assets field. +func (o *Monitor) SetAssets(v []MonitorAsset) { + o.Assets = v +} + // GetCreated returns the Created field value if set, zero value otherwise. func (o *Monitor) GetCreated() time.Time { if o == nil || o.Created == nil { @@ -615,6 +645,9 @@ func (o Monitor) MarshalJSON() ([]byte, error) { if o.UnparsedObject != nil { return datadog.Marshal(o.UnparsedObject) } + if o.Assets != nil { + toSerialize["assets"] = o.Assets + } if o.Created != nil { if o.Created.Nanosecond() == 0 { toSerialize["created"] = o.Created.Format("2006-01-02T15:04:05Z07:00") @@ -683,6 +716,7 @@ func (o Monitor) MarshalJSON() ([]byte, error) { // UnmarshalJSON deserializes the given payload. func (o *Monitor) UnmarshalJSON(bytes []byte) (err error) { all := struct { + Assets []MonitorAsset `json:"assets,omitempty"` Created *time.Time `json:"created,omitempty"` Creator *Creator `json:"creator,omitempty"` Deleted datadog.NullableTime `json:"deleted,omitempty"` @@ -713,12 +747,13 @@ func (o *Monitor) UnmarshalJSON(bytes []byte) (err error) { } additionalProperties := make(map[string]interface{}) if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { - datadog.DeleteKeys(additionalProperties, &[]string{"created", "creator", "deleted", "draft_status", "id", "matching_downtimes", "message", "modified", "multi", "name", "options", "overall_state", "priority", "query", "restricted_roles", "state", "tags", "type"}) + datadog.DeleteKeys(additionalProperties, &[]string{"assets", "created", "creator", "deleted", "draft_status", "id", "matching_downtimes", "message", "modified", "multi", "name", "options", "overall_state", "priority", "query", "restricted_roles", "state", "tags", "type"}) } else { return err } hasInvalidField := false + o.Assets = all.Assets o.Created = all.Created if all.Creator != nil && all.Creator.UnparsedObject != nil && o.UnparsedObject == nil { hasInvalidField = true diff --git a/api/datadogV1/model_monitor_asset.go b/api/datadogV1/model_monitor_asset.go new file mode 100644 index 00000000000..eadacba660f --- /dev/null +++ b/api/datadogV1/model_monitor_asset.go @@ -0,0 +1,250 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +package datadogV1 + +import ( + "fmt" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// MonitorAsset Represents key links tied to a monitor to help users take action on alerts. +// This feature is in Preview and only available to users with the feature enabled. +type MonitorAsset struct { + // Indicates the type of asset this entity represents on a monitor. + Category MonitorAssetCategory `json:"category"` + // Name for the monitor asset + Name string `json:"name"` + // Represents the identifier of the internal Datadog resource that this asset represents. IDs in this field should be passed in as strings. + ResourceKey *string `json:"resource_key,omitempty"` + // Type of internal Datadog resource associated with a monitor asset. + ResourceType *MonitorAssetResourceType `json:"resource_type,omitempty"` + // URL link for the asset. For links with an internal resource type set, this should be the relative path to where the Datadog domain is appended internally. For external links, this should be the full URL path. + Url string `json:"url"` + // UnparsedObject contains the raw value of the object if there was an error when deserializing into the struct + UnparsedObject map[string]interface{} `json:"-"` + AdditionalProperties map[string]interface{} `json:"-"` +} + +// NewMonitorAsset instantiates a new MonitorAsset object. +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed. +func NewMonitorAsset(category MonitorAssetCategory, name string, url string) *MonitorAsset { + this := MonitorAsset{} + this.Category = category + this.Name = name + this.Url = url + return &this +} + +// NewMonitorAssetWithDefaults instantiates a new MonitorAsset object. +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set. +func NewMonitorAssetWithDefaults() *MonitorAsset { + this := MonitorAsset{} + return &this +} + +// GetCategory returns the Category field value. +func (o *MonitorAsset) GetCategory() MonitorAssetCategory { + if o == nil { + var ret MonitorAssetCategory + return ret + } + return o.Category +} + +// GetCategoryOk returns a tuple with the Category field value +// and a boolean to check if the value has been set. +func (o *MonitorAsset) GetCategoryOk() (*MonitorAssetCategory, bool) { + if o == nil { + return nil, false + } + return &o.Category, true +} + +// SetCategory sets field value. +func (o *MonitorAsset) SetCategory(v MonitorAssetCategory) { + o.Category = v +} + +// GetName returns the Name field value. +func (o *MonitorAsset) GetName() string { + if o == nil { + var ret string + return ret + } + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *MonitorAsset) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value. +func (o *MonitorAsset) SetName(v string) { + o.Name = v +} + +// GetResourceKey returns the ResourceKey field value if set, zero value otherwise. +func (o *MonitorAsset) GetResourceKey() string { + if o == nil || o.ResourceKey == nil { + var ret string + return ret + } + return *o.ResourceKey +} + +// GetResourceKeyOk returns a tuple with the ResourceKey field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MonitorAsset) GetResourceKeyOk() (*string, bool) { + if o == nil || o.ResourceKey == nil { + return nil, false + } + return o.ResourceKey, true +} + +// HasResourceKey returns a boolean if a field has been set. +func (o *MonitorAsset) HasResourceKey() bool { + return o != nil && o.ResourceKey != nil +} + +// SetResourceKey gets a reference to the given string and assigns it to the ResourceKey field. +func (o *MonitorAsset) SetResourceKey(v string) { + o.ResourceKey = &v +} + +// GetResourceType returns the ResourceType field value if set, zero value otherwise. +func (o *MonitorAsset) GetResourceType() MonitorAssetResourceType { + if o == nil || o.ResourceType == nil { + var ret MonitorAssetResourceType + return ret + } + return *o.ResourceType +} + +// GetResourceTypeOk returns a tuple with the ResourceType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MonitorAsset) GetResourceTypeOk() (*MonitorAssetResourceType, bool) { + if o == nil || o.ResourceType == nil { + return nil, false + } + return o.ResourceType, true +} + +// HasResourceType returns a boolean if a field has been set. +func (o *MonitorAsset) HasResourceType() bool { + return o != nil && o.ResourceType != nil +} + +// SetResourceType gets a reference to the given MonitorAssetResourceType and assigns it to the ResourceType field. +func (o *MonitorAsset) SetResourceType(v MonitorAssetResourceType) { + o.ResourceType = &v +} + +// GetUrl returns the Url field value. +func (o *MonitorAsset) GetUrl() string { + if o == nil { + var ret string + return ret + } + return o.Url +} + +// GetUrlOk returns a tuple with the Url field value +// and a boolean to check if the value has been set. +func (o *MonitorAsset) GetUrlOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Url, true +} + +// SetUrl sets field value. +func (o *MonitorAsset) SetUrl(v string) { + o.Url = v +} + +// MarshalJSON serializes the struct using spec logic. +func (o MonitorAsset) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.UnparsedObject != nil { + return datadog.Marshal(o.UnparsedObject) + } + toSerialize["category"] = o.Category + toSerialize["name"] = o.Name + if o.ResourceKey != nil { + toSerialize["resource_key"] = o.ResourceKey + } + if o.ResourceType != nil { + toSerialize["resource_type"] = o.ResourceType + } + toSerialize["url"] = o.Url + + for key, value := range o.AdditionalProperties { + toSerialize[key] = value + } + return datadog.Marshal(toSerialize) +} + +// UnmarshalJSON deserializes the given payload. +func (o *MonitorAsset) UnmarshalJSON(bytes []byte) (err error) { + all := struct { + Category *MonitorAssetCategory `json:"category"` + Name *string `json:"name"` + ResourceKey *string `json:"resource_key,omitempty"` + ResourceType *MonitorAssetResourceType `json:"resource_type,omitempty"` + Url *string `json:"url"` + }{} + if err = datadog.Unmarshal(bytes, &all); err != nil { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + if all.Category == nil { + return fmt.Errorf("required field category missing") + } + if all.Name == nil { + return fmt.Errorf("required field name missing") + } + if all.Url == nil { + return fmt.Errorf("required field url missing") + } + additionalProperties := make(map[string]interface{}) + if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { + datadog.DeleteKeys(additionalProperties, &[]string{"category", "name", "resource_key", "resource_type", "url"}) + } else { + return err + } + + hasInvalidField := false + if !all.Category.IsValid() { + hasInvalidField = true + } else { + o.Category = *all.Category + } + o.Name = *all.Name + o.ResourceKey = all.ResourceKey + if all.ResourceType != nil && !all.ResourceType.IsValid() { + hasInvalidField = true + } else { + o.ResourceType = all.ResourceType + } + o.Url = *all.Url + + if len(additionalProperties) > 0 { + o.AdditionalProperties = additionalProperties + } + + if hasInvalidField { + return datadog.Unmarshal(bytes, &o.UnparsedObject) + } + + return nil +} diff --git a/api/datadogV1/model_monitor_asset_category.go b/api/datadogV1/model_monitor_asset_category.go new file mode 100644 index 00000000000..bed8a46a4f4 --- /dev/null +++ b/api/datadogV1/model_monitor_asset_category.go @@ -0,0 +1,64 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +package datadogV1 + +import ( + "fmt" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// MonitorAssetCategory Indicates the type of asset this entity represents on a monitor. +type MonitorAssetCategory string + +// List of MonitorAssetCategory. +const ( + MONITORASSETCATEGORY_RUNBOOK MonitorAssetCategory = "runbook" +) + +var allowedMonitorAssetCategoryEnumValues = []MonitorAssetCategory{ + MONITORASSETCATEGORY_RUNBOOK, +} + +// GetAllowedValues reeturns the list of possible values. +func (v *MonitorAssetCategory) GetAllowedValues() []MonitorAssetCategory { + return allowedMonitorAssetCategoryEnumValues +} + +// UnmarshalJSON deserializes the given payload. +func (v *MonitorAssetCategory) UnmarshalJSON(src []byte) error { + var value string + err := datadog.Unmarshal(src, &value) + if err != nil { + return err + } + *v = MonitorAssetCategory(value) + return nil +} + +// NewMonitorAssetCategoryFromValue returns a pointer to a valid MonitorAssetCategory +// for the value passed as argument, or an error if the value passed is not allowed by the enum. +func NewMonitorAssetCategoryFromValue(v string) (*MonitorAssetCategory, error) { + ev := MonitorAssetCategory(v) + if ev.IsValid() { + return &ev, nil + } + return nil, fmt.Errorf("invalid value '%v' for MonitorAssetCategory: valid values are %v", v, allowedMonitorAssetCategoryEnumValues) +} + +// IsValid return true if the value is valid for the enum, false otherwise. +func (v MonitorAssetCategory) IsValid() bool { + for _, existing := range allowedMonitorAssetCategoryEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to MonitorAssetCategory value. +func (v MonitorAssetCategory) Ptr() *MonitorAssetCategory { + return &v +} diff --git a/api/datadogV1/model_monitor_asset_resource_type.go b/api/datadogV1/model_monitor_asset_resource_type.go new file mode 100644 index 00000000000..8a656c608f7 --- /dev/null +++ b/api/datadogV1/model_monitor_asset_resource_type.go @@ -0,0 +1,64 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2019-Present Datadog, Inc. + +package datadogV1 + +import ( + "fmt" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" +) + +// MonitorAssetResourceType Type of internal Datadog resource associated with a monitor asset. +type MonitorAssetResourceType string + +// List of MonitorAssetResourceType. +const ( + MONITORASSETRESOURCETYPE_NOTEBOOK MonitorAssetResourceType = "notebook" +) + +var allowedMonitorAssetResourceTypeEnumValues = []MonitorAssetResourceType{ + MONITORASSETRESOURCETYPE_NOTEBOOK, +} + +// GetAllowedValues reeturns the list of possible values. +func (v *MonitorAssetResourceType) GetAllowedValues() []MonitorAssetResourceType { + return allowedMonitorAssetResourceTypeEnumValues +} + +// UnmarshalJSON deserializes the given payload. +func (v *MonitorAssetResourceType) UnmarshalJSON(src []byte) error { + var value string + err := datadog.Unmarshal(src, &value) + if err != nil { + return err + } + *v = MonitorAssetResourceType(value) + return nil +} + +// NewMonitorAssetResourceTypeFromValue returns a pointer to a valid MonitorAssetResourceType +// for the value passed as argument, or an error if the value passed is not allowed by the enum. +func NewMonitorAssetResourceTypeFromValue(v string) (*MonitorAssetResourceType, error) { + ev := MonitorAssetResourceType(v) + if ev.IsValid() { + return &ev, nil + } + return nil, fmt.Errorf("invalid value '%v' for MonitorAssetResourceType: valid values are %v", v, allowedMonitorAssetResourceTypeEnumValues) +} + +// IsValid return true if the value is valid for the enum, false otherwise. +func (v MonitorAssetResourceType) IsValid() bool { + for _, existing := range allowedMonitorAssetResourceTypeEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to MonitorAssetResourceType value. +func (v MonitorAssetResourceType) Ptr() *MonitorAssetResourceType { + return &v +} diff --git a/api/datadogV1/model_monitor_update_request.go b/api/datadogV1/model_monitor_update_request.go index b3e5669c1b0..bbab0f2537f 100644 --- a/api/datadogV1/model_monitor_update_request.go +++ b/api/datadogV1/model_monitor_update_request.go @@ -12,6 +12,8 @@ import ( // MonitorUpdateRequest Object describing a monitor update request. type MonitorUpdateRequest struct { + // The list of monitor assets tied to a monitor, which represents key links for users to take action on monitor alerts (for example, runbooks). + Assets []MonitorAsset `json:"assets,omitempty"` // Timestamp of the monitor creation. Created *time.Time `json:"created,omitempty"` // Object describing the creator of the shared element. @@ -77,6 +79,35 @@ func NewMonitorUpdateRequestWithDefaults() *MonitorUpdateRequest { return &this } +// GetAssets returns the Assets field value if set, zero value otherwise (both if not set or set to explicit null). +func (o *MonitorUpdateRequest) GetAssets() []MonitorAsset { + if o == nil { + var ret []MonitorAsset + return ret + } + return o.Assets +} + +// GetAssetsOk returns a tuple with the Assets field value if set, nil otherwise +// and a boolean to check if the value has been set. +// NOTE: If the value is an explicit nil, `nil, true` will be returned. +func (o *MonitorUpdateRequest) GetAssetsOk() (*[]MonitorAsset, bool) { + if o == nil || o.Assets == nil { + return nil, false + } + return &o.Assets, true +} + +// HasAssets returns a boolean if a field has been set. +func (o *MonitorUpdateRequest) HasAssets() bool { + return o != nil && o.Assets != nil +} + +// SetAssets gets a reference to the given []MonitorAsset and assigns it to the Assets field. +func (o *MonitorUpdateRequest) SetAssets(v []MonitorAsset) { + o.Assets = v +} + // GetCreated returns the Created field value if set, zero value otherwise. func (o *MonitorUpdateRequest) GetCreated() time.Time { if o == nil || o.Created == nil { @@ -592,6 +623,9 @@ func (o MonitorUpdateRequest) MarshalJSON() ([]byte, error) { if o.UnparsedObject != nil { return datadog.Marshal(o.UnparsedObject) } + if o.Assets != nil { + toSerialize["assets"] = o.Assets + } if o.Created != nil { if o.Created.Nanosecond() == 0 { toSerialize["created"] = o.Created.Format("2006-01-02T15:04:05Z07:00") @@ -661,6 +695,7 @@ func (o MonitorUpdateRequest) MarshalJSON() ([]byte, error) { // UnmarshalJSON deserializes the given payload. func (o *MonitorUpdateRequest) UnmarshalJSON(bytes []byte) (err error) { all := struct { + Assets []MonitorAsset `json:"assets,omitempty"` Created *time.Time `json:"created,omitempty"` Creator *Creator `json:"creator,omitempty"` Deleted datadog.NullableTime `json:"deleted,omitempty"` @@ -684,12 +719,13 @@ func (o *MonitorUpdateRequest) UnmarshalJSON(bytes []byte) (err error) { } additionalProperties := make(map[string]interface{}) if err = datadog.Unmarshal(bytes, &additionalProperties); err == nil { - datadog.DeleteKeys(additionalProperties, &[]string{"created", "creator", "deleted", "draft_status", "id", "message", "modified", "multi", "name", "options", "overall_state", "priority", "query", "restricted_roles", "state", "tags", "type"}) + datadog.DeleteKeys(additionalProperties, &[]string{"assets", "created", "creator", "deleted", "draft_status", "id", "message", "modified", "multi", "name", "options", "overall_state", "priority", "query", "restricted_roles", "state", "tags", "type"}) } else { return err } hasInvalidField := false + o.Assets = all.Assets o.Created = all.Created if all.Creator != nil && all.Creator.UnparsedObject != nil && o.UnparsedObject == nil { hasInvalidField = true diff --git a/examples/v1/monitors/CreateMonitor_3541766733.go b/examples/v1/monitors/CreateMonitor_3541766733.go new file mode 100644 index 00000000000..c9f712ac06c --- /dev/null +++ b/examples/v1/monitors/CreateMonitor_3541766733.go @@ -0,0 +1,55 @@ +// Create a monitor with assets returns "OK" response + +package main + +import ( + "context" + "encoding/json" + "fmt" + "os" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadog" + "github.com/DataDog/datadog-api-client-go/v2/api/datadogV1" +) + +func main() { + body := datadogV1.Monitor{ + Assets: []datadogV1.MonitorAsset{ + { + Category: datadogV1.MONITORASSETCATEGORY_RUNBOOK, + Name: "Monitor Runbook", + ResourceKey: datadog.PtrString("12345"), + ResourceType: datadogV1.MONITORASSETRESOURCETYPE_NOTEBOOK.Ptr(), + Url: "/notebooks/12345", + }, + }, + Name: datadog.PtrString("Example-Monitor"), + Type: datadogV1.MONITORTYPE_METRIC_ALERT, + Query: "avg(current_1mo):avg:system.load.5{*} > 0.5", + Message: datadog.PtrString("some message Notify: @hipchat-channel"), + Options: &datadogV1.MonitorOptions{ + Thresholds: &datadogV1.MonitorThresholds{ + Critical: datadog.PtrFloat64(0.5), + }, + SchedulingOptions: &datadogV1.MonitorOptionsSchedulingOptions{ + EvaluationWindow: &datadogV1.MonitorOptionsSchedulingOptionsEvaluationWindow{ + DayStarts: datadog.PtrString("04:00"), + MonthStarts: datadog.PtrInt32(1), + }, + }, + }, + } + ctx := datadog.NewDefaultContext(context.Background()) + configuration := datadog.NewConfiguration() + apiClient := datadog.NewAPIClient(configuration) + api := datadogV1.NewMonitorsApi(apiClient) + resp, r, err := api.CreateMonitor(ctx, body) + + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `MonitorsApi.CreateMonitor`: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } + + responseContent, _ := json.MarshalIndent(resp, "", " ") + fmt.Fprintf(os.Stdout, "Response from `MonitorsApi.CreateMonitor`:\n%s\n", responseContent) +} diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.freeze index 2dbbd94e287..9dda83bd1cf 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.freeze +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.freeze @@ -1 +1 @@ -2024-10-10T16:41:03.364Z \ No newline at end of file +2025-11-21T18:03:25.715Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.yaml index 0d9e4e92348..8c133beb451 100644 --- a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.yaml +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Check_if_a_monitor_can_be_deleted_returns_OK_response.yaml @@ -1,7 +1,7 @@ interactions: - request: body: | - {"message":"some message Notify: @hipchat-channel","name":"Test-Check_if_a_monitor_can_be_deleted_returns_OK_response-1728578463","options":{"enable_logs_sample":true,"escalation_message":"the situation has escalated","evaluation_delay":700,"include_tags":true,"locked":false,"new_host_delay":600,"no_data_timeframe":null,"notification_preset_name":"hide_handles","notify_audit":false,"notify_no_data":false,"on_missing_data":"show_and_notify_no_data","renotify_interval":60,"require_full_window":true,"thresholds":{"critical":2,"warning":1},"timeout_h":24},"priority":3,"query":"logs(\"service:foo AND type:error\").index(\"main\").rollup(\"count\").by(\"source\").last(\"5m\") \u003e 2","tags":["test:testcheckifamonitorcanbedeletedreturnsokresponse1728578463","env:ci"],"type":"log alert"} + {"message":"some message Notify: @hipchat-channel","name":"Test-Check_if_a_monitor_can_be_deleted_returns_OK_response-1763748205","options":{"enable_logs_sample":true,"escalation_message":"the situation has escalated","evaluation_delay":700,"include_tags":true,"locked":false,"new_host_delay":600,"no_data_timeframe":null,"notification_preset_name":"hide_handles","notify_audit":false,"notify_no_data":false,"on_missing_data":"show_and_notify_no_data","renotify_interval":60,"require_full_window":true,"thresholds":{"critical":2,"warning":1},"timeout_h":24},"priority":3,"query":"logs(\"service:foo AND type:error\").index(\"main\").rollup(\"count\").by(\"source\").last(\"5m\") \u003e 2","tags":["test:testcheckifamonitorcanbedeletedreturnsokresponse1763748205","env:ci"],"type":"log alert"} form: {} headers: Accept: @@ -12,12 +12,12 @@ interactions: method: POST url: https://api.datadoghq.com/api/v1/monitor response: - body: '{"id":155845287,"org_id":321813,"type":"log alert","name":"Test-Check_if_a_monitor_can_be_deleted_returns_OK_response-1728578463","message":"some - message Notify: @hipchat-channel","tags":["test:testcheckifamonitorcanbedeletedreturnsokresponse1728578463","env:ci"],"query":"logs(\"service:foo + body: '{"id":238669218,"org_id":197728,"type":"log alert","name":"Test-Check_if_a_monitor_can_be_deleted_returns_OK_response-1763748205","message":"some + message Notify: @hipchat-channel","tags":["test:testcheckifamonitorcanbedeletedreturnsokresponse1763748205","env:ci"],"query":"logs(\"service:foo AND type:error\").index(\"main\").rollup(\"count\").by(\"source\").last(\"5m\") > 2","options":{"enable_logs_sample":true,"escalation_message":"the situation - has escalated","evaluation_delay":700,"include_tags":true,"locked":false,"new_host_delay":600,"no_data_timeframe":null,"notification_preset_name":"hide_handles","notify_audit":false,"notify_no_data":false,"on_missing_data":"show_and_notify_no_data","renotify_interval":60,"require_full_window":true,"thresholds":{"critical":2.0,"warning":1.0},"timeout_h":24,"groupby_simple_monitor":false,"silenced":{}},"multi":true,"created_at":1728578463000,"created":"2024-10-10T16:41:03.666877+00:00","modified":"2024-10-10T16:41:03.666877+00:00","deleted":null,"restricted_roles":null,"priority":3,"restriction_policy":null,"overall_state_modified":null,"overall_state":"No - Data","creator":{"name":null,"handle":"frog@datadoghq.com","email":"frog@datadoghq.com","id":1445416}} + has escalated","evaluation_delay":700,"include_tags":true,"locked":false,"new_host_delay":600,"no_data_timeframe":null,"notification_preset_name":"hide_handles","notify_audit":false,"notify_no_data":false,"on_missing_data":"show_and_notify_no_data","renotify_interval":60,"require_full_window":true,"thresholds":{"critical":2.0,"warning":1.0},"timeout_h":24,"groupby_simple_monitor":false,"silenced":{}},"multi":true,"created_at":1763748206000,"created":"2025-11-21T18:03:26.123200+00:00","modified":"2025-11-21T18:03:26.123200+00:00","deleted":null,"priority":3,"restricted_roles":null,"restriction_policy":null,"draft_status":"published","assets":[],"overall_state_modified":null,"overall_state":"No + Data","creator":{"name":"Kevin Pombo","handle":"kevin.pombo@datadoghq.com","email":"kevin.pombo@datadoghq.com","id":25712273}} ' code: 200 @@ -34,9 +34,9 @@ interactions: - application/json id: 1 method: GET - url: https://api.datadoghq.com/api/v1/monitor/can_delete?monitor_ids=155845287 + url: https://api.datadoghq.com/api/v1/monitor/can_delete?monitor_ids=238669218 response: - body: '{"data":{"ok":[155845287]},"errors":null} + body: '{"data":{"ok":[238669218]},"errors":null} ' code: 200 @@ -53,9 +53,9 @@ interactions: - application/json id: 2 method: DELETE - url: https://api.datadoghq.com/api/v1/monitor/155845287 + url: https://api.datadoghq.com/api/v1/monitor/238669218 response: - body: '{"deleted_monitor_id":155845287} + body: '{"deleted_monitor_id":238669218} ' code: 200 diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Create_a_monitor_with_assets_returns_OK_response.freeze b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Create_a_monitor_with_assets_returns_OK_response.freeze new file mode 100644 index 00000000000..12b1e5fed0c --- /dev/null +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Create_a_monitor_with_assets_returns_OK_response.freeze @@ -0,0 +1 @@ +2025-11-21T19:04:55.769Z \ No newline at end of file diff --git a/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Create_a_monitor_with_assets_returns_OK_response.yaml b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Create_a_monitor_with_assets_returns_OK_response.yaml new file mode 100644 index 00000000000..96966751e42 --- /dev/null +++ b/tests/scenarios/cassettes/TestScenarios/v1/Feature_Monitors/Scenario_Create_a_monitor_with_assets_returns_OK_response.yaml @@ -0,0 +1,47 @@ +interactions: +- request: + body: | + {"assets":[{"category":"runbook","name":"Monitor Runbook","resource_key":"12345","resource_type":"notebook","url":"/notebooks/12345"}],"message":"some message Notify: @hipchat-channel","name":"Test-Create_a_monitor_with_assets_returns_OK_response-1763751895","options":{"scheduling_options":{"evaluation_window":{"day_starts":"04:00","month_starts":1}},"thresholds":{"critical":0.5}},"query":"avg(current_1mo):avg:system.load.5{*} \u003e 0.5","type":"metric alert"} + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + id: 0 + method: POST + url: https://api.datadoghq.com/api/v1/monitor + response: + body: '{"id":238681257,"org_id":321813,"type":"query alert","name":"Test-Create_a_monitor_with_assets_returns_OK_response-1763751895","message":"some + message Notify: @hipchat-channel","tags":[],"query":"avg(current_1mo):avg:system.load.5{*} + > 0.5","options":{"scheduling_options":{"evaluation_window":{"day_starts":"04:00","month_starts":1}},"thresholds":{"critical":0.5},"notify_no_data":false,"notify_audit":false,"new_host_delay":300,"include_tags":true,"silenced":{}},"multi":false,"created_at":1763751896000,"created":"2025-11-21T19:04:56.060346+00:00","modified":"2025-11-21T19:04:56.060346+00:00","deleted":null,"priority":null,"restricted_roles":null,"restriction_policy":null,"draft_status":"published","assets":[{"monitor_id":238681257,"name":"Monitor + Runbook","category":"runbook","url":"/notebooks/12345","template_variables":{},"options":{},"resource_key":"12345","resource_type":"notebook"}],"overall_state_modified":null,"overall_state":"No + Data","creator":{"name":"CI Account","handle":"9919ec9b-ebc7-49ee-8dc8-03626e717cca","email":"team-intg-tools-libs-spam@datadoghq.com","id":2320499}} + + ' + code: 200 + duration: 0ms + headers: + Content-Type: + - application/json + status: 200 OK +- request: + body: '' + form: {} + headers: + Accept: + - application/json + id: 1 + method: DELETE + url: https://api.datadoghq.com/api/v1/monitor/238681257 + response: + body: '{"deleted_monitor_id":238681257} + + ' + code: 200 + duration: 0ms + headers: + Content-Type: + - application/json + status: 200 OK +version: 2 diff --git a/tests/scenarios/features/v1/monitors.feature b/tests/scenarios/features/v1/monitors.feature index 64e72f698b4..75a681927b9 100644 --- a/tests/scenarios/features/v1/monitors.feature +++ b/tests/scenarios/features/v1/monitors.feature @@ -131,6 +131,18 @@ Feature: Monitors And the response "type" is equal to "log alert" And the response "query" is equal to "logs(\"service:foo AND type:error\").index(\"main\").rollup(\"count\").by(\"source\").last(\"5m\") > 2" + @team:DataDog/monitor-app + Scenario: Create a monitor with assets returns "OK" response + Given new "CreateMonitor" request + And body with value {"assets": [{"category": "runbook", "name": "Monitor Runbook", "resource_key": "12345", "resource_type": "notebook", "url": "/notebooks/12345"}], "name": "{{ unique }}", "type": "metric alert", "query": "avg(current_1mo):avg:system.load.5{*} > 0.5", "message": "some message Notify: @hipchat-channel", "options":{"thresholds":{"critical":0.5}, "scheduling_options":{"evaluation_window":{"day_starts":"04:00", "month_starts":1}}}} + When the request is sent + Then the response status is 200 OK + And the response "assets[0].category" is equal to "runbook" + And the response "assets[0].name" is equal to "Monitor Runbook" + And the response "assets[0].resource_key" is equal to "12345" + And the response "assets[0].resource_type" is equal to "notebook" + And the response "assets[0].url" is equal to "/notebooks/12345" + @team:DataDog/monitor-app Scenario: Create an Error Tracking monitor returns "OK" response Given new "CreateMonitor" request @@ -169,7 +181,7 @@ Feature: Monitors Scenario: Edit a monitor returns "Bad Request" response Given new "UpdateMonitor" request And request contains "monitor_id" parameter from "REPLACE.ME" - And body with value {"draft_status": "published", "options": {"evaluation_delay": null, "include_tags": true, "min_failure_duration": 0, "min_location_failed": 1, "new_group_delay": null, "new_host_delay": 300, "no_data_timeframe": null, "notification_preset_name": "show_all", "notify_audit": false, "notify_by": [], "on_missing_data": "default", "renotify_interval": null, "renotify_occurrences": null, "renotify_statuses": ["alert"], "scheduling_options": {"custom_schedule": {"recurrences": [{"rrule": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR", "start": "2023-08-31T16:30:00", "timezone": "Europe/Paris"}]}, "evaluation_window": {"day_starts": "04:00", "hour_starts": 0, "month_starts": 1, "timezone": "Europe/Paris"}}, "synthetics_check_id": null, "threshold_windows": {"recovery_window": null, "trigger_window": null}, "thresholds": {"critical_recovery": null, "ok": null, "unknown": null, "warning": null, "warning_recovery": null}, "timeout_h": null, "variables": [{"compute": {"aggregation": "avg", "interval": 60000, "metric": "@duration"}, "data_source": "rum", "group_by": [{"facet": "status", "limit": 10, "sort": {"aggregation": "avg", "order": "desc"}}], "indexes": ["days-3", "days-7"], "name": "query_errors", "search": {"query": "service:query"}}]}, "priority": null, "restricted_roles": [], "tags": [], "type": "query alert"} + And body with value {"assets": [{"category": "runbook", "name": "Monitor Runbook", "resource_key": "12345", "resource_type": "notebook", "url": "/notebooks/12345"}], "draft_status": "published", "options": {"evaluation_delay": null, "include_tags": true, "min_failure_duration": 0, "min_location_failed": 1, "new_group_delay": null, "new_host_delay": 300, "no_data_timeframe": null, "notification_preset_name": "show_all", "notify_audit": false, "notify_by": [], "on_missing_data": "default", "renotify_interval": null, "renotify_occurrences": null, "renotify_statuses": ["alert"], "scheduling_options": {"custom_schedule": {"recurrences": [{"rrule": "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR", "start": "2023-08-31T16:30:00", "timezone": "Europe/Paris"}]}, "evaluation_window": {"day_starts": "04:00", "hour_starts": 0, "month_starts": 1, "timezone": "Europe/Paris"}}, "synthetics_check_id": null, "threshold_windows": {"recovery_window": null, "trigger_window": null}, "thresholds": {"critical_recovery": null, "ok": null, "unknown": null, "warning": null, "warning_recovery": null}, "timeout_h": null, "variables": [{"compute": {"aggregation": "avg", "interval": 60000, "metric": "@duration"}, "data_source": "rum", "group_by": [{"facet": "status", "limit": 10, "sort": {"aggregation": "avg", "order": "desc"}}], "indexes": ["days-3", "days-7"], "name": "query_errors", "search": {"query": "service:query"}}]}, "priority": null, "restricted_roles": [], "tags": [], "type": "query alert"} When the request is sent Then the response status is 400 Bad Request