Skip to content

Commit 0dfe33d

Browse files
authored
fix: populate total_count in mongodbatlas_alert_configurations data source (#1476)
* use new SDK to get total_count * use RFC3339Nano to be consistent con JSON marhalling * IsStringPresent * use new SDK for alert notification Output * get MetricThresholdConfig with new SDK * get ThresholdConfig with new SDK * get Notification with new SDK * get Matcher with new SDK * rename params in V2 methods in resource * use new SDK for results in AlertConfiguration datasource * use only new SDK in Alert Configurations data source * use only new SDK in Alert Configuration data source * fix linter issues * move IsStringPresent to util package * check if time pointers are nil so it creates a null value in TF * check that pointers are valid or use default zero value
1 parent 0a727bb commit 0dfe33d

7 files changed

+408
-122
lines changed

mongodbatlas/framework/conversion/string.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55

66
"github.com/hashicorp/terraform-plugin-framework/types"
7+
"github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas/util"
78
)
89

910
func TypesSetToString(ctx context.Context, set types.Set) []string {
@@ -21,8 +22,13 @@ func TypesListToString(ctx context.Context, set types.List) []string {
2122
// StringNullIfEmpty converts a string value to a Framework String value.
2223
// An empty string is converted to a null String. Useful for optional attributes.
2324
func StringNullIfEmpty(v string) types.String {
24-
if v == "" {
25-
return types.StringNull()
25+
return StringPtrNullIfEmpty(&v)
26+
}
27+
28+
// StringPtrNullIfEmpty is similar to StringNullIfEmpty but can also handle nil string pointers.
29+
func StringPtrNullIfEmpty(p *string) types.String {
30+
if util.IsStringPresent(p) {
31+
return types.StringValue(*p)
2632
}
27-
return types.StringValue(v)
33+
return types.StringNull()
2834
}

mongodbatlas/fw_data_source_mongodbatlas_alert_configuration.go

Lines changed: 81 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import (
1010
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
1111
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
1212
"github.com/hashicorp/terraform-plugin-framework/types"
13+
"github.com/mongodb/terraform-provider-mongodbatlas/mongodbatlas/util"
1314
"github.com/zclconf/go-cty/cty"
14-
matlas "go.mongodb.org/atlas/mongodbatlas"
15+
"go.mongodb.org/atlas-sdk/v20230201006/admin"
1516
)
1617

1718
var _ datasource.DataSource = &AlertConfigurationDS{}
@@ -244,7 +245,6 @@ func (d *AlertConfigurationDS) Schema(ctx context.Context, req datasource.Schema
244245

245246
func (d *AlertConfigurationDS) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
246247
var alertConfigurationConfig tfAlertConfigurationDSModel
247-
conn := d.client.Atlas
248248

249249
resp.Diagnostics.Append(req.Config.Get(ctx, &alertConfigurationConfig)...)
250250
if resp.Diagnostics.HasError() {
@@ -257,23 +257,23 @@ func (d *AlertConfigurationDS) Read(ctx context.Context, req datasource.ReadRequ
257257
alertID := getEncodedID(alertConfigurationConfig.AlertConfigurationID.ValueString(), encodedIDKeyAlertID)
258258
outputs := alertConfigurationConfig.Output
259259

260-
alert, _, err := conn.AlertConfigurations.GetAnAlertConfig(ctx, projectID, alertID)
260+
connV2 := d.client.AtlasV2
261+
alert, _, err := connV2.AlertConfigurationsApi.GetAlertConfiguration(ctx, projectID, alertID).Execute()
261262
if err != nil {
262263
resp.Diagnostics.AddError(errorReadAlertConf, err.Error())
263264
return
264265
}
265266

266267
resultAlertConfigModel := newTFAlertConfigurationDSModel(alert, projectID)
267-
computedOutputs := computeAlertConfigurationOutput(alert, outputs, alert.EventTypeName)
268-
resultAlertConfigModel.Output = computedOutputs
268+
resultAlertConfigModel.Output = computeAlertConfigurationOutput(alert, outputs, *alert.EventTypeName)
269269

270270
// setting initial value for backwards compatibility, but setting the alert_configuration resource id here is not consistent with the resource
271271
resultAlertConfigModel.AlertConfigurationID = alertConfigurationConfig.AlertConfigurationID
272272

273273
resp.Diagnostics.Append(resp.State.Set(ctx, &resultAlertConfigModel)...)
274274
}
275275

276-
func computeAlertConfigurationOutput(alert *matlas.AlertConfiguration, definedOutputs []tfAlertConfigurationOutputModel, defaultLabel string) []tfAlertConfigurationOutputModel {
276+
func computeAlertConfigurationOutput(alert *admin.GroupAlertsConfig, definedOutputs []tfAlertConfigurationOutputModel, defaultLabel string) []tfAlertConfigurationOutputModel {
277277
resultOutputs := make([]tfAlertConfigurationOutputModel, len(definedOutputs))
278278
for i, defined := range definedOutputs {
279279
resultOutput := tfAlertConfigurationOutputModel{}
@@ -291,26 +291,26 @@ func computeAlertConfigurationOutput(alert *matlas.AlertConfiguration, definedOu
291291
return resultOutputs
292292
}
293293

294-
func newTFAlertConfigurationDSModel(apiRespConfig *matlas.AlertConfiguration, projectID string) tfAlertConfigurationDSModel {
294+
func newTFAlertConfigurationDSModel(apiRespConfig *admin.GroupAlertsConfig, projectID string) tfAlertConfigurationDSModel {
295295
return tfAlertConfigurationDSModel{
296296
ID: types.StringValue(encodeStateID(map[string]string{
297-
encodedIDKeyAlertID: apiRespConfig.ID,
297+
encodedIDKeyAlertID: *apiRespConfig.Id,
298298
encodedIDKeyProjectID: projectID,
299299
})),
300300
ProjectID: types.StringValue(projectID),
301-
AlertConfigurationID: types.StringValue(apiRespConfig.ID),
302-
EventType: types.StringValue(apiRespConfig.EventTypeName),
303-
Created: types.StringValue(apiRespConfig.Created),
304-
Updated: types.StringValue(apiRespConfig.Updated),
301+
AlertConfigurationID: types.StringValue(*apiRespConfig.Id),
302+
EventType: types.StringValue(*apiRespConfig.EventTypeName),
303+
Created: types.StringPointerValue(util.TimePtrToStringPtr(apiRespConfig.Created)),
304+
Updated: types.StringPointerValue(util.TimePtrToStringPtr(apiRespConfig.Updated)),
305305
Enabled: types.BoolPointerValue(apiRespConfig.Enabled),
306-
MetricThresholdConfig: newTFMetricThresholdConfigModel(apiRespConfig.MetricThreshold, []tfMetricThresholdConfigModel{}),
307-
ThresholdConfig: newTFThresholdConfigModel(apiRespConfig.Threshold, []tfThresholdConfigModel{}),
308-
Notification: newTFNotificationModelList(apiRespConfig.Notifications, []tfNotificationModel{}),
309-
Matcher: newTFMatcherModelList(apiRespConfig.Matchers, []tfMatcherModel{}),
306+
MetricThresholdConfig: newTFMetricThresholdConfigModelV2(apiRespConfig.MetricThreshold, []tfMetricThresholdConfigModel{}),
307+
ThresholdConfig: newTFThresholdConfigModelV2(apiRespConfig.Threshold, []tfThresholdConfigModel{}),
308+
Notification: newTFNotificationModelListV2(apiRespConfig.Notifications, []tfNotificationModel{}),
309+
Matcher: newTFMatcherModelListV2(apiRespConfig.Matchers, []tfMatcherModel{}),
310310
}
311311
}
312312

313-
func outputAlertConfiguration(alert *matlas.AlertConfiguration, outputType, resourceLabel string) string {
313+
func outputAlertConfiguration(alert *admin.GroupAlertsConfig, outputType, resourceLabel string) string {
314314
if outputType == "resource_hcl" {
315315
return outputAlertConfigurationResourceHcl(resourceLabel, alert)
316316
}
@@ -321,124 +321,119 @@ func outputAlertConfiguration(alert *matlas.AlertConfiguration, outputType, reso
321321
return ""
322322
}
323323

324-
func outputAlertConfigurationResourceHcl(label string, alert *matlas.AlertConfiguration) string {
324+
func outputAlertConfigurationResourceHcl(label string, alert *admin.GroupAlertsConfig) string {
325325
f := hclwrite.NewEmptyFile()
326326
root := f.Body()
327327
resource := root.AppendNewBlock("resource", []string{"mongodbatlas_alert_configuration", label}).Body()
328328

329-
resource.SetAttributeValue("project_id", cty.StringVal(alert.GroupID))
330-
resource.SetAttributeValue("event_type", cty.StringVal(alert.EventTypeName))
329+
resource.SetAttributeValue("project_id", cty.StringVal(*alert.GroupId))
330+
resource.SetAttributeValue("event_type", cty.StringVal(*alert.EventTypeName))
331331

332332
if alert.Enabled != nil {
333333
resource.SetAttributeValue("enabled", cty.BoolVal(*alert.Enabled))
334334
}
335335

336336
for _, matcher := range alert.Matchers {
337-
values := convertMatcherToCtyValues(matcher)
338-
339-
appendBlockWithCtyValues(resource, "matcher", []string{}, values)
337+
appendBlockWithCtyValues(resource, "matcher", []string{}, convertMatcherToCtyValues(matcher))
340338
}
341339

342340
if alert.MetricThreshold != nil {
343-
values := convertMetricThresholdToCtyValues(*alert.MetricThreshold)
344-
345-
appendBlockWithCtyValues(resource, "metric_threshold_config", []string{}, values)
341+
appendBlockWithCtyValues(resource, "metric_threshold_config", []string{}, convertMetricThresholdToCtyValues(*alert.MetricThreshold))
346342
}
347343

348344
if alert.Threshold != nil {
349-
values := convertThresholdToCtyValues(*alert.Threshold)
350-
351-
appendBlockWithCtyValues(resource, "threshold_config", []string{}, values)
345+
appendBlockWithCtyValues(resource, "threshold_config", []string{}, convertThresholdToCtyValues(alert.Threshold))
352346
}
353347

354348
for i := 0; i < len(alert.Notifications); i++ {
355-
values := convertNotificationToCtyValues(&alert.Notifications[i])
356-
357-
appendBlockWithCtyValues(resource, "notification", []string{}, values)
349+
appendBlockWithCtyValues(resource, "notification", []string{}, convertNotificationToCtyValues(&alert.Notifications[i]))
358350
}
359351

360352
return string(f.Bytes())
361353
}
362354

363-
func outputAlertConfigurationResourceImport(label string, alert *matlas.AlertConfiguration) string {
364-
return fmt.Sprintf("terraform import mongodbatlas_alert_configuration.%s %s-%s\n", label, alert.GroupID, alert.ID)
355+
func outputAlertConfigurationResourceImport(label string, alert *admin.GroupAlertsConfig) string {
356+
return fmt.Sprintf("terraform import mongodbatlas_alert_configuration.%s %s-%s\n", label, *alert.GroupId, *alert.Id)
365357
}
366358

367-
func convertMatcherToCtyValues(matcher matlas.Matcher) map[string]cty.Value {
359+
func convertMatcherToCtyValues(matcher map[string]interface{}) map[string]cty.Value {
360+
fieldName, _ := matcher["fieldName"].(string)
361+
operator, _ := matcher["operator"].(string)
362+
value, _ := matcher["value"].(string)
368363
return map[string]cty.Value{
369-
"field_name": cty.StringVal(matcher.FieldName),
370-
"operator": cty.StringVal(matcher.Operator),
371-
"value": cty.StringVal(matcher.Value),
364+
"field_name": cty.StringVal(fieldName),
365+
"operator": cty.StringVal(operator),
366+
"value": cty.StringVal(value),
372367
}
373368
}
374369

375-
func convertMetricThresholdToCtyValues(metric matlas.MetricThreshold) map[string]cty.Value {
370+
func convertMetricThresholdToCtyValues(metric admin.ServerlessMetricThreshold) map[string]cty.Value {
371+
var t float64
372+
if metric.Threshold != nil {
373+
t = *metric.Threshold
374+
}
376375
return map[string]cty.Value{
377-
"metric_name": cty.StringVal(metric.MetricName),
378-
"operator": cty.StringVal(metric.Operator),
379-
"threshold": cty.NumberFloatVal(metric.Threshold),
380-
"units": cty.StringVal(metric.Units),
381-
"mode": cty.StringVal(metric.Mode),
376+
"metric_name": ctyStringPtrVal(metric.MetricName),
377+
"operator": ctyStringPtrVal(metric.Operator),
378+
"threshold": cty.NumberFloatVal(t),
379+
"units": ctyStringPtrVal(metric.Units),
380+
"mode": ctyStringPtrVal(metric.Mode),
382381
}
383382
}
384383

385-
func convertThresholdToCtyValues(threshold matlas.Threshold) map[string]cty.Value {
384+
func convertThresholdToCtyValues(threshold *admin.GreaterThanRawThreshold) map[string]cty.Value {
385+
var t int
386+
if threshold.Threshold != nil {
387+
t = *threshold.Threshold
388+
}
386389
return map[string]cty.Value{
387-
"operator": cty.StringVal(threshold.Operator),
388-
"units": cty.StringVal(threshold.Units),
389-
"threshold": cty.NumberFloatVal(threshold.Threshold),
390+
"operator": ctyStringPtrVal(threshold.Operator),
391+
"units": ctyStringPtrVal(threshold.Units),
392+
"threshold": cty.NumberFloatVal(float64(t)), // int in new SDK but keeping float64 for backward compatibility
390393
}
391394
}
392395

393-
func convertNotificationToCtyValues(notification *matlas.Notification) map[string]cty.Value {
396+
func convertNotificationToCtyValues(notification *admin.AlertsNotificationRootForGroup) map[string]cty.Value {
394397
values := map[string]cty.Value{}
395398

396-
if notification.ChannelName != "" {
397-
values["channel_name"] = cty.StringVal(notification.ChannelName)
399+
if util.IsStringPresent(notification.ChannelName) {
400+
values["channel_name"] = cty.StringVal(*notification.ChannelName)
398401
}
399402

400-
if notification.DatadogRegion != "" {
401-
values["datadog_region"] = cty.StringVal(notification.DatadogRegion)
403+
if util.IsStringPresent(notification.DatadogRegion) {
404+
values["datadog_region"] = cty.StringVal(*notification.DatadogRegion)
402405
}
403406

404-
if notification.EmailAddress != "" {
405-
values["email_address"] = cty.StringVal(notification.EmailAddress)
407+
if util.IsStringPresent(notification.EmailAddress) {
408+
values["email_address"] = cty.StringVal(*notification.EmailAddress)
406409
}
407410

408-
if notification.FlowName != "" {
409-
values["flow_name"] = cty.StringVal(notification.FlowName)
411+
if notification.IntervalMin != nil && *notification.IntervalMin > 0 {
412+
values["interval_min"] = cty.NumberIntVal(int64(*notification.IntervalMin))
410413
}
411414

412-
if notification.IntervalMin > 0 {
413-
values["interval_min"] = cty.NumberIntVal(int64(notification.IntervalMin))
415+
if util.IsStringPresent(notification.MobileNumber) {
416+
values["mobile_number"] = cty.StringVal(*notification.MobileNumber)
414417
}
415418

416-
if notification.MobileNumber != "" {
417-
values["mobile_number"] = cty.StringVal(notification.MobileNumber)
419+
if util.IsStringPresent(notification.OpsGenieRegion) {
420+
values["ops_genie_region"] = cty.StringVal(*notification.OpsGenieRegion)
418421
}
419422

420-
if notification.OpsGenieRegion != "" {
421-
values["ops_genie_region"] = cty.StringVal(notification.OpsGenieRegion)
423+
if util.IsStringPresent(notification.TeamId) {
424+
values["team_id"] = cty.StringVal(*notification.TeamId)
422425
}
423426

424-
if notification.OrgName != "" {
425-
values["org_name"] = cty.StringVal(notification.OrgName)
427+
if util.IsStringPresent(notification.TeamName) {
428+
values["team_name"] = cty.StringVal(*notification.TeamName)
426429
}
427430

428-
if notification.TeamID != "" {
429-
values["team_id"] = cty.StringVal(notification.TeamID)
431+
if util.IsStringPresent(notification.TypeName) {
432+
values["type_name"] = cty.StringVal(*notification.TypeName)
430433
}
431434

432-
if notification.TeamName != "" {
433-
values["team_name"] = cty.StringVal(notification.TeamName)
434-
}
435-
436-
if notification.TypeName != "" {
437-
values["type_name"] = cty.StringVal(notification.TypeName)
438-
}
439-
440-
if notification.Username != "" {
441-
values["username"] = cty.StringVal(notification.Username)
435+
if util.IsStringPresent(notification.Username) {
436+
values["username"] = cty.StringVal(*notification.Username)
442437
}
443438

444439
if notification.DelayMin != nil && *notification.DelayMin > 0 {
@@ -449,8 +444,8 @@ func convertNotificationToCtyValues(notification *matlas.Notification) map[strin
449444
values["email_enabled"] = cty.BoolVal(*notification.EmailEnabled)
450445
}
451446

452-
if notification.SMSEnabled != nil && *notification.SMSEnabled {
453-
values["sms_enabled"] = cty.BoolVal(*notification.SMSEnabled)
447+
if notification.SmsEnabled != nil && *notification.SmsEnabled {
448+
values["sms_enabled"] = cty.BoolVal(*notification.SmsEnabled)
454449
}
455450

456451
if len(notification.Roles) > 0 {
@@ -467,3 +462,10 @@ func convertNotificationToCtyValues(notification *matlas.Notification) map[strin
467462

468463
return values
469464
}
465+
466+
func ctyStringPtrVal(ptr *string) cty.Value {
467+
if ptr == nil {
468+
return cty.StringVal("")
469+
}
470+
return cty.StringVal(*ptr)
471+
}

0 commit comments

Comments
 (0)