diff --git a/.changelog/34672.txt b/.changelog/34672.txt new file mode 100644 index 000000000000..c7bfb292326a --- /dev/null +++ b/.changelog/34672.txt @@ -0,0 +1,7 @@ +```release-note:new-resource +aws_codeguruprofiler_profiling_group +``` + +```release-note:new-data-source +aws_codeguruprofiler_profiling_group +``` \ No newline at end of file diff --git a/internal/service/codeguruprofiler/exports_test.go b/internal/service/codeguruprofiler/exports_test.go new file mode 100644 index 000000000000..2155411f5a03 --- /dev/null +++ b/internal/service/codeguruprofiler/exports_test.go @@ -0,0 +1,11 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package codeguruprofiler + +// Exports for use in tests only. +var ( + ResourceProfilingGroup = newResourceProfilingGroup + + FindProfilingGroupByName = findProfilingGroupByName +) diff --git a/internal/service/codeguruprofiler/profiling_group.go b/internal/service/codeguruprofiler/profiling_group.go new file mode 100644 index 000000000000..130998fa1b29 --- /dev/null +++ b/internal/service/codeguruprofiler/profiling_group.go @@ -0,0 +1,288 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package codeguruprofiler + +import ( + "context" + "errors" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler" + awstypes "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler/types" + "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" + "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/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/id" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/errs" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkResource(name="Profiling Group") +// @Tags(identifierAttribute="arn") +func newResourceProfilingGroup(_ context.Context) (resource.ResourceWithConfigure, error) { + r := &resourceProfilingGroup{} + + return r, nil +} + +const ( + ResNameProfilingGroup = "Profiling Group" +) + +type resourceProfilingGroup struct { + framework.ResourceWithConfigure +} + +func (r *resourceProfilingGroup) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = "aws_codeguruprofiler_profiling_group" +} + +func (r *resourceProfilingGroup) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + computePlatform := fwtypes.StringEnumType[awstypes.ComputePlatform]() + + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "arn": framework.ARNAttributeComputedOnly(), + "compute_platform": schema.StringAttribute{ + CustomType: computePlatform, + Optional: true, + Computed: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + stringplanmodifier.UseStateForUnknown(), + }, + }, + "id": framework.IDAttribute(), + "name": schema.StringAttribute{ + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + names.AttrTags: tftags.TagsAttribute(), + names.AttrTagsAll: tftags.TagsAttributeComputedOnly(), + }, + Blocks: map[string]schema.Block{ + "agent_orchestration_config": schema.ListNestedBlock{ + CustomType: fwtypes.NewListNestedObjectTypeOf[agentOrchestrationConfig](ctx), + Validators: []validator.List{ + listvalidator.SizeAtMost(1), + listvalidator.IsRequired(), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "profiling_enabled": schema.BoolAttribute{ + Required: true, + }, + }, + }, + }, + }, + } +} + +func (r *resourceProfilingGroup) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + conn := r.Meta().CodeGuruProfilerClient(ctx) + + var plan resourceProfilingGroupData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + in := &codeguruprofiler.CreateProfilingGroupInput{} + resp.Diagnostics.Append(flex.Expand(ctx, plan, in)...) + + if resp.Diagnostics.HasError() { + return + } + + in.ProfilingGroupName = flex.StringFromFramework(ctx, plan.Name) + in.ClientToken = aws.String(id.UniqueId()) + in.Tags = getTagsIn(ctx) + + out, err := conn.CreateProfilingGroup(ctx, in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.CodeGuruProfiler, create.ErrActionCreating, ResNameProfilingGroup, plan.Name.ValueString(), err), + err.Error(), + ) + return + } + if out == nil || out.ProfilingGroup == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.CodeGuruProfiler, create.ErrActionCreating, ResNameProfilingGroup, plan.Name.ValueString(), nil), + errors.New("empty output").Error(), + ) + return + } + + state := plan + + resp.Diagnostics.Append(flex.Flatten(ctx, out.ProfilingGroup, &state)...) + + state.ID = flex.StringToFramework(ctx, out.ProfilingGroup.Name) + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceProfilingGroup) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + conn := r.Meta().CodeGuruProfilerClient(ctx) + + var state resourceProfilingGroupData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + out, err := findProfilingGroupByName(ctx, conn, state.ID.ValueString()) + if tfresource.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.CodeGuruProfiler, create.ErrActionSetting, ResNameProfilingGroup, state.ID.ValueString(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + setTagsOut(ctx, out.Tags) + + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) +} + +func (r *resourceProfilingGroup) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + conn := r.Meta().CodeGuruProfilerClient(ctx) + + var plan, state resourceProfilingGroupData + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + + if resp.Diagnostics.HasError() { + return + } + + if !plan.AgentOrchestrationConfig.Equal(state.AgentOrchestrationConfig) { + in := &codeguruprofiler.UpdateProfilingGroupInput{} + resp.Diagnostics.Append(flex.Expand(ctx, plan, in)...) + + if resp.Diagnostics.HasError() { + return + } + + in.ProfilingGroupName = flex.StringFromFramework(ctx, state.ID) + out, err := conn.UpdateProfilingGroup(ctx, in) + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.CodeGuruProfiler, create.ErrActionUpdating, ResNameProfilingGroup, plan.ID.String(), err), + err.Error(), + ) + return + } + + if out == nil || out.ProfilingGroup == nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.CodeGuruProfiler, create.ErrActionUpdating, ResNameProfilingGroup, plan.ID.String(), nil), + errors.New("empty output").Error(), + ) + return + } + } + + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *resourceProfilingGroup) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + conn := r.Meta().CodeGuruProfilerClient(ctx) + + var state resourceProfilingGroupData + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + in := &codeguruprofiler.DeleteProfilingGroupInput{ + ProfilingGroupName: aws.String(state.ID.ValueString()), + } + + _, err := conn.DeleteProfilingGroup(ctx, in) + + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return + } + + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.CodeGuruProfiler, create.ErrActionDeleting, ResNameProfilingGroup, state.ID.String(), err), + err.Error(), + ) + return + } +} + +func (r *resourceProfilingGroup) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} + +func (r *resourceProfilingGroup) ModifyPlan(ctx context.Context, request resource.ModifyPlanRequest, response *resource.ModifyPlanResponse) { + r.SetTagsAll(ctx, request, response) +} + +func findProfilingGroupByName(ctx context.Context, conn *codeguruprofiler.Client, name string) (*awstypes.ProfilingGroupDescription, error) { + in := &codeguruprofiler.DescribeProfilingGroupInput{ + ProfilingGroupName: aws.String(name), + } + + out, err := conn.DescribeProfilingGroup(ctx, in) + if errs.IsA[*awstypes.ResourceNotFoundException](err) { + return nil, &retry.NotFoundError{ + LastError: err, + LastRequest: in, + } + } + + if err != nil { + return nil, err + } + + if out == nil || out.ProfilingGroup == nil { + return nil, tfresource.NewEmptyResultError(in) + } + + return out.ProfilingGroup, nil +} + +type resourceProfilingGroupData struct { + ARN types.String `tfsdk:"arn"` + AgentOrchestrationConfig fwtypes.ListNestedObjectValueOf[agentOrchestrationConfig] `tfsdk:"agent_orchestration_config"` + ComputePlatform fwtypes.StringEnum[awstypes.ComputePlatform] `tfsdk:"compute_platform"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Tags types.Map `tfsdk:"tags"` + TagsAll types.Map `tfsdk:"tags_all"` +} + +type agentOrchestrationConfig struct { + ProfilingEnabled types.Bool `tfsdk:"profiling_enabled"` +} diff --git a/internal/service/codeguruprofiler/profiling_group_data_source.go b/internal/service/codeguruprofiler/profiling_group_data_source.go new file mode 100644 index 000000000000..fa0693499e21 --- /dev/null +++ b/internal/service/codeguruprofiler/profiling_group_data_source.go @@ -0,0 +1,135 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package codeguruprofiler + +import ( + "context" + "time" + + awstypes "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler/types" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-provider-aws/internal/create" + "github.com/hashicorp/terraform-provider-aws/internal/framework" + "github.com/hashicorp/terraform-provider-aws/internal/framework/flex" + fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types" + tftags "github.com/hashicorp/terraform-provider-aws/internal/tags" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +// @FrameworkDataSource(name="Profiling Group") +func newDataSourceProfilingGroup(context.Context) (datasource.DataSourceWithConfigure, error) { + return &dataSourceProfilingGroup{}, nil +} + +const ( + DSNameProfilingGroup = "Profiling Group Data Source" +) + +type dataSourceProfilingGroup struct { + framework.DataSourceWithConfigure +} + +func (d *dataSourceProfilingGroup) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name + resp.TypeName = "aws_codeguruprofiler_profiling_group" +} + +func (d *dataSourceProfilingGroup) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) { + computePlatform := fwtypes.StringEnumType[awstypes.ComputePlatform]() + + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "agent_orchestration_config": schema.ListAttribute{ + CustomType: fwtypes.NewListNestedObjectTypeOf[dsAgentOrchestrationConfig](ctx), + Computed: true, + ElementType: fwtypes.NewObjectTypeOf[dsAgentOrchestrationConfig](ctx), + }, + "arn": framework.ARNAttributeComputedOnly(), + "compute_platform": schema.StringAttribute{ + CustomType: computePlatform, + Computed: true, + }, + "created_at": schema.StringAttribute{ + Computed: true, + }, + "id": framework.IDAttribute(), + "name": schema.StringAttribute{ + Required: true, + }, + "profiling_status": schema.ListAttribute{ + CustomType: fwtypes.NewListNestedObjectTypeOf[dsProfilingStatus](ctx), + Computed: true, + ElementType: fwtypes.NewObjectTypeOf[dsProfilingStatus](ctx), + }, + names.AttrTags: tftags.TagsAttributeComputedOnly(), + "updated_at": schema.StringAttribute{ + Computed: true, + }, + }, + } +} +func (d *dataSourceProfilingGroup) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + conn := d.Meta().CodeGuruProfilerClient(ctx) + + var data dataSourceProfilingGroupData + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + out, err := findProfilingGroupByName(ctx, conn, data.Name.ValueString()) + if tfresource.NotFound(err) { + resp.State.RemoveResource(ctx) + return + } + if err != nil { + resp.Diagnostics.AddError( + create.ProblemStandardMessage(names.CodeGuruProfiler, create.ErrActionSetting, DSNameProfilingGroup, data.Name.ValueString(), err), + err.Error(), + ) + return + } + + resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + data.CreatedAt = flex.StringValueToFramework(ctx, out.CreatedAt.Format(time.RFC3339)) + data.UpdatedAt = flex.StringValueToFramework(ctx, out.UpdatedAt.Format(time.RFC3339)) + data.ID = flex.StringToFramework(ctx, out.Name) + data.Tags = flex.FlattenFrameworkStringValueMap(ctx, out.Tags) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +type dataSourceProfilingGroupData struct { + ARN types.String `tfsdk:"arn"` + AgentOrchestrationConfig fwtypes.ListNestedObjectValueOf[dsAgentOrchestrationConfig] `tfsdk:"agent_orchestration_config"` + ComputePlatform fwtypes.StringEnum[awstypes.ComputePlatform] `tfsdk:"compute_platform"` + CreatedAt types.String `tfsdk:"created_at"` + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + ProfilingStatus fwtypes.ListNestedObjectValueOf[dsProfilingStatus] `tfsdk:"profiling_status"` + Tags types.Map `tfsdk:"tags"` + UpdatedAt types.String `tfsdk:"updated_at"` +} + +type dsAgentOrchestrationConfig struct { + ProfilingEnabled types.Bool `tfsdk:"profiling_enabled"` +} + +type dsProfilingStatus struct { + LatestAgentOrchestratedAt types.String `tfsdk:"latest_agent_orchestrated_at"` + LatestAgentProfileReportedAt types.String `tfsdk:"latest_agent_profile_reported_at"` + LatestAggregatedProfile fwtypes.ListNestedObjectValueOf[dsAggregatedProfileTime] `tfsdk:"latest_aggregated_profile"` +} + +type dsAggregatedProfileTime struct { + Period types.String `tfsdk:"period"` + Start types.String `tfsdk:"start"` +} diff --git a/internal/service/codeguruprofiler/profiling_group_data_source_test.go b/internal/service/codeguruprofiler/profiling_group_data_source_test.go new file mode 100644 index 000000000000..c726630c5e41 --- /dev/null +++ b/internal/service/codeguruprofiler/profiling_group_data_source_test.go @@ -0,0 +1,66 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package codeguruprofiler_test + +import ( + "fmt" + "testing" + + awstypes "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccCodeGuruProfilerProfilingGroupDataSource_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var profilinggroup awstypes.ProfilingGroupDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_codeguruprofiler_profiling_group.test" + resourceName := "aws_codeguruprofiler_profiling_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.CodeGuruProfilerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckProfilingGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccProfilingGroupDataSourceConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, dataSourceName, &profilinggroup), + resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"), + resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"), + resource.TestCheckResourceAttrPair(dataSourceName, "compute_platform", resourceName, "compute_platform"), + resource.TestCheckResourceAttrPair(dataSourceName, "agent_orchestration_config.0.profiling_enabled", resourceName, "agent_orchestration_config.0.profiling_enabled"), + ), + }, + }, + }) +} + +func testAccProfilingGroupDataSourceConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_codeguruprofiler_profiling_group" "test" { + name = %[1]q + compute_platform = "Default" + + agent_orchestration_config { + profiling_enabled = true + } +} + +data "aws_codeguruprofiler_profiling_group" "test" { + name = aws_codeguruprofiler_profiling_group.test.name +} +`, rName) +} diff --git a/internal/service/codeguruprofiler/profiling_group_test.go b/internal/service/codeguruprofiler/profiling_group_test.go new file mode 100644 index 000000000000..3b34c5623965 --- /dev/null +++ b/internal/service/codeguruprofiler/profiling_group_test.go @@ -0,0 +1,307 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package codeguruprofiler_test + +import ( + "context" + "errors" + "fmt" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler" + awstypes "github.com/aws/aws-sdk-go-v2/service/codeguruprofiler/types" + sdkacctest "github.com/hashicorp/terraform-plugin-testing/helper/acctest" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-aws/internal/acctest" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/create" + tfcodeguruprofiler "github.com/hashicorp/terraform-provider-aws/internal/service/codeguruprofiler" + "github.com/hashicorp/terraform-provider-aws/internal/tfresource" + "github.com/hashicorp/terraform-provider-aws/names" +) + +func TestAccCodeGuruProfilerProfilingGroup_basic(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var profilinggroup awstypes.ProfilingGroupDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_codeguruprofiler_profiling_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.CodeGuruProfilerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckProfilingGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccProfilingGroupConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, resourceName, &profilinggroup), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "compute_platform", "Default"), + resource.TestCheckResourceAttr(resourceName, "agent_orchestration_config.0.profiling_enabled", "true"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccCodeGuruProfilerProfilingGroup_disappears(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var profilinggroup awstypes.ProfilingGroupDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_codeguruprofiler_profiling_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.CodeGuruProfilerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckProfilingGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccProfilingGroupConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, resourceName, &profilinggroup), + acctest.CheckFrameworkResourceDisappears(ctx, acctest.Provider, tfcodeguruprofiler.ResourceProfilingGroup, resourceName), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func TestAccCodeGuruProfilerProfilingGroup_update(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var profilinggroup awstypes.ProfilingGroupDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_codeguruprofiler_profiling_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.CodeGuruProfilerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckProfilingGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccProfilingGroupConfig_basic(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, resourceName, &profilinggroup), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "compute_platform", "Default"), + resource.TestCheckResourceAttr(resourceName, "agent_orchestration_config.0.profiling_enabled", "true"), + ), + }, + { + Config: testAccProfilingGroupConfig_update(rName, false), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, resourceName, &profilinggroup), + resource.TestCheckResourceAttr(resourceName, "name", rName), + resource.TestCheckResourceAttrSet(resourceName, "arn"), + resource.TestCheckResourceAttr(resourceName, "compute_platform", "Default"), + resource.TestCheckResourceAttr(resourceName, "agent_orchestration_config.0.profiling_enabled", "false"), + ), + }, + }, + }) +} + +func TestAccCodeGuruProfilerProfilingGroup_tags(t *testing.T) { + ctx := acctest.Context(t) + if testing.Short() { + t.Skip("skipping long-running test in short mode") + } + + var profilinggroup awstypes.ProfilingGroupDescription + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + resourceName := "aws_codeguruprofiler_profiling_group.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + testAccPreCheck(ctx, t) + }, + ErrorCheck: acctest.ErrorCheck(t, names.CodeGuruProfilerEndpointID), + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + CheckDestroy: testAccCheckProfilingGroupDestroy(ctx), + Steps: []resource.TestStep{ + { + Config: testAccProfilingGroupConfig_tags1(rName, "key1", "value1"), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, resourceName, &profilinggroup), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + ), + }, + { + Config: testAccProfilingGroupConfig_tags2(rName, "key1", "value1", "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, resourceName, &profilinggroup), + resource.TestCheckResourceAttr(resourceName, "tags.%", "2"), + resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + { + Config: testAccProfilingGroupConfig_tags1(rName, "key2", "value2"), + Check: resource.ComposeTestCheckFunc( + testAccCheckProfilingGroupExists(ctx, resourceName, &profilinggroup), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"), + ), + }, + }, + }) +} + +func testAccCheckProfilingGroupDestroy(ctx context.Context) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := acctest.Provider.Meta().(*conns.AWSClient).CodeGuruProfilerClient(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "aws_codeguruprofiler_profiling_group" { + continue + } + + _, err := tfcodeguruprofiler.FindProfilingGroupByName(ctx, conn, rs.Primary.ID) + + if tfresource.NotFound(err) { + return nil + } + + if err != nil { + return create.Error(names.CodeGuruProfiler, create.ErrActionCheckingDestroyed, tfcodeguruprofiler.ResNameProfilingGroup, rs.Primary.ID, err) + } + + return create.Error(names.CodeGuruProfiler, create.ErrActionCheckingDestroyed, tfcodeguruprofiler.ResNameProfilingGroup, rs.Primary.ID, errors.New("not destroyed")) + } + + return nil + } +} + +func testAccCheckProfilingGroupExists(ctx context.Context, name string, profilinggroup *awstypes.ProfilingGroupDescription) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[name] + if !ok { + return create.Error(names.CodeGuruProfiler, create.ErrActionCheckingExistence, tfcodeguruprofiler.ResNameProfilingGroup, name, errors.New("not found")) + } + + if rs.Primary.ID == "" { + return create.Error(names.CodeGuruProfiler, create.ErrActionCheckingExistence, tfcodeguruprofiler.ResNameProfilingGroup, name, errors.New("not set")) + } + + conn := acctest.Provider.Meta().(*conns.AWSClient).CodeGuruProfilerClient(ctx) + resp, err := tfcodeguruprofiler.FindProfilingGroupByName(ctx, conn, rs.Primary.ID) + + if err != nil { + return create.Error(names.CodeGuruProfiler, create.ErrActionCheckingExistence, tfcodeguruprofiler.ResNameProfilingGroup, rs.Primary.ID, err) + } + + *profilinggroup = *resp + + return nil + } +} + +func testAccPreCheck(ctx context.Context, t *testing.T) { + conn := acctest.Provider.Meta().(*conns.AWSClient).CodeGuruProfilerClient(ctx) + + input := &codeguruprofiler.ListProfilingGroupsInput{} + _, err := conn.ListProfilingGroups(ctx, input) + + if acctest.PreCheckSkipError(err) { + t.Skipf("skipping acceptance testing: %s", err) + } + if err != nil { + t.Fatalf("unexpected PreCheck error: %s", err) + } +} + +func testAccProfilingGroupConfig_basic(rName string) string { + return fmt.Sprintf(` +resource "aws_codeguruprofiler_profiling_group" "test" { + name = %[1]q + compute_platform = "Default" + + agent_orchestration_config { + profiling_enabled = true + } +} +`, rName) +} + +func testAccProfilingGroupConfig_update(rName string, profilingEnabled bool) string { + return fmt.Sprintf(` +resource "aws_codeguruprofiler_profiling_group" "test" { + name = %[1]q + compute_platform = "Default" + + agent_orchestration_config { + profiling_enabled = %[2]t + } +} +`, rName, profilingEnabled) +} + +func testAccProfilingGroupConfig_tags1(rName, key1, value1 string) string { + return fmt.Sprintf(` +resource "aws_codeguruprofiler_profiling_group" "test" { + name = %[1]q + compute_platform = "Default" + + agent_orchestration_config { + profiling_enabled = true + } + + tags = { + %[2]q = %[3]q + } +} +`, rName, key1, value1) +} +func testAccProfilingGroupConfig_tags2(rName, key1, value1, key2, value2 string) string { + return fmt.Sprintf(` +resource "aws_codeguruprofiler_profiling_group" "test" { + name = %[1]q + compute_platform = "Default" + + agent_orchestration_config { + profiling_enabled = true + } + + tags = { + %[2]q = %[3]q + %[4]q = %[5]q + } +} +`, rName, key1, value1, key2, value2) +} diff --git a/internal/service/codeguruprofiler/service_package_gen.go b/internal/service/codeguruprofiler/service_package_gen.go index 36a71bbefe64..7fbe3497966e 100644 --- a/internal/service/codeguruprofiler/service_package_gen.go +++ b/internal/service/codeguruprofiler/service_package_gen.go @@ -15,11 +15,24 @@ import ( type servicePackage struct{} func (p *servicePackage) FrameworkDataSources(ctx context.Context) []*types.ServicePackageFrameworkDataSource { - return []*types.ServicePackageFrameworkDataSource{} + return []*types.ServicePackageFrameworkDataSource{ + { + Factory: newDataSourceProfilingGroup, + Name: "Profiling Group", + }, + } } func (p *servicePackage) FrameworkResources(ctx context.Context) []*types.ServicePackageFrameworkResource { - return []*types.ServicePackageFrameworkResource{} + return []*types.ServicePackageFrameworkResource{ + { + Factory: newResourceProfilingGroup, + Name: "Profiling Group", + Tags: &types.ServicePackageResourceTags{ + IdentifierAttribute: "arn", + }, + }, + } } func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePackageSDKDataSource { diff --git a/names/names.go b/names/names.go index 8b73a9860687..fdfbbb9e8df9 100644 --- a/names/names.go +++ b/names/names.go @@ -40,6 +40,7 @@ const ( CleanRoomsEndpointID = "cleanrooms" CloudWatchLogsEndpointID = "logs" CodeDeployEndpointID = "codedeploy" + CodeGuruProfilerEndpointID = "codeguru-profiler" CodeStarConnectionsEndpointID = "codestar-connections" CodeStarNotificationsEndpointID = "codestar-notifications" ComprehendEndpointID = "comprehend" diff --git a/website/docs/d/codeguruprofiler_profiling_group.html.markdown b/website/docs/d/codeguruprofiler_profiling_group.html.markdown new file mode 100644 index 000000000000..1cb2e2325a54 --- /dev/null +++ b/website/docs/d/codeguruprofiler_profiling_group.html.markdown @@ -0,0 +1,36 @@ +--- +subcategory: "CodeGuru Profiler" +layout: "aws" +page_title: "AWS: aws_codeguruprofiler_profiling_group" +description: |- + Terraform data source for managing an AWS CodeGuru Profiler Profiling Group. +--- + +# Data Source: aws_codeguruprofiler_profiling_group + +Terraform data source for managing an AWS CodeGuru Profiler Profiling Group. + +## Example Usage + +### Basic Usage + +```terraform +data "aws_codeguruprofiler_profiling_group" "example" { + name = "example" +} +``` + +## Argument Reference + +The following arguments are required: + +* `name` - (Required) The name of the profiling group. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `agent_orchestration_config` - Profiling Group agent orchestration config +* `arn` - ARN of the Profiling Group. +* `compute_platform` - The compute platform of the profiling group. +* `tags` - Mapping of Key-Value tags for the resource. diff --git a/website/docs/r/codeguruprofiler_profiling_group.html.markdown b/website/docs/r/codeguruprofiler_profiling_group.html.markdown new file mode 100644 index 000000000000..2939574095a1 --- /dev/null +++ b/website/docs/r/codeguruprofiler_profiling_group.html.markdown @@ -0,0 +1,65 @@ +--- +subcategory: "CodeGuru Profiler" +layout: "aws" +page_title: "AWS: aws_codeguruprofiler_profiling_group" +description: |- + Terraform resource for managing an AWS CodeGuru Profiler Profiling Group. +--- +# Resource: aws_codeguruprofiler_profiling_group + +Terraform resource for managing an AWS CodeGuru Profiler Profiling Group. + +## Example Usage + +### Basic Usage + +```terraform +resource "aws_codeguruprofiler_profiling_group" "example" { + name = "example" + compute_platform = "Default" + + agent_orchestration_config { + profiling_enabled = true + } +} +``` + +## Argument Reference + +The following arguments are required: + +* `agent_orchestration_config` - (Required) Specifies whether profiling is enabled or disabled for the created profiling. See [Agent Orchestration Config](#agent-orchestration-config) for more details. +* `name` - (Required) The name of the profiling group. + +The following arguments are optional: + +* `compute_platform` - (Optional) The compute platform of the profiling group. +* `tags` - (Optional) A map of tags assigned to the WorkSpaces Connection Alias. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level. + +## Attribute Reference + +This resource exports the following attributes in addition to the arguments above: + +* `arn` - ARN of the Profiling Group. +* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block). + +### Agent Orchestration Config + +* `profiling_enabled` - (Required) Boolean that specifies whether the profiling agent collects profiling data or + +## Import + +In Terraform v1.5.0 and later, use an [`import` block](https://developer.hashicorp.com/terraform/language/import) to import CodeGuru Profiler Profiling Group using the `example_id_arg`. For example: + +```terraform +import { + to = aws_codeguruprofiler_profiling_group.example + id = "profiling_group-name-12345678" +} +``` + +Using `terraform import`, import CodeGuru Profiler Profiling Group using the `name`. For example: + +```console +% terraform import aws_codeguruprofiler_profiling_group.example profiling_group-name-12345678 +```