From 9ee3437bff7cab6d720f5a9934e4b9440b209829 Mon Sep 17 00:00:00 2001 From: Sherzod Karimov Date: Fri, 15 Sep 2023 15:08:01 -0400 Subject: [PATCH] migrate logs collection --- datadog/fwprovider/framework_provider.go | 1 + ..._datadog_integration_aws_log_collection.go | 225 ++++++++++++++++++ datadog/provider.go | 1 - ..._datadog_integration_aws_log_collection.go | 148 ------------ 4 files changed, 226 insertions(+), 149 deletions(-) create mode 100644 datadog/fwprovider/resource_datadog_integration_aws_log_collection.go delete mode 100644 datadog/resource_datadog_integration_aws_log_collection.go diff --git a/datadog/fwprovider/framework_provider.go b/datadog/fwprovider/framework_provider.go index 339d129f4..5767746e8 100644 --- a/datadog/fwprovider/framework_provider.go +++ b/datadog/fwprovider/framework_provider.go @@ -35,6 +35,7 @@ var Resources = []func() resource.Resource{ NewAPIKeyResource, NewDashboardListResource, NewDowntimeScheduleResource, + NewIntegrationAWSLogCollectionResource, NewIntegrationAWSResource, NewIntegrationCloudflareAccountResource, NewIntegrationConfluentAccountResource, diff --git a/datadog/fwprovider/resource_datadog_integration_aws_log_collection.go b/datadog/fwprovider/resource_datadog_integration_aws_log_collection.go new file mode 100644 index 000000000..8432cd827 --- /dev/null +++ b/datadog/fwprovider/resource_datadog_integration_aws_log_collection.go @@ -0,0 +1,225 @@ +package fwprovider + +import ( + "context" + "fmt" + + "github.com/DataDog/datadog-api-client-go/v2/api/datadogV1" + "github.com/hashicorp/terraform-plugin-framework/diag" + frameworkPath "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/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + + "github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils" +) + +var ( + _ resource.ResourceWithConfigure = &integrationAWSLogCollectionResource{} + _ resource.ResourceWithImportState = &integrationAWSLogCollectionResource{} +) + +type integrationAWSLogCollectionResource struct { + Api *datadogV1.AWSLogsIntegrationApi + Auth context.Context +} + +type integrationAWSLogCollectionModel struct { + ID types.String `tfsdk:"id"` + AccountID types.String `tfsdk:"account_id"` + Services types.List `tfsdk:"services"` +} + +func NewIntegrationAWSLogCollectionResource() resource.Resource { + return &integrationAWSLogCollectionResource{} +} + +func (r *integrationAWSLogCollectionResource) Configure(_ context.Context, request resource.ConfigureRequest, response *resource.ConfigureResponse) { + providerData, _ := request.ProviderData.(*FrameworkProvider) + r.Api = providerData.DatadogApiInstances.GetAWSLogsIntegrationApiV1() + r.Auth = providerData.Auth +} + +func (r *integrationAWSLogCollectionResource) Metadata(_ context.Context, request resource.MetadataRequest, response *resource.MetadataResponse) { + response.TypeName = "integration_aws_log_collection" +} + +func (r *integrationAWSLogCollectionResource) Schema(_ context.Context, _ resource.SchemaRequest, response *resource.SchemaResponse) { + response.Schema = schema.Schema{ + Description: "Provides a Datadog - Amazon Web Services integration log collection resource. This can be used to manage which AWS services logs are collected from for an account.", + Attributes: map[string]schema.Attribute{ + "account_id": schema.StringAttribute{ + Required: true, + Description: "Your AWS Account ID without dashes. If your account is a GovCloud or China account, specify the `access_key_id` here.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "services": schema.ListAttribute{ + Required: true, + Description: "A list of services to collect logs from. See the [api docs](https://docs.datadoghq.com/api/v1/aws-logs-integration/#get-list-of-aws-log-ready-services) for more details on which services are supported.", + ElementType: types.StringType, + }, + "id": utils.ResourceIDAttribute(), + }, + } +} + +func (r *integrationAWSLogCollectionResource) ImportState(ctx context.Context, request resource.ImportStateRequest, response *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, frameworkPath.Root("id"), request, response) +} + +func (r *integrationAWSLogCollectionResource) Read(ctx context.Context, request resource.ReadRequest, response *resource.ReadResponse) { + var state integrationAWSLogCollectionModel + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + logCollection, diags := r.getAWSLogCollectionAccount(ctx, &state) + if diags.HasError() { + response.Diagnostics.Append(diags...) + return + } + if logCollection == nil { + response.State.RemoveResource(ctx) + return + } + + r.updateState(ctx, &state, logCollection) + + // Save data into Terraform state + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *integrationAWSLogCollectionResource) Create(ctx context.Context, request resource.CreateRequest, response *resource.CreateResponse) { + var state integrationAWSLogCollectionModel + response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + IntegrationAWSMutex.Lock() + defer IntegrationAWSMutex.Unlock() + + enableLogCollectionServices := r.buildDatadogIntegrationAWSLogCollectionStruct(ctx, &state) + resp, httpresp, err := r.Api.EnableAWSLogServices(r.Auth, *enableLogCollectionServices) + if err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error enabling log collection services for Amazon Web Services integration account")) + return + } + res := resp.(map[string]interface{}) + if status, ok := res["status"]; ok && status == "error" { + response.Diagnostics.AddError("error creating aws log collection", fmt.Sprintf("%s", httpresp.Body)) + return + } + + logCollection, diags := r.getAWSLogCollectionAccount(ctx, &state) + if diags.HasError() { + response.Diagnostics.Append(diags...) + return + } + if logCollection == nil { + response.Diagnostics.AddError("error retrieving log collection", "") + return + } + + r.updateState(ctx, &state, logCollection) + + // Save data into Terraform state + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *integrationAWSLogCollectionResource) Update(ctx context.Context, request resource.UpdateRequest, response *resource.UpdateResponse) { + var state integrationAWSLogCollectionModel + response.Diagnostics.Append(request.Plan.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + IntegrationAWSMutex.Lock() + defer IntegrationAWSMutex.Unlock() + + enableLogCollectionServices := r.buildDatadogIntegrationAWSLogCollectionStruct(ctx, &state) + _, _, err := r.Api.EnableAWSLogServices(r.Auth, *enableLogCollectionServices) + if err != nil { + response.Diagnostics.Append(utils.FrameworkErrorDiag(err, "error updating log collection services for Amazon Web Services integration account")) + return + } + + logCollection, diags := r.getAWSLogCollectionAccount(ctx, &state) + if diags.HasError() { + response.Diagnostics.Append(diags...) + return + } + if logCollection == nil { + response.Diagnostics.AddError("error retrieving log collection", "") + return + } + + r.updateState(ctx, &state, logCollection) + + // Save data into Terraform state + response.Diagnostics.Append(response.State.Set(ctx, &state)...) +} + +func (r *integrationAWSLogCollectionResource) Delete(ctx context.Context, request resource.DeleteRequest, response *resource.DeleteResponse) { + var state integrationAWSLogCollectionModel + response.Diagnostics.Append(request.State.Get(ctx, &state)...) + if response.Diagnostics.HasError() { + return + } + + IntegrationAWSMutex.Lock() + defer IntegrationAWSMutex.Unlock() + + services := []string{} + state.Services.ElementsAs(ctx, &services, false) + + deleteLogCollectionServices := datadogV1.NewAWSLogsServicesRequest(state.AccountID.ValueString(), services) + _, _, err := r.Api.EnableAWSLogServices(r.Auth, *deleteLogCollectionServices) + if err != nil { + response.Diagnostics.AddError("error disabling Amazon Web Services log collection", err.Error()) + } + +} + +func (r *integrationAWSLogCollectionResource) getAWSLogCollectionAccount(ctx context.Context, state *integrationAWSLogCollectionModel) (*datadogV1.AWSLogsListResponse, diag.Diagnostics) { + var diags diag.Diagnostics + + logCollections, _, err := r.Api.ListAWSLogsIntegrations(r.Auth) + if err != nil { + diags.Append(utils.FrameworkErrorDiag(err, "error getting log collection for aws integration.")) + return nil, diags + } + if err := utils.CheckForUnparsed(logCollections); err != nil { + diags.AddError("response contains unparsedObject", err.Error()) + return nil, diags + } + + var logCollection *datadogV1.AWSLogsListResponse + for _, c := range logCollections { + if c.GetAccountId() == state.AccountID.ValueString() { + logCollection = &c + } + } + + return logCollection, diags +} + +func (r *integrationAWSLogCollectionResource) updateState(ctx context.Context, state *integrationAWSLogCollectionModel, collection *datadogV1.AWSLogsListResponse) { + state.ID = types.StringValue(collection.GetAccountId()) + state.AccountID = types.StringValue(collection.GetAccountId()) + state.Services, _ = types.ListValueFrom(ctx, types.StringType, collection.GetServices()) +} + +func (r *integrationAWSLogCollectionResource) buildDatadogIntegrationAWSLogCollectionStruct(ctx context.Context, state *integrationAWSLogCollectionModel) *datadogV1.AWSLogsServicesRequest { + services := []string{} + state.Services.ElementsAs(ctx, &services, false) + + enableLogCollectionServices := datadogV1.NewAWSLogsServicesRequest(state.ID.ValueString(), services) + + return enableLogCollectionServices +} diff --git a/datadog/provider.go b/datadog/provider.go index 32b8746ef..a745620fc 100644 --- a/datadog/provider.go +++ b/datadog/provider.go @@ -162,7 +162,6 @@ func Provider() *schema.Provider { "datadog_downtime": resourceDatadogDowntime(), "datadog_integration_aws_tag_filter": resourceDatadogIntegrationAwsTagFilter(), "datadog_integration_aws_lambda_arn": resourceDatadogIntegrationAwsLambdaArn(), - "datadog_integration_aws_log_collection": resourceDatadogIntegrationAwsLogCollection(), "datadog_integration_azure": resourceDatadogIntegrationAzure(), "datadog_integration_gcp": resourceDatadogIntegrationGcp(), "datadog_integration_opsgenie_service_object": resourceDatadogIntegrationOpsgenieService(), diff --git a/datadog/resource_datadog_integration_aws_log_collection.go b/datadog/resource_datadog_integration_aws_log_collection.go deleted file mode 100644 index 95f1c446e..000000000 --- a/datadog/resource_datadog_integration_aws_log_collection.go +++ /dev/null @@ -1,148 +0,0 @@ -package datadog - -import ( - "context" - "fmt" - - "github.com/terraform-providers/terraform-provider-datadog/datadog/fwprovider" - "github.com/terraform-providers/terraform-provider-datadog/datadog/internal/utils" - - "github.com/DataDog/datadog-api-client-go/v2/api/datadogV1" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -func resourceDatadogIntegrationAwsLogCollection() *schema.Resource { - return &schema.Resource{ - Description: "Provides a Datadog - Amazon Web Services integration log collection resource. This can be used to manage which AWS services logs are collected from for an account.", - CreateContext: resourceDatadogIntegrationAwsLogCollectionCreate, - ReadContext: resourceDatadogIntegrationAwsLogCollectionRead, - UpdateContext: resourceDatadogIntegrationAwsLogCollectionUpdate, - DeleteContext: resourceDatadogIntegrationAwsLogCollectionDelete, - Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, - }, - - SchemaFunc: func() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "account_id": { - Description: "Your AWS Account ID without dashes. If your account is a GovCloud or China account, specify the `access_key_id` here.", - Type: schema.TypeString, - Required: true, - ForceNew: true, - }, - "services": { - Description: "A list of services to collect logs from. See the [api docs](https://docs.datadoghq.com/api/v1/aws-logs-integration/#get-list-of-aws-log-ready-services) for more details on which services are supported.", - Type: schema.TypeList, - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - } - }, - } -} - -func buildDatadogIntegrationAwsLogCollectionStruct(d *schema.ResourceData) *datadogV1.AWSLogsServicesRequest { - accountID := d.Get("account_id").(string) - services := []string{} - if attr, ok := d.GetOk("services"); ok { - for _, s := range attr.([]interface{}) { - services = append(services, s.(string)) - } - } - - enableLogCollectionServices := datadogV1.NewAWSLogsServicesRequest(accountID, services) - - return enableLogCollectionServices -} - -func resourceDatadogIntegrationAwsLogCollectionCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - providerConf := meta.(*ProviderConfiguration) - apiInstances := providerConf.DatadogApiInstances - auth := providerConf.Auth - - // shared with datadog_integration_aws resource - fwprovider.IntegrationAWSMutex.Lock() - defer fwprovider.IntegrationAWSMutex.Unlock() - - accountID := d.Get("account_id").(string) - - enableLogCollectionServices := buildDatadogIntegrationAwsLogCollectionStruct(d) - response, httpresp, err := apiInstances.GetAWSLogsIntegrationApiV1().EnableAWSLogServices(auth, *enableLogCollectionServices) - if err != nil { - return utils.TranslateClientErrorDiag(err, httpresp, "error enabling log collection services for Amazon Web Services integration account") - } - res := response.(map[string]interface{}) - if status, ok := res["status"]; ok && status == "error" { - return diag.FromErr(fmt.Errorf("error creating aws log collection: %s", httpresp.Body)) - } - - d.SetId(accountID) - - return resourceDatadogIntegrationAwsLogCollectionRead(ctx, d, meta) -} - -func resourceDatadogIntegrationAwsLogCollectionUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - providerConf := meta.(*ProviderConfiguration) - apiInstances := providerConf.DatadogApiInstances - auth := providerConf.Auth - - // shared with datadog_integration_aws resource - fwprovider.IntegrationAWSMutex.Lock() - defer fwprovider.IntegrationAWSMutex.Unlock() - - enableLogCollectionServices := buildDatadogIntegrationAwsLogCollectionStruct(d) - _, httpresp, err := apiInstances.GetAWSLogsIntegrationApiV1().EnableAWSLogServices(auth, *enableLogCollectionServices) - if err != nil { - return utils.TranslateClientErrorDiag(err, httpresp, "error updating log collection services for Amazon Web Services integration account") - } - - return resourceDatadogIntegrationAwsLogCollectionRead(ctx, d, meta) -} - -func resourceDatadogIntegrationAwsLogCollectionRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - providerConf := meta.(*ProviderConfiguration) - apiInstances := providerConf.DatadogApiInstances - auth := providerConf.Auth - - accountID := d.Id() - - logCollections, httpresp, err := apiInstances.GetAWSLogsIntegrationApiV1().ListAWSLogsIntegrations(auth) - if err != nil { - return utils.TranslateClientErrorDiag(err, httpresp, "error getting log collection for aws integration.") - } - if err := utils.CheckForUnparsed(logCollections); err != nil { - return diag.FromErr(err) - } - for _, logCollection := range logCollections { - if logCollection.GetAccountId() == accountID { - d.Set("account_id", logCollection.GetAccountId()) - d.Set("services", logCollection.GetServices()) - return nil - } - } - - d.SetId("") - return nil -} - -func resourceDatadogIntegrationAwsLogCollectionDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { - providerConf := meta.(*ProviderConfiguration) - apiInstances := providerConf.DatadogApiInstances - auth := providerConf.Auth - - // shared with datadog_integration_aws resource - fwprovider.IntegrationAWSMutex.Lock() - defer fwprovider.IntegrationAWSMutex.Unlock() - - accountID := d.Id() - services := []string{} - deleteLogCollectionServices := datadogV1.NewAWSLogsServicesRequest(accountID, services) - _, httpresp, err := apiInstances.GetAWSLogsIntegrationApiV1().EnableAWSLogServices(auth, *deleteLogCollectionServices) - - if err != nil { - return utils.TranslateClientErrorDiag(err, httpresp, "error disabling Amazon Web Services log collection") - } - - return nil -}