Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: migrate alert_configuration resource and removing deprecated fields #1385

Merged
merged 9 commits into from
Aug 21, 2023
Merged
2 changes: 1 addition & 1 deletion .github/workflows/acceptance-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ jobs:
- 'mongodbatlas/data_source_mongodbatlas_team*.go'
- 'mongodbatlas/data_source_mongodbatlas_third_party_integration*.go'
- 'mongodbatlas/resource_mongodbatlas_api_key*.go'
- 'mongodbatlas/resource_mongodbatlas_alert_configuration*.go'
- 'mongodbatlas/fw_resource_mongodbatlas_alert_configuration*.go'
- 'mongodbatlas/resource_mongodbatlas_cloud_provider_access_setup*.go'
- 'mongodbatlas/resource_mongodbatlas_cloud_provider_access*.go'
- 'mongodbatlas/resource_mongodbatlas_custom_db_role*.go'
Expand Down
178 changes: 178 additions & 0 deletions mongodbatlas/data_source_mongodbatlas_alert_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package mongodbatlas
import (
"context"
"fmt"
"strings"

"github.com/hashicorp/hcl/v2/hclwrite"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/mwielbut/pointy"
"github.com/spf13/cast"
"github.com/zclconf/go-cty/cty"
matlas "go.mongodb.org/atlas/mongodbatlas"
)
Expand Down Expand Up @@ -504,3 +507,178 @@ func convertNotificationToCtyValues(notification *matlas.Notification) map[strin

return values
}

AgustinBettati marked this conversation as resolved.
Show resolved Hide resolved
func flattenAlertConfigurationMetricThreshold(m *matlas.MetricThreshold) map[string]interface{} {
if m != nil {
return map[string]interface{}{
"metric_name": m.MetricName,
"operator": m.Operator,
"threshold": cast.ToString(m.Threshold),
"units": m.Units,
"mode": m.Mode,
}
}

return map[string]interface{}{}
}
AgustinBettati marked this conversation as resolved.
Show resolved Hide resolved

func flattenAlertConfigurationThreshold(m *matlas.Threshold) map[string]interface{} {
if m != nil {
return map[string]interface{}{
"operator": m.Operator,
"units": m.Units,
"threshold": cast.ToString(m.Threshold),
}
}

return map[string]interface{}{}
}

func flattenAlertConfigurationMetricThresholdConfig(m *matlas.MetricThreshold) []interface{} {
if m != nil {
return []interface{}{map[string]interface{}{
"metric_name": m.MetricName,
"operator": m.Operator,
"threshold": m.Threshold,
"units": m.Units,
"mode": m.Mode,
}}
}

return []interface{}{}
}

func flattenAlertConfigurationThresholdConfig(m *matlas.Threshold) []interface{} {
if m != nil {
return []interface{}{map[string]interface{}{
"operator": m.Operator,
"units": m.Units,
"threshold": m.Threshold,
}}
}

return []interface{}{}
}

func expandAlertConfigurationNotification(d *schema.ResourceData) ([]matlas.Notification, error) {
AgustinBettati marked this conversation as resolved.
Show resolved Hide resolved
notificationCount := 0

if notifications, ok := d.GetOk("notification"); ok {
notificationCount = len(notifications.([]interface{}))
}

notifications := make([]matlas.Notification, notificationCount)

if notificationCount == 0 {
return notifications, nil
}

for i, value := range d.Get("notification").([]interface{}) {
v := value.(map[string]interface{})
if v1, ok := v["interval_min"]; ok && v1.(int) > 0 {
typeName := v["type_name"].(string)
if strings.EqualFold(typeName, pagerDuty) || strings.EqualFold(typeName, opsGenie) || strings.EqualFold(typeName, victorOps) {
return nil, fmt.Errorf(`'interval_min' doesn't need to be set if type_name is 'PAGER_DUTY', 'OPS_GENIE' or 'VICTOR_OPS'`)
}
}
notifications[i] = matlas.Notification{
APIToken: cast.ToString(v["api_token"]),
ChannelName: cast.ToString(v["channel_name"]),
DatadogAPIKey: cast.ToString(v["datadog_api_key"]),
DatadogRegion: cast.ToString(v["datadog_region"]),
DelayMin: pointy.Int(v["delay_min"].(int)),
EmailAddress: cast.ToString(v["email_address"]),
EmailEnabled: pointy.Bool(v["email_enabled"].(bool)),
IntervalMin: cast.ToInt(v["interval_min"]),
MobileNumber: cast.ToString(v["mobile_number"]),
OpsGenieAPIKey: cast.ToString(v["ops_genie_api_key"]),
OpsGenieRegion: cast.ToString(v["ops_genie_region"]),
ServiceKey: cast.ToString(v["service_key"]),
SMSEnabled: pointy.Bool(v["sms_enabled"].(bool)),
TeamID: cast.ToString(v["team_id"]),
TypeName: cast.ToString(v["type_name"]),
Username: cast.ToString(v["username"]),
VictorOpsAPIKey: cast.ToString(v["victor_ops_api_key"]),
VictorOpsRoutingKey: cast.ToString(v["victor_ops_routing_key"]),
Roles: cast.ToStringSlice(v["roles"]),
MicrosoftTeamsWebhookURL: cast.ToString(v["microsoft_teams_webhook_url"]),
WebhookSecret: cast.ToString(v["webhook_secret"]),
WebhookURL: cast.ToString(v["webhook_url"]),
}
}

return notifications, nil
}

func flattenAlertConfigurationNotifications(d *schema.ResourceData, notifications []matlas.Notification) []map[string]interface{} {
notificationsSchema, err := expandAlertConfigurationNotification(d)
if err != nil {
return nil
}

if len(notificationsSchema) > 0 {
for i := range notificationsSchema {
notifications[i].APIToken = notificationsSchema[i].APIToken
notifications[i].DatadogAPIKey = notificationsSchema[i].DatadogAPIKey
notifications[i].OpsGenieAPIKey = notificationsSchema[i].OpsGenieAPIKey
notifications[i].ServiceKey = notificationsSchema[i].ServiceKey
notifications[i].VictorOpsAPIKey = notificationsSchema[i].VictorOpsAPIKey
notifications[i].VictorOpsRoutingKey = notificationsSchema[i].VictorOpsRoutingKey
notifications[i].WebhookURL = notificationsSchema[i].WebhookURL
notifications[i].WebhookSecret = notificationsSchema[i].WebhookSecret
notifications[i].SMSEnabled = notificationsSchema[i].SMSEnabled
notifications[i].EmailEnabled = notificationsSchema[i].EmailEnabled
notifications[i].MicrosoftTeamsWebhookURL = notificationsSchema[i].MicrosoftTeamsWebhookURL
}
}

nts := make([]map[string]interface{}, len(notifications))

for i := range notifications {
nts[i] = map[string]interface{}{
"api_token": notifications[i].APIToken,
"channel_name": notifications[i].ChannelName,
"datadog_api_key": notifications[i].DatadogAPIKey,
"datadog_region": notifications[i].DatadogRegion,
"delay_min": notifications[i].DelayMin,
"email_address": notifications[i].EmailAddress,
"email_enabled": notifications[i].EmailEnabled,
"interval_min": notifications[i].IntervalMin,
"mobile_number": notifications[i].MobileNumber,
"ops_genie_api_key": notifications[i].OpsGenieAPIKey,
"ops_genie_region": notifications[i].OpsGenieRegion,
"service_key": notifications[i].ServiceKey,
"sms_enabled": notifications[i].SMSEnabled,
"team_id": notifications[i].TeamID,
"team_name": notifications[i].TeamName,
"type_name": notifications[i].TypeName,
"username": notifications[i].Username,
"victor_ops_api_key": notifications[i].VictorOpsAPIKey,
"victor_ops_routing_key": notifications[i].VictorOpsRoutingKey,
"microsoft_teams_webhook_url": notifications[i].MicrosoftTeamsWebhookURL,
"webhook_secret": notifications[i].WebhookSecret,
"webhook_url": notifications[i].WebhookURL,
}

// We need to validate it due to the datasource haven't the roles attribute
if len(notifications[i].Roles) > 0 {
nts[i]["roles"] = notifications[i].Roles
}
}

return nts
}

func flattenAlertConfigurationMatchers(matchers []matlas.Matcher) []map[string]interface{} {
mts := make([]map[string]interface{}, len(matchers))

for i, m := range matchers {
mts[i] = map[string]interface{}{
"field_name": m.FieldName,
"operator": m.Operator,
"value": m.Value,
}
}

return mts
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package mongodbatlas
package conversion

import (
"context"
Expand All @@ -17,3 +17,12 @@ func TypesListToString(ctx context.Context, set types.List) []string {
_ = set.ElementsAs(ctx, &results, false)
return results
}

// StringNullIfEmpty converts a string value to a Framework String value.
// An empty string is converted to a null String. Useful for optional attributes.
func StringNullIfEmpty(v string) types.String {
if v == "" {
return types.StringNull()
andreaangiolillo marked this conversation as resolved.
Show resolved Hide resolved
}
return types.StringValue(v)
}
12 changes: 6 additions & 6 deletions mongodbatlas/fw_data_source_mongodbatlas_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,15 +193,15 @@ func (d *ProjectDS) Read(ctx context.Context, req datasource.ReadRequest, resp *
return
}

projectState = toTFProjectDataSourceModel(ctx, project, atlasTeams, atlasProjectSettings, atlasLimits)
projectState = newTFProjectDataSourceModel(ctx, project, atlasTeams, atlasProjectSettings, atlasLimits)

resp.Diagnostics.Append(resp.State.Set(ctx, &projectState)...)
if resp.Diagnostics.HasError() {
return
}
}

func toTFProjectDataSourceModel(ctx context.Context, project *matlas.Project,
func newTFProjectDataSourceModel(ctx context.Context, project *matlas.Project,
teams *matlas.TeamsAssigned, projectSettings *matlas.ProjectSettings, limits []admin.DataFederationLimit) tfProjectDSModel {
return tfProjectDSModel{
ID: types.StringValue(project.ID),
Expand All @@ -216,12 +216,12 @@ func toTFProjectDataSourceModel(ctx context.Context, project *matlas.Project,
IsPerformanceAdvisorEnabled: types.BoolValue(*projectSettings.IsPerformanceAdvisorEnabled),
IsRealtimePerformancePanelEnabled: types.BoolValue(*projectSettings.IsRealtimePerformancePanelEnabled),
IsSchemaAdvisorEnabled: types.BoolValue(*projectSettings.IsSchemaAdvisorEnabled),
Teams: toTFTeamsDataSourceModel(ctx, teams),
Limits: toTFLimitsDataSourceModel(ctx, limits),
Teams: newTFTeamsDataSourceModel(ctx, teams),
Limits: newTFLimitsDataSourceModel(ctx, limits),
}
}

func toTFTeamsDataSourceModel(ctx context.Context, atlasTeams *matlas.TeamsAssigned) []*tfTeamDSModel {
func newTFTeamsDataSourceModel(ctx context.Context, atlasTeams *matlas.TeamsAssigned) []*tfTeamDSModel {
if atlasTeams.TotalCount == 0 {
return nil
}
Expand All @@ -238,7 +238,7 @@ func toTFTeamsDataSourceModel(ctx context.Context, atlasTeams *matlas.TeamsAssig
return teams
}

func toTFLimitsDataSourceModel(ctx context.Context, dataFederationLimits []admin.DataFederationLimit) []*tfLimitModel {
func newTFLimitsDataSourceModel(ctx context.Context, dataFederationLimits []admin.DataFederationLimit) []*tfLimitModel {
limits := make([]*tfLimitModel, len(dataFederationLimits))

for i, dataFederationLimit := range dataFederationLimits {
Expand Down
2 changes: 1 addition & 1 deletion mongodbatlas/fw_data_source_mongodbatlas_projects.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func populateProjectsDataSourceModel(ctx context.Context, conn *matlas.Client, c
if err != nil {
return fmt.Errorf("error while getting project properties for project %s: %v", project.ID, err.Error())
}
projectModel := toTFProjectDataSourceModel(ctx, project, atlasTeams, atlasProjectSettings, atlasLimits)
projectModel := newTFProjectDataSourceModel(ctx, project, atlasTeams, atlasProjectSettings, atlasLimits)
results[i] = &projectModel
}

Expand Down
1 change: 1 addition & 0 deletions mongodbatlas/fw_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ func (p *MongodbtlasProvider) Resources(context.Context) []func() resource.Resou
return []func() resource.Resource{
NewProjectRS,
NewDatabaseUserRS,
NewAlertConfigurationRS,
}
}

Expand Down
Loading