Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data source aws_secretsmanager_secret_versions #35411

Merged
merged 20 commits into from
Aug 8, 2024
Merged
3 changes: 3 additions & 0 deletions .changelog/35411.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_secretsmanager_secret_versions
```
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,12 @@ func TestAccSecretsManagerSecretVersionDataSource_versionStage(t *testing.T) {

func testAccSecretVersionCheckDataSource(datasourceName, resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
resource, ok := s.RootModule().Resources[datasourceName]
dataSource, ok := s.RootModule().Resources[datasourceName]
if !ok {
return fmt.Errorf("root module has no resource called %s", datasourceName)
return fmt.Errorf("root module has no data source called %s", datasourceName)
}

dataSource, ok := s.RootModule().Resources[resourceName]
resource, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("root module has no resource called %s", resourceName)
}
Expand Down
123 changes: 123 additions & 0 deletions internal/service/secretsmanager/secret_versions_data_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package secretsmanager

import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/secretsmanager"
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"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"
"github.com/hashicorp/terraform-provider-aws/names"
)

// @FrameworkDataSource("aws_secretsmanager_secret_versions, name="Secret Versions")
func newDataSourceSecretVersions(context.Context) (datasource.DataSourceWithConfigure, error) {
return &dataSourceSecretVersions{}, nil
}

const (
DSNameSecretVersions = "Secret Versions Data Source"
)

type dataSourceSecretVersions struct {
framework.DataSourceWithConfigure
}

func (d *dataSourceSecretVersions) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { // nosemgrep:ci.meta-in-func-name
resp.TypeName = "aws_secretsmanager_secret_versions"
}

func (d *dataSourceSecretVersions) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
Attributes: map[string]schema.Attribute{
names.AttrARN: schema.StringAttribute{
Computed: true,
Validators: []validator.String{
stringvalidator.LengthBetween(20, 2048),
},
},
names.AttrName: schema.StringAttribute{
Computed: true,
},
"include_deprecated": schema.BoolAttribute{
Optional: true,
},
"secret_id": schema.StringAttribute{
Required: true,
},
"versions": schema.ListAttribute{
Computed: true,
CustomType: fwtypes.NewListNestedObjectTypeOf[dsVersionsData](ctx),
},
},
}
}

func (d *dataSourceSecretVersions) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
conn := d.Meta().SecretsManagerClient(ctx)

var data dsSecretVersionsData
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

paginator := secretsmanager.NewListSecretVersionIdsPaginator(conn, &secretsmanager.ListSecretVersionIdsInput{
SecretId: aws.String(data.SecretID.ValueString()),
})

var out secretsmanager.ListSecretVersionIdsOutput
commonFieldsSet := false
for paginator.HasMorePages() {
page, err := paginator.NextPage(ctx)
if err != nil {
resp.Diagnostics.AddError(
create.ProblemStandardMessage(names.SecretsManager, create.ErrActionReading, DSNameSecretVersions, data.Arn.String(), err),
err.Error(),
)
return
}

if page != nil && len(page.Versions) > 0 {
if !commonFieldsSet {
out.ARN = page.ARN
out.Name = page.Name
commonFieldsSet = true
}
out.Versions = append(out.Versions, page.Versions...)
}
}

resp.Diagnostics.Append(flex.Flatten(ctx, out, &data)...)
if resp.Diagnostics.HasError() {
return
}

resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}

type dsSecretVersionsData struct {
Arn types.String `tfsdk:"arn"`
Name types.String `tfsdk:"name"`
IncludeDeprecated types.Bool `tfsdk:"include_deprecated"`
SecretID types.String `tfsdk:"secret_id"`
Versions fwtypes.ListNestedObjectValueOf[dsVersionsData] `tfsdk:"versions"`
}

type dsVersionsData struct {
CreatedDate timetypes.RFC3339 `tfsdk:"created_time"`
LastAccessedDate types.String `tfsdk:"last_accessed_date"`
VersionID types.String `tfsdk:"version_id"`
VersionStages fwtypes.ListValueOf[types.String] `tfsdk:"version_stages"`
}
100 changes: 100 additions & 0 deletions internal/service/secretsmanager/secret_versions_data_source_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package secretsmanager_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 TestAccSecretsManagerSecretVersionsDataSource_basic(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resource1Name := "aws_secretsmanager_secret_version.test"
dataSourceName := "data.aws_secretsmanager_secret_versions.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSecretVersionsDataSourceConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "secret_id", resource1Name, "secret_id"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.#"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.0.%"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.0.created_time"),
resource.TestCheckResourceAttrSet(dataSourceName, "versions.0.version_id"),
),
},
},
})
}

func TestAccSecretsManagerSecretVersionsDataSource_emptyVer(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceName := "data.aws_secretsmanager_secret_versions.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
acctest.PreCheck(ctx, t)
testAccPreCheck(ctx, t)
},
ErrorCheck: acctest.ErrorCheck(t, names.SecretsManagerServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSecretVersionsDataSourceConfig_emptyVersion(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "versions.#", acctest.Ct0),
),
},
},
})
}

func testAccSecretVersionsDataSourceConfig_basic(rName string) string {
return fmt.Sprintf(`
resource "aws_secretsmanager_secret" "test" {
name = %[1]q
}

resource "aws_secretsmanager_secret_version" "test" {
secret_id = aws_secretsmanager_secret.test.id
secret_string = "test-string"
}

resource "aws_secretsmanager_secret_version" "test2" {
depends_on = [aws_secretsmanager_secret_version.test]
secret_id = aws_secretsmanager_secret.test.id
secret_string = "test-string2"
}

data "aws_secretsmanager_secret_versions" "test" {
depends_on = [aws_secretsmanager_secret_version.test]
secret_id = aws_secretsmanager_secret.test.id
}
`, rName)
}

func testAccSecretVersionsDataSourceConfig_emptyVersion(rName string) string {
return fmt.Sprintf(`
resource "aws_secretsmanager_secret" "test" {
name = "%[1]s"
}
data "aws_secretsmanager_secret_versions" "test" {
secret_id = aws_secretsmanager_secret.test.id
}
`, rName)
}
7 changes: 6 additions & 1 deletion internal/service/secretsmanager/service_package_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

63 changes: 63 additions & 0 deletions website/docs/d/secretsmanager_secret_versions.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
subcategory: "Secrets Manager"
layout: "aws"
page_title: "AWS: aws_secretsmanager_secret_versions"
description: |-
Retrieve the versions of a Secrets Manager secret
---

# Data Source: aws_secretsmanager_secret_versions

Retrieve the versions of a Secrets Manager secret. To retrieve secret metadata, see the data sources [`aws_secretsmanager_secret`](/docs/providers/aws/d/secretsmanager_secret.html) and [`aws_secretsmanager_secret_version`](/docs/providers/aws/d/secretsmanager_secret_version.html).

## Example Usage

### Retrieve All Versions of a Secret

By default, this data sources retrieves all versions of a secret.

```terraform
data "aws_secretsmanager_secret_versions" "secret-versions" {
secret_id = data.aws_secretsmanager_secret.example.id
}
```

### Retrieve Specific Secret Version

```terraform
data "aws_secretsmanager_secret_version" "by-version-stage" {
secret_id = data.aws_secretsmanager_secret.example.id
version_stage = "example"
}
```

### Handling Key-Value Secret Strings in JSON

Reading key-value pairs from JSON back into a native Terraform map can be accomplished in Terraform 0.12 and later with the [`jsondecode()` function](https://www.terraform.io/docs/configuration/functions/jsondecode.html):

```terraform
output "example" {
value = jsondecode(data.aws_secretsmanager_secret_version.example.secret_string)["key1"]
}
```

## Argument Reference

* `secret_id` - (Required) Specifies the secret containing the version that you want to retrieve. You can specify either the ARN or the friendly name of the secret.
* `include_deprecated` - (Optional) If true, all deprecated secret versions are included in the response.
If false, no deprecated secret versions are included in the response. If no value is specified, the default value is `false`.

## Attribute Reference

This data source exports the following attributes in addition to the arguments above:

* `arn` - ARN of the secret.
* `id` - Secret id.
* `versions` - List of the versions of the secret. Attributes are specified below.

### versions

* `created_date` - Date and time this version of the secret was created.
* `last_accessed_date` - Date that this version of the secret was last accessed.
* `version_id` - Unique version identifier of this version of the secret.
* `version_stage` - Staging label attached to the version.
Loading