Skip to content
Merged
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
20 changes: 3 additions & 17 deletions internal/mackerel/alert_group_setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func (ag *AlertGroupSettingModel) Read(ctx context.Context, client *Client) erro
return err
}

ag.merge(newAg)
*ag = newAg
return nil
}

Expand All @@ -66,9 +66,9 @@ func newAlertGroupSetting(ag mackerel.AlertGroupSetting) AlertGroupSettingModel
ID: types.StringValue(ag.ID),
Name: types.StringValue(ag.Name),
Memo: types.StringValue(ag.Memo),
ServiceScopes: ag.ServiceScopes,
ServiceScopes: nilAsEmptySlice(ag.ServiceScopes),
RoleScopes: normalizeScopes(ag.RoleScopes),
MonitorScopes: ag.MonitorScopes,
MonitorScopes: nilAsEmptySlice(ag.MonitorScopes),
NotificationInterval: types.Int64Value(int64(ag.NotificationInterval)),
}
}
Expand All @@ -84,17 +84,3 @@ func (ag AlertGroupSettingModel) mackerelAlertGroupSetting() mackerel.AlertGroup
NotificationInterval: uint64(ag.NotificationInterval.ValueInt64()),
}
}

func (ag *AlertGroupSettingModel) merge(newAg AlertGroupSettingModel) {
// Distinct null and [] by preserving old state
if len(ag.ServiceScopes) == 0 && len(newAg.ServiceScopes) == 0 {
newAg.ServiceScopes = ag.ServiceScopes
}
if len(ag.RoleScopes) == 0 && len(newAg.RoleScopes) == 0 {
newAg.RoleScopes = ag.RoleScopes
}
if len(ag.MonitorScopes) == 0 && len(newAg.MonitorScopes) == 0 {
newAg.MonitorScopes = ag.MonitorScopes
}
*ag = newAg
}
39 changes: 0 additions & 39 deletions internal/mackerel/alert_group_setting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,42 +74,3 @@ func Test_AlertGroupSetting_conv(t *testing.T) {
})
}
}

func Test_AlertGroupSetting_merge(t *testing.T) {
t.Parallel()

// lhs <- rhs = wants
cases := map[string]struct {
lhs AlertGroupSettingModel
rhs AlertGroupSettingModel
wants AlertGroupSettingModel
}{
"nil preserving": {
lhs: AlertGroupSettingModel{
Name: types.StringValue("before"),
},
rhs: AlertGroupSettingModel{
Name: types.StringValue("after"),
ServiceScopes: []string{},
RoleScopes: []string{},
MonitorScopes: []string{},
},
wants: AlertGroupSettingModel{
Name: types.StringValue("after"),
},
},
}

for name, tt := range cases {
t.Run(name, func(t *testing.T) {
t.Parallel()

m := tt.lhs
m.merge(tt.rhs)
if diff := cmp.Diff(m, tt.wants); diff != "" {
t.Error(diff)
}

})
}
}
43 changes: 2 additions & 41 deletions internal/mackerel/aws_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ func (m *AWSIntegrationModel) Read(_ context.Context, client *Client) error {
return err
}

m.merge(*integration)
*m = *integration
return nil
}

Expand Down Expand Up @@ -157,7 +157,7 @@ func newAWSIntegrationModel(aws mackerel.AWSIntegration) (*AWSIntegrationModel,
continue
}
if len(awsService.IncludedMetrics) != 0 {
return nil, fmt.Errorf("%s: IncludedMetrics is not supported.", name)
return nil, fmt.Errorf("%s: IncludedMetrics is not supported", name)
}

svcs[name] = AWSIntegrationService{
Expand Down Expand Up @@ -240,45 +240,6 @@ func (m *AWSIntegrationModel) updateParam() *mackerel.UpdateAWSIntegrationParam
return (*mackerel.UpdateAWSIntegrationParam)(m.createParam())
}

func (m *AWSIntegrationModel) merge(newModel AWSIntegrationModel) {
oldServices := make(map[string]AWSIntegrationService)
m.each(func(name string, service *AWSIntegrationService) *AWSIntegrationService {
if service != nil {
oldServices[name] = *service
}
return service
})

newModel.SecretKey = m.SecretKey
newModel.each(func(name string, service *AWSIntegrationService) *AWSIntegrationService {
oldService, ok := oldServices[name]
if !ok {
return service
}

// If new == nil && old == zero, use old one.
if service == nil {
if !oldService.Enable.ValueBool() &&
len(oldService.ExcludedMetrics) == 0 &&
oldService.Role.IsNull() &&
!oldService.RetireAutomatically.ValueBool() {
return &oldService
} else {
return nil
}
}

if service.Role.ValueString() == "" && oldService.Role.ValueString() == "" {
service.Role = oldService.Role
}
if len(service.ExcludedMetrics) == 0 && len(oldService.ExcludedMetrics) == 0 {
service.ExcludedMetrics = oldService.ExcludedMetrics
}
return service
})
*m = newModel
}

type awsServiceEachFunc func(name string, service *AWSIntegrationService) *AWSIntegrationService

// Iterates and updates over services by name
Expand Down
42 changes: 11 additions & 31 deletions internal/mackerel/downtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func (d *DowntimeModel) Read(_ context.Context, client *Client) error {
if err != nil {
return err
}
d.merge(*newModel)
*d = *newModel
return nil
}

Expand All @@ -95,12 +95,12 @@ func newDowntime(d mackerel.Downtime) *DowntimeModel {
Memo: types.StringValue(d.Memo),
Start: types.Int64Value(d.Start),
Duration: types.Int64Value(d.Duration),
ServiceScopes: d.ServiceScopes,
ServiceExcludeScopes: d.ServiceExcludeScopes,
RoleScopes: d.RoleScopes,
RoleExcludeScopes: d.RoleExcludeScopes,
MonitorScopes: d.MonitorScopes,
MonitorExcludeScopes: d.MonitorExcludeScopes,
ServiceScopes: nilAsEmptySlice(d.ServiceScopes),
ServiceExcludeScopes: nilAsEmptySlice(d.ServiceExcludeScopes),
RoleScopes: nilAsEmptySlice(d.RoleScopes),
RoleExcludeScopes: nilAsEmptySlice(d.RoleExcludeScopes),
MonitorScopes: nilAsEmptySlice(d.MonitorScopes),
MonitorExcludeScopes: nilAsEmptySlice(d.MonitorExcludeScopes),
}
if d.Recurrence != nil {
recurrence := DowntimeRecurrence{
Expand Down Expand Up @@ -178,29 +178,9 @@ func (d *DowntimeModel) mackerelDowntime() *mackerel.Downtime {
return mackerelDowntime
}

func (d *DowntimeModel) merge(newModel DowntimeModel) {
// preserve nil
if len(d.Recurrence) == 1 && len(d.Recurrence[0].Weekdays) == 0 &&
len(newModel.Recurrence) == 1 && len(newModel.Recurrence[0].Weekdays) == 0 {
newModel.Recurrence[0].Weekdays = d.Recurrence[0].Weekdays
}
if len(d.ServiceScopes) == 0 && len(newModel.ServiceScopes) == 0 {
newModel.ServiceScopes = d.ServiceScopes
}
if len(d.ServiceExcludeScopes) == 0 && len(newModel.ServiceExcludeScopes) == 0 {
newModel.ServiceExcludeScopes = d.ServiceExcludeScopes
}
if len(d.RoleScopes) == 0 && len(newModel.RoleScopes) == 0 {
newModel.RoleScopes = d.RoleScopes
}
if len(d.RoleExcludeScopes) == 0 && len(newModel.RoleExcludeScopes) == 0 {
newModel.RoleExcludeScopes = d.RoleExcludeScopes
}
if len(d.MonitorScopes) == 0 && len(newModel.MonitorScopes) == 0 {
newModel.MonitorScopes = d.MonitorScopes
}
if len(d.MonitorExcludeScopes) == 0 && len(newModel.MonitorExcludeScopes) == 0 {
newModel.MonitorExcludeScopes = d.MonitorExcludeScopes
func nilAsEmptySlice[V any](slice []V) []V {
if slice == nil {
return []V{}
}
*d = newModel
return slice
}
128 changes: 32 additions & 96 deletions internal/mackerel/downtime_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,17 @@ func Test_Downtime_ReadDowntime(t *testing.T) {
inID: "5ghjb6vgDFN",

wants: DowntimeModel{
ID: types.StringValue("5ghjb6vgDFN"),
Name: types.StringValue("basic"),
Memo: types.StringValue(""),
Start: types.Int64Value(1735707600),
Duration: types.Int64Value(3600),
ID: types.StringValue("5ghjb6vgDFN"),
Name: types.StringValue("basic"),
Memo: types.StringValue(""),
Start: types.Int64Value(1735707600),
Duration: types.Int64Value(3600),
ServiceScopes: []string{},
ServiceExcludeScopes: []string{},
RoleScopes: []string{},
RoleExcludeScopes: []string{},
MonitorScopes: []string{},
MonitorExcludeScopes: []string{},
},
},
"no downtime": {
Expand Down Expand Up @@ -106,17 +112,29 @@ func Test_Downtime_conv(t *testing.T) {
}{
"basic": {
api: mackerel.Downtime{
ID: "5ghjb6vgDFN",
Name: "basic",
Start: 1735707600,
Duration: 3600,
ID: "5ghjb6vgDFN",
Name: "basic",
Start: 1735707600,
Duration: 3600,
ServiceScopes: []string{},
ServiceExcludeScopes: []string{},
RoleScopes: []string{},
RoleExcludeScopes: []string{},
MonitorScopes: []string{},
MonitorExcludeScopes: []string{},
},
model: DowntimeModel{
ID: types.StringValue("5ghjb6vgDFN"),
Name: types.StringValue("basic"),
Memo: types.StringValue(""),
Start: types.Int64Value(1735707600),
Duration: types.Int64Value(3600),
ID: types.StringValue("5ghjb6vgDFN"),
Name: types.StringValue("basic"),
Memo: types.StringValue(""),
Start: types.Int64Value(1735707600),
Duration: types.Int64Value(3600),
ServiceScopes: []string{},
ServiceExcludeScopes: []string{},
RoleScopes: []string{},
RoleExcludeScopes: []string{},
MonitorScopes: []string{},
MonitorExcludeScopes: []string{},
},
},
"full": {
Expand Down Expand Up @@ -183,85 +201,3 @@ func Test_Downtime_conv(t *testing.T) {
})
}
}

func Test_Downtime_merge(t *testing.T) {
t.Parallel()

// in <- inNew == wants
cases := map[string]struct {
in DowntimeModel
inNew DowntimeModel
wants DowntimeModel
}{
"basic": {
in: DowntimeModel{
ID: types.StringValue("5ghjb6vgDFN"),
Name: types.StringValue("basic"),
Memo: types.StringValue(""),
Start: types.Int64Value(1735707600),
Duration: types.Int64Value(3600),
Recurrence: []DowntimeRecurrence{{
Type: types.StringValue("weekly"),
Interval: types.Int64Value(2),
Weekdays: nil,
Until: types.Int64Value(1767193199),
}},
ServiceScopes: nil,
ServiceExcludeScopes: nil,
RoleScopes: nil,
RoleExcludeScopes: nil,
MonitorScopes: nil,
MonitorExcludeScopes: []string{},
},
inNew: DowntimeModel{
ID: types.StringValue("5ghjb6vgDFN"),
Name: types.StringValue("basic"),
Memo: types.StringValue("memo"), // changed
Start: types.Int64Value(1735707600),
Duration: types.Int64Value(3600),
Recurrence: []DowntimeRecurrence{{
Type: types.StringValue("weekly"),
Interval: types.Int64Value(2),
Weekdays: []string{},
Until: types.Int64Value(1767193199),
}},
ServiceScopes: []string{},
ServiceExcludeScopes: []string{},
RoleScopes: []string{},
RoleExcludeScopes: []string{},
MonitorScopes: []string{},
MonitorExcludeScopes: nil,
},
wants: DowntimeModel{
ID: types.StringValue("5ghjb6vgDFN"),
Name: types.StringValue("basic"),
Memo: types.StringValue("memo"), // changed
Start: types.Int64Value(1735707600),
Duration: types.Int64Value(3600),
Recurrence: []DowntimeRecurrence{{
Type: types.StringValue("weekly"),
Interval: types.Int64Value(2),
Weekdays: nil,
Until: types.Int64Value(1767193199),
}},
ServiceScopes: nil,
ServiceExcludeScopes: nil,
RoleScopes: nil,
RoleExcludeScopes: nil,
MonitorScopes: nil,
MonitorExcludeScopes: []string{},
},
},
}

for name, tt := range cases {
t.Run(name, func(t *testing.T) {
t.Parallel()

tt.in.merge(tt.inNew)
if diff := cmp.Diff(tt.in, tt.wants); diff != "" {
t.Error(diff)
}
})
}
}
12 changes: 12 additions & 0 deletions internal/planmodifierutil/nil_relaxed.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ func NilRelaxedSet() planmodifier.Set {
return nilRelaxedModifier{}
}

func NilRelaxedList() planmodifier.List {
return nilRelaxedModifier{}
}

type nilRelaxedModifier struct{}

const desctiprion = "For compatibility with the states created by SDK provider, Terraform consider nil and zero values to be same."
Expand Down Expand Up @@ -42,3 +46,11 @@ func (_ nilRelaxedModifier) PlanModifySet(ctx context.Context, req planmodifier.
resp.PlanValue = req.StateValue
}
}

func (_ nilRelaxedModifier) PlanModifyList(ctx context.Context, req planmodifier.ListRequest, resp *planmodifier.ListResponse) {
if req.PlanValue.IsUnknown() {
resp.PlanValue = types.ListNull(req.PlanValue.ElementType(ctx))
} else if req.PlanValue.IsNull() && len(req.StateValue.Elements()) == 0 {
resp.PlanValue = req.StateValue
}
}
Loading
Loading