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

New Resources and Data Sources: aws_secretsmanager_secret* #4272

Merged
merged 3 commits into from
Apr 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions aws/data_source_aws_secretsmanager_secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package aws

import (
"errors"
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsSecretsManagerSecret() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsSecretsManagerSecretRead,

Schema: map[string]*schema.Schema{
"arn": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validateArn,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"kms_key_id": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"rotation_enabled": {
Type: schema.TypeBool,
Computed: true,
},
"rotation_lambda_arn": {
Type: schema.TypeString,
Computed: true,
},
"rotation_rules": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"automatically_after_days": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"tags": {
Type: schema.TypeMap,
Computed: true,
},
},
}
}

func dataSourceAwsSecretsManagerSecretRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).secretsmanagerconn
var secretID string
if v, ok := d.GetOk("arn"); ok {
secretID = v.(string)
}
if v, ok := d.GetOk("name"); ok {
if secretID != "" {
return errors.New("specify only arn or name")
}
secretID = v.(string)
}

if secretID == "" {
return errors.New("must specify either arn or name")
}

input := &secretsmanager.DescribeSecretInput{
SecretId: aws.String(secretID),
}

log.Printf("[DEBUG] Reading Secrets Manager Secret: %s", input)
output, err := conn.DescribeSecret(input)
if err != nil {
if isAWSErr(err, secretsmanager.ErrCodeResourceNotFoundException, "") {
return fmt.Errorf("Secrets Manager Secret %q not found", secretID)
}
return fmt.Errorf("error reading Secrets Manager Secret: %s", err)
}

if output.ARN == nil {
return fmt.Errorf("Secrets Manager Secret %q not found", secretID)
}

d.SetId(aws.StringValue(output.ARN))
d.Set("arn", output.ARN)
d.Set("description", output.Description)
d.Set("kms_key_id", output.KmsKeyId)
d.Set("name", output.Name)
d.Set("rotation_enabled", output.RotationEnabled)
d.Set("rotation_lambda_arn", output.RotationLambdaARN)

if err := d.Set("rotation_rules", flattenSecretsManagerRotationRules(output.RotationRules)); err != nil {
return fmt.Errorf("error setting rotation_rules: %s", err)
}

if err := d.Set("tags", tagsToMapSecretsManager(output.Tags)); err != nil {
return fmt.Errorf("error setting tags: %s", err)
}

return nil
}
155 changes: 155 additions & 0 deletions aws/data_source_aws_secretsmanager_secret_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
package aws

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccDataSourceAwsSecretsManagerSecret_Basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsSecretsManagerSecretConfig_MissingRequired,
ExpectError: regexp.MustCompile(`must specify either arn or name`),
},
{
Config: testAccDataSourceAwsSecretsManagerSecretConfig_MultipleSpecified,
ExpectError: regexp.MustCompile(`specify only arn or name`),
},
{
Config: testAccDataSourceAwsSecretsManagerSecretConfig_NonExistent,
ExpectError: regexp.MustCompile(`not found`),
},
},
})
}

func TestAccDataSourceAwsSecretsManagerSecret_ARN(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_secretsmanager_secret.test"
datasourceName := "data.aws_secretsmanager_secret.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsSecretsManagerSecretConfig_ARN(rName),
Check: resource.ComposeTestCheckFunc(
testAccDataSourceAwsSecretsManagerSecretCheck(datasourceName, resourceName),
),
},
},
})
}

func TestAccDataSourceAwsSecretsManagerSecret_Name(t *testing.T) {
rName := acctest.RandomWithPrefix("tf-acc-test")
resourceName := "aws_secretsmanager_secret.test"
datasourceName := "data.aws_secretsmanager_secret.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceAwsSecretsManagerSecretConfig_Name(rName),
Check: resource.ComposeTestCheckFunc(
testAccDataSourceAwsSecretsManagerSecretCheck(datasourceName, resourceName),
),
},
},
})
}

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

dataSource, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("root module has no resource called %s", resourceName)
}

attrNames := []string{
"arn",
"description",
"kms_key_id",
"name",
"rotation_enabled",
"rotation_lambda_arn",
"rotation_rules.#",
"tags.#",
}

for _, attrName := range attrNames {
if resource.Primary.Attributes[attrName] != dataSource.Primary.Attributes[attrName] {
return fmt.Errorf(
"%s is %s; want %s",
attrName,
resource.Primary.Attributes[attrName],
dataSource.Primary.Attributes[attrName],
)
}
}

return nil
}
}

func testAccDataSourceAwsSecretsManagerSecretConfig_ARN(rName string) string {
return fmt.Sprintf(`
resource "aws_secretsmanager_secret" "wrong" {
name = "%[1]s-wrong"
}
resource "aws_secretsmanager_secret" "test" {
name = "%[1]s"
}

data "aws_secretsmanager_secret" "test" {
arn = "${aws_secretsmanager_secret.test.arn}"
}
`, rName)
}

const testAccDataSourceAwsSecretsManagerSecretConfig_MissingRequired = `
data "aws_secretsmanager_secret" "test" {}
`

const testAccDataSourceAwsSecretsManagerSecretConfig_MultipleSpecified = `
data "aws_secretsmanager_secret" "test" {
arn = "arn:aws:secretsmanager:us-east-1:123456789012:secret:tf-acc-test-does-not-exist"
name = "tf-acc-test-does-not-exist"
}
`

func testAccDataSourceAwsSecretsManagerSecretConfig_Name(rName string) string {
return fmt.Sprintf(`
resource "aws_secretsmanager_secret" "wrong" {
name = "%[1]s-wrong"
}
resource "aws_secretsmanager_secret" "test" {
name = "%[1]s"
}

data "aws_secretsmanager_secret" "test" {
name = "${aws_secretsmanager_secret.test.name}"
}
`, rName)
}

const testAccDataSourceAwsSecretsManagerSecretConfig_NonExistent = `
data "aws_secretsmanager_secret" "test" {
name = "tf-acc-test-does-not-exist"
}
`
87 changes: 87 additions & 0 deletions aws/data_source_aws_secretsmanager_secret_version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package aws

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"github.com/hashicorp/terraform/helper/schema"
)

func dataSourceAwsSecretsManagerSecretVersion() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsSecretsManagerSecretVersionRead,

Schema: map[string]*schema.Schema{
"secret_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"secret_string": {
Type: schema.TypeString,
Computed: true,
Sensitive: true,
},
"version_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"version_stage": {
Type: schema.TypeString,
Optional: true,
Default: "AWSCURRENT",
},
"version_stages": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}

func dataSourceAwsSecretsManagerSecretVersionRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).secretsmanagerconn
secretID := d.Get("secret_id").(string)
var version string

input := &secretsmanager.GetSecretValueInput{
SecretId: aws.String(secretID),
}

if v, ok := d.GetOk("version_id"); ok {
versionID := v.(string)
input.VersionId = aws.String(versionID)
version = versionID
} else {
versionStage := d.Get("version_stage").(string)
input.VersionStage = aws.String(versionStage)
version = versionStage
}

log.Printf("[DEBUG] Reading Secrets Manager Secret Version: %s", input)
output, err := conn.GetSecretValue(input)
if err != nil {
if isAWSErr(err, secretsmanager.ErrCodeResourceNotFoundException, "") {
return fmt.Errorf("Secrets Manager Secret %q Version %q not found", secretID, version)
}
if isAWSErr(err, secretsmanager.ErrCodeInvalidRequestException, "You can’t perform this operation on the secret because it was deleted") {
return fmt.Errorf("Secrets Manager Secret %q Version %q not found", secretID, version)
}
return fmt.Errorf("error reading Secrets Manager Secret Version: %s", err)
}

d.SetId(fmt.Sprintf("%s|%s", secretID, version))
d.Set("secret_id", secretID)
d.Set("secret_string", output.SecretString)
d.Set("version_id", output.VersionId)

if err := d.Set("version_stages", flattenStringList(output.VersionStages)); err != nil {
return fmt.Errorf("error setting version_stages: %s", err)
}

return nil
}
Loading