Skip to content

Commit 996e233

Browse files
authored
[datadog_integration_gcp_sts] Add granular namespace filters to GCP V2 Terraform Provider (#3299)
Add metric namespace config filters to GCP V2 terraform resource Update cassettes Run make docs Co-authored-by: ashraf.hanafy <[email protected]>
1 parent 34625de commit 996e233

9 files changed

+194
-150
lines changed

datadog/fwprovider/resource_datadog_integration_gcp_sts.go

Lines changed: 63 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ var (
2626
AttrTypes: map[string]attr.Type{
2727
"id": types.StringType,
2828
"disabled": types.BoolType,
29+
"filters": types.SetType{
30+
ElemType: types.StringType,
31+
},
2932
},
3033
}
3134

@@ -47,7 +50,9 @@ type integrationGcpStsResource struct {
4750
type MetricNamespaceConfigModel struct {
4851
ID types.String `tfsdk:"id"`
4952
Disabled types.Bool `tfsdk:"disabled"`
53+
Filters types.Set `tfsdk:"filters"`
5054
}
55+
5156
type MonitoredResourceConfigModel struct {
5257
Type types.String `tfsdk:"type"`
5358
Filters types.Set `tfsdk:"filters"`
@@ -183,6 +188,7 @@ func (r *integrationGcpStsResource) Read(ctx context.Context, request resource.R
183188
if response.Diagnostics.HasError() {
184189
return
185190
}
191+
186192
resp, httpResp, err := r.Api.ListGCPSTSAccounts(r.Auth)
187193
if err != nil {
188194
if httpResp != nil && httpResp.StatusCode == 404 {
@@ -201,7 +207,7 @@ func (r *integrationGcpStsResource) Read(ctx context.Context, request resource.R
201207
for _, account := range resp.GetData() {
202208
if account.GetId() == state.ID.ValueString() {
203209
found = true
204-
r.updateState(ctx, &state, &account)
210+
r.parseGcpStsResponseBody(ctx, &state, &account)
205211
break
206212
}
207213
}
@@ -216,12 +222,11 @@ func (r *integrationGcpStsResource) Read(ctx context.Context, request resource.R
216222
}
217223

218224
func (r *integrationGcpStsResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) {
219-
var state integrationGcpStsModel
220-
response.Diagnostics.Append(request.Plan.Get(ctx, &state)...)
225+
var plan integrationGcpStsModel
226+
response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...)
221227
if response.Diagnostics.HasError() {
222228
return
223229
}
224-
225230
integrationGcpStsMutex.Lock()
226231
defer integrationGcpStsMutex.Unlock()
227232

@@ -236,11 +241,11 @@ func (r *integrationGcpStsResource) Create(ctx context.Context, request resource
236241
return
237242
}
238243
delegateEmail := delegateResponse.Data.Attributes.GetDelegateAccountEmail()
239-
state.DelegateAccountEmail = types.StringValue(delegateEmail)
244+
plan.DelegateAccountEmail = types.StringValue(delegateEmail)
240245

241-
attributes, diags := r.buildIntegrationGcpStsRequestBody(ctx, &state)
242-
if !state.ClientEmail.IsNull() {
243-
attributes.SetClientEmail(state.ClientEmail.ValueString())
246+
attributes, diags := r.buildGcpStsRequestBody(ctx, &plan)
247+
if !plan.ClientEmail.IsNull() {
248+
attributes.SetClientEmail(plan.ClientEmail.ValueString())
244249
}
245250

246251
body := datadogV2.NewGCPSTSServiceAccountCreateRequestWithDefaults()
@@ -260,26 +265,26 @@ func (r *integrationGcpStsResource) Create(ctx context.Context, request resource
260265
response.Diagnostics.AddError("response contains unparsedObject", err.Error())
261266
return
262267
}
263-
r.updateState(ctx, &state, resp.Data)
268+
269+
r.parseGcpStsResponseBody(ctx, &plan, resp.Data)
264270

265271
// Save data into Terraform state
266-
response.Diagnostics.Append(response.State.Set(ctx, &state)...)
272+
response.Diagnostics.Append(response.State.Set(ctx, &plan)...)
267273
}
268274

269275
func (r *integrationGcpStsResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) {
270-
var state integrationGcpStsModel
271-
272-
response.Diagnostics.Append(request.Plan.Get(ctx, &state)...)
276+
var plan integrationGcpStsModel
277+
response.Diagnostics.Append(request.Plan.Get(ctx, &plan)...)
273278
if response.Diagnostics.HasError() {
274279
return
275280
}
276281

277282
integrationGcpStsMutex.Lock()
278283
defer integrationGcpStsMutex.Unlock()
279284

280-
id := state.ID.ValueString()
285+
id := plan.ID.ValueString()
281286

282-
attributes, diags := r.buildIntegrationGcpStsRequestBody(ctx, &state)
287+
attributes, diags := r.buildGcpStsRequestBody(ctx, &plan)
283288
body := datadogV2.NewGCPSTSServiceAccountUpdateRequestWithDefaults()
284289
body.Data = datadogV2.NewGCPSTSServiceAccountUpdateRequestDataWithDefaults()
285290
body.Data.SetAttributes(attributes)
@@ -294,14 +299,16 @@ func (r *integrationGcpStsResource) Update(ctx context.Context, request resource
294299
response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error retrieving Integration Gcp Sts"))
295300
return
296301
}
302+
297303
if err := utils.CheckForUnparsed(resp); err != nil {
298304
response.Diagnostics.AddError("response contains unparsedObject", err.Error())
299305
return
300306
}
301-
r.updateState(ctx, &state, resp.Data)
307+
308+
r.parseGcpStsResponseBody(ctx, &plan, resp.Data)
302309

303310
// Save data into Terraform state
304-
response.Diagnostics.Append(response.State.Set(ctx, &state)...)
311+
response.Diagnostics.Append(response.State.Set(ctx, &plan)...)
305312
}
306313

307314
func (r *integrationGcpStsResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) {
@@ -326,99 +333,101 @@ func (r *integrationGcpStsResource) Delete(ctx context.Context, request resource
326333
}
327334
}
328335

329-
func (r *integrationGcpStsResource) updateState(ctx context.Context, state *integrationGcpStsModel, resp *datadogV2.GCPSTSServiceAccount) {
330-
state.ID = types.StringValue(resp.GetId())
336+
func (r *integrationGcpStsResource) parseGcpStsResponseBody(ctx context.Context, model *integrationGcpStsModel, resp *datadogV2.GCPSTSServiceAccount) {
337+
model.ID = types.StringValue(resp.GetId())
331338

332339
attributes := resp.GetAttributes()
333340
if automute, ok := attributes.GetAutomuteOk(); ok {
334-
state.Automute = types.BoolValue(*automute)
341+
model.Automute = types.BoolValue(*automute)
335342
}
336343
if clientEmail, ok := attributes.GetClientEmailOk(); ok {
337-
state.ClientEmail = types.StringValue(*clientEmail)
344+
model.ClientEmail = types.StringValue(*clientEmail)
338345
}
339346
if isCspmEnabled, ok := attributes.GetIsCspmEnabledOk(); ok {
340-
state.IsCspmEnabled = types.BoolValue(*isCspmEnabled)
347+
model.IsCspmEnabled = types.BoolValue(*isCspmEnabled)
341348
}
342349
if isSecurityCommandCenterEnabled, ok := attributes.GetIsSecurityCommandCenterEnabledOk(); ok {
343-
state.IsSecurityCommandCenterEnabled = types.BoolValue(*isSecurityCommandCenterEnabled)
350+
model.IsSecurityCommandCenterEnabled = types.BoolValue(*isSecurityCommandCenterEnabled)
344351
}
345352
if isResourceChangeCollectionEnabled, ok := attributes.GetIsResourceChangeCollectionEnabledOk(); ok {
346-
state.IsResourceChangeCollectionEnabled = types.BoolValue(*isResourceChangeCollectionEnabled)
353+
model.IsResourceChangeCollectionEnabled = types.BoolValue(*isResourceChangeCollectionEnabled)
347354
}
348355
if isPerProjectQuotaEnabled, ok := attributes.GetIsPerProjectQuotaEnabledOk(); ok {
349-
state.IsPerProjectQuotaEnabled = types.BoolValue(*isPerProjectQuotaEnabled)
356+
model.IsPerProjectQuotaEnabled = types.BoolValue(*isPerProjectQuotaEnabled)
350357
}
351358
if resourceCollectionEnabled, ok := attributes.GetResourceCollectionEnabledOk(); ok {
352-
state.ResourceCollectionEnabled = types.BoolValue(*resourceCollectionEnabled)
359+
model.ResourceCollectionEnabled = types.BoolValue(*resourceCollectionEnabled)
353360
}
354361

355362
if accountTags := attributes.GetAccountTags(); len(accountTags) > 0 {
356-
state.AccountTags, _ = types.SetValueFrom(ctx, types.StringType, accountTags)
363+
model.AccountTags, _ = types.SetValueFrom(ctx, types.StringType, accountTags)
357364
}
358365

359366
mncs := make([]*MetricNamespaceConfigModel, 0)
360-
for _, mnc := range attributes.GetMetricNamespaceConfigs() {
361-
mncs = append(mncs, &MetricNamespaceConfigModel{
362-
ID: types.StringValue(mnc.GetId()),
363-
Disabled: types.BoolValue(mnc.GetDisabled()),
364-
})
367+
for _, cfg := range attributes.GetMetricNamespaceConfigs() {
368+
var mdl MetricNamespaceConfigModel
369+
mdl.ID = types.StringValue(cfg.GetId())
370+
mdl.Disabled = types.BoolValue(cfg.GetDisabled())
371+
mdl.Filters, _ = types.SetValueFrom(ctx, types.StringType, cfg.GetFilters())
372+
mncs = append(mncs, &mdl)
365373
}
366-
state.MetricNamespaceConfigs, _ = types.SetValueFrom(ctx, MetricNamespaceConfigSpec, mncs)
374+
model.MetricNamespaceConfigs, _ = types.SetValueFrom(ctx, MetricNamespaceConfigSpec, mncs)
367375

368-
state.HostFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetHostFilters())
369-
state.CloudRunRevisionFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetCloudRunRevisionFilters())
376+
model.HostFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetHostFilters())
377+
model.CloudRunRevisionFilters, _ = types.SetValueFrom(ctx, types.StringType, attributes.GetCloudRunRevisionFilters())
370378
mrcs := make([]*MonitoredResourceConfigModel, 0)
371379
for _, mrc := range attributes.GetMonitoredResourceConfigs() {
372380
var mdl MonitoredResourceConfigModel
373381
mdl.Type = types.StringValue(string(mrc.GetType()))
374382
mdl.Filters, _ = types.SetValueFrom(ctx, types.StringType, mrc.GetFilters())
375383
mrcs = append(mrcs, &mdl)
376384
}
377-
state.MonitoredResourceConfigs, _ = types.SetValueFrom(ctx, MonitoredResourceConfigSpec, mrcs)
385+
model.MonitoredResourceConfigs, _ = types.SetValueFrom(ctx, MonitoredResourceConfigSpec, mrcs)
378386
}
379387

380-
func (r *integrationGcpStsResource) buildIntegrationGcpStsRequestBody(ctx context.Context, state *integrationGcpStsModel) (datadogV2.GCPSTSServiceAccountAttributes, diag.Diagnostics) {
388+
func (r *integrationGcpStsResource) buildGcpStsRequestBody(ctx context.Context, model *integrationGcpStsModel) (datadogV2.GCPSTSServiceAccountAttributes, diag.Diagnostics) {
381389
diags := diag.Diagnostics{}
382390
attributes := datadogV2.GCPSTSServiceAccountAttributes{}
383391

384-
if !state.Automute.IsNull() {
385-
attributes.SetAutomute(state.Automute.ValueBool())
392+
if !model.Automute.IsNull() {
393+
attributes.SetAutomute(model.Automute.ValueBool())
386394
}
387-
if !state.IsCspmEnabled.IsNull() {
388-
attributes.SetIsCspmEnabled(state.IsCspmEnabled.ValueBool())
395+
if !model.IsCspmEnabled.IsNull() {
396+
attributes.SetIsCspmEnabled(model.IsCspmEnabled.ValueBool())
389397
}
390-
if !state.IsSecurityCommandCenterEnabled.IsUnknown() {
391-
attributes.SetIsSecurityCommandCenterEnabled(state.IsSecurityCommandCenterEnabled.ValueBool())
398+
if !model.IsSecurityCommandCenterEnabled.IsUnknown() {
399+
attributes.SetIsSecurityCommandCenterEnabled(model.IsSecurityCommandCenterEnabled.ValueBool())
392400
}
393-
if !state.IsResourceChangeCollectionEnabled.IsUnknown() {
394-
attributes.SetIsResourceChangeCollectionEnabled(state.IsResourceChangeCollectionEnabled.ValueBool())
401+
if !model.IsResourceChangeCollectionEnabled.IsUnknown() {
402+
attributes.SetIsResourceChangeCollectionEnabled(model.IsResourceChangeCollectionEnabled.ValueBool())
395403
}
396-
if !state.ResourceCollectionEnabled.IsUnknown() {
397-
attributes.SetResourceCollectionEnabled(state.ResourceCollectionEnabled.ValueBool())
404+
if !model.ResourceCollectionEnabled.IsUnknown() {
405+
attributes.SetResourceCollectionEnabled(model.ResourceCollectionEnabled.ValueBool())
398406
}
399-
if !state.IsPerProjectQuotaEnabled.IsUnknown() {
400-
attributes.SetIsPerProjectQuotaEnabled(state.IsPerProjectQuotaEnabled.ValueBool())
407+
if !model.IsPerProjectQuotaEnabled.IsUnknown() {
408+
attributes.SetIsPerProjectQuotaEnabled(model.IsPerProjectQuotaEnabled.ValueBool())
401409
}
402410

403-
attributes.SetAccountTags(tfCollectionToSlice[string](ctx, diags, state.AccountTags))
411+
attributes.SetAccountTags(tfCollectionToSlice[string](ctx, diags, model.AccountTags))
404412

405413
// only set this field if the user explicitly sets the field
406414
// otherwise we want to omit it so that the API server can populate defaults when applicable
407-
if cfgs := state.MetricNamespaceConfigs; !cfgs.IsUnknown() {
415+
if cfgs := model.MetricNamespaceConfigs; !cfgs.IsUnknown() {
408416
mncs := make([]datadogV2.GCPMetricNamespaceConfig, 0)
409417
for _, mnc := range tfCollectionToSlice[*MetricNamespaceConfigModel](ctx, diags, cfgs) {
410418
mncs = append(mncs, datadogV2.GCPMetricNamespaceConfig{
411419
Id: mnc.ID.ValueStringPointer(),
412420
Disabled: mnc.Disabled.ValueBoolPointer(),
421+
Filters: tfCollectionToSlice[string](ctx, diags, mnc.Filters),
413422
})
414423
}
415424
attributes.SetMetricNamespaceConfigs(mncs)
416425
}
417426

418-
attributes.SetHostFilters(tfCollectionToSlice[string](ctx, diags, state.HostFilters))
419-
attributes.SetCloudRunRevisionFilters(tfCollectionToSlice[string](ctx, diags, state.CloudRunRevisionFilters))
427+
attributes.SetHostFilters(tfCollectionToSlice[string](ctx, diags, model.HostFilters))
428+
attributes.SetCloudRunRevisionFilters(tfCollectionToSlice[string](ctx, diags, model.CloudRunRevisionFilters))
420429
mrcs := make([]datadogV2.GCPMonitoredResourceConfig, 0)
421-
for _, mrc := range tfCollectionToSlice[*MonitoredResourceConfigModel](ctx, diags, state.MonitoredResourceConfigs) {
430+
for _, mrc := range tfCollectionToSlice[*MonitoredResourceConfigModel](ctx, diags, model.MonitoredResourceConfigs) {
422431
mrcs = append(mrcs, datadogV2.GCPMonitoredResourceConfig{
423432
Type: ptrTo(datadogV2.GCPMonitoredResourceConfigType(mrc.Type.ValueString())),
424433
Filters: tfCollectionToSlice[string](ctx, diags, mrc.Filters),
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2025-10-28T13:40:01.25536-04:00
1+
2025-10-30T11:38:29.608552-04:00

0 commit comments

Comments
 (0)