From 404c26acf6a838c3731af7899cec906b9be1e26f Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Fri, 6 Sep 2024 13:23:53 +0200 Subject: [PATCH 1/9] add asm_exclusion_filters resource --- ...ource_datadog_asm_waf_exclusion_filters.go | 137 ++++++++++ datadog/fwprovider/framework_provider.go | 2 + ...ource_datadog_asm_waf_exclusion_filters.go | 249 ++++++++++++++++++ .../internal/utils/api_instances_helper.go | 9 + go.mod | 2 +- go.sum | 2 + 6 files changed, 400 insertions(+), 1 deletion(-) create mode 100644 datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go create mode 100644 datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go diff --git a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go new file mode 100644 index 0000000000..0ac22bd182 --- /dev/null +++ b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go @@ -0,0 +1,137 @@ +package fwprovider + +import ( + "context" + "crypto/sha256" + "fmt" + "strings" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadogV2" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + + "github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils" +) + +var ( + _ datasource.DataSourceWithConfigure = &asmWafExclusionFiltersDataSource{} +) + +type asmWafExclusionFiltersDataSource struct { + api *datadogV2.ASMExclusionFiltersApi + auth context.Context +} + +type asmWafExclusionFiltersDataSourceModel struct { + Id types.String `tfsdk:"id"` + ExclusionFiltersIds types.List `tfsdk:"exclusion_filters_ids"` + ExclusionFilters []asmWafExclusionFiltersModel `tfsdk:"exclusion_filters"` +} + +func NewAsmWafExclusionFiltersDataSource() datasource.DataSource { + return &asmWafExclusionFiltersDataSource{} +} + +func (r *asmWafExclusionFiltersDataSource) Configure(_ context.Context, request datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { + providerData := request.ProviderData.(*FrameworkProvider) + r.api = providerData.DatadogApiInstances.GetASMExclusionFiltersApiV2() + r.auth = providerData.Auth +} + +func (*asmWafExclusionFiltersDataSource) Metadata(_ context.Context, _ datasource.MetadataRequest, response *datasource.MetadataResponse) { + response.TypeName = "asm_waf_exclusion_filters" +} + +func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var state asmWafExclusionFiltersDataSourceModel + response.Diagnostics.Append(request.Config.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + // Fetch the exclusion filters using the API + res, _, err := r.api.ListASMExclusionFilters(r.auth) + if err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error while fetching exclusion filters")) + return + } + + data := res.GetData() + exclusionFiltersIds := make([]string, len(data)) + exclusionFilters := make([]asmWafExclusionFiltersModel, len(data)) + + // Iterate through the exclusion filters data received + for idx, exclusionFilter := range res.GetData() { + var exclusionFilterModel asmWafExclusionFiltersModel + + // Direct mapping of fields from exclusionFilter struct + exclusionFilterModel.Id = types.StringValue(exclusionFilter.GetId()) + + // Corrected access to Attributes (with uppercase A) + attributes := exclusionFilter.GetAttributes() + + exclusionFilterModel.Description = types.StringValue(attributes.GetDescription()) + exclusionFilterModel.Enabled = types.BoolValue(attributes.GetEnabled()) + exclusionFilterModel.Search_Query = types.StringValue(attributes.GetSearchQuery()) + + // Collect the exclusion filter IDs and model + exclusionFiltersIds[idx] = exclusionFilter.GetId() + exclusionFilters[idx] = exclusionFilterModel + } + + // Set the state ID based on the exclusion filters IDs + stateId := strings.Join(exclusionFiltersIds, "--") + state.Id = types.StringValue(computeExclusionFiltersDataSourceID(&stateId)) + + // Convert the exclusion filter IDs to a Terraform list + tfExclusionFiltersIds, diags := types.ListValueFrom(ctx, types.StringType, exclusionFiltersIds) + response.Diagnostics.Append(diags...) + state.ExclusionFiltersIds = tfExclusionFiltersIds + state.ExclusionFilters = exclusionFilters + + // Save the state + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func computeExclusionFiltersDataSourceID(exclusionFiltersIds *string) string { // return to state.Id + // Key for hashing + var b strings.Builder + if exclusionFiltersIds != nil { + b.WriteString(*exclusionFiltersIds) + } + keyStr := b.String() + h := sha256.New() + h.Write([]byte(keyStr)) + + return fmt.Sprintf("%x", h.Sum(nil)) +} + +func (*asmWafExclusionFiltersDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) { + response.Schema = schema.Schema{ + Description: "Use this data source to retrieve information about existing WAF exclusion filters.", + Attributes: map[string]schema.Attribute{ + "id": utils.ResourceIDAttribute(), + "exclusion_filters_ids": schema.ListAttribute{ + Computed: true, + Description: "List of IDs for the exclusion filters.", + ElementType: types.StringType, + }, + "exclusion_filters": schema.ListAttribute{ + Computed: true, + Description: "List of exclusion filters", + ElementType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "id": types.StringType, + // "type": types.StringType, + "description": types.StringType, + "enabled": types.BoolType, + // "path_glob": types.StringType, + "search_query": types.StringType, + }, + }, + }, + }, + } +} diff --git a/datadog/fwprovider/framework_provider.go b/datadog/fwprovider/framework_provider.go index e6bc7cd901..2737635fea 100644 --- a/datadog/fwprovider/framework_provider.go +++ b/datadog/fwprovider/framework_provider.go @@ -62,6 +62,7 @@ var Resources = []func() resource.Resource{ NewUserRoleResource, NewSecurityMonitoringSuppressionResource, NewCSMThreatsAgentRuleResource, + NewAsmWafExclusionFiltersResource, NewServiceAccountResource, NewWebhookResource, NewWebhookCustomVariableResource, @@ -86,6 +87,7 @@ var Datasources = []func() datasource.DataSource{ NewDatadogRoleUsersDataSource, NewSecurityMonitoringSuppressionDataSource, NewCSMThreatsAgentRulesDataSource, + NewAsmWafExclusionFiltersDataSource, } // FrameworkProvider struct diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go new file mode 100644 index 0000000000..e77a5afb22 --- /dev/null +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -0,0 +1,249 @@ +package fwprovider + +import ( + "context" + "sync" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadogV2" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + + "github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils" +) + +var ( + asmWafExclusionFiltersMutex sync.Mutex + _ resource.ResourceWithConfigure = &asmWafExclusionFiltersResource{} + _ resource.ResourceWithImportState = &asmWafExclusionFiltersResource{} +) + +type asmWafExclusionFiltersModel struct { + Id types.String `tfsdk:"id"` + Description types.String `tfsdk:"description"` + Enabled types.Bool `tfsdk:"enabled"` + Search_Query types.String `tfsdk:"search_query"` +} + +type asmWafExclusionFiltersResource struct { + api *datadogV2.ASMExclusionFiltersApi + auth context.Context +} + +func NewAsmWafExclusionFiltersResource() resource.Resource { + return &asmWafExclusionFiltersResource{} +} + +func (r *asmWafExclusionFiltersResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "asm_waf_exclusion_filters" +} + +func (r *asmWafExclusionFiltersResource) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { + providerData := request.ProviderData.(*FrameworkProvider) + r.api = providerData.DatadogApiInstances.GetASMExclusionFiltersApiV2() // to change + r.auth = providerData.Auth +} + +func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { // to change + response.Schema = schema.Schema{ + Description: "Provides a Datadog ASM WAF Exclusion Filters API resource.", + Attributes: map[string]schema.Attribute{ + "id": utils.ResourceIDAttribute(), + "description": schema.StringAttribute{ + Optional: true, + Description: "A description for the exclusion filter.", + Default: stringdefault.StaticString(""), + Computed: true, + }, + "enabled": schema.BoolAttribute{ + Required: true, + Description: "Indicates whether the exclusion filter is enabled.", + }, + "search_query": schema.StringAttribute{ + Required: true, + Description: "The search query of the exclusion filter", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + }, + } +} + +func (r *asmWafExclusionFiltersResource) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) +} + +func (r *asmWafExclusionFiltersResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + // var state asmWafExclusionFiltersModel + // response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) + // if response.Diagnostics.HasError() { + // return + // } + + // asmWafExclusionFiltersMutex.Lock() + // defer asmWafExclusionFiltersMutex.Unlock() + + // exclusionFiltersPayload, err := r.buildCreateAsmWafExclusionFiltersPayload(&state) + // if err != nil { + // response.Diagnostics.AddError("error while parsing resource", err.Error()) + // } + + // res, _, err := r.api.handlePostExclusionFilters(r.auth, *exclusionFiltersPayload) // to change: endpoint POST + // if err != nil { + // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error creating agent rule")) + // return + // } + // if err := utils.CheckForUnparsed(response); err != nil { + // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) + // return + // } + + // r.updateStateFromResponse(ctx, &state, &res) + // response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var state asmWafExclusionFiltersModel + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + exclusionFiltersId := state.Id.ValueString() + res, httpResponse, err := r.api.ListASMExclusionFilters(r.auth) + + if err != nil { + if httpResponse != nil && httpResponse.StatusCode == 404 { + response.State.RemoveResource(ctx) + return + } + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error fetching exclusion filters")) + return + } + + var matchedExclusionFilter *datadogV2.ASMExclusionFilter + for _, exclusionFilter := range res.GetData() { + if exclusionFilter.GetId() == exclusionFiltersId { + matchedExclusionFilter = &exclusionFilter + break + } + } + + if matchedExclusionFilter == nil { + response.State.RemoveResource(ctx) + return + } + + if err := utils.CheckForUnparsed(response); err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) + return + } + + r.updateStateFromResponse(ctx, &state, matchedExclusionFilter) + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *asmWafExclusionFiltersResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + // var state asmWafExclusionFiltersModel + // response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) + // if response.Diagnostics.HasError() { + // return + // } + + // asmWafExclusionFiltersMutex.Lock() + // defer asmWafExclusionFiltersMutex.Unlock() + + // exclusionFiltersPayload, err := r.buildUpdateAsmWafExclusionFiltersPayload(&state) + // if err != nil { + // response.Diagnostics.AddError("error while parsing resource", err.Error()) + // } + + // res, _, err := r.api.handlePutExclusionFilter(r.auth, state.Id.ValueString(), *exclusionFiltersPayload) // to change: endpoint PATCH/PUT + // if err != nil { + // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error updating agent rule")) + // return + // } + // if err := utils.CheckForUnparsed(response); err != nil { + // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) + // return + // } + + // r.updateStateFromResponse(ctx, &state, &res) + // response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + // var state asmWafExclusionFiltersModel + // response.Diagnostics.Append(request.State.Get(ctx, &state)...) + // if response.Diagnostics.HasError() { + // return + // } + + // asmWafExclusionFiltersMutex.Lock() + // defer asmWafExclusionFiltersMutex.Unlock() + + // id := state.Id.ValueString() + + // httpResp, err := r.api.handleDeleteExclusionFilterByID(r.auth, id) // to change: endpoint DELETE + // + // if err != nil { + // if httpResp != nil && httpResp.StatusCode == 404 { + // return + // } + // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error deleting agent rule")) + // return + // } +} + +// // to change: payload from the Create function +// func (r *asmWafExclusionFiltersResource) buildCreateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.CloudWorkloadSecurityExclusionFiltersCreateRequest, error) { +// _, description, enabled, search_query := r.extractExclusionFiltersAttributesFromResource(state) + +// attributes := datadogV2.CloudWorkloadSecurityExclusionFiltersCreateAttributes{} +// attributes.Search_Query = search_query +// attributes.Description = description +// attributes.Enabled = &enabled + +// data := datadogV2.NewCloudWorkloadSecurityExclusionFiltersCreateData(attributes, datadogV2.CLOUDWORKLOADSECURITYEXCLUSIONFILTERSTYPE_AGENT_RULE) +// return datadogV2.NewCloudWorkloadSecurityExclusionFiltersCreateRequest(*data), nil +// } + +// // to change: payload from the Update function +// func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.CloudWorkloadSecurityExclusionFiltersUpdateRequest, error) { +// exclusionFiltersId, _, description, enabled, _ := r.extractExclusionFiltersAttributesFromResource(state) + +// attributes := datadogV2.CloudWorkloadSecurityExclusionFiltersUpdateAttributes{} +// attributes.Description = description +// attributes.Enabled = &enabled + +// data := datadogV2.NewCloudWorkloadSecurityExclusionFiltersUpdateData(attributes, datadogV2.CLOUDWORKLOADSECURITYEXCLUSIONFILTERSTYPE_AGENT_RULE) +// data.Id = &exclusionFiltersId +// return datadogV2.NewCloudWorkloadSecurityExclusionFiltersUpdateRequest(*data), nil +// } + +// // called from the payloads above +// func (r *asmWafExclusionFiltersResource) extractExclusionFiltersAttributesFromResource(state *asmWafExclusionFiltersModel) (string, *string, bool, string) { +// // Mandatory fields +// id := state.Id.ValueString() +// enabled := state.Enabled.ValueBool() +// search_query := state.Search_Query.ValueString() +// description := state.Description.ValueStringPointer() + +// return id, description, enabled, search_query +// } + +// to change: from the Create and Update functions +func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Context, state *asmWafExclusionFiltersModel, exclusionFilter *datadogV2.ASMExclusionFilter) { + // Met à jour l'état avec les attributs de l'API + state.Id = types.StringValue(exclusionFilter.GetId()) + attributes := exclusionFilter.GetAttributes() + + state.Enabled = types.BoolValue(attributes.GetEnabled()) + state.Description = types.StringValue(attributes.GetDescription()) + state.Search_Query = types.StringValue(attributes.GetSearchQuery()) +} diff --git a/datadog/internal/utils/api_instances_helper.go b/datadog/internal/utils/api_instances_helper.go index eebd849f73..48586b98f9 100644 --- a/datadog/internal/utils/api_instances_helper.go +++ b/datadog/internal/utils/api_instances_helper.go @@ -46,6 +46,7 @@ type ApiInstances struct { //V2 APIs apiManagementAPIV2 *datadogV2.APIManagementApi apmRetentionFiltersApiV2 *datadogV2.APMRetentionFiltersApi + ASMExclusionFiltersApiV2 *datadogV2.ASMExclusionFiltersApi auditApiV2 *datadogV2.AuditApi authNMappingsApiV2 *datadogV2.AuthNMappingsApi cloudflareIntegrationApiV2 *datadogV2.CloudflareIntegrationApi @@ -332,6 +333,14 @@ func (i *ApiInstances) GetWebhooksIntegrationApiV1() *datadogV1.WebhooksIntegrat return i.webhooksIntegrationApiV1 } +// GetASMExclusionFiltersApiV2 get instance of ASMExclusionFiltersApi +func (i *ApiInstances) GetASMExclusionFiltersApiV2() *datadogV2.ASMExclusionFiltersApi { + if i.ASMExclusionFiltersApiV2 == nil { + i.ASMExclusionFiltersApiV2 = datadogV2.NewASMExclusionFiltersApi(i.HttpClient) + } + return i.ASMExclusionFiltersApiV2 +} + // GetAuditApiV2 get instance of AuditApi func (i *ApiInstances) GetAuditApiV2() *datadogV2.AuditApi { if i.auditApiV2 == nil { diff --git a/go.mod b/go.mod index 16c7ad321d..e8fa839f08 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.30.0 + github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab29 github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index 40c3266c81..d692426bf3 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-api-client-go/v2 v2.30.0 h1:WHAo6RA8CqAzaUh3dERqz/n6SuG2GJ/WthBkccn0MIQ= github.com/DataDog/datadog-api-client-go/v2 v2.30.0/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab29 h1:O812nx0T7cli3HIDLkKMyzk9T/KRKeVEXl/OocRgwUI= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab29/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From 994c33d886dd1c9946ba3c16cc2ed7c8fa85e859 Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Fri, 6 Sep 2024 17:15:05 +0200 Subject: [PATCH 2/9] change read function from ListASMExclusionFilters to GetASMExclusionFilters + change schema --- ...ource_datadog_asm_waf_exclusion_filters.go | 77 ++++++++++++----- ...ource_datadog_asm_waf_exclusion_filters.go | 86 ++++++++++--------- go.mod | 2 +- go.sum | 2 + 4 files changed, 104 insertions(+), 63 deletions(-) diff --git a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go index 0ac22bd182..5838c42216 100644 --- a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go @@ -69,28 +69,58 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat // Direct mapping of fields from exclusionFilter struct exclusionFilterModel.Id = types.StringValue(exclusionFilter.GetId()) - // Corrected access to Attributes (with uppercase A) attributes := exclusionFilter.GetAttributes() - exclusionFilterModel.Description = types.StringValue(attributes.GetDescription()) exclusionFilterModel.Enabled = types.BoolValue(attributes.GetEnabled()) - exclusionFilterModel.Search_Query = types.StringValue(attributes.GetSearchQuery()) + exclusionFilterModel.PathGlob = types.StringValue(attributes.GetPathGlob()) + + // Handle scope as a list of nested objects + var scopes []attr.Value + for _, scope := range attributes.GetScope() { + scopeObject, diags := types.ObjectValue(map[string]attr.Type{ + "env": types.StringType, + "service": types.StringType, + }, map[string]attr.Value{ + "env": types.StringValue(scope.GetEnv()), + "service": types.StringValue(scope.GetService()), + }) + // Append diagnostics if there are any issues + response.Diagnostics.Append(diags...) + scopes = append(scopes, scopeObject) + } + + // Convert the scopes to a Terraform list + tfScopes, diags := types.ListValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "env": types.StringType, + "service": types.StringType, + }, + }, scopes) + // Append diagnostics if there are any issues + response.Diagnostics.Append(diags...) + exclusionFilterModel.Scope = tfScopes // Collect the exclusion filter IDs and model exclusionFiltersIds[idx] = exclusionFilter.GetId() exclusionFilters[idx] = exclusionFilterModel } - // Set the state ID based on the exclusion filters IDs - stateId := strings.Join(exclusionFiltersIds, "--") - state.Id = types.StringValue(computeExclusionFiltersDataSourceID(&stateId)) + // Convert exclusionFiltersIds from []string to []attr.Value + var exclusionFiltersIdsAttr []attr.Value + for _, id := range exclusionFiltersIds { + exclusionFiltersIdsAttr = append(exclusionFiltersIdsAttr, types.StringValue(id)) + } // Convert the exclusion filter IDs to a Terraform list - tfExclusionFiltersIds, diags := types.ListValueFrom(ctx, types.StringType, exclusionFiltersIds) + tfExclusionFiltersIds, diags := types.ListValue(types.StringType, exclusionFiltersIdsAttr) response.Diagnostics.Append(diags...) state.ExclusionFiltersIds = tfExclusionFiltersIds state.ExclusionFilters = exclusionFilters + // Set the state ID based on the exclusion filters IDs + stateId := strings.Join(exclusionFiltersIds, "--") + state.Id = types.StringValue(computeExclusionFiltersDataSourceID(&stateId)) + // Save the state response.Diagnostics.Append(response.State.Set(ctx, &state)...) } @@ -108,28 +138,29 @@ func computeExclusionFiltersDataSourceID(exclusionFiltersIds *string) string { / return fmt.Sprintf("%x", h.Sum(nil)) } -func (*asmWafExclusionFiltersDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) { +func (r *asmWafExclusionFiltersDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) { response.Schema = schema.Schema{ - Description: "Use this data source to retrieve information about existing WAF exclusion filters.", + Description: "Retrieves Datadog ASM WAF Exclusion Filters.", Attributes: map[string]schema.Attribute{ "id": utils.ResourceIDAttribute(), - "exclusion_filters_ids": schema.ListAttribute{ + "description": schema.StringAttribute{ + Optional: true, + Computed: true, + Description: "A description for the exclusion filter.", + }, + "enabled": schema.BoolAttribute{ + Computed: true, + Description: "Indicates whether the exclusion filter is enabled.", + }, + "path_glob": schema.StringAttribute{ Computed: true, - Description: "List of IDs for the exclusion filters.", - ElementType: types.StringType, + Description: "The path glob for the exclusion filter.", }, - "exclusion_filters": schema.ListAttribute{ + "scope": schema.ListAttribute{ + Description: "The scope of the exclusion filter. Each entry is a map with 'env' and 'service' keys.", Computed: true, - Description: "List of exclusion filters", - ElementType: types.ObjectType{ - AttrTypes: map[string]attr.Type{ - "id": types.StringType, - // "type": types.StringType, - "description": types.StringType, - "enabled": types.BoolType, - // "path_glob": types.StringType, - "search_query": types.StringType, - }, + ElementType: types.MapType{ + ElemType: types.StringType, }, }, }, diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go index e77a5afb22..61fca94b20 100644 --- a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -2,15 +2,15 @@ package fwprovider import ( "context" + "fmt" "sync" "github.com/DataDog/datadog-api-client-go/v2/api/datadogV2" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils" @@ -23,10 +23,11 @@ var ( ) type asmWafExclusionFiltersModel struct { - Id types.String `tfsdk:"id"` - Description types.String `tfsdk:"description"` - Enabled types.Bool `tfsdk:"enabled"` - Search_Query types.String `tfsdk:"search_query"` + Id types.String `tfsdk:"id"` + Description types.String `tfsdk:"description"` + Enabled types.Bool `tfsdk:"enabled"` + PathGlob types.String `tfsdk:"path_glob"` + Scope types.List `tfsdk:"scope"` } type asmWafExclusionFiltersResource struct { @@ -48,7 +49,7 @@ func (r *asmWafExclusionFiltersResource) Configure(_ context.Context, request re r.auth = providerData.Auth } -func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { // to change +func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { response.Schema = schema.Schema{ Description: "Provides a Datadog ASM WAF Exclusion Filters API resource.", Attributes: map[string]schema.Attribute{ @@ -63,11 +64,15 @@ func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.Sc Required: true, Description: "Indicates whether the exclusion filter is enabled.", }, - "search_query": schema.StringAttribute{ + "path_glob": schema.StringAttribute{ Required: true, - Description: "The search query of the exclusion filter", - PlanModifiers: []planmodifier.String{ - stringplanmodifier.RequiresReplace(), + Description: "The path glob for the exclusion filter.", + }, + "scope": schema.ListAttribute{ + Description: "The scope of the exclusion filter. Each entry is a map with 'env' and 'service' keys.", + Optional: true, + ElementType: types.MapType{ + ElemType: types.StringType, }, }, }, @@ -114,37 +119,51 @@ func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resou return } - exclusionFiltersId := state.Id.ValueString() - res, httpResponse, err := r.api.ListASMExclusionFilters(r.auth) + // Récupérer l'ID de l'exclusion filter + exclusionFilterId := state.Id.ValueString() + // Appel à l'API pour obtenir le filtre d'exclusion correspondant à l'ID + res, httpResponse, err := r.api.GetASMExclusionFilters(r.auth, exclusionFilterId) if err != nil { if httpResponse != nil && httpResponse.StatusCode == 404 { response.State.RemoveResource(ctx) return } - response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error fetching exclusion filters")) + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error fetching exclusion filter")) return } - var matchedExclusionFilter *datadogV2.ASMExclusionFilter - for _, exclusionFilter := range res.GetData() { - if exclusionFilter.GetId() == exclusionFiltersId { - matchedExclusionFilter = &exclusionFilter - break - } - } - - if matchedExclusionFilter == nil { - response.State.RemoveResource(ctx) + // Extraire les données à partir de la réponse + dataList, ok := res.AdditionalProperties["data"].([]interface{}) + if !ok || len(dataList) == 0 { + response.Diagnostics.Append(utils.FrameworkErrorDiag(fmt.Errorf("no data found in response"), "error extracting exclusion filter data")) return } - if err := utils.CheckForUnparsed(response); err != nil { - response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) - return + // Extraire les informations du premier élément (car la requête renvoie un seul filtre d'exclusion) + filterData := dataList[0].(map[string]interface{}) + attributes := filterData["attributes"].(map[string]interface{}) + + // Mettre à jour l'état en fonction des attributs extraits + state.Id = types.StringValue(filterData["id"].(string)) + state.Description = types.StringValue(attributes["description"].(string)) + state.Enabled = types.BoolValue(attributes["enabled"].(bool)) + + // Extraire le scope + var scopes []attr.Value + if scopeList, ok := attributes["scope"].([]interface{}); ok { + for _, scopeItem := range scopeList { + scopeMap := scopeItem.(map[string]interface{}) + scopeValue, _ := types.MapValue(types.StringType, map[string]attr.Value{ + "env": types.StringValue(scopeMap["env"].(string)), + "service": types.StringValue(scopeMap["service"].(string)), + }) + scopes = append(scopes, scopeValue) + } } + state.Scope, _ = types.ListValue(types.MapType{ElemType: types.StringType}, scopes) - r.updateStateFromResponse(ctx, &state, matchedExclusionFilter) + // Mettre à jour l'état response.Diagnostics.Append(response.State.Set(ctx, &state)...) } @@ -236,14 +255,3 @@ func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request res // return id, description, enabled, search_query // } - -// to change: from the Create and Update functions -func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Context, state *asmWafExclusionFiltersModel, exclusionFilter *datadogV2.ASMExclusionFilter) { - // Met à jour l'état avec les attributs de l'API - state.Id = types.StringValue(exclusionFilter.GetId()) - attributes := exclusionFilter.GetAttributes() - - state.Enabled = types.BoolValue(attributes.GetEnabled()) - state.Description = types.StringValue(attributes.GetDescription()) - state.Search_Query = types.StringValue(attributes.GetSearchQuery()) -} diff --git a/go.mod b/go.mod index e8fa839f08..5cd04f076c 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab29 + github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906124549-230f6e38e965 github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index d692426bf3..76d8be7b21 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/DataDog/datadog-api-client-go/v2 v2.30.0 h1:WHAo6RA8CqAzaUh3dERqz/n6S github.com/DataDog/datadog-api-client-go/v2 v2.30.0/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab29 h1:O812nx0T7cli3HIDLkKMyzk9T/KRKeVEXl/OocRgwUI= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab29/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906124549-230f6e38e965 h1:7KBUuEvPCx9G7frpnfmRdolWSTdNRBtNEs4nLGtedjU= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906124549-230f6e38e965/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From 887838369e0aa4e08d32c1a5143ad7259eed8239 Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Mon, 9 Sep 2024 10:01:36 +0200 Subject: [PATCH 3/9] fix path_glob param --- ...ource_datadog_asm_waf_exclusion_filters.go | 14 ++------- ...ource_datadog_asm_waf_exclusion_filters.go | 31 +++++++++++-------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go index 5838c42216..b4923cf918 100644 --- a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go @@ -51,7 +51,6 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat return } - // Fetch the exclusion filters using the API res, _, err := r.api.ListASMExclusionFilters(r.auth) if err != nil { response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error while fetching exclusion filters")) @@ -62,11 +61,9 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat exclusionFiltersIds := make([]string, len(data)) exclusionFilters := make([]asmWafExclusionFiltersModel, len(data)) - // Iterate through the exclusion filters data received for idx, exclusionFilter := range res.GetData() { var exclusionFilterModel asmWafExclusionFiltersModel - // Direct mapping of fields from exclusionFilter struct exclusionFilterModel.Id = types.StringValue(exclusionFilter.GetId()) attributes := exclusionFilter.GetAttributes() @@ -74,7 +71,6 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat exclusionFilterModel.Enabled = types.BoolValue(attributes.GetEnabled()) exclusionFilterModel.PathGlob = types.StringValue(attributes.GetPathGlob()) - // Handle scope as a list of nested objects var scopes []attr.Value for _, scope := range attributes.GetScope() { scopeObject, diags := types.ObjectValue(map[string]attr.Type{ @@ -84,44 +80,38 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat "env": types.StringValue(scope.GetEnv()), "service": types.StringValue(scope.GetService()), }) - // Append diagnostics if there are any issues + response.Diagnostics.Append(diags...) scopes = append(scopes, scopeObject) } - // Convert the scopes to a Terraform list tfScopes, diags := types.ListValue(types.ObjectType{ AttrTypes: map[string]attr.Type{ "env": types.StringType, "service": types.StringType, }, }, scopes) - // Append diagnostics if there are any issues + response.Diagnostics.Append(diags...) exclusionFilterModel.Scope = tfScopes - // Collect the exclusion filter IDs and model exclusionFiltersIds[idx] = exclusionFilter.GetId() exclusionFilters[idx] = exclusionFilterModel } - // Convert exclusionFiltersIds from []string to []attr.Value var exclusionFiltersIdsAttr []attr.Value for _, id := range exclusionFiltersIds { exclusionFiltersIdsAttr = append(exclusionFiltersIdsAttr, types.StringValue(id)) } - // Convert the exclusion filter IDs to a Terraform list tfExclusionFiltersIds, diags := types.ListValue(types.StringType, exclusionFiltersIdsAttr) response.Diagnostics.Append(diags...) state.ExclusionFiltersIds = tfExclusionFiltersIds state.ExclusionFilters = exclusionFilters - // Set the state ID based on the exclusion filters IDs stateId := strings.Join(exclusionFiltersIds, "--") state.Id = types.StringValue(computeExclusionFiltersDataSourceID(&stateId)) - // Save the state response.Diagnostics.Append(response.State.Set(ctx, &state)...) } diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go index 61fca94b20..37872d1506 100644 --- a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -119,10 +119,8 @@ func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resou return } - // Récupérer l'ID de l'exclusion filter exclusionFilterId := state.Id.ValueString() - // Appel à l'API pour obtenir le filtre d'exclusion correspondant à l'ID res, httpResponse, err := r.api.GetASMExclusionFilters(r.auth, exclusionFilterId) if err != nil { if httpResponse != nil && httpResponse.StatusCode == 404 { @@ -133,37 +131,44 @@ func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resou return } - // Extraire les données à partir de la réponse dataList, ok := res.AdditionalProperties["data"].([]interface{}) if !ok || len(dataList) == 0 { response.Diagnostics.Append(utils.FrameworkErrorDiag(fmt.Errorf("no data found in response"), "error extracting exclusion filter data")) return } - // Extraire les informations du premier élément (car la requête renvoie un seul filtre d'exclusion) filterData := dataList[0].(map[string]interface{}) attributes := filterData["attributes"].(map[string]interface{}) - // Mettre à jour l'état en fonction des attributs extraits state.Id = types.StringValue(filterData["id"].(string)) state.Description = types.StringValue(attributes["description"].(string)) state.Enabled = types.BoolValue(attributes["enabled"].(bool)) + state.PathGlob = types.StringValue(attributes["path_glob"].(string)) - // Extraire le scope var scopes []attr.Value if scopeList, ok := attributes["scope"].([]interface{}); ok { for _, scopeItem := range scopeList { - scopeMap := scopeItem.(map[string]interface{}) - scopeValue, _ := types.MapValue(types.StringType, map[string]attr.Value{ - "env": types.StringValue(scopeMap["env"].(string)), - "service": types.StringValue(scopeMap["service"].(string)), - }) - scopes = append(scopes, scopeValue) + scopeMap, isMap := scopeItem.(map[string]interface{}) + if isMap { + scopeValues := map[string]attr.Value{} + + if envValue, envExists := scopeMap["env"]; envExists { + scopeValues["env"] = types.StringValue(envValue.(string)) + } + + if serviceValue, serviceExists := scopeMap["service"]; serviceExists { + scopeValues["service"] = types.StringValue(serviceValue.(string)) + } + + if len(scopeValues) > 0 { + scopeValue, _ := types.MapValue(types.StringType, scopeValues) + scopes = append(scopes, scopeValue) + } + } } } state.Scope, _ = types.ListValue(types.MapType{ElemType: types.StringType}, scopes) - // Mettre à jour l'état response.Diagnostics.Append(response.State.Set(ctx, &state)...) } From d2735a680a580feeca156cde727db97766622797 Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Tue, 10 Sep 2024 17:35:42 +0200 Subject: [PATCH 4/9] add create/update/delete functions --- ...ource_datadog_asm_waf_exclusion_filters.go | 87 +++-- ...ource_datadog_asm_waf_exclusion_filters.go | 319 ++++++++++-------- go.mod | 2 +- go.sum | 10 + 4 files changed, 248 insertions(+), 170 deletions(-) diff --git a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go index b4923cf918..7e7784b89a 100644 --- a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go @@ -58,12 +58,11 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat } data := res.GetData() - exclusionFiltersIds := make([]string, len(data)) + exclusionFilterIds := make([]string, len(data)) exclusionFilters := make([]asmWafExclusionFiltersModel, len(data)) for idx, exclusionFilter := range res.GetData() { var exclusionFilterModel asmWafExclusionFiltersModel - exclusionFilterModel.Id = types.StringValue(exclusionFilter.GetId()) attributes := exclusionFilter.GetAttributes() @@ -80,42 +79,57 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat "env": types.StringValue(scope.GetEnv()), "service": types.StringValue(scope.GetService()), }) - response.Diagnostics.Append(diags...) scopes = append(scopes, scopeObject) } - tfScopes, diags := types.ListValue(types.ObjectType{ AttrTypes: map[string]attr.Type{ "env": types.StringType, "service": types.StringType, }, }, scopes) - response.Diagnostics.Append(diags...) exclusionFilterModel.Scope = tfScopes - exclusionFiltersIds[idx] = exclusionFilter.GetId() - exclusionFilters[idx] = exclusionFilterModel - } + var rulesTargets []attr.Value + for _, ruleTarget := range attributes.GetRulesTarget() { + tags, tagsOk := ruleTarget.GetTagsOk() + if tagsOk && tags != nil { + ruleTargetObject, diags := types.ObjectValue(map[string]attr.Type{ + "category": types.StringType, + "type": types.StringType, + }, map[string]attr.Value{ + "category": types.StringValue(tags.GetCategory()), + "type": types.StringValue(tags.GetType()), + }) + response.Diagnostics.Append(diags...) + rulesTargets = append(rulesTargets, ruleTargetObject) + } + } + tfRulesTargets, diags := types.ListValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "category": types.StringType, + "type": types.StringType, + }, + }, rulesTargets) + response.Diagnostics.Append(diags...) + exclusionFilterModel.RulesTarget = tfRulesTargets - var exclusionFiltersIdsAttr []attr.Value - for _, id := range exclusionFiltersIds { - exclusionFiltersIdsAttr = append(exclusionFiltersIdsAttr, types.StringValue(id)) + exclusionFilterIds[idx] = exclusionFilter.GetId() + exclusionFilters[idx] = exclusionFilterModel } - tfExclusionFiltersIds, diags := types.ListValue(types.StringType, exclusionFiltersIdsAttr) + stateId := strings.Join(exclusionFilterIds, "--") + state.Id = types.StringValue(computeExclusionFiltersDataSourceID(&stateId)) + tfExclusionFilterIds, diags := types.ListValueFrom(ctx, types.StringType, exclusionFilterIds) response.Diagnostics.Append(diags...) - state.ExclusionFiltersIds = tfExclusionFiltersIds + state.ExclusionFiltersIds = tfExclusionFilterIds state.ExclusionFilters = exclusionFilters - stateId := strings.Join(exclusionFiltersIds, "--") - state.Id = types.StringValue(computeExclusionFiltersDataSourceID(&stateId)) - response.Diagnostics.Append(response.State.Set(ctx, &state)...) } -func computeExclusionFiltersDataSourceID(exclusionFiltersIds *string) string { // return to state.Id +func computeExclusionFiltersDataSourceID(exclusionFiltersIds *string) string { // Key for hashing var b strings.Builder if exclusionFiltersIds != nil { @@ -133,24 +147,33 @@ func (r *asmWafExclusionFiltersDataSource) Schema(_ context.Context, _ datasourc Description: "Retrieves Datadog ASM WAF Exclusion Filters.", Attributes: map[string]schema.Attribute{ "id": utils.ResourceIDAttribute(), - "description": schema.StringAttribute{ - Optional: true, - Computed: true, - Description: "A description for the exclusion filter.", - }, - "enabled": schema.BoolAttribute{ - Computed: true, - Description: "Indicates whether the exclusion filter is enabled.", - }, - "path_glob": schema.StringAttribute{ + "exclusion_filters_ids": schema.ListAttribute{ Computed: true, - Description: "The path glob for the exclusion filter.", + Description: "List of IDs for the ASM exclusion filters.", + ElementType: types.StringType, }, - "scope": schema.ListAttribute{ - Description: "The scope of the exclusion filter. Each entry is a map with 'env' and 'service' keys.", + "exclusion_filters": schema.ListAttribute{ Computed: true, - ElementType: types.MapType{ - ElemType: types.StringType, + Description: "List of ASM WAF exclusion filters", + ElementType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "id": types.StringType, + "description": types.StringType, + "enabled": types.BoolType, + "path_glob": types.StringType, + "scope": types.ListType{ElemType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "env": types.StringType, + "service": types.StringType, + }, + }}, + "rules_target": types.ListType{ElemType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "category": types.StringType, + "type": types.StringType, + }, + }}, + }, }, }, }, diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go index 37872d1506..7d871c7f69 100644 --- a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -28,6 +28,7 @@ type asmWafExclusionFiltersModel struct { Enabled types.Bool `tfsdk:"enabled"` PathGlob types.String `tfsdk:"path_glob"` Scope types.List `tfsdk:"scope"` + RulesTarget types.List `tfsdk:"rules_target"` } type asmWafExclusionFiltersResource struct { @@ -71,6 +72,15 @@ func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.Sc "scope": schema.ListAttribute{ Description: "The scope of the exclusion filter. Each entry is a map with 'env' and 'service' keys.", Optional: true, + Computed: true, + ElementType: types.MapType{ + ElemType: types.StringType, + }, + }, + "rules_target": schema.ListAttribute{ + Description: "The rules target of the exclusion filter. Each entry contains tags with 'category' and 'type'.", + Optional: true, + Computed: true, ElementType: types.MapType{ ElemType: types.StringType, }, @@ -84,32 +94,34 @@ func (r *asmWafExclusionFiltersResource) ImportState(ctx context.Context, reques } func (r *asmWafExclusionFiltersResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { - // var state asmWafExclusionFiltersModel - // response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) - // if response.Diagnostics.HasError() { - // return - // } - - // asmWafExclusionFiltersMutex.Lock() - // defer asmWafExclusionFiltersMutex.Unlock() - - // exclusionFiltersPayload, err := r.buildCreateAsmWafExclusionFiltersPayload(&state) - // if err != nil { - // response.Diagnostics.AddError("error while parsing resource", err.Error()) - // } - - // res, _, err := r.api.handlePostExclusionFilters(r.auth, *exclusionFiltersPayload) // to change: endpoint POST - // if err != nil { - // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error creating agent rule")) - // return - // } - // if err := utils.CheckForUnparsed(response); err != nil { - // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) - // return - // } - - // r.updateStateFromResponse(ctx, &state, &res) - // response.Diagnostics.Append(response.State.Set(ctx, &state)...) + var state asmWafExclusionFiltersModel + response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + asmWafExclusionFiltersMutex.Lock() + defer asmWafExclusionFiltersMutex.Unlock() + + exclusionFilterPayload, err := r.buildCreateASMExclusionFilterPayload(&state) + if err != nil { + response.Diagnostics.AddError("error while parsing resource", err.Error()) + return + } + + res, _, err := r.api.CreateASMExclusionFilter(r.auth, *exclusionFilterPayload) + if err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error creating exclusion filter")) + return + } + + if err := utils.CheckForUnparsed(response); err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) + return + } + + r.updateStateFromCreateResponse(ctx, &state, &res) + response.Diagnostics.Append(response.State.Set(ctx, &state)...) } func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { @@ -131,132 +143,165 @@ func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resou return } - dataList, ok := res.AdditionalProperties["data"].([]interface{}) - if !ok || len(dataList) == 0 { + if len(res.Data) == 0 { response.Diagnostics.Append(utils.FrameworkErrorDiag(fmt.Errorf("no data found in response"), "error extracting exclusion filter data")) return } - filterData := dataList[0].(map[string]interface{}) - attributes := filterData["attributes"].(map[string]interface{}) + r.updateStateFromResponse(ctx, &state, &res) - state.Id = types.StringValue(filterData["id"].(string)) - state.Description = types.StringValue(attributes["description"].(string)) - state.Enabled = types.BoolValue(attributes["enabled"].(bool)) - state.PathGlob = types.StringValue(attributes["path_glob"].(string)) + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} - var scopes []attr.Value - if scopeList, ok := attributes["scope"].([]interface{}); ok { - for _, scopeItem := range scopeList { - scopeMap, isMap := scopeItem.(map[string]interface{}) - if isMap { - scopeValues := map[string]attr.Value{} +func (r *asmWafExclusionFiltersResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var state asmWafExclusionFiltersModel + response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } - if envValue, envExists := scopeMap["env"]; envExists { - scopeValues["env"] = types.StringValue(envValue.(string)) - } + asmWafExclusionFiltersMutex.Lock() + defer asmWafExclusionFiltersMutex.Unlock() - if serviceValue, serviceExists := scopeMap["service"]; serviceExists { - scopeValues["service"] = types.StringValue(serviceValue.(string)) - } + exclusionFiltersPayload, err := r.buildUpdateAsmWafExclusionFiltersPayload(&state) + if err != nil { + response.Diagnostics.AddError("error while parsing resource", err.Error()) + } - if len(scopeValues) > 0 { - scopeValue, _ := types.MapValue(types.StringType, scopeValues) - scopes = append(scopes, scopeValue) - } - } - } + res, _, err := r.api.UpdateASMExclusionFilter(r.auth, state.Id.ValueString(), *exclusionFiltersPayload) // to change: endpoint PATCH/PUT + if err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error updating agent rule")) + return + } + if err := utils.CheckForUnparsed(response); err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) + return } - state.Scope, _ = types.ListValue(types.MapType{ElemType: types.StringType}, scopes) + r.updateStateFromResponse(ctx, &state, &res) response.Diagnostics.Append(response.State.Set(ctx, &state)...) } -func (r *asmWafExclusionFiltersResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { - // var state asmWafExclusionFiltersModel - // response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) - // if response.Diagnostics.HasError() { - // return - // } - - // asmWafExclusionFiltersMutex.Lock() - // defer asmWafExclusionFiltersMutex.Unlock() - - // exclusionFiltersPayload, err := r.buildUpdateAsmWafExclusionFiltersPayload(&state) - // if err != nil { - // response.Diagnostics.AddError("error while parsing resource", err.Error()) - // } - - // res, _, err := r.api.handlePutExclusionFilter(r.auth, state.Id.ValueString(), *exclusionFiltersPayload) // to change: endpoint PATCH/PUT - // if err != nil { - // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error updating agent rule")) - // return - // } - // if err := utils.CheckForUnparsed(response); err != nil { - // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "response contains unparsed object")) - // return - // } - - // r.updateStateFromResponse(ctx, &state, &res) - // response.Diagnostics.Append(response.State.Set(ctx, &state)...) +func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var state asmWafExclusionFiltersModel + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + asmWafExclusionFiltersMutex.Lock() + defer asmWafExclusionFiltersMutex.Unlock() + + id := state.Id.ValueString() + + httpResp, err := r.api.DeleteASMExclusionFilter(r.auth, id) + + if err != nil { + if httpResp != nil && httpResp.StatusCode == 404 { + return + } + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error deleting exclusion filter")) + return + } } -func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { - // var state asmWafExclusionFiltersModel - // response.Diagnostics.Append(request.State.Get(ctx, &state)...) - // if response.Diagnostics.HasError() { - // return - // } - - // asmWafExclusionFiltersMutex.Lock() - // defer asmWafExclusionFiltersMutex.Unlock() - - // id := state.Id.ValueString() - - // httpResp, err := r.api.handleDeleteExclusionFilterByID(r.auth, id) // to change: endpoint DELETE - // - // if err != nil { - // if httpResp != nil && httpResp.StatusCode == 404 { - // return - // } - // response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error deleting agent rule")) - // return - // } +func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterUpdateRequest, error) { + exclusionFiltersId, enabled, description, pathGlob := r.extractExclusionFilterAttributesFromResource(state) + + attributes := datadogV2.ASMExclusionFilterUpdateAttributes{} + attributes.Description = &description + attributes.Enabled = &enabled + attributes.PathGlob = &pathGlob + + data := datadogV2.NewASMExclusionFilterUpdateData(attributes, datadogV2.ASMEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) + data.Id = &exclusionFiltersId + return datadogV2.NewASMExclusionFilterUpdateRequest(*data), nil } -// // to change: payload from the Create function -// func (r *asmWafExclusionFiltersResource) buildCreateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.CloudWorkloadSecurityExclusionFiltersCreateRequest, error) { -// _, description, enabled, search_query := r.extractExclusionFiltersAttributesFromResource(state) - -// attributes := datadogV2.CloudWorkloadSecurityExclusionFiltersCreateAttributes{} -// attributes.Search_Query = search_query -// attributes.Description = description -// attributes.Enabled = &enabled - -// data := datadogV2.NewCloudWorkloadSecurityExclusionFiltersCreateData(attributes, datadogV2.CLOUDWORKLOADSECURITYEXCLUSIONFILTERSTYPE_AGENT_RULE) -// return datadogV2.NewCloudWorkloadSecurityExclusionFiltersCreateRequest(*data), nil -// } - -// // to change: payload from the Update function -// func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.CloudWorkloadSecurityExclusionFiltersUpdateRequest, error) { -// exclusionFiltersId, _, description, enabled, _ := r.extractExclusionFiltersAttributesFromResource(state) - -// attributes := datadogV2.CloudWorkloadSecurityExclusionFiltersUpdateAttributes{} -// attributes.Description = description -// attributes.Enabled = &enabled - -// data := datadogV2.NewCloudWorkloadSecurityExclusionFiltersUpdateData(attributes, datadogV2.CLOUDWORKLOADSECURITYEXCLUSIONFILTERSTYPE_AGENT_RULE) -// data.Id = &exclusionFiltersId -// return datadogV2.NewCloudWorkloadSecurityExclusionFiltersUpdateRequest(*data), nil -// } - -// // called from the payloads above -// func (r *asmWafExclusionFiltersResource) extractExclusionFiltersAttributesFromResource(state *asmWafExclusionFiltersModel) (string, *string, bool, string) { -// // Mandatory fields -// id := state.Id.ValueString() -// enabled := state.Enabled.ValueBool() -// search_query := state.Search_Query.ValueString() -// description := state.Description.ValueStringPointer() - -// return id, description, enabled, search_query -// } +func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterCreateRequest, error) { + _, enabled, description, pathGlob := r.extractExclusionFilterAttributesFromResource(state) + + attributes := datadogV2.ASMExclusionFilterCreateAttributes{} + attributes.Description = description + attributes.Enabled = enabled + attributes.PathGlob = &pathGlob + + data := datadogV2.NewASMExclusionFilterCreateData(attributes, datadogV2.ASMEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) + return datadogV2.NewASMExclusionFilterCreateRequest(*data), nil +} + +func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromResource(state *asmWafExclusionFiltersModel) (string, bool, string, string) { + id := state.Id.ValueString() + enabled := state.Enabled.ValueBool() + description := state.Description.ValueString() + pathGlob := state.PathGlob.ValueString() + + return id, enabled, description, pathGlob +} + +func (r *asmWafExclusionFiltersResource) updateStateFromCreateResponse(ctx context.Context, state *asmWafExclusionFiltersModel, res *datadogV2.ASMExclusionFilterResponse) { + if len(res.GetData()) == 0 { + return + } + + filterData := res.GetData()[0] + attributes := filterData.Attributes + + state.Id = types.StringValue(filterData.GetId()) + state.Description = types.StringValue(attributes.GetDescription()) + state.Enabled = types.BoolValue(attributes.GetEnabled()) + state.PathGlob = types.StringValue(attributes.GetPathGlob()) +} + +func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Context, state *asmWafExclusionFiltersModel, res *datadogV2.ASMExclusionFilterResponse) { + + if len(res.Data) == 0 { + return + } + + filterData := res.Data[0] + + attributes := filterData.Attributes + + state.Id = types.StringValue(filterData.GetId()) + state.Description = types.StringValue(attributes.GetDescription()) + state.Enabled = types.BoolValue(attributes.GetEnabled()) + state.PathGlob = types.StringValue(attributes.GetPathGlob()) + + var scopes []attr.Value + if scopeList := attributes.GetScope(); len(scopeList) > 0 { + for _, scopeItem := range scopeList { + scopeValues := map[string]attr.Value{} + + if envValue := scopeItem.GetEnv(); envValue != "" { + scopeValues["env"] = types.StringValue(envValue) + } + + if serviceValue := scopeItem.GetService(); serviceValue != "" { + scopeValues["service"] = types.StringValue(serviceValue) + } + + if len(scopeValues) > 0 { + scopeValue, _ := types.MapValue(types.StringType, scopeValues) + scopes = append(scopes, scopeValue) + } + } + } + state.Scope, _ = types.ListValue(types.MapType{ElemType: types.StringType}, scopes) + + var rulesTarget []attr.Value + if rulesTargetList := attributes.GetRulesTarget(); len(rulesTargetList) > 0 { + for _, targetItem := range rulesTargetList { + tags, tagsOk := targetItem.GetTagsOk() + if tagsOk && tags != nil { + tagValues := map[string]attr.Value{ + "category": types.StringValue(tags.GetCategory()), + "type": types.StringValue(tags.GetType()), + } + tagMapValue, _ := types.MapValue(types.StringType, tagValues) + rulesTarget = append(rulesTarget, tagMapValue) + } + } + } + state.RulesTarget, _ = types.ListValue(types.MapType{ElemType: types.StringType}, rulesTarget) +} diff --git a/go.mod b/go.mod index 5cd04f076c..6f97beab7b 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906124549-230f6e38e965 + github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910123820-1130cb153bb9 github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index 76d8be7b21..262a9c5fe7 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,16 @@ github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab2 github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906094748-f9803de3ab29/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906124549-230f6e38e965 h1:7KBUuEvPCx9G7frpnfmRdolWSTdNRBtNEs4nLGtedjU= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240906124549-230f6e38e965/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910075127-c4378d7383b2 h1:qzPjLyErF/Ne/MTLh60YXKl3GZS3yGYs7nSyy6XxR5w= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910075127-c4378d7383b2/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910083650-a9a038468ca5 h1:g6LNRDaMY5evLycUaTnRLOoKQ7FDEQMtaMuaQ+ltCjo= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910083650-a9a038468ca5/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910090407-6b912b4a606b h1:dktoN99sRqf04rslBGEGpI4T9pAbA11yr9TcyvhHTPQ= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910090407-6b912b4a606b/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910094327-2f1b04fd19ee h1:DGEOoIUymv2dqb/n07KlF1LXGHCQ+8NS3Oar4jXWW4I= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910094327-2f1b04fd19ee/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910123820-1130cb153bb9 h1:FmghEL9mW601yCfzAhaLwrJ4mdWziGEyMkivwGRvBnw= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240910123820-1130cb153bb9/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From 6eee5afb2afe98a521bdf0dfed1b0594745f0a02 Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Thu, 12 Sep 2024 17:12:41 +0200 Subject: [PATCH 5/9] add scope and rules_target parameters --- ...ource_datadog_asm_waf_exclusion_filters.go | 168 +++++++++++++----- go.mod | 2 +- go.sum | 6 + 3 files changed, 128 insertions(+), 48 deletions(-) diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go index 90bce3f8fc..6914d9ff61 100644 --- a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -80,8 +80,8 @@ func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.Sc }, }, "rules_target": schema.ListAttribute{ - Optional: true, Description: "The rules target of the exclusion filter with 'rule_id' and 'rule_name'.", + Optional: true, ElementType: types.ObjectType{ AttrTypes: map[string]attr.Type{ "rule_id": types.StringType, @@ -124,7 +124,7 @@ func (r *asmWafExclusionFiltersResource) Create(ctx context.Context, request res return } - r.updateStateFromCreateResponse(ctx, &state, &res) + r.updateStateFromResponse(ctx, &state, &res) response.Diagnostics.Append(response.State.Set(ctx, &state)...) } @@ -211,12 +211,35 @@ func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request res } func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterUpdateRequest, error) { - exclusionFiltersId, enabled, description, pathGlob := r.extractExclusionFilterAttributesFromResource(state) + exclusionFiltersId, enabled, description, pathGlob, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) - attributes := datadogV2.ASMExclusionFilterUpdateAttributes{} - attributes.Description = &description - attributes.Enabled = &enabled - attributes.PathGlob = &pathGlob + attributes := datadogV2.ASMExclusionFilterUpdateAttributes{ + Description: description, + Enabled: enabled, + PathGlob: &pathGlob, + } + + if len(scopeList) > 0 { + var newScopeList []datadogV2.ASMExclusionFilterScope + for _, scopeItem := range scopeList { + newScopeList = append(newScopeList, datadogV2.ASMExclusionFilterScope{ + Env: scopeItem.Env, + Service: scopeItem.Service, + }) + } + attributes.Scope = newScopeList + } + + if len(rulesTargetList) > 0 { + var newRulesTargetList []datadogV2.ASMExclusionFilterRulesTarget + for _, targetItem := range rulesTargetList { + newRulesTargetList = append(newRulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ + RuleId: targetItem.RuleId, + RuleName: targetItem.RuleName, + }) + } + attributes.RulesTarget = newRulesTargetList + } data := datadogV2.NewASMExclusionFilterUpdateData(attributes, datadogV2.ASMEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) data.Id = &exclusionFiltersId @@ -224,38 +247,83 @@ func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayloa } func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterCreateRequest, error) { - _, enabled, description, pathGlob := r.extractExclusionFilterAttributesFromResource(state) + _, enabled, description, pathGlob, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) + + attributes := datadogV2.ASMExclusionFilterCreateAttributes{ + Description: description, + Enabled: enabled, + PathGlob: &pathGlob, + } - attributes := datadogV2.ASMExclusionFilterCreateAttributes{} - attributes.Description = description - attributes.Enabled = enabled - attributes.PathGlob = &pathGlob + if len(scopeList) > 0 { + var newScopeList []datadogV2.ASMExclusionFilterScope + for _, scopeItem := range scopeList { + newScopeList = append(newScopeList, datadogV2.ASMExclusionFilterScope{ + Env: scopeItem.Env, + Service: scopeItem.Service, + }) + } + attributes.Scope = newScopeList + } + + if len(rulesTargetList) > 0 { + var newRulesTargetList []datadogV2.ASMExclusionFilterRulesTarget + for _, targetItem := range rulesTargetList { + newRulesTargetList = append(newRulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ + RuleId: targetItem.RuleId, + RuleName: targetItem.RuleName, + }) + } + attributes.RulesTarget = newRulesTargetList + } data := datadogV2.NewASMExclusionFilterCreateData(attributes, datadogV2.ASMEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) return datadogV2.NewASMExclusionFilterCreateRequest(*data), nil } -func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromResource(state *asmWafExclusionFiltersModel) (string, bool, string, string) { +func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromResource(state *asmWafExclusionFiltersModel) (string, bool, string, string, []datadogV2.ASMExclusionFilterScope, []datadogV2.ASMExclusionFilterRulesTarget) { id := state.Id.ValueString() enabled := state.Enabled.ValueBool() description := state.Description.ValueString() pathGlob := state.PathGlob.ValueString() - return id, enabled, description, pathGlob -} + var scopeList []datadogV2.ASMExclusionFilterScope + if !state.Scope.IsNull() && len(state.Scope.Elements()) > 0 { + for _, scopeItem := range state.Scope.Elements() { + scopeMap := scopeItem.(types.Object).Attributes() -func (r *asmWafExclusionFiltersResource) updateStateFromCreateResponse(ctx context.Context, state *asmWafExclusionFiltersModel, res *datadogV2.ASMExclusionFilterResponse) { - if len(res.GetData()) == 0 { - return + env := scopeMap["env"].(types.String).ValueString() + service := scopeMap["service"].(types.String).ValueString() + + envPtr := &env + servicePtr := &service + + scopeList = append(scopeList, datadogV2.ASMExclusionFilterScope{ + Env: envPtr, + Service: servicePtr, + }) + } } - filterData := res.GetData()[0] - attributes := filterData.Attributes + var rulesTargetList []datadogV2.ASMExclusionFilterRulesTarget + if !state.RulesTarget.IsNull() && len(state.RulesTarget.Elements()) > 0 { + for _, targetItem := range state.RulesTarget.Elements() { + rulesMap := targetItem.(types.Object).Attributes() - state.Id = types.StringValue(filterData.GetId()) - state.Description = types.StringValue(attributes.GetDescription()) - state.Enabled = types.BoolValue(attributes.GetEnabled()) - state.PathGlob = types.StringValue(attributes.GetPathGlob()) + ruleId := rulesMap["rule_id"].(types.String).ValueString() + ruleName := rulesMap["rule_name"].(types.String).ValueString() + + ruleIdPtr := &ruleId + ruleNamePtr := &ruleName + + rulesTargetList = append(rulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ + RuleId: ruleIdPtr, + RuleName: ruleNamePtr, + }) + } + } + + return id, enabled, description, pathGlob, scopeList, rulesTargetList } func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Context, state *asmWafExclusionFiltersModel, res *datadogV2.ASMExclusionFilterResponse) { @@ -276,37 +344,43 @@ func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Con var scopes []attr.Value if scopeList := attributes.GetScope(); len(scopeList) > 0 { for _, scopeItem := range scopeList { - scopeValues := map[string]attr.Value{} - - if envValue := scopeItem.GetEnv(); envValue != "" { - scopeValues["env"] = types.StringValue(envValue) - } - - if serviceValue := scopeItem.GetService(); serviceValue != "" { - scopeValues["service"] = types.StringValue(serviceValue) - } - - if len(scopeValues) > 0 { - scopeValue, _ := types.MapValue(types.StringType, scopeValues) - scopes = append(scopes, scopeValue) + scopeObject := map[string]attr.Value{ + "env": types.StringValue(scopeItem.GetEnv()), + "service": types.StringValue(scopeItem.GetService()), } + scopeValue, _ := types.ObjectValue(map[string]attr.Type{ + "env": types.StringType, + "service": types.StringType, + }, scopeObject) + scopes = append(scopes, scopeValue) } } - state.Scope, _ = types.ListValue(types.MapType{ElemType: types.StringType}, scopes) + state.Scope, _ = types.ListValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "env": types.StringType, + "service": types.StringType, + }, + }, scopes) var rulesTarget []attr.Value if rulesTargetList := attributes.GetRulesTarget(); len(rulesTargetList) > 0 { for _, targetItem := range rulesTargetList { - tags, tagsOk := targetItem.GetTagsOk() - if tagsOk && tags != nil { - tagValues := map[string]attr.Value{ - "category": types.StringValue(tags.GetCategory()), - "type": types.StringValue(tags.GetType()), - } - tagMapValue, _ := types.MapValue(types.StringType, tagValues) - rulesTarget = append(rulesTarget, tagMapValue) + ruleValues := map[string]attr.Value{ + "rule_id": types.StringValue(targetItem.GetRuleId()), + "rule_name": types.StringValue(targetItem.GetRuleName()), } + ruleObject, _ := types.ObjectValue(map[string]attr.Type{ + "rule_id": types.StringType, + "rule_name": types.StringType, + }, ruleValues) + rulesTarget = append(rulesTarget, ruleObject) } } - state.RulesTarget, _ = types.ListValue(types.MapType{ElemType: types.StringType}, rulesTarget) + state.RulesTarget, _ = types.ListValue(types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "rule_id": types.StringType, + "rule_name": types.StringType, + }, + }, rulesTarget) + } diff --git a/go.mod b/go.mod index b37d49a6d0..54a401ec3b 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240911195025-92128b15dc8c + github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407 github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index c455a02604..32b3ec2dfb 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,12 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240911195025-92128b15dc8c h1:+yokfxyjea3W7KpyCTeTIKqPFNeGEAubmI0RCO7sBdE= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240911195025-92128b15dc8c/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912113408-b130fc40a2e0 h1:GD/Nkks0pcSRLt41ptyebR1gigA/ly61iJRGhNByFEA= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912113408-b130fc40a2e0/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912115910-5ed7055da702 h1:AhqkRKUNlslY6sn/+SbFz2QEIqk39vymqh2IQwu9/U0= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912115910-5ed7055da702/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407 h1:jxTW79Yvsn+34Nkew9tFprF9QtkfZrFfR6KWJHbYMcs= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From f5bba59e515182827d535f64c738ebc063bdb37b Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Fri, 13 Sep 2024 17:57:10 +0200 Subject: [PATCH 6/9] add "parameters" param --- ...ource_datadog_asm_waf_exclusion_filters.go | 11 +++++ ...ource_datadog_asm_waf_exclusion_filters.go | 44 ++++++++++++++----- go.mod | 2 +- go.sum | 6 +++ 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go index 7e7784b89a..d3fa6e09ac 100644 --- a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go @@ -70,6 +70,14 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat exclusionFilterModel.Enabled = types.BoolValue(attributes.GetEnabled()) exclusionFilterModel.PathGlob = types.StringValue(attributes.GetPathGlob()) + var parameters []attr.Value + for _, param := range attributes.GetParameters() { + parameters = append(parameters, types.StringValue(param)) + } + tfParameters, diags := types.ListValue(types.StringType, parameters) + response.Diagnostics.Append(diags...) + exclusionFilterModel.Parameters = tfParameters + var scopes []attr.Value for _, scope := range attributes.GetScope() { scopeObject, diags := types.ObjectValue(map[string]attr.Type{ @@ -161,6 +169,9 @@ func (r *asmWafExclusionFiltersDataSource) Schema(_ context.Context, _ datasourc "description": types.StringType, "enabled": types.BoolType, "path_glob": types.StringType, + "parameters": types.ListType{ + ElemType: types.StringType, + }, "scope": types.ListType{ElemType: types.ObjectType{ AttrTypes: map[string]attr.Type{ "env": types.StringType, diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go index 6914d9ff61..b2b6a13073 100644 --- a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" - "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils" @@ -27,6 +26,7 @@ type asmWafExclusionFiltersModel struct { Description types.String `tfsdk:"description"` Enabled types.Bool `tfsdk:"enabled"` PathGlob types.String `tfsdk:"path_glob"` + Parameters types.List `tfsdk:"parameters"` Scope types.List `tfsdk:"scope"` RulesTarget types.List `tfsdk:"rules_target"` } @@ -56,10 +56,8 @@ func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.Sc Attributes: map[string]schema.Attribute{ "id": utils.ResourceIDAttribute(), "description": schema.StringAttribute{ - Optional: true, + Required: true, Description: "A description for the exclusion filter.", - Default: stringdefault.StaticString(""), - Computed: true, }, "enabled": schema.BoolAttribute{ Required: true, @@ -69,6 +67,11 @@ func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.Sc Required: true, Description: "The path glob for the exclusion filter.", }, + "parameters": schema.ListAttribute{ + Description: "List of parameters for the exclusion filters.", + Optional: true, + ElementType: types.StringType, + }, "scope": schema.ListAttribute{ Description: "The scope of the exclusion filter. Each entry contains 'env' and 'service'.", Optional: true, @@ -211,12 +214,16 @@ func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request res } func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterUpdateRequest, error) { - exclusionFiltersId, enabled, description, pathGlob, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) + exclusionFiltersId, enabled, description, pathGlob, parameters, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) attributes := datadogV2.ASMExclusionFilterUpdateAttributes{ Description: description, Enabled: enabled, - PathGlob: &pathGlob, + PathGlob: pathGlob, + } + + if len(parameters) > 0 { + attributes.Parameters = parameters } if len(scopeList) > 0 { @@ -247,12 +254,16 @@ func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayloa } func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterCreateRequest, error) { - _, enabled, description, pathGlob, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) + _, enabled, description, pathGlob, parameters, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) attributes := datadogV2.ASMExclusionFilterCreateAttributes{ Description: description, Enabled: enabled, - PathGlob: &pathGlob, + PathGlob: pathGlob, + } + + if len(parameters) > 0 { + attributes.Parameters = parameters } if len(scopeList) > 0 { @@ -281,12 +292,19 @@ func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(st return datadogV2.NewASMExclusionFilterCreateRequest(*data), nil } -func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromResource(state *asmWafExclusionFiltersModel) (string, bool, string, string, []datadogV2.ASMExclusionFilterScope, []datadogV2.ASMExclusionFilterRulesTarget) { +func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromResource(state *asmWafExclusionFiltersModel) (string, bool, string, string, []string, []datadogV2.ASMExclusionFilterScope, []datadogV2.ASMExclusionFilterRulesTarget) { id := state.Id.ValueString() enabled := state.Enabled.ValueBool() description := state.Description.ValueString() pathGlob := state.PathGlob.ValueString() + var parameters []string + if !state.Parameters.IsNull() && len(state.Parameters.Elements()) > 0 { + for _, param := range state.Parameters.Elements() { + parameters = append(parameters, param.(types.String).ValueString()) + } + } + var scopeList []datadogV2.ASMExclusionFilterScope if !state.Scope.IsNull() && len(state.Scope.Elements()) > 0 { for _, scopeItem := range state.Scope.Elements() { @@ -323,7 +341,7 @@ func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromRes } } - return id, enabled, description, pathGlob, scopeList, rulesTargetList + return id, enabled, description, pathGlob, parameters, scopeList, rulesTargetList } func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Context, state *asmWafExclusionFiltersModel, res *datadogV2.ASMExclusionFilterResponse) { @@ -341,6 +359,12 @@ func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Con state.Enabled = types.BoolValue(attributes.GetEnabled()) state.PathGlob = types.StringValue(attributes.GetPathGlob()) + var parameters []attr.Value + for _, param := range attributes.GetParameters() { + parameters = append(parameters, types.StringValue(param)) + } + state.Parameters, _ = types.ListValue(types.StringType, parameters) + var scopes []attr.Value if scopeList := attributes.GetScope(); len(scopeList) > 0 { for _, scopeItem := range scopeList { diff --git a/go.mod b/go.mod index 54a401ec3b..b37a2ad0fc 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407 + github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index 32b3ec2dfb..620be6f523 100644 --- a/go.sum +++ b/go.sum @@ -8,6 +8,12 @@ github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912115910-5ed7055da70 github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912115910-5ed7055da702/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407 h1:jxTW79Yvsn+34Nkew9tFprF9QtkfZrFfR6KWJHbYMcs= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913075644-c0bd784c7562 h1:mGtZkw0rQoVd4qO+3y918S6xFYwTlq9tmeIDSK0tKfg= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913075644-c0bd784c7562/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913113358-49405396bb85 h1:E5uG9KDYFzkKeEmNn/Lu1VV4NldbXVXpOQ/DwU7Cl9U= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913113358-49405396bb85/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c h1:eI1JqynhY1vQbAf4isrFJGTgOIP/5fPB+gwVQmAZnQI= +github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From 4a32361a9d945a57b4c90d153bbac87148c1b2b0 Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Tue, 8 Oct 2024 17:22:54 +0200 Subject: [PATCH 7/9] remove rule_name parameter --- ...ource_datadog_asm_waf_exclusion_filters.go | 25 ++++++------------- go.mod | 2 +- go.sum | 2 ++ 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go index b2b6a13073..e9cf12bd58 100644 --- a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -83,12 +83,11 @@ func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.Sc }, }, "rules_target": schema.ListAttribute{ - Description: "The rules target of the exclusion filter with 'rule_id' and 'rule_name'.", + Description: "The rules target of the exclusion filter with 'rule_id'.", Optional: true, ElementType: types.ObjectType{ AttrTypes: map[string]attr.Type{ - "rule_id": types.StringType, - "rule_name": types.StringType, + "rule_id": types.StringType, }, }, }, @@ -241,8 +240,7 @@ func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayloa var newRulesTargetList []datadogV2.ASMExclusionFilterRulesTarget for _, targetItem := range rulesTargetList { newRulesTargetList = append(newRulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ - RuleId: targetItem.RuleId, - RuleName: targetItem.RuleName, + RuleId: targetItem.RuleId, }) } attributes.RulesTarget = newRulesTargetList @@ -281,8 +279,7 @@ func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(st var newRulesTargetList []datadogV2.ASMExclusionFilterRulesTarget for _, targetItem := range rulesTargetList { newRulesTargetList = append(newRulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ - RuleId: targetItem.RuleId, - RuleName: targetItem.RuleName, + RuleId: targetItem.RuleId, }) } attributes.RulesTarget = newRulesTargetList @@ -329,14 +326,11 @@ func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromRes rulesMap := targetItem.(types.Object).Attributes() ruleId := rulesMap["rule_id"].(types.String).ValueString() - ruleName := rulesMap["rule_name"].(types.String).ValueString() ruleIdPtr := &ruleId - ruleNamePtr := &ruleName rulesTargetList = append(rulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ - RuleId: ruleIdPtr, - RuleName: ruleNamePtr, + RuleId: ruleIdPtr, }) } } @@ -390,20 +384,17 @@ func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Con if rulesTargetList := attributes.GetRulesTarget(); len(rulesTargetList) > 0 { for _, targetItem := range rulesTargetList { ruleValues := map[string]attr.Value{ - "rule_id": types.StringValue(targetItem.GetRuleId()), - "rule_name": types.StringValue(targetItem.GetRuleName()), + "rule_id": types.StringValue(targetItem.GetRuleId()), } ruleObject, _ := types.ObjectValue(map[string]attr.Type{ - "rule_id": types.StringType, - "rule_name": types.StringType, + "rule_id": types.StringType, }, ruleValues) rulesTarget = append(rulesTarget, ruleObject) } } state.RulesTarget, _ = types.ListValue(types.ObjectType{ AttrTypes: map[string]attr.Type{ - "rule_id": types.StringType, - "rule_name": types.StringType, + "rule_id": types.StringType, }, }, rulesTarget) diff --git a/go.mod b/go.mod index b37a2ad0fc..562174f794 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c + github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3 github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index 620be6f523..c896e1790e 100644 --- a/go.sum +++ b/go.sum @@ -14,6 +14,8 @@ github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913113358-49405396bb8 github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913113358-49405396bb85/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c h1:eI1JqynhY1vQbAf4isrFJGTgOIP/5fPB+gwVQmAZnQI= github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3 h1:dsO4PLeYTedLTSvJV/WxUkxTSjaVEOwjA8t0cIuUFJQ= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From 42ba0b87ecb4649f932c95613d7b5a42042dd3f7 Mon Sep 17 00:00:00 2001 From: Quentin Guillard Date: Tue, 15 Oct 2024 13:48:32 +0200 Subject: [PATCH 8/9] change the acronym ASM to ApplicationSecurity --- ...ource_datadog_asm_waf_exclusion_filters.go | 44 +++---- datadog/fwprovider/framework_provider.go | 4 +- ...ource_datadog_asm_waf_exclusion_filters.go | 114 +++++++++--------- .../internal/utils/api_instances_helper.go | 88 +++++++------- go.mod | 2 +- go.sum | 4 + 6 files changed, 130 insertions(+), 126 deletions(-) diff --git a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go index d3fa6e09ac..05ac5ccaa9 100644 --- a/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/data_source_datadog_asm_waf_exclusion_filters.go @@ -16,42 +16,42 @@ import ( ) var ( - _ datasource.DataSourceWithConfigure = &asmWafExclusionFiltersDataSource{} + _ datasource.DataSourceWithConfigure = &applicationSecurityExclusionFiltersDataSource{} ) -type asmWafExclusionFiltersDataSource struct { - api *datadogV2.ASMExclusionFiltersApi +type applicationSecurityExclusionFiltersDataSource struct { + api *datadogV2.ApplicationSecurityExclusionFiltersApi auth context.Context } -type asmWafExclusionFiltersDataSourceModel struct { - Id types.String `tfsdk:"id"` - ExclusionFiltersIds types.List `tfsdk:"exclusion_filters_ids"` - ExclusionFilters []asmWafExclusionFiltersModel `tfsdk:"exclusion_filters"` +type applicationSecurityExclusionFiltersDataSourceModel struct { + Id types.String `tfsdk:"id"` + ExclusionFiltersIds types.List `tfsdk:"exclusion_filters_ids"` + ExclusionFilters []applicationSecurityExclusionFiltersModel `tfsdk:"exclusion_filters"` } -func NewAsmWafExclusionFiltersDataSource() datasource.DataSource { - return &asmWafExclusionFiltersDataSource{} +func NewApplicationSecurityExclusionFiltersDataSource() datasource.DataSource { + return &applicationSecurityExclusionFiltersDataSource{} } -func (r *asmWafExclusionFiltersDataSource) Configure(_ context.Context, request datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { +func (r *applicationSecurityExclusionFiltersDataSource) Configure(_ context.Context, request datasource.ConfigureRequest, _ *datasource.ConfigureResponse) { providerData := request.ProviderData.(*FrameworkProvider) - r.api = providerData.DatadogApiInstances.GetASMExclusionFiltersApiV2() + r.api = providerData.DatadogApiInstances.GetApplicationSecurityExclusionFiltersApiV2() r.auth = providerData.Auth } -func (*asmWafExclusionFiltersDataSource) Metadata(_ context.Context, _ datasource.MetadataRequest, response *datasource.MetadataResponse) { - response.TypeName = "asm_waf_exclusion_filters" +func (*applicationSecurityExclusionFiltersDataSource) Metadata(_ context.Context, _ datasource.MetadataRequest, response *datasource.MetadataResponse) { + response.TypeName = "application_security_exclusion_filters" } -func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { - var state asmWafExclusionFiltersDataSourceModel +func (r *applicationSecurityExclusionFiltersDataSource) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + var state applicationSecurityExclusionFiltersDataSourceModel response.Diagnostics.Append(request.Config.Get(ctx, &state)...) if response.Diagnostics.HasError() { return } - res, _, err := r.api.ListASMExclusionFilters(r.auth) + res, _, err := r.api.ListApplicationSecurityExclusionFilters(r.auth) if err != nil { response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error while fetching exclusion filters")) return @@ -59,10 +59,10 @@ func (r *asmWafExclusionFiltersDataSource) Read(ctx context.Context, request dat data := res.GetData() exclusionFilterIds := make([]string, len(data)) - exclusionFilters := make([]asmWafExclusionFiltersModel, len(data)) + exclusionFilters := make([]applicationSecurityExclusionFiltersModel, len(data)) for idx, exclusionFilter := range res.GetData() { - var exclusionFilterModel asmWafExclusionFiltersModel + var exclusionFilterModel applicationSecurityExclusionFiltersModel exclusionFilterModel.Id = types.StringValue(exclusionFilter.GetId()) attributes := exclusionFilter.GetAttributes() @@ -150,19 +150,19 @@ func computeExclusionFiltersDataSourceID(exclusionFiltersIds *string) string { return fmt.Sprintf("%x", h.Sum(nil)) } -func (r *asmWafExclusionFiltersDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) { +func (r *applicationSecurityExclusionFiltersDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, response *datasource.SchemaResponse) { response.Schema = schema.Schema{ - Description: "Retrieves Datadog ASM WAF Exclusion Filters.", + Description: "Retrieves Datadog Application Security Exclusion Filters.", Attributes: map[string]schema.Attribute{ "id": utils.ResourceIDAttribute(), "exclusion_filters_ids": schema.ListAttribute{ Computed: true, - Description: "List of IDs for the ASM exclusion filters.", + Description: "List of IDs for the Application Security exclusion filters.", ElementType: types.StringType, }, "exclusion_filters": schema.ListAttribute{ Computed: true, - Description: "List of ASM WAF exclusion filters", + Description: "List of Application Security exclusion filters", ElementType: types.ObjectType{ AttrTypes: map[string]attr.Type{ "id": types.StringType, diff --git a/datadog/fwprovider/framework_provider.go b/datadog/fwprovider/framework_provider.go index 2737635fea..a957aef04d 100644 --- a/datadog/fwprovider/framework_provider.go +++ b/datadog/fwprovider/framework_provider.go @@ -62,7 +62,7 @@ var Resources = []func() resource.Resource{ NewUserRoleResource, NewSecurityMonitoringSuppressionResource, NewCSMThreatsAgentRuleResource, - NewAsmWafExclusionFiltersResource, + NewApplicationSecurityExclusionFiltersResource, NewServiceAccountResource, NewWebhookResource, NewWebhookCustomVariableResource, @@ -87,7 +87,7 @@ var Datasources = []func() datasource.DataSource{ NewDatadogRoleUsersDataSource, NewSecurityMonitoringSuppressionDataSource, NewCSMThreatsAgentRulesDataSource, - NewAsmWafExclusionFiltersDataSource, + NewApplicationSecurityExclusionFiltersDataSource, } // FrameworkProvider struct diff --git a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go index e9cf12bd58..12a4d750d9 100644 --- a/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go +++ b/datadog/fwprovider/resource_datadog_asm_waf_exclusion_filters.go @@ -16,12 +16,12 @@ import ( ) var ( - asmWafExclusionFiltersMutex sync.Mutex - _ resource.ResourceWithConfigure = &asmWafExclusionFiltersResource{} - _ resource.ResourceWithImportState = &asmWafExclusionFiltersResource{} + applicationSecurityExclusionFiltersMutex sync.Mutex + _ resource.ResourceWithConfigure = &applicationSecurityExclusionFiltersResource{} + _ resource.ResourceWithImportState = &applicationSecurityExclusionFiltersResource{} ) -type asmWafExclusionFiltersModel struct { +type applicationSecurityExclusionFiltersModel struct { Id types.String `tfsdk:"id"` Description types.String `tfsdk:"description"` Enabled types.Bool `tfsdk:"enabled"` @@ -31,28 +31,28 @@ type asmWafExclusionFiltersModel struct { RulesTarget types.List `tfsdk:"rules_target"` } -type asmWafExclusionFiltersResource struct { - api *datadogV2.ASMExclusionFiltersApi +type applicationSecurityExclusionFiltersResource struct { + api *datadogV2.ApplicationSecurityExclusionFiltersApi auth context.Context } -func NewAsmWafExclusionFiltersResource() resource.Resource { - return &asmWafExclusionFiltersResource{} +func NewApplicationSecurityExclusionFiltersResource() resource.Resource { + return &applicationSecurityExclusionFiltersResource{} } -func (r *asmWafExclusionFiltersResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { - response.TypeName = "asm_waf_exclusion_filters" +func (r *applicationSecurityExclusionFiltersResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "application_security_exclusion_filters" } -func (r *asmWafExclusionFiltersResource) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { +func (r *applicationSecurityExclusionFiltersResource) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { providerData := request.ProviderData.(*FrameworkProvider) - r.api = providerData.DatadogApiInstances.GetASMExclusionFiltersApiV2() // to change + r.api = providerData.DatadogApiInstances.GetApplicationSecurityExclusionFiltersApiV2() r.auth = providerData.Auth } -func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { +func (r *applicationSecurityExclusionFiltersResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { response.Schema = schema.Schema{ - Description: "Provides a Datadog ASM WAF Exclusion Filters API resource.", + Description: "Provides a Datadog Application Security Exclusion Filters API resource.", Attributes: map[string]schema.Attribute{ "id": utils.ResourceIDAttribute(), "description": schema.StringAttribute{ @@ -95,27 +95,27 @@ func (r *asmWafExclusionFiltersResource) Schema(_ context.Context, _ resource.Sc } } -func (r *asmWafExclusionFiltersResource) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { +func (r *applicationSecurityExclusionFiltersResource) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { resource.ImportStatePassthroughID(ctx, path.Root("id"), request, response) } -func (r *asmWafExclusionFiltersResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { - var state asmWafExclusionFiltersModel +func (r *applicationSecurityExclusionFiltersResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var state applicationSecurityExclusionFiltersModel response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) if response.Diagnostics.HasError() { return } - asmWafExclusionFiltersMutex.Lock() - defer asmWafExclusionFiltersMutex.Unlock() + applicationSecurityExclusionFiltersMutex.Lock() + defer applicationSecurityExclusionFiltersMutex.Unlock() - exclusionFilterPayload, err := r.buildCreateASMExclusionFilterPayload(&state) + exclusionFilterPayload, err := r.buildCreateApplicationSecurityExclusionFilterPayload(&state) if err != nil { response.Diagnostics.AddError("error while parsing resource", err.Error()) return } - res, _, err := r.api.CreateASMExclusionFilter(r.auth, *exclusionFilterPayload) + res, _, err := r.api.CreateApplicationSecurityExclusionFilter(r.auth, *exclusionFilterPayload) if err != nil { response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error creating exclusion filter")) return @@ -130,8 +130,8 @@ func (r *asmWafExclusionFiltersResource) Create(ctx context.Context, request res response.Diagnostics.Append(response.State.Set(ctx, &state)...) } -func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { - var state asmWafExclusionFiltersModel +func (r *applicationSecurityExclusionFiltersResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var state applicationSecurityExclusionFiltersModel response.Diagnostics.Append(request.State.Get(ctx, &state)...) if response.Diagnostics.HasError() { @@ -140,7 +140,7 @@ func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resou exclusionFilterId := state.Id.ValueString() - res, httpResponse, err := r.api.GetASMExclusionFilters(r.auth, exclusionFilterId) + res, httpResponse, err := r.api.GetApplicationSecurityExclusionFilters(r.auth, exclusionFilterId) if err != nil { if httpResponse != nil && httpResponse.StatusCode == 404 { response.State.RemoveResource(ctx) @@ -160,22 +160,22 @@ func (r *asmWafExclusionFiltersResource) Read(ctx context.Context, request resou response.Diagnostics.Append(response.State.Set(ctx, &state)...) } -func (r *asmWafExclusionFiltersResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { - var state asmWafExclusionFiltersModel +func (r *applicationSecurityExclusionFiltersResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var state applicationSecurityExclusionFiltersModel response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) if response.Diagnostics.HasError() { return } - asmWafExclusionFiltersMutex.Lock() - defer asmWafExclusionFiltersMutex.Unlock() + applicationSecurityExclusionFiltersMutex.Lock() + defer applicationSecurityExclusionFiltersMutex.Unlock() - exclusionFiltersPayload, err := r.buildUpdateAsmWafExclusionFiltersPayload(&state) + exclusionFiltersPayload, err := r.buildUpdateApplicationSecurityExclusionFiltersPayload(&state) if err != nil { response.Diagnostics.AddError("error while parsing resource", err.Error()) } - res, _, err := r.api.UpdateASMExclusionFilter(r.auth, state.Id.ValueString(), *exclusionFiltersPayload) // to change: endpoint PATCH/PUT + res, _, err := r.api.UpdateApplicationSecurityExclusionFilter(r.auth, state.Id.ValueString(), *exclusionFiltersPayload) // to change: endpoint PATCH/PUT if err != nil { response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error updating agent rule")) return @@ -189,19 +189,19 @@ func (r *asmWafExclusionFiltersResource) Update(ctx context.Context, request res response.Diagnostics.Append(response.State.Set(ctx, &state)...) } -func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { - var state asmWafExclusionFiltersModel +func (r *applicationSecurityExclusionFiltersResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var state applicationSecurityExclusionFiltersModel response.Diagnostics.Append(request.State.Get(ctx, &state)...) if response.Diagnostics.HasError() { return } - asmWafExclusionFiltersMutex.Lock() - defer asmWafExclusionFiltersMutex.Unlock() + applicationSecurityExclusionFiltersMutex.Lock() + defer applicationSecurityExclusionFiltersMutex.Unlock() id := state.Id.ValueString() - httpResp, err := r.api.DeleteASMExclusionFilter(r.auth, id) + httpResp, err := r.api.DeleteApplicationSecurityExclusionFilter(r.auth, id) if err != nil { if httpResp != nil && httpResp.StatusCode == 404 { @@ -212,10 +212,10 @@ func (r *asmWafExclusionFiltersResource) Delete(ctx context.Context, request res } } -func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterUpdateRequest, error) { +func (r *applicationSecurityExclusionFiltersResource) buildUpdateApplicationSecurityExclusionFiltersPayload(state *applicationSecurityExclusionFiltersModel) (*datadogV2.ApplicationSecurityExclusionFilterUpdateRequest, error) { exclusionFiltersId, enabled, description, pathGlob, parameters, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) - attributes := datadogV2.ASMExclusionFilterUpdateAttributes{ + attributes := datadogV2.ApplicationSecurityExclusionFilterUpdateAttributes{ Description: description, Enabled: enabled, PathGlob: pathGlob, @@ -226,9 +226,9 @@ func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayloa } if len(scopeList) > 0 { - var newScopeList []datadogV2.ASMExclusionFilterScope + var newScopeList []datadogV2.ApplicationSecurityExclusionFilterScope for _, scopeItem := range scopeList { - newScopeList = append(newScopeList, datadogV2.ASMExclusionFilterScope{ + newScopeList = append(newScopeList, datadogV2.ApplicationSecurityExclusionFilterScope{ Env: scopeItem.Env, Service: scopeItem.Service, }) @@ -237,24 +237,24 @@ func (r *asmWafExclusionFiltersResource) buildUpdateAsmWafExclusionFiltersPayloa } if len(rulesTargetList) > 0 { - var newRulesTargetList []datadogV2.ASMExclusionFilterRulesTarget + var newRulesTargetList []datadogV2.ApplicationSecurityExclusionFilterRulesTarget for _, targetItem := range rulesTargetList { - newRulesTargetList = append(newRulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ + newRulesTargetList = append(newRulesTargetList, datadogV2.ApplicationSecurityExclusionFilterRulesTarget{ RuleId: targetItem.RuleId, }) } attributes.RulesTarget = newRulesTargetList } - data := datadogV2.NewASMExclusionFilterUpdateData(attributes, datadogV2.ASMEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) + data := datadogV2.NewApplicationSecurityExclusionFilterUpdateData(attributes, datadogV2.APPLICATIONSECURITYEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) data.Id = &exclusionFiltersId - return datadogV2.NewASMExclusionFilterUpdateRequest(*data), nil + return datadogV2.NewApplicationSecurityExclusionFilterUpdateRequest(*data), nil } -func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(state *asmWafExclusionFiltersModel) (*datadogV2.ASMExclusionFilterCreateRequest, error) { +func (r *applicationSecurityExclusionFiltersResource) buildCreateApplicationSecurityExclusionFilterPayload(state *applicationSecurityExclusionFiltersModel) (*datadogV2.ApplicationSecurityExclusionFilterCreateRequest, error) { _, enabled, description, pathGlob, parameters, scopeList, rulesTargetList := r.extractExclusionFilterAttributesFromResource(state) - attributes := datadogV2.ASMExclusionFilterCreateAttributes{ + attributes := datadogV2.ApplicationSecurityExclusionFilterCreateAttributes{ Description: description, Enabled: enabled, PathGlob: pathGlob, @@ -265,9 +265,9 @@ func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(st } if len(scopeList) > 0 { - var newScopeList []datadogV2.ASMExclusionFilterScope + var newScopeList []datadogV2.ApplicationSecurityExclusionFilterScope for _, scopeItem := range scopeList { - newScopeList = append(newScopeList, datadogV2.ASMExclusionFilterScope{ + newScopeList = append(newScopeList, datadogV2.ApplicationSecurityExclusionFilterScope{ Env: scopeItem.Env, Service: scopeItem.Service, }) @@ -276,20 +276,20 @@ func (r *asmWafExclusionFiltersResource) buildCreateASMExclusionFilterPayload(st } if len(rulesTargetList) > 0 { - var newRulesTargetList []datadogV2.ASMExclusionFilterRulesTarget + var newRulesTargetList []datadogV2.ApplicationSecurityExclusionFilterRulesTarget for _, targetItem := range rulesTargetList { - newRulesTargetList = append(newRulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ + newRulesTargetList = append(newRulesTargetList, datadogV2.ApplicationSecurityExclusionFilterRulesTarget{ RuleId: targetItem.RuleId, }) } attributes.RulesTarget = newRulesTargetList } - data := datadogV2.NewASMExclusionFilterCreateData(attributes, datadogV2.ASMEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) - return datadogV2.NewASMExclusionFilterCreateRequest(*data), nil + data := datadogV2.NewApplicationSecurityExclusionFilterCreateData(attributes, datadogV2.APPLICATIONSECURITYEXCLUSIONFILTERTYPE_EXCLUSION_FILTER) + return datadogV2.NewApplicationSecurityExclusionFilterCreateRequest(*data), nil } -func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromResource(state *asmWafExclusionFiltersModel) (string, bool, string, string, []string, []datadogV2.ASMExclusionFilterScope, []datadogV2.ASMExclusionFilterRulesTarget) { +func (r *applicationSecurityExclusionFiltersResource) extractExclusionFilterAttributesFromResource(state *applicationSecurityExclusionFiltersModel) (string, bool, string, string, []string, []datadogV2.ApplicationSecurityExclusionFilterScope, []datadogV2.ApplicationSecurityExclusionFilterRulesTarget) { id := state.Id.ValueString() enabled := state.Enabled.ValueBool() description := state.Description.ValueString() @@ -302,7 +302,7 @@ func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromRes } } - var scopeList []datadogV2.ASMExclusionFilterScope + var scopeList []datadogV2.ApplicationSecurityExclusionFilterScope if !state.Scope.IsNull() && len(state.Scope.Elements()) > 0 { for _, scopeItem := range state.Scope.Elements() { scopeMap := scopeItem.(types.Object).Attributes() @@ -313,14 +313,14 @@ func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromRes envPtr := &env servicePtr := &service - scopeList = append(scopeList, datadogV2.ASMExclusionFilterScope{ + scopeList = append(scopeList, datadogV2.ApplicationSecurityExclusionFilterScope{ Env: envPtr, Service: servicePtr, }) } } - var rulesTargetList []datadogV2.ASMExclusionFilterRulesTarget + var rulesTargetList []datadogV2.ApplicationSecurityExclusionFilterRulesTarget if !state.RulesTarget.IsNull() && len(state.RulesTarget.Elements()) > 0 { for _, targetItem := range state.RulesTarget.Elements() { rulesMap := targetItem.(types.Object).Attributes() @@ -329,7 +329,7 @@ func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromRes ruleIdPtr := &ruleId - rulesTargetList = append(rulesTargetList, datadogV2.ASMExclusionFilterRulesTarget{ + rulesTargetList = append(rulesTargetList, datadogV2.ApplicationSecurityExclusionFilterRulesTarget{ RuleId: ruleIdPtr, }) } @@ -338,7 +338,7 @@ func (r *asmWafExclusionFiltersResource) extractExclusionFilterAttributesFromRes return id, enabled, description, pathGlob, parameters, scopeList, rulesTargetList } -func (r *asmWafExclusionFiltersResource) updateStateFromResponse(ctx context.Context, state *asmWafExclusionFiltersModel, res *datadogV2.ASMExclusionFilterResponse) { +func (r *applicationSecurityExclusionFiltersResource) updateStateFromResponse(ctx context.Context, state *applicationSecurityExclusionFiltersModel, res *datadogV2.ApplicationSecurityExclusionFilterResponse) { if len(res.Data) == 0 { return diff --git a/datadog/internal/utils/api_instances_helper.go b/datadog/internal/utils/api_instances_helper.go index 48586b98f9..8d501991c7 100644 --- a/datadog/internal/utils/api_instances_helper.go +++ b/datadog/internal/utils/api_instances_helper.go @@ -44,45 +44,45 @@ type ApiInstances struct { webhooksIntegrationApiV1 *datadogV1.WebhooksIntegrationApi //V2 APIs - apiManagementAPIV2 *datadogV2.APIManagementApi - apmRetentionFiltersApiV2 *datadogV2.APMRetentionFiltersApi - ASMExclusionFiltersApiV2 *datadogV2.ASMExclusionFiltersApi - auditApiV2 *datadogV2.AuditApi - authNMappingsApiV2 *datadogV2.AuthNMappingsApi - cloudflareIntegrationApiV2 *datadogV2.CloudflareIntegrationApi - csmThreatsApiV2 *datadogV2.CSMThreatsApi - confluentCloudApiV2 *datadogV2.ConfluentCloudApi - dashboardListsApiV2 *datadogV2.DashboardListsApi - downtimesApiV2 *datadogV2.DowntimesApi - eventsApiV2 *datadogV2.EventsApi - fastlyIntegrationApiV2 *datadogV2.FastlyIntegrationApi - gcpStsIntegrationApiV2 *datadogV2.GCPIntegrationApi - incidentServicesApiV2 *datadogV2.IncidentServicesApi - incidentTeamsApiV2 *datadogV2.IncidentTeamsApi - incidentsApiV2 *datadogV2.IncidentsApi - ipAllowlistApiV2 *datadogV2.IPAllowlistApi - keyManagementApiV2 *datadogV2.KeyManagementApi - logsApiV2 *datadogV2.LogsApi - logsArchivesApiV2 *datadogV2.LogsArchivesApi - logsCustomDestinationsApiV2 *datadogV2.LogsCustomDestinationsApi - logsMetricsApiV2 *datadogV2.LogsMetricsApi - metricsApiV2 *datadogV2.MetricsApi - monitorsApiV2 *datadogV2.MonitorsApi - opsgenieIntegrationApiV2 *datadogV2.OpsgenieIntegrationApi - organizationsApiV2 *datadogV2.OrganizationsApi - processesApiV2 *datadogV2.ProcessesApi - powerpackApiV2 *datadogV2.PowerpackApi - restrictionPolicyApiV2 *datadogV2.RestrictionPoliciesApi - rolesApiV2 *datadogV2.RolesApi - rumApiV2 *datadogV2.RUMApi - securityMonitoringApiV2 *datadogV2.SecurityMonitoringApi - sensitiveDataScannerApiV2 *datadogV2.SensitiveDataScannerApi - serviceAccountsApiV2 *datadogV2.ServiceAccountsApi - spansMetricsApiV2 *datadogV2.SpansMetricsApi - syntheticsApiV2 *datadogV2.SyntheticsApi - teamsApiV2 *datadogV2.TeamsApi - usageMeteringApiV2 *datadogV2.UsageMeteringApi - usersApiV2 *datadogV2.UsersApi + apiManagementAPIV2 *datadogV2.APIManagementApi + apmRetentionFiltersApiV2 *datadogV2.APMRetentionFiltersApi + ApplicationSecurityExclusionFiltersApiV2 *datadogV2.ApplicationSecurityExclusionFiltersApi + auditApiV2 *datadogV2.AuditApi + authNMappingsApiV2 *datadogV2.AuthNMappingsApi + cloudflareIntegrationApiV2 *datadogV2.CloudflareIntegrationApi + csmThreatsApiV2 *datadogV2.CSMThreatsApi + confluentCloudApiV2 *datadogV2.ConfluentCloudApi + dashboardListsApiV2 *datadogV2.DashboardListsApi + downtimesApiV2 *datadogV2.DowntimesApi + eventsApiV2 *datadogV2.EventsApi + fastlyIntegrationApiV2 *datadogV2.FastlyIntegrationApi + gcpStsIntegrationApiV2 *datadogV2.GCPIntegrationApi + incidentServicesApiV2 *datadogV2.IncidentServicesApi + incidentTeamsApiV2 *datadogV2.IncidentTeamsApi + incidentsApiV2 *datadogV2.IncidentsApi + ipAllowlistApiV2 *datadogV2.IPAllowlistApi + keyManagementApiV2 *datadogV2.KeyManagementApi + logsApiV2 *datadogV2.LogsApi + logsArchivesApiV2 *datadogV2.LogsArchivesApi + logsCustomDestinationsApiV2 *datadogV2.LogsCustomDestinationsApi + logsMetricsApiV2 *datadogV2.LogsMetricsApi + metricsApiV2 *datadogV2.MetricsApi + monitorsApiV2 *datadogV2.MonitorsApi + opsgenieIntegrationApiV2 *datadogV2.OpsgenieIntegrationApi + organizationsApiV2 *datadogV2.OrganizationsApi + processesApiV2 *datadogV2.ProcessesApi + powerpackApiV2 *datadogV2.PowerpackApi + restrictionPolicyApiV2 *datadogV2.RestrictionPoliciesApi + rolesApiV2 *datadogV2.RolesApi + rumApiV2 *datadogV2.RUMApi + securityMonitoringApiV2 *datadogV2.SecurityMonitoringApi + sensitiveDataScannerApiV2 *datadogV2.SensitiveDataScannerApi + serviceAccountsApiV2 *datadogV2.ServiceAccountsApi + spansMetricsApiV2 *datadogV2.SpansMetricsApi + syntheticsApiV2 *datadogV2.SyntheticsApi + teamsApiV2 *datadogV2.TeamsApi + usageMeteringApiV2 *datadogV2.UsageMeteringApi + usersApiV2 *datadogV2.UsersApi } // GetAuthenticationApiV1 get instance of AuthenticationApi @@ -333,12 +333,12 @@ func (i *ApiInstances) GetWebhooksIntegrationApiV1() *datadogV1.WebhooksIntegrat return i.webhooksIntegrationApiV1 } -// GetASMExclusionFiltersApiV2 get instance of ASMExclusionFiltersApi -func (i *ApiInstances) GetASMExclusionFiltersApiV2() *datadogV2.ASMExclusionFiltersApi { - if i.ASMExclusionFiltersApiV2 == nil { - i.ASMExclusionFiltersApiV2 = datadogV2.NewASMExclusionFiltersApi(i.HttpClient) +// GetApplicationSecurityExclusionFiltersApiV2 get instance of ApplicationSecurityExclusionFiltersApi +func (i *ApiInstances) GetApplicationSecurityExclusionFiltersApiV2() *datadogV2.ApplicationSecurityExclusionFiltersApi { + if i.ApplicationSecurityExclusionFiltersApiV2 == nil { + i.ApplicationSecurityExclusionFiltersApiV2 = datadogV2.NewApplicationSecurityExclusionFiltersApi(i.HttpClient) } - return i.ASMExclusionFiltersApiV2 + return i.ApplicationSecurityExclusionFiltersApiV2 } // GetAuditApiV2 get instance of AuditApi diff --git a/go.mod b/go.mod index 562174f794..c2dd8d3996 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3 + github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015091326-8142b5c59978 github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index c896e1790e..fa931ebe81 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,10 @@ github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0 github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3 h1:dsO4PLeYTedLTSvJV/WxUkxTSjaVEOwjA8t0cIuUFJQ= github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015080524-c31d058d9cf4 h1:p9wvL7mykEDFa+kl6YL48kveJScUwTINBW5S5ldJqiw= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015080524-c31d058d9cf4/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015091326-8142b5c59978 h1:nj5d3zw/drUtUgqULAgvki3VO0sCz9+LXLy62aWRSq8= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015091326-8142b5c59978/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= From 1dd35e83505b7511bcdefc522385c9fd5a81037d Mon Sep 17 00:00:00 2001 From: Bruce Tu Date: Wed, 16 Oct 2024 11:31:33 -0400 Subject: [PATCH 9/9] fix go-client commit hash, fix ToplistWidgetDisplay --- datadog/resource_datadog_dashboard.go | 5 +---- go.mod | 2 +- go.sum | 24 ++---------------------- 3 files changed, 4 insertions(+), 27 deletions(-) diff --git a/datadog/resource_datadog_dashboard.go b/datadog/resource_datadog_dashboard.go index d7d45ecd61..99509b45f8 100644 --- a/datadog/resource_datadog_dashboard.go +++ b/datadog/resource_datadog_dashboard.go @@ -8031,10 +8031,7 @@ func buildDatadogToplistStyle(terraformToplistStyle map[string]interface{}) data if t, ok := v["type"].(string); ok && len(t) != 0 { if t == "stacked" { datadogToplistStyle.SetDisplay(datadogV1.ToplistWidgetDisplay{ - ToplistWidgetStacked: datadogV1.NewToplistWidgetStacked( - datadogV1.TOPLISTWIDGETLEGEND_AUTOMATIC, - datadogV1.TOPLISTWIDGETSTACKEDTYPE_STACKED, - ), + ToplistWidgetStacked: datadogV1.NewToplistWidgetStackedWithDefaults(), }) } else if t == "flat" { datadogToplistStyle.SetDisplay(datadogV1.ToplistWidgetDisplay{ diff --git a/go.mod b/go.mod index c2dd8d3996..a0dff3b88c 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/terraform-providers/terraform-provider-datadog require ( - github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015091326-8142b5c59978 + github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015145846-232436a03559 github.com/DataDog/dd-sdk-go-testing v0.0.0-20211116174033-1cd082e322ad github.com/Masterminds/semver/v3 v3.1.1 github.com/google/go-cmp v0.5.9 diff --git a/go.sum b/go.sum index 87d3ba75db..f7fbcd68d8 100644 --- a/go.sum +++ b/go.sum @@ -1,27 +1,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240911195025-92128b15dc8c h1:+yokfxyjea3W7KpyCTeTIKqPFNeGEAubmI0RCO7sBdE= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240911195025-92128b15dc8c/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912113408-b130fc40a2e0 h1:GD/Nkks0pcSRLt41ptyebR1gigA/ly61iJRGhNByFEA= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912113408-b130fc40a2e0/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912115910-5ed7055da702 h1:AhqkRKUNlslY6sn/+SbFz2QEIqk39vymqh2IQwu9/U0= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912115910-5ed7055da702/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407 h1:jxTW79Yvsn+34Nkew9tFprF9QtkfZrFfR6KWJHbYMcs= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240912135525-758a35b09407/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913075644-c0bd784c7562 h1:mGtZkw0rQoVd4qO+3y918S6xFYwTlq9tmeIDSK0tKfg= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913075644-c0bd784c7562/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913113358-49405396bb85 h1:E5uG9KDYFzkKeEmNn/Lu1VV4NldbXVXpOQ/DwU7Cl9U= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913113358-49405396bb85/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c h1:eI1JqynhY1vQbAf4isrFJGTgOIP/5fPB+gwVQmAZnQI= -github.com/DataDog/datadog-api-client-go/v2 v2.30.1-0.20240913115908-53c669e5ee0c/go.mod h1:QKOu6vscsh87fMY1lHfLEmNSunyXImj8BUaUWJXOehc= -github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3 h1:dsO4PLeYTedLTSvJV/WxUkxTSjaVEOwjA8t0cIuUFJQ= -github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241008140801-e02c46d693b3/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= -github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015080524-c31d058d9cf4 h1:p9wvL7mykEDFa+kl6YL48kveJScUwTINBW5S5ldJqiw= -github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015080524-c31d058d9cf4/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= -github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015091326-8142b5c59978 h1:nj5d3zw/drUtUgqULAgvki3VO0sCz9+LXLy62aWRSq8= -github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015091326-8142b5c59978/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= -github.com/DataDog/datadog-api-client-go/v2 v2.31.0 h1:JfJhYlHfLzvauI8u6h23smTooWYe6quNhhg9gpTszWY= -github.com/DataDog/datadog-api-client-go/v2 v2.31.0/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015145846-232436a03559 h1:puARPt0ChvKQSplleU8FQK7xCffHgj3w6smBuK9RuQY= +github.com/DataDog/datadog-api-client-go/v2 v2.31.1-0.20241015145846-232436a03559/go.mod h1:d3tOEgUd2kfsr9uuHQdY+nXrWp4uikgTgVCPdKNK30U= github.com/DataDog/datadog-go v4.4.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/datadog-go v4.8.3+incompatible h1:fNGaYSuObuQb5nzeTQqowRAd9bpDIRRV4/gUtIBjh8Q= github.com/DataDog/datadog-go v4.8.3+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=