From be44f61548d07c87bd611d46dda8a3de8be3e501 Mon Sep 17 00:00:00 2001 From: shkaruna Date: Tue, 23 Jun 2026 14:01:37 +0530 Subject: [PATCH 1/5] feat: add aclp alert channel API support --- monitor_alert_channels.go | 24 +++++ ...nitions_test.go => monitor_alerts_test.go} | 46 ++++++++ test/unit/monitor_alert_channels_test.go | 100 ++++++++++++++---- 3 files changed, 148 insertions(+), 22 deletions(-) rename test/integration/{monitor_alert_definitions_test.go => monitor_alerts_test.go} (88%) diff --git a/monitor_alert_channels.go b/monitor_alert_channels.go index 7de93d86e..7ca6e6217 100644 --- a/monitor_alert_channels.go +++ b/monitor_alert_channels.go @@ -77,8 +77,32 @@ func (a *AlertChannel) UnmarshalJSON(b []byte) error { return nil } +// AlertChannelCreateOptions represents options for creating an alert notification channel. +type AlertChannelCreateOptions struct { + ChannelType AlertNotificationType `json:"channel_type"` + Details AlertChannelDetailsOptions `json:"details"` + Label *string `json:"label,omitzero"` +} + +// AlertChannelDetailsOptions represents the details configuration for an alert channel. +type AlertChannelDetailsOptions struct { + Email *EmailChannelCreateOptions `json:"email,omitzero"` +} + +// EmailChannelCreateOptions represents email-specific configuration for an alert channel. +type EmailChannelCreateOptions struct { + Usernames []string `json:"usernames"` + RecipientType *string `json:"recipient_type,omitzero"` +} + // ListAlertChannels gets a paginated list of Alert Channels. func (c *Client) ListAlertChannels(ctx context.Context, opts *ListOptions) ([]AlertChannel, error) { endpoint := formatAPIPath("monitor/alert-channels") return getPaginatedResults[AlertChannel](ctx, c, endpoint, opts) } + +// CreateAlertChannel creates a new alert notification channel. +func (c *Client) CreateAlertChannel(ctx context.Context, opts AlertChannelCreateOptions) (*AlertChannel, error) { + endpoint := formatAPIPath("monitor/alert-channels") + return doPOSTRequest[AlertChannel](ctx, c, endpoint, opts) +} diff --git a/test/integration/monitor_alert_definitions_test.go b/test/integration/monitor_alerts_test.go similarity index 88% rename from test/integration/monitor_alert_definitions_test.go rename to test/integration/monitor_alerts_test.go index 42050d3d9..3b306c1e8 100644 --- a/test/integration/monitor_alert_definitions_test.go +++ b/test/integration/monitor_alerts_test.go @@ -8,6 +8,7 @@ import ( "github.com/linode/linodego/v2" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) const ( @@ -331,3 +332,48 @@ func TestMonitorAlertDefinitionEntities_List(t *testing.T) { assert.NotEmpty(t, entity.URL) } } + +func TestMonitorAlertChannel_Create_smoke(t *testing.T) { + client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_Create") + defer teardown() + + profile, err := client.GetProfile(context.Background()) //To supply a valid email recipient username + require.NoError(t, err) + require.NotEmpty(t, profile.Username) + + label := "go-test-alert-channel-create-" + getUniqueText() + recipientType := "user" + + createOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{profile.Username}, + RecipientType: &recipientType, + }, + }, + } + + channel, err := client.CreateAlertChannel(context.Background(), createOpts) + require.NoError(t, err) + require.NotNil(t, channel) + + assert.NotZero(t, channel.ID) + assert.Equal(t, label, channel.Label) + assert.Equal(t, createOpts.ChannelType, channel.ChannelType) + assert.Equal(t, linodego.UserAlertChannel, channel.Type) + + require.NotNil(t, channel.Details.Email) + assert.Equal(t, createOpts.Details.Email.Usernames, channel.Details.Email.Usernames) + assert.Equal(t, recipientType, channel.Details.Email.RecipientType) + + assert.NotEmpty(t, channel.Alerts.URL) + assert.NotEmpty(t, channel.Alerts.Type) + assert.GreaterOrEqual(t, channel.Alerts.AlertCount, 0) + + assertDateSet(t, channel.Created) + assertDateSet(t, channel.Updated) + + // Intentionally no cleanup: delete API for monitor alert channels is not available. +} diff --git a/test/unit/monitor_alert_channels_test.go b/test/unit/monitor_alert_channels_test.go index 6b4bac32f..ba5bca222 100644 --- a/test/unit/monitor_alert_channels_test.go +++ b/test/unit/monitor_alert_channels_test.go @@ -10,35 +10,59 @@ import ( "github.com/stretchr/testify/require" ) -const monitorAlertChannelListResponse = `{ - "data": [{ - "id": 123, - "label": "alert notification channel", +const ( + monitorAlertChannelListResponse = `{ + "data": [{ + "id": 123, + "label": "alert notification channel", + "channel_type": "email", + "type": "user", + "details": { + "email": { + "usernames": [ + "admin-user1", + "admin-user2" + ], + "recipient_type": "user" + } + }, + "alerts": { + "url": "/monitor/alert-channels/123/alerts", + "type": "alerts-definitions", + "alert_count": 0 + }, + "created": "2024-01-01T00:00:00", + "updated": "2024-01-01T00:00:00", + "created_by": "tester", + "updated_by": "tester" + }], + "page": 1, + "pages": 1, + "results": 1 + }` + + monitorAlertChannelCreateResponse = `{ + "id": 10000, + "label": "My Email Alert Channel", "channel_type": "email", "type": "user", + "created": "2026-06-23T09:43:00", + "created_by": "johndoe", + "updated": "2026-06-23T09:43:00", + "updated_by": "johndoe", "details": { "email": { - "usernames": [ - "admin-user1", - "admin-user2" - ], - "recipient_type": "user" + "recipient_type": "user", + "usernames": ["johndoe", "janedoe"] } }, "alerts": { - "url": "/monitor/alert-channels/123/alerts", - "type": "alerts-definitions", - "alert_count": 0 - }, - "created": "2024-01-01T00:00:00", - "updated": "2024-01-01T00:00:00", - "created_by": "tester", - "updated_by": "tester" - }], - "page": 1, - "pages": 1, - "results": 1 -}` + "alert_count": 0, + "type": "alert-definitions", + "url": "/monitor/alert-channels/10000/alerts" + } + }` +) func TestListAlertChannels(t *testing.T) { var base ClientBaseCase @@ -62,3 +86,35 @@ func TestListAlertChannels(t *testing.T) { assert.Equal(t, 0, channel.Alerts.AlertCount) assert.Equal(t, "/monitor/alert-channels/123/alerts", channel.Alerts.URL) } + +func TestCreateAlertChannel(t *testing.T) { + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockPost("monitor/alert-channels", json.RawMessage(monitorAlertChannelCreateResponse)) + + opts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: linodego.Pointer("My Email Alert Channel"), + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{"johndoe", "janedoe"}, + }, + }, + } + + channel, err := base.Client.CreateAlertChannel(context.Background(), opts) + require.NoError(t, err) + require.NotNil(t, channel) + + assert.Equal(t, 10000, channel.ID) + assert.Equal(t, "My Email Alert Channel", channel.Label) + assert.Equal(t, linodego.EmailAlertNotification, channel.ChannelType) + assert.Equal(t, linodego.UserAlertChannel, channel.Type) + require.NotNil(t, channel.Details.Email) + assert.Equal(t, []string{"johndoe", "janedoe"}, channel.Details.Email.Usernames) + assert.Equal(t, "user", channel.Details.Email.RecipientType) + assert.Equal(t, 0, channel.Alerts.AlertCount) + assert.Equal(t, "/monitor/alert-channels/10000/alerts", channel.Alerts.URL) +} From 4690ce38791733e612ef5a22ff3fbcfbd15ccd64 Mon Sep 17 00:00:00 2001 From: shkaruna Date: Tue, 7 Jul 2026 00:29:58 +0530 Subject: [PATCH 2/5] feat: add aclp alert channel support --- monitor_alert_channels.go | 28 ++ .../TestMonitorAlertChannel_Create.yaml | 276 ++++++++++++++++++ test/integration/monitor_alerts_test.go | 43 ++- test/unit/monitor_alert_channels_test.go | 76 ++++- 4 files changed, 409 insertions(+), 14 deletions(-) create mode 100644 test/integration/fixtures/TestMonitorAlertChannel_Create.yaml diff --git a/monitor_alert_channels.go b/monitor_alert_channels.go index 7ca6e6217..7c53148d4 100644 --- a/monitor_alert_channels.go +++ b/monitor_alert_channels.go @@ -95,6 +95,22 @@ type EmailChannelCreateOptions struct { RecipientType *string `json:"recipient_type,omitzero"` } +// AlertChannelUpdateOptions represents options for updating an alert notification channel. +type AlertChannelUpdateOptions struct { + Details *AlertChannelUpdateDetailsOptions `json:"details,omitzero"` + Label *string `json:"label,omitzero"` +} + +// AlertChannelUpdateDetailsOptions represents update details for an alert channel. +type AlertChannelUpdateDetailsOptions struct { + Email *EmailChannelUpdateOptions `json:"email,omitzero"` +} + +// EmailChannelUpdateOptions represents email-specific update configuration for an alert channel. +type EmailChannelUpdateOptions struct { + Usernames []string `json:"usernames,omitzero"` +} + // ListAlertChannels gets a paginated list of Alert Channels. func (c *Client) ListAlertChannels(ctx context.Context, opts *ListOptions) ([]AlertChannel, error) { endpoint := formatAPIPath("monitor/alert-channels") @@ -106,3 +122,15 @@ func (c *Client) CreateAlertChannel(ctx context.Context, opts AlertChannelCreate endpoint := formatAPIPath("monitor/alert-channels") return doPOSTRequest[AlertChannel](ctx, c, endpoint, opts) } + +// UpdateAlertChannel updates an alert notification channel. +func (c *Client) UpdateAlertChannel(ctx context.Context, channelID int, opts AlertChannelUpdateOptions) (*AlertChannel, error) { + endpoint := formatAPIPath("monitor/alert-channels/%d", channelID) + return doPUTRequest[AlertChannel](ctx, c, endpoint, opts) +} + +// DeleteAlertChannel deletes an alert notification channel. +func (c *Client) DeleteAlertChannel(ctx context.Context, channelID int) error { + endpoint := formatAPIPath("monitor/alert-channels/%d", channelID) + return doDELETERequest(ctx, c, endpoint) +} diff --git a/test/integration/fixtures/TestMonitorAlertChannel_Create.yaml b/test/integration/fixtures/TestMonitorAlertChannel_Create.yaml new file mode 100644 index 000000000..7d627db54 --- /dev/null +++ b/test/integration/fixtures/TestMonitorAlertChannel_Create.yaml @@ -0,0 +1,276 @@ +--- +version: 1 +interactions: +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/account/users?page=1 + method: GET + response: + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+48695154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["bfenski", "fenio", "fenio", "fenio", "fenio"], "tfa_enabled": + true, "verified_phone_number": "+48513467293", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Mon, 06 Jul 2026 18:46:20 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - account:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-sdk-test-alert-channel"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id": 10284, "label": "linodego-sdk-test-alert-channel", "channel_type": + "email", "type": "user", "details": {"email": {"usernames": ["test_user1", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10284/alerts", + "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", + "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": + "tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "470" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Mon, 06 Jul 2026 18:46:21 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"details":{"email":{"usernames":["test_user1","test_user2"]}},"label":"linodego-sdk-test-alert-channel-updated"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10284 + method: PUT + response: + body: '{"id": 10284, "label": "linodego-sdk-test-alert-channel-updated", "channel_type": + "email", "type": "user", "details": {"email": {"usernames": ["test_user1", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10284/alerts", + "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", + "created_by": "tester", "updated_by": "tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "478" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Mon, 06 Jul 2026 18:46:22 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10284 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Mon, 06 Jul 2026 18:46:25 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/monitor_alerts_test.go b/test/integration/monitor_alerts_test.go index 3b306c1e8..5dd601f92 100644 --- a/test/integration/monitor_alerts_test.go +++ b/test/integration/monitor_alerts_test.go @@ -337,11 +337,13 @@ func TestMonitorAlertChannel_Create_smoke(t *testing.T) { client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_Create") defer teardown() - profile, err := client.GetProfile(context.Background()) //To supply a valid email recipient username - require.NoError(t, err) - require.NotEmpty(t, profile.Username) + // Get valid users to use for the email alert channel + users, err := client.ListUsers(context.Background(), nil) + if err != nil { + t.Fatalf("Error listing users: %v", err) + } - label := "go-test-alert-channel-create-" + getUniqueText() + label := "linodego-sdk-test-alert-channel" recipientType := "user" createOpts := linodego.AlertChannelCreateOptions{ @@ -349,16 +351,27 @@ func TestMonitorAlertChannel_Create_smoke(t *testing.T) { Label: &label, Details: linodego.AlertChannelDetailsOptions{ Email: &linodego.EmailChannelCreateOptions{ - Usernames: []string{profile.Username}, + Usernames: []string{users[0].Username, users[1].Username}, RecipientType: &recipientType, }, }, } + // Create the alert channel channel, err := client.CreateAlertChannel(context.Background(), createOpts) require.NoError(t, err) require.NotNil(t, channel) + // Delete the created alert channel after the test completes + defer func() { + if channel != nil { + time.Sleep(2 * time.Second) + if err := client.DeleteAlertChannel(context.Background(), channel.ID); err != nil { + t.Logf("DeleteAlertChannel returned error: %#v", err) + } + } + }() + assert.NotZero(t, channel.ID) assert.Equal(t, label, channel.Label) assert.Equal(t, createOpts.ChannelType, channel.ChannelType) @@ -375,5 +388,23 @@ func TestMonitorAlertChannel_Create_smoke(t *testing.T) { assertDateSet(t, channel.Created) assertDateSet(t, channel.Updated) - // Intentionally no cleanup: delete API for monitor alert channels is not available. + // Update the created alert channel + updatedLabel := label + "-updated" + updateOpts := linodego.AlertChannelUpdateOptions{ + Label: &updatedLabel, + Details: &linodego.AlertChannelUpdateDetailsOptions{ + Email: &linodego.EmailChannelUpdateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + }, + }, + } + updatedChannel, err := client.UpdateAlertChannel(context.Background(), channel.ID, updateOpts) + require.NoError(t, err) + require.NotNil(t, updatedChannel) + + assert.Equal(t, channel.ID, updatedChannel.ID) + assert.Equal(t, updatedLabel, updatedChannel.Label) + assert.Equal(t, createOpts.ChannelType, updatedChannel.ChannelType) + require.NotNil(t, updatedChannel.Details.Email) + assert.Equal(t, createOpts.Details.Email.Usernames, updatedChannel.Details.Email.Usernames) } diff --git a/test/unit/monitor_alert_channels_test.go b/test/unit/monitor_alert_channels_test.go index ba5bca222..2cbffec6f 100644 --- a/test/unit/monitor_alert_channels_test.go +++ b/test/unit/monitor_alert_channels_test.go @@ -43,17 +43,39 @@ const ( monitorAlertChannelCreateResponse = `{ "id": 10000, - "label": "My Email Alert Channel", + "label": "Email Alert Channel", "channel_type": "email", "type": "user", "created": "2026-06-23T09:43:00", - "created_by": "johndoe", + "created_by": "tester", "updated": "2026-06-23T09:43:00", - "updated_by": "johndoe", + "updated_by": "tester", "details": { "email": { "recipient_type": "user", - "usernames": ["johndoe", "janedoe"] + "usernames": ["tester1", "tester2"] + } + }, + "alerts": { + "alert_count": 0, + "type": "alert-definitions", + "url": "/monitor/alert-channels/10000/alerts" + } + }` + + monitorAlertChannelUpdateResponse = `{ + "id": 10000, + "label": "Email Alert Channel Updated", + "channel_type": "email", + "type": "user", + "created": "2026-06-23T09:43:00", + "created_by": "tester", + "updated": "2026-06-24T09:43:00", + "updated_by": "tester", + "details": { + "email": { + "recipient_type": "user", + "usernames": ["tester"] } }, "alerts": { @@ -96,10 +118,10 @@ func TestCreateAlertChannel(t *testing.T) { opts := linodego.AlertChannelCreateOptions{ ChannelType: linodego.EmailAlertNotification, - Label: linodego.Pointer("My Email Alert Channel"), + Label: linodego.Pointer("Email Alert Channel"), Details: linodego.AlertChannelDetailsOptions{ Email: &linodego.EmailChannelCreateOptions{ - Usernames: []string{"johndoe", "janedoe"}, + Usernames: []string{"tester1", "tester2"}, }, }, } @@ -109,11 +131,49 @@ func TestCreateAlertChannel(t *testing.T) { require.NotNil(t, channel) assert.Equal(t, 10000, channel.ID) - assert.Equal(t, "My Email Alert Channel", channel.Label) + assert.Equal(t, "Email Alert Channel", channel.Label) + assert.Equal(t, linodego.EmailAlertNotification, channel.ChannelType) + assert.Equal(t, linodego.UserAlertChannel, channel.Type) + require.NotNil(t, channel.Details.Email) + assert.Equal(t, []string{"tester1", "tester2"}, channel.Details.Email.Usernames) + assert.Equal(t, "user", channel.Details.Email.RecipientType) + assert.Equal(t, 0, channel.Alerts.AlertCount) + assert.Equal(t, "/monitor/alert-channels/10000/alerts", channel.Alerts.URL) +} + +func TestDeleteAlertChannel(t *testing.T) { + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockDelete("monitor/alert-channels/10000", nil) + + err := base.Client.DeleteAlertChannel(context.Background(), 10000) + assert.NoError(t, err) +} + +func TestUpdateAlertChannel(t *testing.T) { + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockPut("monitor/alert-channels/10000", json.RawMessage(monitorAlertChannelUpdateResponse)) + + label := "Email Alert Channel Updated" + opts := linodego.AlertChannelUpdateOptions{ + Label: &label, + } + + channel, err := base.Client.UpdateAlertChannel(context.Background(), 10000, opts) + require.NoError(t, err) + require.NotNil(t, channel) + + assert.Equal(t, 10000, channel.ID) + assert.Equal(t, label, channel.Label) assert.Equal(t, linodego.EmailAlertNotification, channel.ChannelType) assert.Equal(t, linodego.UserAlertChannel, channel.Type) require.NotNil(t, channel.Details.Email) - assert.Equal(t, []string{"johndoe", "janedoe"}, channel.Details.Email.Usernames) + assert.Equal(t, []string{"tester"}, channel.Details.Email.Usernames) assert.Equal(t, "user", channel.Details.Email.RecipientType) assert.Equal(t, 0, channel.Alerts.AlertCount) assert.Equal(t, "/monitor/alert-channels/10000/alerts", channel.Alerts.URL) From d37b1cb011815aa5f1ade4a4b1c73121c80bb843 Mon Sep 17 00:00:00 2001 From: shkaruna Date: Thu, 16 Jul 2026 22:03:54 +0530 Subject: [PATCH 3/5] feat: add aclp alert channel support --- monitor_alert_channels.go | 21 ++++ ...yaml => TestMonitorAlertChannel_CRUD.yaml} | 99 ++++++++++++++++--- test/integration/monitor_alerts_test.go | 18 +++- test/unit/monitor_alert_channels_test.go | 52 ++++++++++ 4 files changed, 175 insertions(+), 15 deletions(-) rename test/integration/fixtures/{TestMonitorAlertChannel_Create.yaml => TestMonitorAlertChannel_CRUD.yaml} (74%) diff --git a/monitor_alert_channels.go b/monitor_alert_channels.go index 7c53148d4..1ba87dda5 100644 --- a/monitor_alert_channels.go +++ b/monitor_alert_channels.go @@ -111,12 +111,27 @@ type EmailChannelUpdateOptions struct { Usernames []string `json:"usernames,omitzero"` } +// Alert represents an alert definition assigned to a notification channel. +type Alert struct { + ID int `json:"id"` + Label string `json:"label"` + ServiceType string `json:"service_type"` + Type string `json:"type"` + URL string `json:"url"` +} + // ListAlertChannels gets a paginated list of Alert Channels. func (c *Client) ListAlertChannels(ctx context.Context, opts *ListOptions) ([]AlertChannel, error) { endpoint := formatAPIPath("monitor/alert-channels") return getPaginatedResults[AlertChannel](ctx, c, endpoint, opts) } +// GetAlertChannel retrieves a single Alert Channel by ID. +func (c *Client) GetAlertChannel(ctx context.Context, channelID int) (*AlertChannel, error) { + endpoint := formatAPIPath("monitor/alert-channels/%d", channelID) + return doGETRequest[AlertChannel](ctx, c, endpoint) +} + // CreateAlertChannel creates a new alert notification channel. func (c *Client) CreateAlertChannel(ctx context.Context, opts AlertChannelCreateOptions) (*AlertChannel, error) { endpoint := formatAPIPath("monitor/alert-channels") @@ -134,3 +149,9 @@ func (c *Client) DeleteAlertChannel(ctx context.Context, channelID int) error { endpoint := formatAPIPath("monitor/alert-channels/%d", channelID) return doDELETERequest(ctx, c, endpoint) } + +// ListAlertsForChannel gets a paginated list of Alert Definitions for a specific alert notification channel. +func (c *Client) ListAlertsForChannel(ctx context.Context, channelID int, opts *ListOptions) ([]Alert, error) { + endpoint := formatAPIPath("monitor/alert-channels/%d/alerts", channelID) + return getPaginatedResults[Alert](ctx, c, endpoint, opts) +} diff --git a/test/integration/fixtures/TestMonitorAlertChannel_Create.yaml b/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml similarity index 74% rename from test/integration/fixtures/TestMonitorAlertChannel_Create.yaml rename to test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml index 7d627db54..1a838382c 100644 --- a/test/integration/fixtures/TestMonitorAlertChannel_Create.yaml +++ b/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml @@ -16,11 +16,11 @@ interactions: response: body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": - "+48695154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": "test_user2", "email": "test_user2@example.com", "restricted": false, - "ssh_keys": ["bfenski", "fenio", "fenio", "fenio", "fenio"], "tfa_enabled": - true, "verified_phone_number": "+48513467293", "password_created": "2018-01-02T03:04:05", + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' headers: @@ -45,7 +45,7 @@ interactions: Content-Type: - application/json Expires: - - Mon, 06 Jul 2026 18:46:20 GMT + - Thu, 16 Jul 2026 07:16:05 GMT Pragma: - no-cache Strict-Transport-Security: @@ -86,9 +86,9 @@ interactions: url: https://api.linode.com/v4beta/monitor/alert-channels method: POST response: - body: '{"id": 10284, "label": "linodego-sdk-test-alert-channel", "channel_type": + body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel", "channel_type": "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10284/alerts", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": "tester"}' @@ -116,7 +116,7 @@ interactions: Content-Type: - application/json Expires: - - Mon, 06 Jul 2026 18:46:21 GMT + - Thu, 16 Jul 2026 07:16:06 GMT Pragma: - no-cache Strict-Transport-Security: @@ -142,6 +142,76 @@ interactions: status: 200 OK code: 200 duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10304 + method: GET + response: + body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel", "channel_type": + "email", "type": "user", "details": {"email": {"usernames": ["test_user1", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", + "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", + "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": + "tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "470" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 07:16:07 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" - request: body: '{"details":{"email":{"usernames":["test_user1","test_user2"]}},"label":"linodego-sdk-test-alert-channel-updated"}' form: {} @@ -152,14 +222,15 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10284 + url: https://api.linode.com/v4beta/monitor/alert-channels/10304 method: PUT response: - body: '{"id": 10284, "label": "linodego-sdk-test-alert-channel-updated", "channel_type": + body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel-updated", "channel_type": "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10284/alerts", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", - "created_by": "tester", "updated_by": "tester"}' + "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": + "tester"}' headers: Access-Control-Allow-Credentials: - "true" @@ -184,7 +255,7 @@ interactions: Content-Type: - application/json Expires: - - Mon, 06 Jul 2026 18:46:22 GMT + - Thu, 16 Jul 2026 07:16:09 GMT Pragma: - no-cache Strict-Transport-Security: @@ -220,7 +291,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10284 + url: https://api.linode.com/v4beta/monitor/alert-channels/10304 method: DELETE response: body: '{}' @@ -248,7 +319,7 @@ interactions: Content-Type: - application/json Expires: - - Mon, 06 Jul 2026 18:46:25 GMT + - Thu, 16 Jul 2026 07:16:12 GMT Pragma: - no-cache Strict-Transport-Security: diff --git a/test/integration/monitor_alerts_test.go b/test/integration/monitor_alerts_test.go index 5dd601f92..a14e97086 100644 --- a/test/integration/monitor_alerts_test.go +++ b/test/integration/monitor_alerts_test.go @@ -333,7 +333,7 @@ func TestMonitorAlertDefinitionEntities_List(t *testing.T) { } } -func TestMonitorAlertChannel_Create_smoke(t *testing.T) { +func TestMonitorAlertChannel_CRUD_E2E(t *testing.T) { client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_Create") defer teardown() @@ -388,6 +388,22 @@ func TestMonitorAlertChannel_Create_smoke(t *testing.T) { assertDateSet(t, channel.Created) assertDateSet(t, channel.Updated) + // Fetch the channel via GetAlertChannel + fetchedChannel, err := client.GetAlertChannel(context.Background(), channel.ID) + require.NoError(t, err) + require.NotNil(t, fetchedChannel) + + assert.Equal(t, channel.ID, fetchedChannel.ID) + assert.Equal(t, channel.Label, fetchedChannel.Label) + assert.Equal(t, channel.ChannelType, fetchedChannel.ChannelType) + assert.Equal(t, channel.Type, fetchedChannel.Type) + require.NotNil(t, fetchedChannel.Details.Email) + assert.Equal(t, channel.Details.Email.Usernames, fetchedChannel.Details.Email.Usernames) + assert.Equal(t, channel.Details.Email.RecipientType, fetchedChannel.Details.Email.RecipientType) + assert.Equal(t, channel.Alerts.URL, fetchedChannel.Alerts.URL) + assert.Equal(t, channel.Alerts.Type, fetchedChannel.Alerts.Type) + assert.Equal(t, channel.Alerts.AlertCount, fetchedChannel.Alerts.AlertCount) + // Update the created alert channel updatedLabel := label + "-updated" updateOpts := linodego.AlertChannelUpdateOptions{ diff --git a/test/unit/monitor_alert_channels_test.go b/test/unit/monitor_alert_channels_test.go index 2cbffec6f..3810dd8d5 100644 --- a/test/unit/monitor_alert_channels_test.go +++ b/test/unit/monitor_alert_channels_test.go @@ -84,6 +84,21 @@ const ( "url": "/monitor/alert-channels/10000/alerts" } }` + + monitorAlertChannelListAlertsForChannelResponse = `{ + "data": [ + { + "id": 10000, + "label": "Dbaas alert definition", + "service_type": "dbaas", + "type": "system", + "url": "/monitor/services/dbaas/alerts-definitions/10000" + } + ], + "page": 1, + "pages": 1, + "results": 1 + }` ) func TestListAlertChannels(t *testing.T) { @@ -178,3 +193,40 @@ func TestUpdateAlertChannel(t *testing.T) { assert.Equal(t, 0, channel.Alerts.AlertCount) assert.Equal(t, "/monitor/alert-channels/10000/alerts", channel.Alerts.URL) } +func TestGetAlertChannel(t *testing.T) { + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("monitor/alert-channels/10000", json.RawMessage(monitorAlertChannelCreateResponse)) + + channel, err := base.Client.GetAlertChannel(context.Background(), 10000) + require.NoError(t, err) + require.NotNil(t, channel) + + assert.Equal(t, 10000, channel.ID) + assert.Equal(t, "Email Alert Channel", channel.Label) + assert.Equal(t, linodego.EmailAlertNotification, channel.ChannelType) + assert.Equal(t, linodego.UserAlertChannel, channel.Type) + require.NotNil(t, channel.Details.Email) + assert.Equal(t, []string{"tester1", "tester2"}, channel.Details.Email.Usernames) + assert.Equal(t, "user", channel.Details.Email.RecipientType) + assert.Equal(t, 0, channel.Alerts.AlertCount) + assert.Equal(t, "/monitor/alert-channels/10000/alerts", channel.Alerts.URL) +} + +func TestListAlertsForAlertChannel(t *testing.T) { + var base ClientBaseCase + base.SetUp(t) + defer base.TearDown(t) + + base.MockGet("monitor/alert-channels/123/alerts", json.RawMessage(monitorAlertChannelListAlertsForChannelResponse)) + + alerts, err := base.Client.ListAlertsForChannel(context.Background(), 123, nil) + require.NoError(t, err) + require.Len(t, alerts, 1) + + assert.Equal(t, 10000, alerts[0].ID) + assert.Equal(t, "dbaas", alerts[0].ServiceType) + assert.Equal(t, "system", alerts[0].Type) +} From 756f66669ad7c2fa900f0869c56ff56a33b12fb6 Mon Sep 17 00:00:00 2001 From: shkaruna Date: Thu, 16 Jul 2026 23:11:24 +0530 Subject: [PATCH 4/5] ref: updated aclp integration tests --- .../TestMonitorAlertChannel_CRUD.yaml | 30 +- .../TestMonitorAlertChannel_ListAlerts.yaml | 413 ++++++++++++++++++ .../fixtures/TestMonitorAlertDefinition.yaml | 274 ++++++++++-- .../TestMonitorAlertDefinition_Clone.yaml | 230 +++++++--- ...AlertDefinition_CreateWithIdempotency.yaml | 181 ++++++-- test/integration/monitor_alerts_test.go | 267 ++++++++--- 6 files changed, 1200 insertions(+), 195 deletions(-) create mode 100644 test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml diff --git a/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml b/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml index 1a838382c..63a195bf8 100644 --- a/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml +++ b/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml @@ -45,7 +45,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:05 GMT + - Thu, 16 Jul 2026 17:23:56 GMT Pragma: - no-cache Strict-Transport-Security: @@ -86,9 +86,9 @@ interactions: url: https://api.linode.com/v4beta/monitor/alert-channels method: POST response: - body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel", "channel_type": - "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", + body: '{"id": 10310, "label": "linodego-sdk-test-alert-channel", "channel_type": + "details": {"email": {"usernames": ["test_user1", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10310/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": "tester"}' @@ -116,7 +116,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:06 GMT + - Thu, 16 Jul 2026 17:23:57 GMT Pragma: - no-cache Strict-Transport-Security: @@ -152,12 +152,12 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10304 + url: https://api.linode.com/v4beta/monitor/alert-channels/10310 method: GET response: - body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel", "channel_type": + body: '{"id": 10310, "label": "linodego-sdk-test-alert-channel", "channel_type": "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10310/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": "tester"}' @@ -185,7 +185,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:07 GMT + - Thu, 16 Jul 2026 17:23:58 GMT Pragma: - no-cache Strict-Transport-Security: @@ -222,12 +222,12 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10304 + url: https://api.linode.com/v4beta/monitor/alert-channels/10310 method: PUT response: - body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel-updated", "channel_type": + body: '{"id": 10310, "label": "linodego-sdk-test-alert-channel-updated", "channel_type": "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10310/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": "tester"}' @@ -255,7 +255,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:09 GMT + - Thu, 16 Jul 2026 17:23:59 GMT Pragma: - no-cache Strict-Transport-Security: @@ -291,7 +291,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10304 + url: https://api.linode.com/v4beta/monitor/alert-channels/10310 method: DELETE response: body: '{}' @@ -319,7 +319,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:12 GMT + - Thu, 16 Jul 2026 17:24:02 GMT Pragma: - no-cache Strict-Transport-Security: diff --git a/test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml b/test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml new file mode 100644 index 000000000..a8e6ef789 --- /dev/null +++ b/test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml @@ -0,0 +1,413 @@ +--- +version: 1 +interactions: +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/account/users?page=1 + method: GET + response: + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:34 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - account:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-sdk-test-alert-channel-listalerts"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id": 10309, "label": "linodego-sdk-test-alert-channel-listalerts", "channel_type": + "email", "type": "user", "details": {"email": {"usernames": ["test_user1", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10309/alerts", + "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", + "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": + "tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:35 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"label":"go-integration-test-alert","severity":2,"channel_ids":[10309],"rule_criteria":{"rules":[{"aggregate_function":"avg","metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1}}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions + method: POST + response: + body: '{"id": 11632, "label": "go-integration-test-alert", "description": null, + "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": + [], "status": "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": + "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": + "avg", "operator": "gt", "threshold": 90, "dimension_filters": []}]}, "alert_channels": + [{"id": 10309, "label": "linodego-sdk-test-alert-channel-listalerts", "url": + "/monitor/alert-channels/10309", "type": "alert-channels"}], "trigger_conditions": + {"criteria_condition": "ALL", "polling_interval_seconds": 300, "evaluation_period_seconds": + 300, "trigger_occurrences": 1}, "created": "2018-01-02T03:04:05", "updated": + "2018-01-02T03:04:05", "created_by": "tester", "updated_by": + "tester", "group_by": ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11632/entities", + "has_more_resources": false, "count": 0}}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:36 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - databases:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10309/alerts?page=1 + method: GET + response: + body: '{"pages": 1, "page": 1, "results": 1, "data": [{"id": 11632, "label": "go-integration-test-alert", + "url": "/monitor/services/dbaas/alerts-definitions/11632", "type": "alerts-definitions", + "service_type": "dbaas"}]}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "214" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:36 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11632 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:38 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - databases:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10309 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:38 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/fixtures/TestMonitorAlertDefinition.yaml b/test/integration/fixtures/TestMonitorAlertDefinition.yaml index f93859117..e4312db6f 100644 --- a/test/integration/fixtures/TestMonitorAlertDefinition.yaml +++ b/test/integration/fixtures/TestMonitorAlertDefinition.yaml @@ -61,7 +61,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:16 GMT + - Thu, 16 Jul 2026 18:18:45 GMT Pragma: - no-cache Strict-Transport-Security: @@ -90,7 +90,143 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-create","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/account/users?page=1 + method: GET + response: + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:18:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - account:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-alert-channel-1784225925966684533"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id":10315,"label":"linodego-alert-channel-1784225926985434344","channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"alerts":{"url":"/monitor/alert-channels/10315/alerts","type":"alerts-definitions","alert_count":0},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:18:46 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"label":"linodego-alert-1784225926985434344","severity":2,"channel_ids":[10315],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation","group_by":["entity_id"]}' form: {} headers: @@ -103,20 +239,20 @@ interactions: url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions method: POST response: - body: '{"id": 11230, "label": "go-test-alert-definition-create", "description": + body: '{"id": 11638, "label": "linodego-alert-1784225926985434344", "description": "Test alert definition creation", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11230/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10315, + "label": "linodego-alert-channel-1784225925966684533", "url": "/monitor/alert-channels/10315", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11638/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -139,7 +275,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:17 GMT + - Thu, 16 Jul 2026 18:18:48 GMT Pragma: - no-cache Strict-Transport-Security: @@ -176,23 +312,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11230 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11638 method: GET response: - body: '{"id": 11230, "label": "go-test-alert-definition-create", "description": + body: '{"id": 11638, "label": "linodego-alert-1784225926985434344", "description": "Test alert definition creation", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "enabled", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11230/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10315, + "label": "linodego-alert-channel-1784225925966684533", "url": "/monitor/alert-channels/10315", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11638/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -215,7 +351,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:33 GMT + - Thu, 16 Jul 2026 18:19:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -244,7 +380,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-create-updated","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: '{"label":"linodego-alert-1784225926985434344-updated","severity":2,"channel_ids":[10315],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation"}' form: {} headers: @@ -254,23 +390,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11230 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11638 method: PUT response: - body: '{"id": 11230, "label": "go-test-alert-definition-create-updated", "description": + body: '{"id": 11638, "label": "linodego-alert-1784225926985434344-updated", "description": "Test alert definition creation", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "enabled", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11230/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10315, + "label": "linodego-alert-channel-1784225925966684533", "url": "/monitor/alert-channels/10315", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11638/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -293,7 +429,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:35 GMT + - Thu, 16 Jul 2026 18:19:06 GMT Pragma: - no-cache Strict-Transport-Security: @@ -330,7 +466,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11230 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11638 method: DELETE response: body: '{}' @@ -358,7 +494,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:36 GMT + - Thu, 16 Jul 2026 18:19:06 GMT Pragma: - no-cache Strict-Transport-Security: @@ -384,3 +520,67 @@ interactions: status: 200 OK code: 200 duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10315 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:19:07 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml b/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml index 61bed1a88..ad6d700fd 100644 --- a/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml +++ b/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml @@ -11,20 +11,18 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels?page=1 + url: https://api.linode.com/v4beta/account/users?page=1 method: GET response: - body: '{"pages": 1, "page": 1, "results": 2, "data": [{"id": 10000, "label": "Read-Write - Channel", "channel_type": "email", "type": "system", "details": {"email": {"usernames": - [], "recipient_type": "read_write_users"}}, "alerts": {"url": "/monitor/alert-channels/10000/alerts", - "type": "alerts-definitions", "alert_count": 9}, "created": "2018-01-02T03:04:05", - "updated": "2018-01-02T03:04:05", "created_by": "system", "updated_by": "system"}, - {"id": 10118, "label": "notification channel", "channel_type": "email", "type": "user", - "details": {"email": {"usernames": ["tester"], "recipient_type": - "user"}}, "alerts": {"url": "/monitor/alert-channels/10118/alerts", "type": - "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": - "2018-01-02T03:04:05", "created_by": "tester", "updated_by": - "tester"}]}' + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' headers: Access-Control-Allow-Credentials: - "true" @@ -47,7 +45,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:31 GMT + - Thu, 16 Jul 2026 18:21:01 GMT Pragma: - no-cache Strict-Transport-Security: @@ -57,7 +55,71 @@ interactions: - Authorization, X-Filter - Accept-Encoding X-Accepted-Oauth-Scopes: - - monitor:read_only + - account:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-alert-channel-1784226061531360907"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id":10317,"label":"linodego-alert-channel-1784226061531360907","channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"alerts":{"url":"/monitor/alert-channels/10317/alerts","type":"alerts-definitions","alert_count":0},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:21:02 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write X-Content-Type-Options: - nosniff X-Frame-Options: @@ -76,7 +138,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-clone-source","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Source + body: '{"label":"go-test-alert-definition-clone-source","severity":2,"channel_ids":[10317],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Source alert definition for clone test","group_by":["entity_id"]}' form: {} headers: @@ -89,20 +151,20 @@ interactions: url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions method: POST response: - body: '{"id": 11228, "label": "go-test-alert-definition-clone-source", "description": + body: '{"id": 11640, "label": "go-test-alert-definition-clone-source", "description": "Source alert definition for clone test", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11228/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10317, + "label": "linodego-alert-channel-1784226061531360907", "url": "/monitor/alert-channels/10317", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11640/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -125,7 +187,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:32 GMT + - Thu, 16 Jul 2026 18:21:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -162,23 +224,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11228 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11640 method: GET response: - body: '{"id": 11228, "label": "go-test-alert-definition-clone-source", "description": + body: '{"id": 11640, "label": "go-test-alert-definition-clone-source", "description": "Source alert definition for clone test", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "enabled", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11228/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10317, + "label": "linodego-alert-channel-1784226061531360907", "url": "/monitor/alert-channels/10317", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11640/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -201,7 +263,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:48 GMT + - Thu, 16 Jul 2026 18:21:20 GMT Pragma: - no-cache Strict-Transport-Security: @@ -230,7 +292,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-clone-source-clone","severity":1,"channel_ids":[10000],"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":900,"polling_interval_seconds":300,"trigger_occurrences":3},"description":"Cloned + body: '{"label":"go-test-alert-definition-clone-source-clone","severity":1,"channel_ids":[10317],"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":900,"polling_interval_seconds":300,"trigger_occurrences":3},"description":"Cloned alert definition"}' form: {} headers: @@ -240,23 +302,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11228/clone + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11640/clone method: POST response: - body: '{"id": 11229, "label": "go-test-alert-definition-clone-source-clone", "description": + body: '{"id": 11641, "label": "go-test-alert-definition-clone-source-clone", "description": "Cloned alert definition", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "provisioning", "severity": 1, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 900, "trigger_occurrences": 3}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11229/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10317, + "label": "linodego-alert-channel-1784226061531360907", "url": "/monitor/alert-channels/10317", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 900, "trigger_occurrences": + 3}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11641/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -279,7 +341,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:50 GMT + - Thu, 16 Jul 2026 18:21:22 GMT Pragma: - no-cache Strict-Transport-Security: @@ -316,7 +378,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11228 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11640 method: DELETE response: body: '{}' @@ -344,7 +406,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:51 GMT + - Thu, 16 Jul 2026 18:21:22 GMT Pragma: - no-cache Strict-Transport-Security: @@ -380,7 +442,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11229 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11641 method: DELETE response: body: '{}' @@ -408,7 +470,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:52 GMT + - Thu, 16 Jul 2026 18:21:23 GMT Pragma: - no-cache Strict-Transport-Security: @@ -434,3 +496,67 @@ interactions: status: 200 OK code: 200 duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10317 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:21:24 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml b/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml index 82983afec..39b92c00c 100644 --- a/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml +++ b/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml @@ -11,20 +11,18 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels?page=1 + url: https://api.linode.com/v4beta/account/users?page=1 method: GET response: - body: '{"pages": 1, "page": 1, "results": 2, "data": [{"id": 10000, "label": "Read-Write - Channel", "channel_type": "email", "type": "system", "details": {"email": {"usernames": - [], "recipient_type": "read_write_users"}}, "alerts": {"url": "/monitor/alert-channels/10000/alerts", - "type": "alerts-definitions", "alert_count": 9}, "created": "2018-01-02T03:04:05", - "updated": "2018-01-02T03:04:05", "created_by": "system", "updated_by": "system"}, - {"id": 10118, "label": "notification channel", "channel_type": "email", "type": "user", - "details": {"email": {"usernames": ["tester"], "recipient_type": - "user"}}, "alerts": {"url": "/monitor/alert-channels/10118/alerts", "type": - "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": - "2018-01-02T03:04:05", "created_by": "tester", "updated_by": - "tester"}]}' + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' headers: Access-Control-Allow-Credentials: - "true" @@ -47,7 +45,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:32 GMT + - Thu, 16 Jul 2026 18:20:01 GMT Pragma: - no-cache Strict-Transport-Security: @@ -57,7 +55,7 @@ interactions: - Authorization, X-Filter - Accept-Encoding X-Accepted-Oauth-Scopes: - - monitor:read_only + - account:read_only X-Content-Type-Options: - nosniff X-Frame-Options: @@ -76,7 +74,71 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-idempotency-1780593452875420575","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-alert-channel-1784226001847126351"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id":10316,"label":"linodego-alert-channel-1784226001847126351","channel_type":"email","type":"user","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"alerts":{"url":"/monitor/alert-channels/10316/alerts","type":"alerts-definitions","alert_count":0},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:20:02 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"label":"go-test-alert-definition-idempotency-1784226002893832314","severity":2,"channel_ids":[10316],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation with idempotency"}' form: {} headers: @@ -89,20 +151,7 @@ interactions: url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions method: POST response: - body: '{"id": 11234, "label": "go-test-alert-definition-idempotency-1780593452875420575", - "description": "Test alert definition creation with idempotency", "service_type": - "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": - "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory - Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", - "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", - "dimension_label": "node_type", "operator": "eq", "value": "primary"}]}]}, "alert_channels": - [{"id": 10000, "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", - "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", - "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": - 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": - "tester", "updated_by": "tester", "group_by": - ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11234/entities", - "has_more_resources": false, "count": 0}}' + body: '{"id":11639,"label":"go-test-alert-definition-idempotency-1784226002893832314","description":"Test alert definition creation with idempotency","service_type":"dbaas","type":"user","scope":"entity","class":null,"regions":[],"status":"provisioning","severity":2,"rule_criteria":{"rules":[{"label":"Memory Usage","metric":"memory_usage","unit":"percent","aggregate_function":"avg","operator":"gt","threshold":90,"dimension_filters":[{"label":"Node Type","dimension_label":"node_type","operator":"eq","value":"primary"}]}]},"alert_channels":[{"id":10316,"label":"linodego-alert-channel-1784226001847126351","url":"/monitor/alert-channels/10316","type":"alert-channels"}],"trigger_conditions":{"criteria_condition":"ALL","polling_interval_seconds":300,"evaluation_period_seconds":300,"trigger_occurrences":1},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester","group_by":["entity_id"],"entities":{"url":"/monitor/services/dbaas/alert-definitions/11639/entities","has_more_resources":false,"count":0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -125,7 +174,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:34 GMT + - Thu, 16 Jul 2026 18:20:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -153,7 +202,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-idempotency-1780593452875420575","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: '{"label":"go-test-alert-definition-idempotency-1784226002893832314","severity":2,"channel_ids":[10316],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation with idempotency"}' form: {} headers: @@ -184,7 +233,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:34 GMT + - Thu, 16 Jul 2026 18:20:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -213,7 +262,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11234 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11639 method: DELETE response: body: '{}' @@ -241,7 +290,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:35 GMT + - Thu, 16 Jul 2026 18:20:05 GMT Pragma: - no-cache Strict-Transport-Security: @@ -267,3 +316,67 @@ interactions: status: 200 OK code: 200 duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10316 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:20:06 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/monitor_alerts_test.go b/test/integration/monitor_alerts_test.go index 39cfb1057..078da6023 100644 --- a/test/integration/monitor_alerts_test.go +++ b/test/integration/monitor_alerts_test.go @@ -46,6 +46,32 @@ func deleteMonitorAlertDefinitionWithRetry(t *testing.T, client *linodego.Client assert.NoError(t, err, "DeleteMonitorAlertDefinition failed after retries for alert ID %d: %v", alertID, lastErr) } +func deleteAlertChannelWithRetry(t *testing.T, client *linodego.Client, channelID int) { + t.Helper() + if channelID == 0 { + return + } + + maxWait := 2 * time.Minute + baseDelay := 2 * time.Second + var err error + start := time.Now() + + for attempt := 0; time.Since(start) < maxWait; attempt++ { + err = client.DeleteAlertChannel(context.Background(), channelID) + if err == nil { + break + } + sleep := baseDelay * (1 << attempt) + if sleep > 30*time.Second { + sleep = 30 * time.Second + } + time.Sleep(sleep) + } + + assert.NoError(t, err, "DeleteAlertChannel failed after retries for channel ID %d: %v", channelID, err) +} + func TestMonitorAlertDefinition_smoke(t *testing.T) { ctx := waitContext(t, 300*time.Second) @@ -79,31 +105,34 @@ func TestMonitorAlertDefinition_smoke(t *testing.T) { // Basic assertions based on the fixture assert.NoError(t, err) - // Determine a channel ID to use for creating a new alert definition: - var channelID int - var fetchedChannelLabel string - var fetchedChannelID int - if len(alerts) > 0 && len(alerts[0].AlertChannels) > 0 { - channelID = alerts[0].AlertChannels[0].ID - fetchedChannelID = alerts[0].AlertChannels[0].ID - fetchedChannelLabel = alerts[0].AlertChannels[0].Label - } else { - // Fallback to ListAlertChannels to get available channels - channels, err := client.ListAlertChannels(context.Background(), nil) - if err != nil || len(channels) == 0 { - t.Fatalf("failed to determine a monitor channel to use: %s", err) - } - channelID = channels[0].ID - fetchedChannelID = channels[0].ID - fetchedChannelLabel = channels[0].Label + // Create an alert channel to use for creating a new alert definition + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := fmt.Sprintf("linodego-alert-channel-%d", time.Now().UnixNano()) + recipientType := "user" + createChannelOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, } - // Validate the chosen channel - assert.NotZero(t, fetchedChannelID, "fetchedChannel.ID should not be zero") - assert.NotEmpty(t, fetchedChannelLabel, "fetchedChannel.Label should not be empty") + + ch, err := client.CreateAlertChannel(context.Background(), createChannelOpts) + if err != nil { + t.Fatalf("failed to create alert channel: %v", err) + } + defer deleteAlertChannelWithRetry(t, client, ch.ID) + + channelID := ch.ID // Test creating a new Monitor Alert Definition createOpts := linodego.AlertDefinitionCreateOptions{ - Label: "go-test-alert-definition-create", + Label: fmt.Sprintf("linodego-alert-%d", time.Now().UnixNano()), Severity: int(linodego.SeverityLow), Description: linodego.Pointer("Test alert definition creation"), ChannelIDs: []int{channelID}, @@ -141,9 +170,16 @@ func TestMonitorAlertDefinition_smoke(t *testing.T) { t.Logf("CreateMonitorAlertDefinition returned error, skipping create assertions: %s", err) return } - assert.NoError(t, err) - assert.NotNil(t, createdAlert) - assert.Equal(t, createOpts.Label, createdAlert.Label) + require.NoError(t, err) + require.NotNil(t, createdAlert) + // ensure cleanup of created alert definition even if later assertions fail + defer func() { + if createdAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, createdAlert.ID) + } + }() + + require.Contains(t, createdAlert.Label, "linodego-alert-") assert.Equal(t, createOpts.Severity, createdAlert.Severity) assert.Equal(t, *createOpts.Description, createdAlert.Description) assert.NotNil(t, createdAlert.GroupBy) @@ -207,10 +243,7 @@ func TestMonitorAlertDefinition_smoke(t *testing.T) { assert.NotNil(t, updatedAlert.GroupBy) } - // Clean up created alert definition - if createdAlert != nil { - deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, createdAlert.ID) - } + // Cleanup handled by deferred cleanup above } func TestMonitorAlertDefinitions_List(t *testing.T) { @@ -252,12 +285,30 @@ func TestMonitorAlertDefinition_CreateWithIdempotency(t *testing.T) { client, teardown := createTestClient(t, "fixtures/TestMonitorAlertDefinition_CreateWithIdempotency") defer teardown() - // Get a channel ID to use - channels, err := client.ListAlertChannels(context.Background(), nil) - if err != nil || len(channels) == 0 { - t.Fatalf("failed to determine a monitor channel to use: %s", err) + // Create alert channel to use for this test + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := fmt.Sprintf("linodego-alert-channel-%d", time.Now().UnixNano()) + recipientType := "user" + createChannelOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, + } + + ch, err := client.CreateAlertChannel(context.Background(), createChannelOpts) + if err != nil { + t.Fatalf("failed to create alert channel: %v", err) } - channelID := channels[0].ID + defer deleteAlertChannelWithRetry(t, client, ch.ID) + + channelID := ch.ID uniqueLabel := fmt.Sprintf("go-test-alert-definition-idempotency-%d", time.Now().UnixNano()) @@ -307,8 +358,14 @@ func TestMonitorAlertDefinition_CreateWithIdempotency(t *testing.T) { createdAlert, err = client.CreateMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createOpts) } } - assert.NoError(t, err) - assert.NotNil(t, createdAlert) + require.NoError(t, err) + require.NotNil(t, createdAlert) + // ensure cleanup of created alert definition + defer func() { + if createdAlert != nil { + _ = client.DeleteMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createdAlert.ID) + } + }() // Attempt to create the same alert definition again to test idempotency // Expected to return Error as per the API behavior @@ -316,10 +373,7 @@ func TestMonitorAlertDefinition_CreateWithIdempotency(t *testing.T) { assert.Error(t, err) assert.Contains(t, err.Error(), "An alert with this label already exists") - // Cleanup - if createdAlert != nil { - _ = client.DeleteMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createdAlert.ID) - } + // Cleanup handled by deferred cleanup above } func TestMonitorAlertDefinitionEntities_List(t *testing.T) { @@ -354,11 +408,30 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { client, teardown := createTestClient(t, "fixtures/TestMonitorAlertDefinition_Clone") defer teardown() - // Get a channel ID to use - channels, err := client.ListAlertChannels(context.Background(), nil) - require.NoErrorf(t, err, "failed to determine a monitor channel to use: %v", err) - require.NotEmpty(t, channels, "no alert channels available to use for cloning test") - testChannelID := channels[0].ID + // Create alert channel to use for cloning + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := fmt.Sprintf("linodego-alert-channel-%d", time.Now().UnixNano()) + recipientType := "user" + createChannelOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, + } + + ch, err := client.CreateAlertChannel(context.Background(), createChannelOpts) + if err != nil { + t.Fatalf("failed to create alert channel: %v", err) + } + defer deleteAlertChannelWithRetry(t, client, ch.ID) + + testChannelID := ch.ID // Create the source alert definition createOpts := linodego.AlertDefinitionCreateOptions{ @@ -395,7 +468,17 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { sourceAlert, err := client.CreateMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createOpts) require.NoErrorf(t, err, "CreateMonitorAlertDefinition failed: %s", err) - assert.NotNil(t, sourceAlert) + require.NotNil(t, sourceAlert) + // ensure cleanup of source and cloned alerts + var clonedAlert *linodego.AlertDefinition + defer func() { + if sourceAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, sourceAlert.ID) + } + if clonedAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, clonedAlert.ID) + } + }() assert.Equal(t, createOpts.Label, sourceAlert.Label) assert.NotNil(t, sourceAlert.GroupBy) @@ -424,13 +507,11 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { }, } - clonedAlert, err := client.CloneMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, sourceAlert.ID, cloneOpts) + clonedAlert, err = client.CloneMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, sourceAlert.ID, cloneOpts) if err != nil { - // Cleanup source before failing - _ = client.DeleteMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, sourceAlert.ID) t.Fatalf("CloneMonitorAlertDefinition failed: %s", err) } - assert.NotNil(t, clonedAlert) + require.NotNil(t, clonedAlert) assert.NotEqual(t, sourceAlert.ID, clonedAlert.ID, "cloned alert should have a different ID") assert.Equal(t, cloneLabel, clonedAlert.Label, "cloned alert should have the specified label") assert.Equal(t, *cloneOpts.Description, clonedAlert.Description, "cloned alert should have the overridden description") @@ -441,21 +522,16 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { assert.Equal(t, cloneOpts.TriggerConditions.PollingIntervalSeconds, clonedAlert.TriggerConditions.PollingIntervalSeconds) assert.Equal(t, cloneOpts.TriggerConditions.TriggerOccurrences, clonedAlert.TriggerConditions.TriggerOccurrences) - // Cleanup both source and cloned alert definitions - for _, alertID := range []int{sourceAlert.ID, clonedAlert.ID} { - deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, alertID) - } + // Cleanup handled by deferred cleanup above } func TestMonitorAlertChannel_CRUD_E2E(t *testing.T) { - client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_Create") + client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_CRUD") defer teardown() // Get valid users to use for the email alert channel users, err := client.ListUsers(context.Background(), nil) - if err != nil { - t.Fatalf("Error listing users: %v", err) - } + require.NoErrorf(t, err, "failed to list users: %v", err) label := "linodego-sdk-test-alert-channel" recipientType := "user" @@ -538,3 +614,80 @@ func TestMonitorAlertChannel_CRUD_E2E(t *testing.T) { require.NotNil(t, updatedChannel.Details.Email) assert.Equal(t, createOpts.Details.Email.Usernames, updatedChannel.Details.Email.Usernames) } + +func TestMonitorAlertChannel_ListAlerts(t *testing.T) { + client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_ListAlerts") + defer teardown() + + // Create an alert channel + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := "linodego-sdk-test-alert-channel-listalerts" + recipientType := "user" + + createOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, + } + + channel, err := client.CreateAlertChannel(context.Background(), createOpts) + require.NoErrorf(t, err, "failed to create alert channel: %v", err) + require.NotNil(t, channel, "created channel is nil") + + // ensure cleanup + var createdAlert *linodego.AlertDefinition + defer func() { + if createdAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, createdAlert.ID) + } + deleteAlertChannelWithRetry(t, client, channel.ID) + }() + + // Create an alert definition attached to the created channel + serviceType := "dbaas" + createAlertOpts := linodego.AlertDefinitionCreateOptions{ + Label: "go-integration-test-alert", + Severity: int(linodego.SeverityLow), + ChannelIDs: []int{channel.ID}, + TriggerConditions: &linodego.TriggerConditions{ + CriteriaCondition: string(linodego.CriteriaConditionAll), + EvaluationPeriodSeconds: 300, + PollingIntervalSeconds: 300, + TriggerOccurrences: 1, + }, + RuleCriteria: &linodego.RuleCriteriaOptions{ + Rules: []linodego.RuleOptions{ + { + AggregateFunction: "avg", + Metric: "memory_usage", + Operator: "gt", + Threshold: 90.0, + }, + }, + }, + } + + createdAlert, err = client.CreateMonitorAlertDefinition(context.Background(), serviceType, createAlertOpts) + require.NoErrorf(t, err, "failed to create monitor alert definition: %v", err) + require.NotNil(t, createdAlert) + + // List alerts for the channel and verify at least one alert is attached + alerts, err := client.ListAlertsForChannel(context.Background(), channel.ID, nil) + require.NoErrorf(t, err, "failed to list alerts for channel: %v", err) + require.NotEmpty(t, alerts, "expected at least one alert for channel %d", channel.ID) + + // Assert fields on the first alert + a := alerts[0] + assert.NotZero(t, a.ID, "alert.ID should not be zero") + assert.NotEmpty(t, a.Label, "alert.Label should not be empty") + assert.NotEmpty(t, a.ServiceType, "alert.ServiceType should not be empty") + assert.NotEmpty(t, a.Type, "alert.Type should not be empty") + assert.NotEmpty(t, a.URL, "alert.URL should not be empty") +} From f1cdcf4181d6c188b832b5b4f47458885b09d511 Mon Sep 17 00:00:00 2001 From: shkaruna Date: Thu, 16 Jul 2026 23:11:24 +0530 Subject: [PATCH 5/5] ref: updated aclp integration tests --- .../TestMonitorAlertChannel_CRUD.yaml | 30 +- .../TestMonitorAlertChannel_ListAlerts.yaml | 413 ++++++++++++++++++ .../fixtures/TestMonitorAlertDefinition.yaml | 274 ++++++++++-- .../TestMonitorAlertDefinition_Clone.yaml | 230 +++++++--- ...AlertDefinition_CreateWithIdempotency.yaml | 181 ++++++-- test/integration/monitor_alerts_test.go | 272 +++++++++--- 6 files changed, 1201 insertions(+), 199 deletions(-) create mode 100644 test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml diff --git a/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml b/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml index 1a838382c..bbe8b5d45 100644 --- a/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml +++ b/test/integration/fixtures/TestMonitorAlertChannel_CRUD.yaml @@ -45,7 +45,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:05 GMT + - Thu, 16 Jul 2026 17:23:56 GMT Pragma: - no-cache Strict-Transport-Security: @@ -86,9 +86,9 @@ interactions: url: https://api.linode.com/v4beta/monitor/alert-channels method: POST response: - body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel", "channel_type": - "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", + body: '{"id": 10310, "label": "linodego-sdk-test-alert-channel", + "channel_type":"email", "type":"user", "details": {"email": {"usernames": ["test_user1", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10310/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": "tester"}' @@ -116,7 +116,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:06 GMT + - Thu, 16 Jul 2026 17:23:57 GMT Pragma: - no-cache Strict-Transport-Security: @@ -152,12 +152,12 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10304 + url: https://api.linode.com/v4beta/monitor/alert-channels/10310 method: GET response: - body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel", "channel_type": + body: '{"id": 10310, "label": "linodego-sdk-test-alert-channel", "channel_type": "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10310/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": "tester"}' @@ -185,7 +185,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:07 GMT + - Thu, 16 Jul 2026 17:23:58 GMT Pragma: - no-cache Strict-Transport-Security: @@ -222,12 +222,12 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10304 + url: https://api.linode.com/v4beta/monitor/alert-channels/10310 method: PUT response: - body: '{"id": 10304, "label": "linodego-sdk-test-alert-channel-updated", "channel_type": + body: '{"id": 10310, "label": "linodego-sdk-test-alert-channel-updated", "channel_type": "email", "type": "user", "details": {"email": {"usernames": ["test_user1", - "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10304/alerts", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10310/alerts", "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": "tester"}' @@ -255,7 +255,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:09 GMT + - Thu, 16 Jul 2026 17:23:59 GMT Pragma: - no-cache Strict-Transport-Security: @@ -291,7 +291,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels/10304 + url: https://api.linode.com/v4beta/monitor/alert-channels/10310 method: DELETE response: body: '{}' @@ -319,7 +319,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 16 Jul 2026 07:16:12 GMT + - Thu, 16 Jul 2026 17:24:02 GMT Pragma: - no-cache Strict-Transport-Security: diff --git a/test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml b/test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml new file mode 100644 index 000000000..a8e6ef789 --- /dev/null +++ b/test/integration/fixtures/TestMonitorAlertChannel_ListAlerts.yaml @@ -0,0 +1,413 @@ +--- +version: 1 +interactions: +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/account/users?page=1 + method: GET + response: + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:34 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - account:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-sdk-test-alert-channel-listalerts"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id": 10309, "label": "linodego-sdk-test-alert-channel-listalerts", "channel_type": + "email", "type": "user", "details": {"email": {"usernames": ["test_user1", + "test_user2"], "recipient_type": "user"}}, "alerts": {"url": "/monitor/alert-channels/10309/alerts", + "type": "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", + "updated": "2018-01-02T03:04:05", "created_by": "tester", "updated_by": + "tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:35 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"label":"go-integration-test-alert","severity":2,"channel_ids":[10309],"rule_criteria":{"rules":[{"aggregate_function":"avg","metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1}}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions + method: POST + response: + body: '{"id": 11632, "label": "go-integration-test-alert", "description": null, + "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": + [], "status": "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": + "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": + "avg", "operator": "gt", "threshold": 90, "dimension_filters": []}]}, "alert_channels": + [{"id": 10309, "label": "linodego-sdk-test-alert-channel-listalerts", "url": + "/monitor/alert-channels/10309", "type": "alert-channels"}], "trigger_conditions": + {"criteria_condition": "ALL", "polling_interval_seconds": 300, "evaluation_period_seconds": + 300, "trigger_occurrences": 1}, "created": "2018-01-02T03:04:05", "updated": + "2018-01-02T03:04:05", "created_by": "tester", "updated_by": + "tester", "group_by": ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11632/entities", + "has_more_resources": false, "count": 0}}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:36 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - databases:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10309/alerts?page=1 + method: GET + response: + body: '{"pages": 1, "page": 1, "results": 1, "data": [{"id": 11632, "label": "go-integration-test-alert", + "url": "/monitor/services/dbaas/alerts-definitions/11632", "type": "alerts-definitions", + "service_type": "dbaas"}]}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "214" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:36 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11632 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:38 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - databases:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10309 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 17:19:38 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/fixtures/TestMonitorAlertDefinition.yaml b/test/integration/fixtures/TestMonitorAlertDefinition.yaml index f93859117..e4312db6f 100644 --- a/test/integration/fixtures/TestMonitorAlertDefinition.yaml +++ b/test/integration/fixtures/TestMonitorAlertDefinition.yaml @@ -61,7 +61,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:16 GMT + - Thu, 16 Jul 2026 18:18:45 GMT Pragma: - no-cache Strict-Transport-Security: @@ -90,7 +90,143 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-create","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/account/users?page=1 + method: GET + response: + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:18:45 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + - Authorization, X-Filter + - Accept-Encoding + X-Accepted-Oauth-Scopes: + - account:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-alert-channel-1784225925966684533"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id":10315,"label":"linodego-alert-channel-1784225926985434344","channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"alerts":{"url":"/monitor/alert-channels/10315/alerts","type":"alerts-definitions","alert_count":0},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:18:46 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"label":"linodego-alert-1784225926985434344","severity":2,"channel_ids":[10315],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation","group_by":["entity_id"]}' form: {} headers: @@ -103,20 +239,20 @@ interactions: url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions method: POST response: - body: '{"id": 11230, "label": "go-test-alert-definition-create", "description": + body: '{"id": 11638, "label": "linodego-alert-1784225926985434344", "description": "Test alert definition creation", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11230/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10315, + "label": "linodego-alert-channel-1784225925966684533", "url": "/monitor/alert-channels/10315", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11638/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -139,7 +275,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:17 GMT + - Thu, 16 Jul 2026 18:18:48 GMT Pragma: - no-cache Strict-Transport-Security: @@ -176,23 +312,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11230 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11638 method: GET response: - body: '{"id": 11230, "label": "go-test-alert-definition-create", "description": + body: '{"id": 11638, "label": "linodego-alert-1784225926985434344", "description": "Test alert definition creation", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "enabled", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11230/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10315, + "label": "linodego-alert-channel-1784225925966684533", "url": "/monitor/alert-channels/10315", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11638/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -215,7 +351,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:33 GMT + - Thu, 16 Jul 2026 18:19:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -244,7 +380,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-create-updated","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: '{"label":"linodego-alert-1784225926985434344-updated","severity":2,"channel_ids":[10315],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation"}' form: {} headers: @@ -254,23 +390,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11230 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11638 method: PUT response: - body: '{"id": 11230, "label": "go-test-alert-definition-create-updated", "description": + body: '{"id": 11638, "label": "linodego-alert-1784225926985434344-updated", "description": "Test alert definition creation", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "enabled", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11230/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10315, + "label": "linodego-alert-channel-1784225925966684533", "url": "/monitor/alert-channels/10315", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11638/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -293,7 +429,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:35 GMT + - Thu, 16 Jul 2026 18:19:06 GMT Pragma: - no-cache Strict-Transport-Security: @@ -330,7 +466,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11230 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11638 method: DELETE response: body: '{}' @@ -358,7 +494,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:41:36 GMT + - Thu, 16 Jul 2026 18:19:06 GMT Pragma: - no-cache Strict-Transport-Security: @@ -384,3 +520,67 @@ interactions: status: 200 OK code: 200 duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10315 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:19:07 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml b/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml index 61bed1a88..ad6d700fd 100644 --- a/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml +++ b/test/integration/fixtures/TestMonitorAlertDefinition_Clone.yaml @@ -11,20 +11,18 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels?page=1 + url: https://api.linode.com/v4beta/account/users?page=1 method: GET response: - body: '{"pages": 1, "page": 1, "results": 2, "data": [{"id": 10000, "label": "Read-Write - Channel", "channel_type": "email", "type": "system", "details": {"email": {"usernames": - [], "recipient_type": "read_write_users"}}, "alerts": {"url": "/monitor/alert-channels/10000/alerts", - "type": "alerts-definitions", "alert_count": 9}, "created": "2018-01-02T03:04:05", - "updated": "2018-01-02T03:04:05", "created_by": "system", "updated_by": "system"}, - {"id": 10118, "label": "notification channel", "channel_type": "email", "type": "user", - "details": {"email": {"usernames": ["tester"], "recipient_type": - "user"}}, "alerts": {"url": "/monitor/alert-channels/10118/alerts", "type": - "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": - "2018-01-02T03:04:05", "created_by": "tester", "updated_by": - "tester"}]}' + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' headers: Access-Control-Allow-Credentials: - "true" @@ -47,7 +45,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:31 GMT + - Thu, 16 Jul 2026 18:21:01 GMT Pragma: - no-cache Strict-Transport-Security: @@ -57,7 +55,71 @@ interactions: - Authorization, X-Filter - Accept-Encoding X-Accepted-Oauth-Scopes: - - monitor:read_only + - account:read_only + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-alert-channel-1784226061531360907"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id":10317,"label":"linodego-alert-channel-1784226061531360907","channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"alerts":{"url":"/monitor/alert-channels/10317/alerts","type":"alerts-definitions","alert_count":0},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:21:02 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write X-Content-Type-Options: - nosniff X-Frame-Options: @@ -76,7 +138,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-clone-source","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Source + body: '{"label":"go-test-alert-definition-clone-source","severity":2,"channel_ids":[10317],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Source alert definition for clone test","group_by":["entity_id"]}' form: {} headers: @@ -89,20 +151,20 @@ interactions: url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions method: POST response: - body: '{"id": 11228, "label": "go-test-alert-definition-clone-source", "description": + body: '{"id": 11640, "label": "go-test-alert-definition-clone-source", "description": "Source alert definition for clone test", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11228/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10317, + "label": "linodego-alert-channel-1784226061531360907", "url": "/monitor/alert-channels/10317", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11640/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -125,7 +187,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:32 GMT + - Thu, 16 Jul 2026 18:21:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -162,23 +224,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11228 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11640 method: GET response: - body: '{"id": 11228, "label": "go-test-alert-definition-clone-source", "description": + body: '{"id": 11640, "label": "go-test-alert-definition-clone-source", "description": "Source alert definition for clone test", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "enabled", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 300, "trigger_occurrences": 1}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11228/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10317, + "label": "linodego-alert-channel-1784226061531360907", "url": "/monitor/alert-channels/10317", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": + 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11640/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -201,7 +263,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:48 GMT + - Thu, 16 Jul 2026 18:21:20 GMT Pragma: - no-cache Strict-Transport-Security: @@ -230,7 +292,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-clone-source-clone","severity":1,"channel_ids":[10000],"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":900,"polling_interval_seconds":300,"trigger_occurrences":3},"description":"Cloned + body: '{"label":"go-test-alert-definition-clone-source-clone","severity":1,"channel_ids":[10317],"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":900,"polling_interval_seconds":300,"trigger_occurrences":3},"description":"Cloned alert definition"}' form: {} headers: @@ -240,23 +302,23 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11228/clone + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11640/clone method: POST response: - body: '{"id": 11229, "label": "go-test-alert-definition-clone-source-clone", "description": + body: '{"id": 11641, "label": "go-test-alert-definition-clone-source-clone", "description": "Cloned alert definition", "service_type": "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": "provisioning", "severity": 1, "rule_criteria": {"rules": [{"label": "Memory Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", "dimension_label": "node_type", - "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10000, - "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", "type": - "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", "polling_interval_seconds": - 300, "evaluation_period_seconds": 900, "trigger_occurrences": 3}, "created": - "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": "tester", - "updated_by": "tester", "group_by": ["entity_id"], "entities": - {"url": "/monitor/services/dbaas/alert-definitions/11229/entities", "has_more_resources": - false, "count": 0}}' + "operator": "eq", "value": "primary"}]}]}, "alert_channels": [{"id": 10317, + "label": "linodego-alert-channel-1784226061531360907", "url": "/monitor/alert-channels/10317", + "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", + "polling_interval_seconds": 300, "evaluation_period_seconds": 900, "trigger_occurrences": + 3}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": + "tester", "updated_by": "tester", "group_by": + ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11641/entities", + "has_more_resources": false, "count": 0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -279,7 +341,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:50 GMT + - Thu, 16 Jul 2026 18:21:22 GMT Pragma: - no-cache Strict-Transport-Security: @@ -316,7 +378,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11228 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11640 method: DELETE response: body: '{}' @@ -344,7 +406,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:51 GMT + - Thu, 16 Jul 2026 18:21:22 GMT Pragma: - no-cache Strict-Transport-Security: @@ -380,7 +442,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11229 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11641 method: DELETE response: body: '{}' @@ -408,7 +470,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 10:36:52 GMT + - Thu, 16 Jul 2026 18:21:23 GMT Pragma: - no-cache Strict-Transport-Security: @@ -434,3 +496,67 @@ interactions: status: 200 OK code: 200 duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10317 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:21:24 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml b/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml index 82983afec..39b92c00c 100644 --- a/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml +++ b/test/integration/fixtures/TestMonitorAlertDefinition_CreateWithIdempotency.yaml @@ -11,20 +11,18 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/alert-channels?page=1 + url: https://api.linode.com/v4beta/account/users?page=1 method: GET response: - body: '{"pages": 1, "page": 1, "results": 2, "data": [{"id": 10000, "label": "Read-Write - Channel", "channel_type": "email", "type": "system", "details": {"email": {"usernames": - [], "recipient_type": "read_write_users"}}, "alerts": {"url": "/monitor/alert-channels/10000/alerts", - "type": "alerts-definitions", "alert_count": 9}, "created": "2018-01-02T03:04:05", - "updated": "2018-01-02T03:04:05", "created_by": "system", "updated_by": "system"}, - {"id": 10118, "label": "notification channel", "channel_type": "email", "type": "user", - "details": {"email": {"usernames": ["tester"], "recipient_type": - "user"}}, "alerts": {"url": "/monitor/alert-channels/10118/alerts", "type": - "alerts-definitions", "alert_count": 0}, "created": "2018-01-02T03:04:05", "updated": - "2018-01-02T03:04:05", "created_by": "tester", "updated_by": - "tester"}]}' + body: '{"data": [{"username": "test_user1", "email": "test_user1@example.com", + "restricted": false, "ssh_keys": [], "tfa_enabled": true, "verified_phone_number": + "+19895154186", "password_created": "2018-01-02T03:04:05", "last_login": {"login_datetime": + "2018-01-02T03:04:05", "status": "successful"}, "user_type": "default"}, {"username": + "test_user2", "email": "test_user2@example.com", "restricted": false, + "ssh_keys": ["key1", "key2", "key3", "key4", "key5"], "tfa_enabled": + true, "verified_phone_number": "+19895154187", "password_created": "2018-01-02T03:04:05", + "last_login": {"login_datetime": "2018-01-02T03:04:05", "status": "successful"}, + "user_type": "default"}], "page": 1, "pages": 1, "results": 2}' headers: Access-Control-Allow-Credentials: - "true" @@ -47,7 +45,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:32 GMT + - Thu, 16 Jul 2026 18:20:01 GMT Pragma: - no-cache Strict-Transport-Security: @@ -57,7 +55,7 @@ interactions: - Authorization, X-Filter - Accept-Encoding X-Accepted-Oauth-Scopes: - - monitor:read_only + - account:read_only X-Content-Type-Options: - nosniff X-Frame-Options: @@ -76,7 +74,71 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-idempotency-1780593452875420575","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: '{"channel_type":"email","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"label":"linodego-alert-channel-1784226001847126351"}' + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels + method: POST + response: + body: '{"id":10316,"label":"linodego-alert-channel-1784226001847126351","channel_type":"email","type":"user","details":{"email":{"usernames":["test_user1","test_user2"],"recipient_type":"user"}},"alerts":{"url":"/monitor/alert-channels/10316/alerts","type":"alerts-definitions","alert_count":0},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester"}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "481" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:20:02 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" +- request: + body: '{"label":"go-test-alert-definition-idempotency-1784226002893832314","severity":2,"channel_ids":[10316],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation with idempotency"}' form: {} headers: @@ -89,20 +151,7 @@ interactions: url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions method: POST response: - body: '{"id": 11234, "label": "go-test-alert-definition-idempotency-1780593452875420575", - "description": "Test alert definition creation with idempotency", "service_type": - "dbaas", "type": "user", "scope": "entity", "class": null, "regions": [], "status": - "provisioning", "severity": 2, "rule_criteria": {"rules": [{"label": "Memory - Usage", "metric": "memory_usage", "unit": "percent", "aggregate_function": "avg", - "operator": "gt", "threshold": 90, "dimension_filters": [{"label": "Node Type", - "dimension_label": "node_type", "operator": "eq", "value": "primary"}]}]}, "alert_channels": - [{"id": 10000, "label": "Read-Write Channel", "url": "/monitor/alert-channels/10000", - "type": "alert-channels"}], "trigger_conditions": {"criteria_condition": "ALL", - "polling_interval_seconds": 300, "evaluation_period_seconds": 300, "trigger_occurrences": - 1}, "created": "2018-01-02T03:04:05", "updated": "2018-01-02T03:04:05", "created_by": - "tester", "updated_by": "tester", "group_by": - ["entity_id"], "entities": {"url": "/monitor/services/dbaas/alert-definitions/11234/entities", - "has_more_resources": false, "count": 0}}' + body: '{"id":11639,"label":"go-test-alert-definition-idempotency-1784226002893832314","description":"Test alert definition creation with idempotency","service_type":"dbaas","type":"user","scope":"entity","class":null,"regions":[],"status":"provisioning","severity":2,"rule_criteria":{"rules":[{"label":"Memory Usage","metric":"memory_usage","unit":"percent","aggregate_function":"avg","operator":"gt","threshold":90,"dimension_filters":[{"label":"Node Type","dimension_label":"node_type","operator":"eq","value":"primary"}]}]},"alert_channels":[{"id":10316,"label":"linodego-alert-channel-1784226001847126351","url":"/monitor/alert-channels/10316","type":"alert-channels"}],"trigger_conditions":{"criteria_condition":"ALL","polling_interval_seconds":300,"evaluation_period_seconds":300,"trigger_occurrences":1},"created":"2018-01-02T03:04:05","updated":"2018-01-02T03:04:05","created_by":"tester","updated_by":"tester","group_by":["entity_id"],"entities":{"url":"/monitor/services/dbaas/alert-definitions/11639/entities","has_more_resources":false,"count":0}}' headers: Access-Control-Allow-Credentials: - "true" @@ -125,7 +174,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:34 GMT + - Thu, 16 Jul 2026 18:20:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -153,7 +202,7 @@ interactions: code: 200 duration: "" - request: - body: '{"label":"go-test-alert-definition-idempotency-1780593452875420575","severity":2,"channel_ids":[10000],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test + body: '{"label":"go-test-alert-definition-idempotency-1784226002893832314","severity":2,"channel_ids":[10316],"rule_criteria":{"rules":[{"aggregate_function":"avg","dimension_filters":[{"dimension_label":"node_type","operator":"eq","value":"primary"}],"metric":"memory_usage","operator":"gt","threshold":90}]},"trigger_conditions":{"criteria_condition":"ALL","evaluation_period_seconds":300,"polling_interval_seconds":300,"trigger_occurrences":1},"description":"Test alert definition creation with idempotency"}' form: {} headers: @@ -184,7 +233,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:34 GMT + - Thu, 16 Jul 2026 18:20:04 GMT Pragma: - no-cache Strict-Transport-Security: @@ -213,7 +262,7 @@ interactions: - application/json User-Agent: - linodego/dev https://github.com/linode/linodego - url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11234 + url: https://api.linode.com/v4beta/monitor/services/dbaas/alert-definitions/11639 method: DELETE response: body: '{}' @@ -241,7 +290,7 @@ interactions: Content-Type: - application/json Expires: - - Thu, 04 Jun 2026 17:17:35 GMT + - Thu, 16 Jul 2026 18:20:05 GMT Pragma: - no-cache Strict-Transport-Security: @@ -267,3 +316,67 @@ interactions: status: 200 OK code: 200 duration: "" +- request: + body: "" + form: {} + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - linodego/dev https://github.com/linode/linodego + url: https://api.linode.com/v4beta/monitor/alert-channels/10316 + method: DELETE + response: + body: '{}' + headers: + Access-Control-Allow-Credentials: + - "true" + Access-Control-Allow-Headers: + - Authorization, Origin, X-Requested-With, Content-Type, Accept, X-Filter + Access-Control-Allow-Methods: + - HEAD, GET, OPTIONS, POST, PUT, DELETE + Access-Control-Allow-Origin: + - '*' + Access-Control-Expose-Headers: + - X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status + Akamai-Internal-Account: + - '*' + Cache-Control: + - max-age=0, no-cache, no-store + Connection: + - keep-alive + Content-Length: + - "2" + Content-Security-Policy: + - default-src 'none' + Content-Type: + - application/json + Expires: + - Thu, 16 Jul 2026 18:20:06 GMT + Pragma: + - no-cache + Strict-Transport-Security: + - max-age=31536000 + Vary: + - Authorization, X-Filter + X-Accepted-Oauth-Scopes: + - monitor:read_write + X-Content-Type-Options: + - nosniff + X-Frame-Options: + - DENY + - DENY + X-Oauth-Scopes: + - account:read_only databases:read_only domains:read_only events:read_only firewall:read_only + images:read_only ips:read_only linodes:read_only lke:read_only longview:read_only + monitor:read_write nodebalancers:read_only object_storage:read_only stackscripts:read_only + volumes:read_only + X-Ratelimit-Limit: + - "1840" + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/test/integration/monitor_alerts_test.go b/test/integration/monitor_alerts_test.go index 39cfb1057..7abd5ee90 100644 --- a/test/integration/monitor_alerts_test.go +++ b/test/integration/monitor_alerts_test.go @@ -46,6 +46,32 @@ func deleteMonitorAlertDefinitionWithRetry(t *testing.T, client *linodego.Client assert.NoError(t, err, "DeleteMonitorAlertDefinition failed after retries for alert ID %d: %v", alertID, lastErr) } +func deleteAlertChannelWithRetry(t *testing.T, client *linodego.Client, channelID int) { + t.Helper() + if channelID == 0 { + return + } + + maxWait := 2 * time.Minute + baseDelay := 2 * time.Second + var err error + start := time.Now() + + for attempt := 0; time.Since(start) < maxWait; attempt++ { + err = client.DeleteAlertChannel(context.Background(), channelID) + if err == nil { + break + } + sleep := baseDelay * (1 << attempt) + if sleep > 30*time.Second { + sleep = 30 * time.Second + } + time.Sleep(sleep) + } + + assert.NoError(t, err, "DeleteAlertChannel failed after retries for channel ID %d: %v", channelID, err) +} + func TestMonitorAlertDefinition_smoke(t *testing.T) { ctx := waitContext(t, 300*time.Second) @@ -79,31 +105,34 @@ func TestMonitorAlertDefinition_smoke(t *testing.T) { // Basic assertions based on the fixture assert.NoError(t, err) - // Determine a channel ID to use for creating a new alert definition: - var channelID int - var fetchedChannelLabel string - var fetchedChannelID int - if len(alerts) > 0 && len(alerts[0].AlertChannels) > 0 { - channelID = alerts[0].AlertChannels[0].ID - fetchedChannelID = alerts[0].AlertChannels[0].ID - fetchedChannelLabel = alerts[0].AlertChannels[0].Label - } else { - // Fallback to ListAlertChannels to get available channels - channels, err := client.ListAlertChannels(context.Background(), nil) - if err != nil || len(channels) == 0 { - t.Fatalf("failed to determine a monitor channel to use: %s", err) - } - channelID = channels[0].ID - fetchedChannelID = channels[0].ID - fetchedChannelLabel = channels[0].Label + // Create an alert channel to use for creating a new alert definition + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := fmt.Sprintf("linodego-alert-channel-%d", time.Now().UnixNano()) + recipientType := "user" + createChannelOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, } - // Validate the chosen channel - assert.NotZero(t, fetchedChannelID, "fetchedChannel.ID should not be zero") - assert.NotEmpty(t, fetchedChannelLabel, "fetchedChannel.Label should not be empty") + + ch, err := client.CreateAlertChannel(context.Background(), createChannelOpts) + if err != nil { + t.Fatalf("failed to create alert channel: %v", err) + } + defer deleteAlertChannelWithRetry(t, client, ch.ID) + + channelID := ch.ID // Test creating a new Monitor Alert Definition createOpts := linodego.AlertDefinitionCreateOptions{ - Label: "go-test-alert-definition-create", + Label: fmt.Sprintf("linodego-alert-%d", time.Now().UnixNano()), Severity: int(linodego.SeverityLow), Description: linodego.Pointer("Test alert definition creation"), ChannelIDs: []int{channelID}, @@ -141,9 +170,16 @@ func TestMonitorAlertDefinition_smoke(t *testing.T) { t.Logf("CreateMonitorAlertDefinition returned error, skipping create assertions: %s", err) return } - assert.NoError(t, err) - assert.NotNil(t, createdAlert) - assert.Equal(t, createOpts.Label, createdAlert.Label) + require.NoError(t, err) + require.NotNil(t, createdAlert) + // ensure cleanup of created alert definition even if later assertions fail + defer func() { + if createdAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, createdAlert.ID) + } + }() + + require.Contains(t, createdAlert.Label, "linodego-alert-") assert.Equal(t, createOpts.Severity, createdAlert.Severity) assert.Equal(t, *createOpts.Description, createdAlert.Description) assert.NotNil(t, createdAlert.GroupBy) @@ -207,10 +243,7 @@ func TestMonitorAlertDefinition_smoke(t *testing.T) { assert.NotNil(t, updatedAlert.GroupBy) } - // Clean up created alert definition - if createdAlert != nil { - deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, createdAlert.ID) - } + // Cleanup handled by deferred cleanup above } func TestMonitorAlertDefinitions_List(t *testing.T) { @@ -252,12 +285,30 @@ func TestMonitorAlertDefinition_CreateWithIdempotency(t *testing.T) { client, teardown := createTestClient(t, "fixtures/TestMonitorAlertDefinition_CreateWithIdempotency") defer teardown() - // Get a channel ID to use - channels, err := client.ListAlertChannels(context.Background(), nil) - if err != nil || len(channels) == 0 { - t.Fatalf("failed to determine a monitor channel to use: %s", err) + // Create alert channel to use for this test + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := fmt.Sprintf("linodego-alert-channel-%d", time.Now().UnixNano()) + recipientType := "user" + createChannelOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, } - channelID := channels[0].ID + + ch, err := client.CreateAlertChannel(context.Background(), createChannelOpts) + if err != nil { + t.Fatalf("failed to create alert channel: %v", err) + } + defer deleteAlertChannelWithRetry(t, client, ch.ID) + + channelID := ch.ID uniqueLabel := fmt.Sprintf("go-test-alert-definition-idempotency-%d", time.Now().UnixNano()) @@ -307,8 +358,14 @@ func TestMonitorAlertDefinition_CreateWithIdempotency(t *testing.T) { createdAlert, err = client.CreateMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createOpts) } } - assert.NoError(t, err) - assert.NotNil(t, createdAlert) + require.NoError(t, err) + require.NotNil(t, createdAlert) + // ensure cleanup of created alert definition + defer func() { + if createdAlert != nil { + _ = client.DeleteMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createdAlert.ID) + } + }() // Attempt to create the same alert definition again to test idempotency // Expected to return Error as per the API behavior @@ -316,10 +373,7 @@ func TestMonitorAlertDefinition_CreateWithIdempotency(t *testing.T) { assert.Error(t, err) assert.Contains(t, err.Error(), "An alert with this label already exists") - // Cleanup - if createdAlert != nil { - _ = client.DeleteMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createdAlert.ID) - } + // Cleanup handled by deferred cleanup above } func TestMonitorAlertDefinitionEntities_List(t *testing.T) { @@ -354,11 +408,30 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { client, teardown := createTestClient(t, "fixtures/TestMonitorAlertDefinition_Clone") defer teardown() - // Get a channel ID to use - channels, err := client.ListAlertChannels(context.Background(), nil) - require.NoErrorf(t, err, "failed to determine a monitor channel to use: %v", err) - require.NotEmpty(t, channels, "no alert channels available to use for cloning test") - testChannelID := channels[0].ID + // Create alert channel to use for cloning + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := fmt.Sprintf("linodego-alert-channel-%d", time.Now().UnixNano()) + recipientType := "user" + createChannelOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, + } + + ch, err := client.CreateAlertChannel(context.Background(), createChannelOpts) + if err != nil { + t.Fatalf("failed to create alert channel: %v", err) + } + defer deleteAlertChannelWithRetry(t, client, ch.ID) + + testChannelID := ch.ID // Create the source alert definition createOpts := linodego.AlertDefinitionCreateOptions{ @@ -395,7 +468,17 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { sourceAlert, err := client.CreateMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, createOpts) require.NoErrorf(t, err, "CreateMonitorAlertDefinition failed: %s", err) - assert.NotNil(t, sourceAlert) + require.NotNil(t, sourceAlert) + // ensure cleanup of source and cloned alerts + var clonedAlert *linodego.AlertDefinition + defer func() { + if sourceAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, sourceAlert.ID) + } + if clonedAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, clonedAlert.ID) + } + }() assert.Equal(t, createOpts.Label, sourceAlert.Label) assert.NotNil(t, sourceAlert.GroupBy) @@ -424,13 +507,11 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { }, } - clonedAlert, err := client.CloneMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, sourceAlert.ID, cloneOpts) + clonedAlert, err = client.CloneMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, sourceAlert.ID, cloneOpts) if err != nil { - // Cleanup source before failing - _ = client.DeleteMonitorAlertDefinition(context.Background(), testMonitorAlertDefinitionServiceType, sourceAlert.ID) t.Fatalf("CloneMonitorAlertDefinition failed: %s", err) } - assert.NotNil(t, clonedAlert) + require.NotNil(t, clonedAlert) assert.NotEqual(t, sourceAlert.ID, clonedAlert.ID, "cloned alert should have a different ID") assert.Equal(t, cloneLabel, clonedAlert.Label, "cloned alert should have the specified label") assert.Equal(t, *cloneOpts.Description, clonedAlert.Description, "cloned alert should have the overridden description") @@ -441,21 +522,16 @@ func TestMonitorAlertDefinition_Clone(t *testing.T) { assert.Equal(t, cloneOpts.TriggerConditions.PollingIntervalSeconds, clonedAlert.TriggerConditions.PollingIntervalSeconds) assert.Equal(t, cloneOpts.TriggerConditions.TriggerOccurrences, clonedAlert.TriggerConditions.TriggerOccurrences) - // Cleanup both source and cloned alert definitions - for _, alertID := range []int{sourceAlert.ID, clonedAlert.ID} { - deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, alertID) - } + // Cleanup handled by deferred cleanup above } func TestMonitorAlertChannel_CRUD_E2E(t *testing.T) { - client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_Create") + client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_CRUD") defer teardown() // Get valid users to use for the email alert channel users, err := client.ListUsers(context.Background(), nil) - if err != nil { - t.Fatalf("Error listing users: %v", err) - } + require.NoErrorf(t, err, "failed to list users: %v", err) label := "linodego-sdk-test-alert-channel" recipientType := "user" @@ -479,10 +555,7 @@ func TestMonitorAlertChannel_CRUD_E2E(t *testing.T) { // Delete the created alert channel after the test completes defer func() { if channel != nil { - time.Sleep(2 * time.Second) - if err := client.DeleteAlertChannel(context.Background(), channel.ID); err != nil { - t.Logf("DeleteAlertChannel returned error: %#v", err) - } + deleteAlertChannelWithRetry(t, client, channel.ID) } }() @@ -538,3 +611,80 @@ func TestMonitorAlertChannel_CRUD_E2E(t *testing.T) { require.NotNil(t, updatedChannel.Details.Email) assert.Equal(t, createOpts.Details.Email.Usernames, updatedChannel.Details.Email.Usernames) } + +func TestMonitorAlertChannel_ListAlerts(t *testing.T) { + client, teardown := createTestClient(t, "fixtures/TestMonitorAlertChannel_ListAlerts") + defer teardown() + + // Create an alert channel + users, err := client.ListUsers(context.Background(), nil) + require.NoErrorf(t, err, "failed to list users: %v", err) + + label := "linodego-sdk-test-alert-channel-listalerts" + recipientType := "user" + + createOpts := linodego.AlertChannelCreateOptions{ + ChannelType: linodego.EmailAlertNotification, + Label: &label, + Details: linodego.AlertChannelDetailsOptions{ + Email: &linodego.EmailChannelCreateOptions{ + Usernames: []string{users[0].Username, users[1].Username}, + RecipientType: &recipientType, + }, + }, + } + + channel, err := client.CreateAlertChannel(context.Background(), createOpts) + require.NoErrorf(t, err, "failed to create alert channel: %v", err) + require.NotNil(t, channel, "created channel is nil") + + // ensure cleanup + var createdAlert *linodego.AlertDefinition + defer func() { + if createdAlert != nil { + deleteMonitorAlertDefinitionWithRetry(t, client, testMonitorAlertDefinitionServiceType, createdAlert.ID) + } + deleteAlertChannelWithRetry(t, client, channel.ID) + }() + + // Create an alert definition attached to the created channel + serviceType := "dbaas" + createAlertOpts := linodego.AlertDefinitionCreateOptions{ + Label: "go-integration-test-alert", + Severity: int(linodego.SeverityLow), + ChannelIDs: []int{channel.ID}, + TriggerConditions: &linodego.TriggerConditions{ + CriteriaCondition: string(linodego.CriteriaConditionAll), + EvaluationPeriodSeconds: 300, + PollingIntervalSeconds: 300, + TriggerOccurrences: 1, + }, + RuleCriteria: &linodego.RuleCriteriaOptions{ + Rules: []linodego.RuleOptions{ + { + AggregateFunction: "avg", + Metric: "memory_usage", + Operator: "gt", + Threshold: 90.0, + }, + }, + }, + } + + createdAlert, err = client.CreateMonitorAlertDefinition(context.Background(), serviceType, createAlertOpts) + require.NoErrorf(t, err, "failed to create monitor alert definition: %v", err) + require.NotNil(t, createdAlert) + + // List alerts for the channel and verify at least one alert is attached + alerts, err := client.ListAlertsForChannel(context.Background(), channel.ID, nil) + require.NoErrorf(t, err, "failed to list alerts for channel: %v", err) + require.NotEmpty(t, alerts, "expected at least one alert for channel %d", channel.ID) + + // Assert fields on the first alert + a := alerts[0] + assert.NotZero(t, a.ID, "alert.ID should not be zero") + assert.NotEmpty(t, a.Label, "alert.Label should not be empty") + assert.NotEmpty(t, a.ServiceType, "alert.ServiceType should not be empty") + assert.NotEmpty(t, a.Type, "alert.Type should not be empty") + assert.NotEmpty(t, a.URL, "alert.URL should not be empty") +}