Skip to content

Commit 59e4a0b

Browse files
CLOUDP-57522: Creating Atlas Alert Configuration (#30)
* CLOUDP-57522: Creating Atlas Alert Configuration
1 parent ac25b32 commit 59e4a0b

12 files changed

+562
-55
lines changed

e2e/atlas_alertconfig_test.go

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ import (
2222
"testing"
2323
)
2424

25+
//const (
26+
// group = "GROUP"
27+
// eventTypeName = "NO_PRIMARY"
28+
// intervalMin = 5
29+
// delayMin = 0
30+
//)
31+
2532
func TestAtlasAlertConfig(t *testing.T) {
2633
cliPath, err := filepath.Abs("../bin/mcli")
2734
if err != nil {
@@ -34,7 +41,62 @@ func TestAtlasAlertConfig(t *testing.T) {
3441
}
3542

3643
atlasEntity := "atlas"
37-
alertConfigEntity := "alert-config"
44+
alertConfigEntity := "alerts configs"
45+
46+
//t.Run("Create", func(t *testing.T) {
47+
// cmd := exec.Command(cliPath,
48+
// atlasEntity,
49+
// alertConfigEntity,
50+
// "create",
51+
// "--event",
52+
// eventTypeName,
53+
// "--enabled=true",
54+
// "--notificationTypeName",
55+
// group,
56+
// "--notificationIntervalMin",
57+
// strconv.Itoa(intervalMin),
58+
// "--notificationDelayMin",
59+
// strconv.Itoa(delayMin),
60+
// "--notificationSmsEnabled=false",
61+
// "--notificationEmailEnabled=true")
62+
// cmd.Env = os.Environ()
63+
// resp, err := cmd.CombinedOutput()
64+
//
65+
// if err != nil {
66+
// t.Fatalf("unexpected error: %v, resp: %v", err, string(resp))
67+
// }
68+
//
69+
// alert := mongodbatlas.AlertConfiguration{}
70+
// err = json.Unmarshal(resp, &alert)
71+
// if err != nil {
72+
// t.Fatalf("unexpected error: %v", err)
73+
// }
74+
//
75+
// if alert.EventTypeName != eventTypeName {
76+
// t.Errorf("got=%#v\nwant=%#v\n", alert.EventTypeName, eventTypeName)
77+
// }
78+
//
79+
// if len(alert.Notifications) != 1 {
80+
// t.Errorf("len(alert.Notifications) got=%#v\nwant=%#v\n", len(alert.Notifications), 1)
81+
// }
82+
//
83+
// if *alert.Notifications[0].DelayMin != delay_min {
84+
// t.Errorf("got=%#v\nwant=%#v\n", alert.Notifications[0].DelayMin, delay_min)
85+
// }
86+
//
87+
// if alert.Notifications[0].TypeName != group {
88+
// t.Errorf("got=%#v\nwant=%#v\n", alert.Notifications[0].TypeName, group)
89+
// }
90+
//
91+
// if alert.Notifications[0].IntervalMin != interval_min {
92+
// t.Errorf("got=%#v\nwant=%#v\n", alert.Notifications[0].IntervalMin, interval_min)
93+
// }
94+
//
95+
// if *alert.Notifications[0].SMSEnabled != false {
96+
// t.Errorf("got=%#v\nwant=%#v\n", alert.Notifications[0].SMSEnabled, false)
97+
// }
98+
//
99+
//})
38100

39101
t.Run("List", func(t *testing.T) {
40102
cmd := exec.Command(cliPath, atlasEntity, alertConfigEntity, "ls")
@@ -45,4 +107,5 @@ func TestAtlasAlertConfig(t *testing.T) {
45107
t.Fatalf("unexpected error: %v, resp: %v", err, string(resp))
46108
}
47109
})
110+
48111
}

internal/cli/atlas.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func AtlasBuilder() *cobra.Command {
2626
cmd.AddCommand(AtlasClustersBuilder())
2727
cmd.AddCommand(AtlasDBUsersBuilder())
2828
cmd.AddCommand(AtlasWhitelistBuilder())
29-
cmd.AddCommand(AtlasAlertConfigBuilder())
29+
cmd.AddCommand(AtlasAlertsBuilder())
3030

3131
return cmd
3232
}

internal/cli/atlas_alertconfig.go renamed to internal/cli/atlas_alert_config.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ import (
1818
"github.com/spf13/cobra"
1919
)
2020

21-
func AtlasAlertConfigBuilder() *cobra.Command {
21+
func AtlasAlertConfigsBuilder() *cobra.Command {
2222
cmd := &cobra.Command{
23-
Use: "alert-config",
24-
Aliases: []string{"alertConfig", "alertConfigs", "alert-configs"},
23+
Use: "configs",
24+
Aliases: []string{"config"},
2525
Short: "Manage Atlas alert configurations for your project.",
26-
Long: "The alertConfigs command provides access to your alerts configurations. You can create, edit, and delete alert configurations.",
26+
Long: "The configs command provides access to your alerts configurations. You can create, edit, and delete alert configurations.",
2727
}
28+
29+
cmd.AddCommand(AtlasAlertConfigCreateBuilder())
2830
cmd.AddCommand(AtlasAlertConfigListBuilder())
2931

3032
return cmd
Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
// Copyright 2020 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package cli
16+
17+
import (
18+
"strings"
19+
20+
atlas "github.com/mongodb/go-client-mongodb-atlas/mongodbatlas"
21+
"github.com/mongodb/mcli/internal/flags"
22+
"github.com/mongodb/mcli/internal/json"
23+
"github.com/mongodb/mcli/internal/store"
24+
"github.com/mongodb/mcli/internal/usage"
25+
"github.com/spf13/cobra"
26+
)
27+
28+
const (
29+
datadog = "DATADOG"
30+
slack = "SLACK"
31+
victor = "VICTOR_OPS"
32+
flowdock = "FLOWDOCK"
33+
email = "EMAIL"
34+
ops = "OPS_GENIE"
35+
org = "ORG"
36+
pager = "PAGER_DUTY"
37+
sms = "SMS"
38+
group = "GROUP"
39+
user = "USER"
40+
)
41+
42+
type atlasAlertConfigCreateOpts struct {
43+
*globalOpts
44+
event string
45+
matcherFieldName string
46+
matcherOperator string
47+
matcherValue string
48+
metricThresholdMetricName string
49+
metricThresholdOperator string
50+
metricThresholdUnits string
51+
metricThresholdMode string
52+
notificationToken string // notificationsApiToken, notificationsFlowdockApiToken
53+
notificationChannelName string
54+
apiKey string // notificationsDatadogApiKey, notificationsOpsGenieApiKey, notificationsVictorOpsApiKey
55+
notificationEmailAddress string
56+
notificationFlowName string
57+
notificationMobileNumber string
58+
notificationRegion string // notificationsOpsGenieRegion, notificationsDatadogRegion
59+
notificationOrgName string
60+
notificationServiceKey string
61+
notificationTeamID string
62+
notificationType string
63+
notificationUsername string
64+
notificationVictorOpsRoutingKey string
65+
notificationDelayMin int
66+
notificationIntervalMin int
67+
notificationSmsEnabled bool
68+
enabled bool
69+
notificationEmailEnabled bool
70+
metricThresholdThreshold float64
71+
store store.AlertConfigurationCreator
72+
}
73+
74+
func (opts *atlasAlertConfigCreateOpts) init() error {
75+
if opts.ProjectID() == "" {
76+
return errMissingProjectID
77+
}
78+
79+
var err error
80+
opts.store, err = store.New()
81+
return err
82+
}
83+
84+
func (opts *atlasAlertConfigCreateOpts) Run() error {
85+
alert := opts.buildAlertConfiguration()
86+
result, err := opts.store.CreateAlertConfiguration(alert)
87+
88+
if err != nil {
89+
return err
90+
}
91+
92+
return json.PrettyPrint(result)
93+
}
94+
95+
func (opts *atlasAlertConfigCreateOpts) buildAlertConfiguration() *atlas.AlertConfiguration {
96+
97+
out := new(atlas.AlertConfiguration)
98+
99+
out.GroupID = opts.ProjectID()
100+
out.EventTypeName = strings.ToUpper(opts.event)
101+
out.Enabled = &opts.enabled
102+
103+
if opts.matcherFieldName != "" {
104+
out.Matchers = []atlas.Matcher{*newMatcher(opts)}
105+
}
106+
107+
if opts.metricThresholdMetricName != "" {
108+
out.MetricThreshold = newMetricThreshold(opts)
109+
}
110+
111+
out.Notifications = []atlas.Notification{*newNotification(opts)}
112+
113+
return out
114+
}
115+
116+
func newNotification(opts *atlasAlertConfigCreateOpts) *atlas.Notification {
117+
118+
out := new(atlas.Notification)
119+
out.TypeName = strings.ToUpper(opts.notificationType)
120+
out.DelayMin = &opts.notificationDelayMin
121+
out.IntervalMin = opts.notificationIntervalMin
122+
out.TeamID = opts.notificationTeamID
123+
out.Username = opts.notificationUsername
124+
125+
switch out.TypeName {
126+
127+
case victor:
128+
out.VictorOpsAPIKey = opts.apiKey
129+
out.VictorOpsRoutingKey = opts.notificationVictorOpsRoutingKey
130+
131+
case slack:
132+
out.VictorOpsAPIKey = opts.apiKey
133+
out.VictorOpsRoutingKey = opts.notificationVictorOpsRoutingKey
134+
out.APIToken = opts.notificationToken
135+
136+
case datadog:
137+
out.DatadogAPIKey = opts.apiKey
138+
out.DatadogRegion = strings.ToUpper(opts.notificationRegion)
139+
140+
case email:
141+
out.EmailAddress = opts.notificationEmailAddress
142+
143+
case flowdock:
144+
out.FlowdockAPIToken = opts.notificationToken
145+
out.FlowName = opts.notificationFlowName
146+
out.OrgName = opts.notificationOrgName
147+
148+
case sms:
149+
out.MobileNumber = opts.notificationMobileNumber
150+
151+
case group, user, org:
152+
out.SMSEnabled = &opts.notificationSmsEnabled
153+
out.EmailEnabled = &opts.notificationEmailEnabled
154+
155+
case ops:
156+
out.OpsGenieAPIKey = opts.apiKey
157+
out.OpsGenieRegion = opts.notificationRegion
158+
159+
case pager:
160+
out.ServiceKey = opts.notificationServiceKey
161+
162+
}
163+
164+
return out
165+
}
166+
167+
func newMetricThreshold(opts *atlasAlertConfigCreateOpts) *atlas.MetricThreshold {
168+
return &atlas.MetricThreshold{
169+
MetricName: strings.ToUpper(opts.metricThresholdMetricName),
170+
Operator: strings.ToUpper(opts.metricThresholdOperator),
171+
Threshold: opts.metricThresholdThreshold,
172+
Units: strings.ToUpper(opts.metricThresholdUnits),
173+
Mode: strings.ToUpper(opts.metricThresholdMode),
174+
}
175+
}
176+
177+
func newMatcher(opts *atlasAlertConfigCreateOpts) *atlas.Matcher {
178+
return &atlas.Matcher{
179+
FieldName: strings.ToUpper(opts.matcherFieldName),
180+
Operator: strings.ToUpper(opts.matcherOperator),
181+
Value: strings.ToUpper(opts.matcherValue),
182+
}
183+
}
184+
185+
// mcli atlas alert-config(s) create -event event --enabled [--matcherField fieldName --matcherOperator operator --matcherValue value]
186+
// [--notificationType type --notificationDelayMin min --notificationEmailEnabled --notificationSmsEnabled --notificationUsername username --notificationTeamID id
187+
// --notificationEmailAddress email --notificationMobileNumber number --notificationChannelName channel --notificationApiToken --notificationRegion region] [--projectId projectId]
188+
func AtlasAlertConfigCreateBuilder() *cobra.Command {
189+
opts := &atlasAlertConfigCreateOpts{
190+
globalOpts: newGlobalOpts(),
191+
}
192+
cmd := &cobra.Command{
193+
Use: "create",
194+
Short: "Create an Atlas alert configuration for a project.",
195+
Args: cobra.NoArgs,
196+
PreRunE: func(cmd *cobra.Command, args []string) error {
197+
return opts.init()
198+
},
199+
RunE: func(cmd *cobra.Command, args []string) error {
200+
return opts.Run()
201+
},
202+
}
203+
204+
cmd.Flags().StringVar(&opts.event, flags.Event, "", usage.Event)
205+
cmd.Flags().BoolVar(&opts.enabled, flags.Enabled, false, usage.Enabled)
206+
cmd.Flags().StringVar(&opts.matcherFieldName, flags.MatcherFieldName, "", usage.MatcherFieldName)
207+
cmd.Flags().StringVar(&opts.matcherOperator, flags.MatcherOperator, "", usage.MatcherOperator)
208+
cmd.Flags().StringVar(&opts.matcherValue, flags.MatcherValue, "", usage.MatcherValue)
209+
cmd.Flags().StringVar(&opts.metricThresholdMetricName, flags.MetricName, "", usage.MetricName)
210+
cmd.Flags().StringVar(&opts.metricThresholdOperator, flags.MetricOperator, "", usage.MetricOperator)
211+
cmd.Flags().Float64Var(&opts.metricThresholdThreshold, flags.MetricThreshold, 0, usage.MetricThreshold)
212+
cmd.Flags().StringVar(&opts.metricThresholdUnits, flags.MetricUnits, "", usage.MetricUnits)
213+
cmd.Flags().StringVar(&opts.metricThresholdMode, flags.MetricMode, "", usage.MetricMode)
214+
cmd.Flags().StringVar(&opts.notificationToken, flags.NotificationToken, "", usage.NotificationToken)
215+
cmd.Flags().StringVar(&opts.notificationChannelName, flags.NotificationChannelName, "", usage.NotificationsChannelName)
216+
cmd.Flags().StringVar(&opts.apiKey, flags.APIKey, "", usage.APIKey)
217+
cmd.Flags().StringVar(&opts.notificationRegion, flags.NotificationRegion, "", usage.NotificationRegion)
218+
cmd.Flags().IntVar(&opts.notificationDelayMin, flags.NotificationDelayMin, 0, usage.NotificationDelayMin)
219+
cmd.Flags().StringVar(&opts.notificationEmailAddress, flags.NotificationEmailAddress, "", usage.NotificationEmailAddress)
220+
cmd.Flags().BoolVar(&opts.notificationEmailEnabled, flags.NotificationEmailEnabled, false, usage.NotificationEmailEnabled)
221+
cmd.Flags().StringVar(&opts.notificationFlowName, flags.NotificationFlowName, "", usage.NotificationFlowName)
222+
cmd.Flags().IntVar(&opts.notificationIntervalMin, flags.NotificationIntervalMin, 0, usage.NotificationIntervalMin)
223+
cmd.Flags().StringVar(&opts.notificationMobileNumber, flags.NotificationMobileNumber, "", usage.NotificationMobileNumber)
224+
cmd.Flags().StringVar(&opts.notificationOrgName, flags.NotificationOrgName, "", usage.NotificationOrgName)
225+
cmd.Flags().StringVar(&opts.notificationServiceKey, flags.NotificationServiceKey, "", usage.NotificationServiceKey)
226+
cmd.Flags().BoolVar(&opts.notificationSmsEnabled, flags.NotificationSmsEnabled, false, usage.NotificationSmsEnabled)
227+
cmd.Flags().StringVar(&opts.notificationTeamID, flags.NotificationTeamID, "", usage.NotificationTeamID)
228+
cmd.Flags().StringVar(&opts.notificationType, flags.NotificationType, "", usage.NotificationType)
229+
cmd.Flags().StringVar(&opts.notificationUsername, flags.NotificationUsername, "", usage.NotificationUsername)
230+
cmd.Flags().StringVar(&opts.notificationVictorOpsRoutingKey, flags.NotificationVictorOpsRoutingKey, "", usage.NotificationVictorOpsRoutingKey)
231+
232+
cmd.Flags().StringVar(&opts.projectID, flags.ProjectID, "", usage.ProjectID)
233+
234+
return cmd
235+
}

0 commit comments

Comments
 (0)