Skip to content

Commit 117d54f

Browse files
committed
Add metric namespace config filters to GCP V2 terraform resource
1 parent 176bfe6 commit 117d54f

File tree

2 files changed

+119
-343
lines changed

2 files changed

+119
-343
lines changed

datadog/fwprovider/resource_datadog_integration_gcp_sts.go

Lines changed: 87 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,25 @@ var (
2121
integrationGcpStsMutex sync.Mutex
2222
_ resource.ResourceWithConfigure = &integrationGcpStsResource{}
2323
_ resource.ResourceWithImportState = &integrationGcpStsResource{}
24+
25+
MetricNamespaceConfigSpec = types.ObjectType{
26+
AttrTypes: map[string]attr.Type{
27+
"id": types.StringType,
28+
"disabled": types.BoolType,
29+
"filters": types.SetType{
30+
ElemType: types.StringType,
31+
},
32+
},
33+
}
34+
35+
MonitoredResourceConfigSpec = types.ObjectType{
36+
AttrTypes: map[string]attr.Type{
37+
"type": types.StringType,
38+
"filters": types.SetType{
39+
ElemType: types.StringType,
40+
},
41+
},
42+
}
2443
)
2544

2645
type integrationGcpStsResource struct {
@@ -31,22 +50,7 @@ type integrationGcpStsResource struct {
3150
type MetricNamespaceConfigModel struct {
3251
ID types.String `tfsdk:"id"`
3352
Disabled types.Bool `tfsdk:"disabled"`
34-
}
35-
36-
var MetricNamespaceConfigSpec = types.ObjectType{
37-
AttrTypes: map[string]attr.Type{
38-
"id": types.StringType,
39-
"disabled": types.BoolType,
40-
},
41-
}
42-
43-
var MonitoredResourceConfigSpec = types.ObjectType{
44-
AttrTypes: map[string]attr.Type{
45-
"type": types.StringType,
46-
"filters": types.SetType{
47-
ElemType: types.StringType,
48-
},
49-
},
53+
Filters types.Set `tfsdk:"filters"`
5054
}
5155

5256
type MonitoredResourceConfigModel struct {
@@ -158,8 +162,7 @@ func (r *integrationGcpStsResource) Schema(_ context.Context, _ resource.SchemaR
158162
Computed: true,
159163
},
160164
"metric_namespace_configs": schema.SetAttribute{
161-
Optional: true,
162-
// if this field is not set by the user, then we will disable prometheus by default
165+
Optional: true,
163166
Computed: true,
164167
Description: "Configurations for GCP metric namespaces.",
165168
ElementType: MetricNamespaceConfigSpec,
@@ -184,6 +187,7 @@ func (r *integrationGcpStsResource) Read(ctx context.Context, request resource.R
184187
if response.Diagnostics.HasError() {
185188
return
186189
}
190+
187191
resp, httpResp, err := r.Api.ListGCPSTSAccounts(r.Auth)
188192
if err != nil {
189193
if httpResp != nil && httpResp.StatusCode == 404 {
@@ -202,7 +206,7 @@ func (r *integrationGcpStsResource) Read(ctx context.Context, request resource.R
202206
for _, account := range resp.GetData() {
203207
if account.GetId() == state.ID.ValueString() {
204208
found = true
205-
r.updateState(ctx, &state, &account)
209+
r.parseGcpStsResponseBody(ctx, &state, &account)
206210
break
207211
}
208212
}
@@ -217,12 +221,11 @@ func (r *integrationGcpStsResource) Read(ctx context.Context, request resource.R
217221
}
218222

219223
func (r *integrationGcpStsResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
220-
var state integrationGcpStsModel
221-
response.Diagnostics.Append(request.Plan.Get(ctx, &state)...)
224+
var plan integrationGcpStsModel
225+
response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...)
222226
if response.Diagnostics.HasError() {
223227
return
224228
}
225-
226229
integrationGcpStsMutex.Lock()
227230
defer integrationGcpStsMutex.Unlock()
228231

@@ -237,11 +240,11 @@ func (r *integrationGcpStsResource) Create(ctx context.Context, request resource
237240
return
238241
}
239242
delegateEmail := delegateResponse.Data.Attributes.GetDelegateAccountEmail()
240-
state.DelegateAccountEmail = types.StringValue(delegateEmail)
243+
plan.DelegateAccountEmail = types.StringValue(delegateEmail)
241244

242-
attributes, diags := r.buildIntegrationGcpStsRequestBody(ctx, &state, false)
243-
if !state.ClientEmail.IsNull() {
244-
attributes.SetClientEmail(state.ClientEmail.ValueString())
245+
attributes, diags := r.buildGcpStsRequestBody(ctx, &plan)
246+
if !plan.ClientEmail.IsNull() {
247+
attributes.SetClientEmail(plan.ClientEmail.ValueString())
245248
}
246249

247250
body := datadogV2.NewGCPSTSServiceAccountCreateRequestWithDefaults()
@@ -261,29 +264,26 @@ func (r *integrationGcpStsResource) Create(ctx context.Context, request resource
261264
response.Diagnostics.AddError("response contains unparsedObject", err.Error())
262265
return
263266
}
264-
r.updateState(ctx, &state, resp.Data)
267+
268+
r.parseGcpStsResponseBody(ctx, &plan, resp.Data)
265269

266270
// Save data into Terraform state
267-
response.Diagnostics.Append(response.State.Set(ctx, &state)...)
271+
response.Diagnostics.Append(response.State.Set(ctx, &plan)...)
268272
}
269273

270274
func (r *integrationGcpStsResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
271-
var state integrationGcpStsModel
272-
273-
var priorState integrationGcpStsModel
274-
275-
response.Diagnostics.Append(request.Plan.Get(ctx, &state)...)
276-
response.Diagnostics.Append(request.State.Get(ctx, &priorState)...)
275+
var plan integrationGcpStsModel
276+
response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...)
277277
if response.Diagnostics.HasError() {
278278
return
279279
}
280280

281281
integrationGcpStsMutex.Lock()
282282
defer integrationGcpStsMutex.Unlock()
283283

284-
id := state.ID.ValueString()
284+
id := plan.ID.ValueString()
285285

286-
attributes, diags := r.buildIntegrationGcpStsRequestBody(ctx, &state, !mncsContainsOnlyPrometheus(ctx, priorState.MetricNamespaceConfigs, response.Diagnostics))
286+
attributes, diags := r.buildGcpStsRequestBody(ctx, &plan)
287287
body := datadogV2.NewGCPSTSServiceAccountUpdateRequestWithDefaults()
288288
body.Data = datadogV2.NewGCPSTSServiceAccountUpdateRequestDataWithDefaults()
289289
body.Data.SetAttributes(attributes)
@@ -298,14 +298,16 @@ func (r *integrationGcpStsResource) Update(ctx context.Context, request resource
298298
response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error retrieving Integration Gcp Sts"))
299299
return
300300
}
301+
301302
if err := utils.CheckForUnparsed(resp); err != nil {
302303
response.Diagnostics.AddError("response contains unparsedObject", err.Error())
303304
return
304305
}
305-
r.updateState(ctx, &state, resp.Data)
306+
307+
r.parseGcpStsResponseBody(ctx, &plan, resp.Data)
306308

307309
// Save data into Terraform state
308-
response.Diagnostics.Append(response.State.Set(ctx, &state)...)
310+
response.Diagnostics.Append(response.State.Set(ctx, &plan)...)
309311
}
310312

311313
func (r *integrationGcpStsResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
@@ -330,103 +332,99 @@ func (r *integrationGcpStsResource) Delete(ctx context.Context, request resource
330332
}
331333
}
332334

333-
func (r *integrationGcpStsResource) updateState(ctx context.Context, state *integrationGcpStsModel, resp *datadogV2.GCPSTSServiceAccount) {
334-
state.ID = types.StringValue(resp.GetId())
335+
func (r *integrationGcpStsResource) parseGcpStsResponseBody(ctx context.Context, model *integrationGcpStsModel, resp *datadogV2.GCPSTSServiceAccount) {
336+
model.ID = types.StringValue(resp.GetId())
335337

336338
attributes := resp.GetAttributes()
337339
if automute, ok := attributes.GetAutomuteOk(); ok {
338-
state.Automute = types.BoolValue(*automute)
340+
model.Automute = types.BoolValue(*automute)
339341
}
340342
if clientEmail, ok := attributes.GetClientEmailOk(); ok {
341-
state.ClientEmail = types.StringValue(*clientEmail)
343+
model.ClientEmail = types.StringValue(*clientEmail)
342344
}
343345
if isCspmEnabled, ok := attributes.GetIsCspmEnabledOk(); ok {
344-
state.IsCspmEnabled = types.BoolValue(*isCspmEnabled)
346+
model.IsCspmEnabled = types.BoolValue(*isCspmEnabled)
345347
}
346348
if isSecurityCommandCenterEnabled, ok := attributes.GetIsSecurityCommandCenterEnabledOk(); ok {
347-
state.IsSecurityCommandCenterEnabled = types.BoolValue(*isSecurityCommandCenterEnabled)
349+
model.IsSecurityCommandCenterEnabled = types.BoolValue(*isSecurityCommandCenterEnabled)
348350
}
349351
if isResourceChangeCollectionEnabled, ok := attributes.GetIsResourceChangeCollectionEnabledOk(); ok {
350-
state.IsResourceChangeCollectionEnabled = types.BoolValue(*isResourceChangeCollectionEnabled)
352+
model.IsResourceChangeCollectionEnabled = types.BoolValue(*isResourceChangeCollectionEnabled)
351353
}
352354
if isPerProjectQuotaEnabled, ok := attributes.GetIsPerProjectQuotaEnabledOk(); ok {
353-
state.IsPerProjectQuotaEnabled = types.BoolValue(*isPerProjectQuotaEnabled)
355+
model.IsPerProjectQuotaEnabled = types.BoolValue(*isPerProjectQuotaEnabled)
354356
}
355357
if resourceCollectionEnabled, ok := attributes.GetResourceCollectionEnabledOk(); ok {
356-
state.ResourceCollectionEnabled = types.BoolValue(*resourceCollectionEnabled)
358+
model.ResourceCollectionEnabled = types.BoolValue(*resourceCollectionEnabled)
357359
}
358360

359361
if accountTags := attributes.GetAccountTags(); len(accountTags) > 0 {
360-
state.AccountTags, _ = types.SetValueFrom(ctx, types.StringType, accountTags)
362+
model.AccountTags, _ = types.SetValueFrom(ctx, types.StringType, accountTags)
361363
}
362364

363-
mncsapi := attributes.GetMetricNamespaceConfigs()
364-
mncs := make([]*MetricNamespaceConfigModel, 0, len(mncsapi))
365-
for _, mnc := range mncsapi {
366-
mncs = append(mncs, &MetricNamespaceConfigModel{
367-
ID: types.StringValue(mnc.GetId()),
368-
Disabled: types.BoolValue(mnc.GetDisabled()),
369-
})
365+
mncs := make([]*MetricNamespaceConfigModel, 0)
366+
for _, cfg := range attributes.GetMetricNamespaceConfigs() {
367+
var mdl MetricNamespaceConfigModel
368+
mdl.ID = types.StringValue(cfg.GetId())
369+
mdl.Disabled = types.BoolValue(cfg.GetDisabled())
370+
mdl.Filters, _ = types.SetValueFrom(ctx, types.StringType, cfg.GetFilters())
371+
mncs = append(mncs, &mdl)
370372
}
371-
state.MetricNamespaceConfigs, _ = types.SetValueFrom(ctx, MetricNamespaceConfigSpec, mncs)
373+
model.MetricNamespaceConfigs, _ = types.SetValueFrom(ctx, MetricNamespaceConfigSpec, mncs)
372374

373-
state.HostFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetHostFilters())
374-
state.CloudRunRevisionFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetCloudRunRevisionFilters())
375+
model.HostFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetHostFilters())
376+
model.CloudRunRevisionFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetCloudRunRevisionFilters())
375377
mrcs := make([]*MonitoredResourceConfigModel, 0)
376378
for _, mrc := range attributes.GetMonitoredResourceConfigs() {
377379
var mdl MonitoredResourceConfigModel
378380
mdl.Type = types.StringValue(string(mrc.GetType()))
379381
mdl.Filters, _ = types.SetValueFrom(ctx, types.StringType, mrc.GetFilters())
380382
mrcs = append(mrcs, &mdl)
381383
}
382-
state.MonitoredResourceConfigs, _ = types.SetValueFrom(ctx, MonitoredResourceConfigSpec, mrcs)
384+
model.MonitoredResourceConfigs, _ = types.SetValueFrom(ctx, MonitoredResourceConfigSpec, mrcs)
383385
}
384386

385-
func (r *integrationGcpStsResource) buildIntegrationGcpStsRequestBody(ctx context.Context, state *integrationGcpStsModel, forUpdate bool) (datadogV2.GCPSTSServiceAccountAttributes, diag.Diagnostics) {
387+
func (r *integrationGcpStsResource) buildGcpStsRequestBody(ctx context.Context, model *integrationGcpStsModel) (datadogV2.GCPSTSServiceAccountAttributes, diag.Diagnostics) {
386388
diags := diag.Diagnostics{}
387389
attributes := datadogV2.GCPSTSServiceAccountAttributes{}
388390

389-
if !state.Automute.IsNull() {
390-
attributes.SetAutomute(state.Automute.ValueBool())
391+
if !model.Automute.IsNull() {
392+
attributes.SetAutomute(model.Automute.ValueBool())
391393
}
392-
if !state.IsCspmEnabled.IsNull() {
393-
attributes.SetIsCspmEnabled(state.IsCspmEnabled.ValueBool())
394+
if !model.IsCspmEnabled.IsNull() {
395+
attributes.SetIsCspmEnabled(model.IsCspmEnabled.ValueBool())
394396
}
395-
if !state.IsSecurityCommandCenterEnabled.IsUnknown() {
396-
attributes.SetIsSecurityCommandCenterEnabled(state.IsSecurityCommandCenterEnabled.ValueBool())
397+
if !model.IsSecurityCommandCenterEnabled.IsUnknown() {
398+
attributes.SetIsSecurityCommandCenterEnabled(model.IsSecurityCommandCenterEnabled.ValueBool())
397399
}
398-
if !state.IsResourceChangeCollectionEnabled.IsUnknown() {
399-
attributes.SetIsResourceChangeCollectionEnabled(state.IsResourceChangeCollectionEnabled.ValueBool())
400+
if !model.IsResourceChangeCollectionEnabled.IsUnknown() {
401+
attributes.SetIsResourceChangeCollectionEnabled(model.IsResourceChangeCollectionEnabled.ValueBool())
400402
}
401-
if !state.ResourceCollectionEnabled.IsUnknown() {
402-
attributes.SetResourceCollectionEnabled(state.ResourceCollectionEnabled.ValueBool())
403+
if !model.ResourceCollectionEnabled.IsUnknown() {
404+
attributes.SetResourceCollectionEnabled(model.ResourceCollectionEnabled.ValueBool())
403405
}
404-
if !state.IsPerProjectQuotaEnabled.IsUnknown() {
405-
attributes.SetIsPerProjectQuotaEnabled(state.IsPerProjectQuotaEnabled.ValueBool())
406+
if !model.IsPerProjectQuotaEnabled.IsUnknown() {
407+
attributes.SetIsPerProjectQuotaEnabled(model.IsPerProjectQuotaEnabled.ValueBool())
406408
}
407409

408-
attributes.SetAccountTags(tfCollectionToSlice[string](ctx, diags, state.AccountTags))
410+
attributes.SetAccountTags(tfCollectionToSlice[string](ctx, diags, model.AccountTags))
409411

410-
mncs := make([]datadogV2.GCPMetricNamespaceConfig, 0)
411-
for _, mnc := range tfCollectionToSlice[*MetricNamespaceConfigModel](ctx, diags, state.MetricNamespaceConfigs) {
412-
mncs = append(mncs, datadogV2.GCPMetricNamespaceConfig{
413-
Id: mnc.ID.ValueStringPointer(),
414-
Disabled: mnc.Disabled.ValueBoolPointer(),
415-
})
416-
}
417-
418-
// only set this field if:
419-
// it's for an Update OR
420-
// the user explicitly sets the field
421-
// otherwise we want to omit it so that the API server can populate defaults when applicable
422-
if forUpdate || !state.MetricNamespaceConfigs.IsUnknown() {
412+
if cfgs := model.MetricNamespaceConfigs; !cfgs.IsUnknown() {
413+
mncs := make([]datadogV2.GCPMetricNamespaceConfig, 0)
414+
for _, mnc := range tfCollectionToSlice[*MetricNamespaceConfigModel](ctx, diags, cfgs) {
415+
mncs = append(mncs, datadogV2.GCPMetricNamespaceConfig{
416+
Id: mnc.ID.ValueStringPointer(),
417+
Disabled: mnc.Disabled.ValueBoolPointer(),
418+
Filters: tfCollectionToSlice[string](ctx, diags, mnc.Filters),
419+
})
420+
}
423421
attributes.SetMetricNamespaceConfigs(mncs)
424422
}
425423

426-
attributes.SetHostFilters(tfCollectionToSlice[string](ctx, diags, state.HostFilters))
427-
attributes.SetCloudRunRevisionFilters(tfCollectionToSlice[string](ctx, diags, state.CloudRunRevisionFilters))
424+
attributes.SetHostFilters(tfCollectionToSlice[string](ctx, diags, model.HostFilters))
425+
attributes.SetCloudRunRevisionFilters(tfCollectionToSlice[string](ctx, diags, model.CloudRunRevisionFilters))
428426
mrcs := make([]datadogV2.GCPMonitoredResourceConfig, 0)
429-
for _, mrc := range tfCollectionToSlice[*MonitoredResourceConfigModel](ctx, diags, state.MonitoredResourceConfigs) {
427+
for _, mrc := range tfCollectionToSlice[*MonitoredResourceConfigModel](ctx, diags, model.MonitoredResourceConfigs) {
430428
mrcs = append(mrcs, datadogV2.GCPMonitoredResourceConfig{
431429
Type: ptrTo(datadogV2.GCPMonitoredResourceConfigType(mrc.Type.ValueString())),
432430
Filters: tfCollectionToSlice[string](ctx, diags, mrc.Filters),
@@ -437,20 +435,6 @@ func (r *integrationGcpStsResource) buildIntegrationGcpStsRequestBody(ctx contex
437435
return attributes, diags
438436
}
439437

440-
func mncsContainsOnlyPrometheus(ctx context.Context, s types.Set, diags diag.Diagnostics) bool {
441-
if s.IsNull() || s.IsUnknown() {
442-
return false
443-
}
444-
var items []MetricNamespaceConfigModel
445-
diags.Append(s.ElementsAs(ctx, &items, false)...)
446-
if diags.HasError() || len(items) != 1 {
447-
return false
448-
}
449-
450-
return items[0].ID.ValueString() == "prometheus" &&
451-
items[0].Disabled.ValueBool()
452-
}
453-
454438
func tfCollectionToSlice[T any](ctx context.Context, diags diag.Diagnostics, col tfCollection) []T {
455439
slice := make([]T, 0)
456440
if !col.IsNull() {

0 commit comments

Comments
 (0)