diff --git a/.changelog/42727.txt b/.changelog/42727.txt new file mode 100644 index 000000000000..630ba2aa8233 --- /dev/null +++ b/.changelog/42727.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +aws_grafana_workspaces +``` diff --git a/internal/service/grafana/service_package_gen.go b/internal/service/grafana/service_package_gen.go index 9e2dcccfa261..ab63e45d3b83 100644 --- a/internal/service/grafana/service_package_gen.go +++ b/internal/service/grafana/service_package_gen.go @@ -41,6 +41,11 @@ func (p *servicePackage) SDKDataSources(ctx context.Context) []*types.ServicePac Name: "Workspace", Tags: &types.ServicePackageResourceTags{}, }, + { + Factory: dataSourceWorkspaces, + TypeName: "aws_grafana_workspaces", + Name: "Workspaces", + }, } } diff --git a/internal/service/grafana/workspaces_data_source.go b/internal/service/grafana/workspaces_data_source.go new file mode 100644 index 000000000000..7c120bc76b87 --- /dev/null +++ b/internal/service/grafana/workspaces_data_source.go @@ -0,0 +1,90 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package grafana + +import ( + "context" + + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/grafana" + "github.com/aws/aws-sdk-go-v2/service/grafana/types" + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-aws/internal/conns" + "github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag" +) + +// @SDKDataSource("aws_grafana_workspaces", name="Workspaces") +func dataSourceWorkspaces() *schema.Resource { // nosemgrep:ci.caps0-in-func-name + return &schema.Resource{ + ReadWithoutTimeout: dataSourceWorkspacesRead, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + }, + "names": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "workspace_ids": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func dataSourceWorkspacesRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { // nosemgrep:ci.caps0-in-func-name + var diags diag.Diagnostics + conn := meta.(*conns.AWSClient).GrafanaClient(ctx) + + name := d.Get("name").(string) + workspaces, err := findWorkspaces(ctx, conn, name) + + if err != nil { + return sdkdiag.AppendErrorf(diags, "reading Prometheus Workspaces: %s", err) + } + + var names, workspaceIDs []string + for _, w := range workspaces { + names = append(names, aws.ToString(w.Name)) + workspaceIDs = append(workspaceIDs, aws.ToString(w.Id)) + } + + d.SetId(meta.(*conns.AWSClient).Region(ctx)) + d.Set("names", names) + d.Set("workspace_ids", workspaceIDs) + + return diags +} + +func findWorkspaces(ctx context.Context, conn *grafana.Client, name string) ([]types.WorkspaceSummary, error) { // nosemgrep:ci.caps0-in-func-name + input := &grafana.ListWorkspacesInput{} + + var output []types.WorkspaceSummary + + pages := grafana.NewListWorkspacesPaginator(conn, input) + for pages.HasMorePages() { + page, err := pages.NextPage(ctx) + + if err != nil { + return nil, err + } + if name == "" { + output = append(output, page.Workspaces...) + } else { + for _, workspace := range page.Workspaces { + if *workspace.Name == name { + output = append(output, workspace) + } + } + } + } + + return output, nil +} diff --git a/internal/service/grafana/workspaces_data_source_test.go b/internal/service/grafana/workspaces_data_source_test.go new file mode 100644 index 000000000000..892c5812b1b5 --- /dev/null +++ b/internal/service/grafana/workspaces_data_source_test.go @@ -0,0 +1,111 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package grafana_test + +import ( + "fmt" + "testing" + + 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 TestAccGrafanaWorkspacesDataSource_basic(t *testing.T) { // nosemgrep:ci.caps0-in-func-name + ctx := acctest.Context(t) + rCount := sdkacctest.RandIntRange(1, 4) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_grafana_workspaces.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.GrafanaEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GrafanaServiceID), + PreventPostDestroyRefresh: true, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccWorkspacesDataSourceConfig_base(rName, rCount), + }, + { + Config: testAccWorkspacesDataSourceConfig_basic(rName, rCount), + Check: resource.ComposeTestCheckFunc( + acctest.CheckResourceAttrGreaterThanOrEqualValue(dataSourceName, "names.#", rCount), + acctest.CheckResourceAttrGreaterThanOrEqualValue(dataSourceName, "workspace_ids.#", rCount), + ), + }, + }, + }) +} + +func TestAccGrafanaWorkspacesDataSource_name(t *testing.T) { // nosemgrep:ci.caps0-in-func-name + ctx := acctest.Context(t) + rCount := sdkacctest.RandIntRange(1, 4) + rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix) + dataSourceName := "data.aws_grafana_workspaces.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + acctest.PreCheck(ctx, t) + acctest.PreCheckPartitionHasService(t, names.GrafanaEndpointID) + }, + ErrorCheck: acctest.ErrorCheck(t, names.GrafanaServiceID), + PreventPostDestroyRefresh: true, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories, + Steps: []resource.TestStep{ + { + Config: testAccWorkspacesDataSourceConfig_name(rName, rCount), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(dataSourceName, "names.#", "1"), + resource.TestCheckResourceAttr(dataSourceName, "workspace_ids.#", "1"), + ), + }, + }, + }) +} + +func testAccWorkspacesDataSourceConfig_base(rName string, rCount int) string { // nosemgrep:ci.caps0-in-func-name + return fmt.Sprintf(` +resource "aws_iam_role" "assume" { + name = %[1]q + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Principal = { + Service = "grafana.amazonaws.com" + } + }, + ] + }) +} +resource "aws_grafana_workspace" "test" { + count = %[2]d + account_access_type = "CURRENT_ACCOUNT" + authentication_providers = ["SAML"] + permission_type = "SERVICE_MANAGED" + role_arn = aws_iam_role.assume.arn + name = "%[1]s-${count.index}" +} +`, rName, rCount) +} + +func testAccWorkspacesDataSourceConfig_basic(rName string, rCount int) string { // nosemgrep:ci.caps0-in-func-name + return acctest.ConfigCompose(testAccWorkspacesDataSourceConfig_base(rName, rCount), ` +data "aws_grafana_workspaces" "test" {} +`) +} + +func testAccWorkspacesDataSourceConfig_name(rName string, rCount int) string { // nosemgrep:ci.caps0-in-func-name + return acctest.ConfigCompose(testAccWorkspacesDataSourceConfig_base(rName, rCount), ` +data "aws_grafana_workspaces" "test" { + name = aws_grafana_workspace.test[0].name +} +`) +} diff --git a/website/docs/d/grafana_workspaces.html.markdown b/website/docs/d/grafana_workspaces.html.markdown new file mode 100644 index 000000000000..a98820cd1382 --- /dev/null +++ b/website/docs/d/grafana_workspaces.html.markdown @@ -0,0 +1,41 @@ +--- +subcategory: "Managed Grafana" +layout: "aws" +page_title: "AWS: aws_grafana_workspaces" +description: |- + Gets the names and workspace IDs of Amazon Managed Grafana workspaces. +--- + +# Data Source: aws_grafana_workspaces + +Provides the names and workspace IDs of Amazon Managed Grafana workspaces. + +## Example Usage + +The following example returns all of the workspaces in a region: + +```terraform +data "aws_grafana_workspaces" "example" {} +``` + +The following example filters the workspaces by name. Only the workspaces with +a name that matches the provided value of `name` will be returned: + +```terraform +data "aws_grafana_workspaces" "example" { + name = "example" +} +``` + +## Argument Reference + +This data source supports the following arguments: + +* `name` - (Optional) Limits results to workspaces with a name that matches with this value. + +## Attribute Reference + +This data source exports the following attributes in addition to the arguments above: + +* `names` - List of aliases of the matched Grafana workspaces. +* `workspace_ids` - List of workspace IDs of the matched Grafana workspaces.