Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions monitor_alert_channels.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/linode/linodego/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

const (
Expand Down Expand Up @@ -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.
}
100 changes: 78 additions & 22 deletions test/unit/monitor_alert_channels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}