Skip to content

Commit a0dfb04

Browse files
committed
fix: project filters are now computed
1 parent 9bd1bbc commit a0dfb04

File tree

2 files changed

+128
-79
lines changed

2 files changed

+128
-79
lines changed

internal/provider/resource_project.go

Lines changed: 88 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ import (
1515
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
1616
"github.com/hashicorp/terraform-plugin-framework/resource/schema/boolplanmodifier"
1717
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier"
18+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
1819
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
20+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/setplanmodifier"
1921
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
2022
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
2123
"github.com/hashicorp/terraform-plugin-framework/types"
24+
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
2225
"github.com/jianyuan/go-utils/sliceutils"
2326
"github.com/jianyuan/terraform-provider-sentry/internal/apiclient"
2427
"github.com/jianyuan/terraform-provider-sentry/internal/diagutils"
@@ -34,6 +37,14 @@ type ProjectFilterResourceModel struct {
3437
ErrorMessages types.Set `tfsdk:"error_messages"`
3538
}
3639

40+
func (m ProjectFilterResourceModel) AttributeTypes() map[string]attr.Type {
41+
return map[string]attr.Type{
42+
"blacklisted_ips": types.SetType{ElemType: types.StringType},
43+
"releases": types.SetType{ElemType: types.StringType},
44+
"error_messages": types.SetType{ElemType: types.StringType},
45+
}
46+
}
47+
3748
func (m *ProjectFilterResourceModel) Fill(ctx context.Context, project apiclient.Project) (diags diag.Diagnostics) {
3849
if project.Options == nil {
3950
m.BlacklistedIps = types.SetNull(types.StringType)
@@ -45,7 +56,7 @@ func (m *ProjectFilterResourceModel) Fill(ctx context.Context, project apiclient
4556

4657
if values, ok := project.Options["filters:blacklisted_ips"].(string); ok {
4758
if values == "" {
48-
m.BlacklistedIps = types.SetNull(types.StringType)
59+
m.BlacklistedIps = types.SetValueMust(types.StringType, []attr.Value{})
4960
} else {
5061
m.BlacklistedIps = types.SetValueMust(types.StringType, sliceutils.Map(func(v string) attr.Value {
5162
return types.StringValue(v)
@@ -57,7 +68,7 @@ func (m *ProjectFilterResourceModel) Fill(ctx context.Context, project apiclient
5768

5869
if values, ok := project.Options["filters:releases"].(string); ok {
5970
if values == "" {
60-
m.Releases = types.SetNull(types.StringType)
71+
m.Releases = types.SetValueMust(types.StringType, []attr.Value{})
6172
} else {
6273
m.Releases = types.SetValueMust(types.StringType, sliceutils.Map(func(v string) attr.Value {
6374
return types.StringValue(v)
@@ -69,7 +80,7 @@ func (m *ProjectFilterResourceModel) Fill(ctx context.Context, project apiclient
6980

7081
if values, ok := project.Options["filters:error_messages"].(string); ok {
7182
if values == "" {
72-
m.ErrorMessages = types.SetNull(types.StringType)
83+
m.ErrorMessages = types.SetValueMust(types.StringType, []attr.Value{})
7384
} else {
7485
m.ErrorMessages = types.SetValueMust(types.StringType, sliceutils.Map(func(v string) attr.Value {
7586
return types.StringValue(v)
@@ -83,22 +94,22 @@ func (m *ProjectFilterResourceModel) Fill(ctx context.Context, project apiclient
8394
}
8495

8596
type ProjectResourceModel struct {
86-
Id types.String `tfsdk:"id"`
87-
Organization types.String `tfsdk:"organization"`
88-
Teams types.Set `tfsdk:"teams"`
89-
Name types.String `tfsdk:"name"`
90-
Slug types.String `tfsdk:"slug"`
91-
Platform types.String `tfsdk:"platform"`
92-
DefaultRules types.Bool `tfsdk:"default_rules"`
93-
DefaultKey types.Bool `tfsdk:"default_key"`
94-
InternalId types.String `tfsdk:"internal_id"`
95-
Features types.Set `tfsdk:"features"`
96-
DigestsMinDelay types.Int64 `tfsdk:"digests_min_delay"`
97-
DigestsMaxDelay types.Int64 `tfsdk:"digests_max_delay"`
98-
ResolveAge types.Int64 `tfsdk:"resolve_age"`
99-
Filters *ProjectFilterResourceModel `tfsdk:"filters"`
100-
FingerprintingRules sentrytypes.TrimmedString `tfsdk:"fingerprinting_rules"`
101-
GroupingEnhancements sentrytypes.TrimmedString `tfsdk:"grouping_enhancements"`
97+
Id types.String `tfsdk:"id"`
98+
Organization types.String `tfsdk:"organization"`
99+
Teams types.Set `tfsdk:"teams"`
100+
Name types.String `tfsdk:"name"`
101+
Slug types.String `tfsdk:"slug"`
102+
Platform types.String `tfsdk:"platform"`
103+
DefaultRules types.Bool `tfsdk:"default_rules"`
104+
DefaultKey types.Bool `tfsdk:"default_key"`
105+
InternalId types.String `tfsdk:"internal_id"`
106+
Features types.Set `tfsdk:"features"`
107+
DigestsMinDelay types.Int64 `tfsdk:"digests_min_delay"`
108+
DigestsMaxDelay types.Int64 `tfsdk:"digests_max_delay"`
109+
ResolveAge types.Int64 `tfsdk:"resolve_age"`
110+
Filters types.Object `tfsdk:"filters"`
111+
FingerprintingRules sentrytypes.TrimmedString `tfsdk:"fingerprinting_rules"`
112+
GroupingEnhancements sentrytypes.TrimmedString `tfsdk:"grouping_enhancements"`
102113
}
103114

104115
func (m *ProjectResourceModel) Fill(ctx context.Context, project apiclient.Project) (diags diag.Diagnostics) {
@@ -125,9 +136,12 @@ func (m *ProjectResourceModel) Fill(ctx context.Context, project apiclient.Proje
125136
m.DigestsMaxDelay = types.Int64Value(project.DigestsMaxDelay)
126137
m.ResolveAge = types.Int64Value(project.ResolveAge)
127138

128-
if m.Filters != nil {
129-
diags.Append(m.Filters.Fill(ctx, project)...)
130-
}
139+
var filters ProjectFilterResourceModel
140+
diags.Append(filters.Fill(ctx, project)...)
141+
142+
var filtersDiags diag.Diagnostics
143+
m.Filters, filtersDiags = types.ObjectValueFrom(ctx, filters.AttributeTypes(), filters)
144+
diags.Append(filtersDiags...)
131145

132146
m.FingerprintingRules = sentrytypes.TrimmedStringValue(project.FingerprintingRules)
133147
m.GroupingEnhancements = sentrytypes.TrimmedStringValue(project.GroupingEnhancements)
@@ -209,6 +223,9 @@ func (r *ProjectResource) Schema(ctx context.Context, req resource.SchemaRequest
209223
"features": schema.SetAttribute{
210224
ElementType: types.StringType,
211225
Computed: true,
226+
PlanModifiers: []planmodifier.Set{
227+
setplanmodifier.UseStateForUnknown(),
228+
},
212229
},
213230
"digests_min_delay": schema.Int64Attribute{
214231
Description: "The minimum amount of time (in seconds) to wait between scheduling digests for delivery after the initial scheduling.",
@@ -237,32 +254,48 @@ func (r *ProjectResource) Schema(ctx context.Context, req resource.SchemaRequest
237254
"filters": schema.SingleNestedAttribute{
238255
Description: "Custom filters for this project.",
239256
Optional: true,
257+
Computed: true,
240258
Attributes: map[string]schema.Attribute{
241259
"blacklisted_ips": schema.SetAttribute{
242260
Description: "Filter events from these IP addresses. (e.g. 127.0.0.1 or 10.0.0.0/8)",
243261
ElementType: types.StringType,
244262
Optional: true,
263+
Computed: true,
245264
Validators: []validator.Set{
246265
setvalidator.SizeAtLeast(1),
247266
},
267+
PlanModifiers: []planmodifier.Set{
268+
setplanmodifier.UseStateForUnknown(),
269+
},
248270
},
249271
"releases": schema.SetAttribute{
250272
MarkdownDescription: "Filter events from these releases. Allows [glob pattern matching](https://en.wikipedia.org/wiki/Glob_(programming)). (e.g. 1.* or [!3].[0-9].*)",
251273
ElementType: types.StringType,
252274
Optional: true,
275+
Computed: true,
253276
Validators: []validator.Set{
254277
setvalidator.SizeAtLeast(1),
255278
},
279+
PlanModifiers: []planmodifier.Set{
280+
setplanmodifier.UseStateForUnknown(),
281+
},
256282
},
257283
"error_messages": schema.SetAttribute{
258284
MarkdownDescription: "Filter events by error messages. Allows [glob pattern matching](https://en.wikipedia.org/wiki/Glob_(programming)). (e.g. TypeError* or *: integer division or modulo by zero)",
259285
ElementType: types.StringType,
260286
Optional: true,
287+
Computed: true,
261288
Validators: []validator.Set{
262289
setvalidator.SizeAtLeast(1),
263290
},
291+
PlanModifiers: []planmodifier.Set{
292+
setplanmodifier.UseStateForUnknown(),
293+
},
264294
},
265295
},
296+
PlanModifiers: []planmodifier.Object{
297+
objectplanmodifier.UseStateForUnknown(),
298+
},
266299
},
267300
"fingerprinting_rules": schema.StringAttribute{
268301
MarkdownDescription: "This can be used to modify the fingerprint rules on the server with custom rules. Rules follow the pattern `matcher:glob -> fingerprint, values`. To learn more about fingerprint rules, [read the docs](https://docs.sentry.io/concepts/data-management/event-grouping/fingerprint-rules/).",
@@ -355,35 +388,35 @@ func (r *ProjectResource) Create(ctx context.Context, req resource.CreateRequest
355388
updateBody.ResolveAge = data.ResolveAge.ValueInt64Pointer()
356389
}
357390

358-
if data.Filters != nil {
391+
if !data.Filters.IsUnknown() {
392+
var filters ProjectFilterResourceModel
393+
resp.Diagnostics.Append(data.Filters.As(ctx, &filters, basetypes.ObjectAsOptions{})...)
394+
if resp.Diagnostics.HasError() {
395+
return
396+
}
397+
359398
options := make(map[string]interface{})
360-
if data.Filters.BlacklistedIps.IsNull() {
361-
options["filters:blacklisted_ips"] = ""
362-
} else {
363-
values := []string{}
364-
resp.Diagnostics.Append(data.Filters.BlacklistedIps.ElementsAs(ctx, &values, false)...)
399+
if !filters.BlacklistedIps.IsUnknown() {
400+
var values []string
401+
resp.Diagnostics.Append(filters.BlacklistedIps.ElementsAs(ctx, &values, false)...)
365402
if resp.Diagnostics.HasError() {
366403
return
367404
}
368405
options["filters:blacklisted_ips"] = strings.Join(values, "\n")
369406
}
370407

371-
if data.Filters.Releases.IsNull() {
372-
options["filters:releases"] = ""
373-
} else {
374-
values := []string{}
375-
resp.Diagnostics.Append(data.Filters.Releases.ElementsAs(ctx, &values, false)...)
408+
if !filters.Releases.IsUnknown() {
409+
var values []string
410+
resp.Diagnostics.Append(filters.Releases.ElementsAs(ctx, &values, false)...)
376411
if resp.Diagnostics.HasError() {
377412
return
378413
}
379414
options["filters:releases"] = strings.Join(values, "\n")
380415
}
381416

382-
if data.Filters.ErrorMessages.IsNull() {
383-
options["filters:error_messages"] = ""
384-
} else {
385-
values := []string{}
386-
resp.Diagnostics.Append(data.Filters.ErrorMessages.ElementsAs(ctx, &values, false)...)
417+
if !filters.ErrorMessages.IsUnknown() {
418+
var values []string
419+
resp.Diagnostics.Append(filters.ErrorMessages.ElementsAs(ctx, &values, false)...)
387420
if resp.Diagnostics.HasError() {
388421
return
389422
}
@@ -538,35 +571,36 @@ func (r *ProjectResource) Update(ctx context.Context, req resource.UpdateRequest
538571
updateBody.ResolveAge = plan.ResolveAge.ValueInt64Pointer()
539572
}
540573

541-
if plan.Filters != nil {
574+
if !plan.Filters.Equal(state.Filters) {
575+
var filtersPlan, filtersState ProjectFilterResourceModel
576+
resp.Diagnostics.Append(plan.Filters.As(ctx, &filtersPlan, basetypes.ObjectAsOptions{})...)
577+
resp.Diagnostics.Append(state.Filters.As(ctx, &filtersState, basetypes.ObjectAsOptions{})...)
578+
if resp.Diagnostics.HasError() {
579+
return
580+
}
581+
542582
options := make(map[string]interface{})
543-
if plan.Filters.BlacklistedIps.IsNull() {
544-
options["filters:blacklisted_ips"] = ""
545-
} else {
546-
values := []string{}
547-
resp.Diagnostics.Append(plan.Filters.BlacklistedIps.ElementsAs(ctx, &values, false)...)
583+
if !filtersPlan.BlacklistedIps.Equal(filtersState.BlacklistedIps) {
584+
var values []string
585+
resp.Diagnostics.Append(filtersPlan.BlacklistedIps.ElementsAs(ctx, &values, false)...)
548586
if resp.Diagnostics.HasError() {
549587
return
550588
}
551589
options["filters:blacklisted_ips"] = strings.Join(values, "\n")
552590
}
553591

554-
if plan.Filters.Releases.IsNull() {
555-
options["filters:releases"] = ""
556-
} else {
557-
values := []string{}
558-
resp.Diagnostics.Append(plan.Filters.Releases.ElementsAs(ctx, &values, false)...)
592+
if !filtersPlan.Releases.Equal(filtersState.Releases) {
593+
var values []string
594+
resp.Diagnostics.Append(filtersPlan.Releases.ElementsAs(ctx, &values, false)...)
559595
if resp.Diagnostics.HasError() {
560596
return
561597
}
562598
options["filters:releases"] = strings.Join(values, "\n")
563599
}
564600

565-
if plan.Filters.ErrorMessages.IsNull() {
566-
options["filters:error_messages"] = ""
567-
} else {
568-
values := []string{}
569-
resp.Diagnostics.Append(plan.Filters.ErrorMessages.ElementsAs(ctx, &values, false)...)
601+
if !filtersPlan.ErrorMessages.Equal(filtersState.ErrorMessages) {
602+
var values []string
603+
resp.Diagnostics.Append(filtersPlan.ErrorMessages.ElementsAs(ctx, &values, false)...)
570604
if resp.Diagnostics.HasError() {
571605
return
572606
}

0 commit comments

Comments
 (0)