provider/aws: Enforced kms_key_* attributes to be ARNs (#10356)

* Added kms_key_* validation to force ARNs

* Added Redshift Cluster KMS key test

* Added cloudtrail kms key test

* Added EBS volume kms key

* Added Elastic Transcoder Pipeline kms key arn test
This commit is contained in:
Ninir 2016-11-30 12:50:26 +01:00 committed by Paul Stack
parent b15b8bd99a
commit 5481e9ecb3
21 changed files with 579 additions and 286 deletions

View File

@ -107,7 +107,7 @@ func TestAccDataSourceAWSS3BucketObject_kmsEncrypted(t *testing.T) {
resource.TestMatchResourceAttr("data.aws_s3_bucket_object.obj", "etag", regexp.MustCompile("^[a-f0-9]{32}$")),
resource.TestCheckResourceAttr("data.aws_s3_bucket_object.obj", "server_side_encryption", "aws:kms"),
resource.TestMatchResourceAttr("data.aws_s3_bucket_object.obj", "sse_kms_key_id",
regexp.MustCompile("^arn:aws:kms:us-west-2:[0-9]{12}:key/[a-z0-9-]{36}$")),
regexp.MustCompile("^arn:aws:kms:[a-z]{2}-[a-z]+-\\d{1}:[0-9]{12}:key/[a-z0-9-]{36}$")),
resource.TestMatchResourceAttr("data.aws_s3_bucket_object.obj", "last_modified",
regexp.MustCompile("^[a-zA-Z]{3}, [0-9]+ [a-zA-Z]+ [0-9]{4} [0-9:]+ [A-Z]+$")),
resource.TestCheckResourceAttr("data.aws_s3_bucket_object.obj", "body", "Keep Calm and Carry On"),

View File

@ -20,60 +20,61 @@ func resourceAwsCloudTrail() *schema.Resource {
},
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"enable_logging": &schema.Schema{
"enable_logging": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"s3_bucket_name": &schema.Schema{
"s3_bucket_name": {
Type: schema.TypeString,
Required: true,
},
"s3_key_prefix": &schema.Schema{
"s3_key_prefix": {
Type: schema.TypeString,
Optional: true,
},
"cloud_watch_logs_role_arn": &schema.Schema{
"cloud_watch_logs_role_arn": {
Type: schema.TypeString,
Optional: true,
},
"cloud_watch_logs_group_arn": &schema.Schema{
"cloud_watch_logs_group_arn": {
Type: schema.TypeString,
Optional: true,
},
"include_global_service_events": &schema.Schema{
"include_global_service_events": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"is_multi_region_trail": &schema.Schema{
"is_multi_region_trail": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"sns_topic_name": &schema.Schema{
"sns_topic_name": {
Type: schema.TypeString,
Optional: true,
},
"enable_log_file_validation": &schema.Schema{
"enable_log_file_validation": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"kms_key_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},
"home_region": &schema.Schema{
"home_region": {
Type: schema.TypeString,
Computed: true,
},
"arn": &schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},

View File

@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"regexp"
)
func TestAccAWSCloudTrail_basic(t *testing.T) {
@ -21,7 +22,7 @@ func TestAccAWSCloudTrail_basic(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudTrailDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -30,7 +31,7 @@ func TestAccAWSCloudTrail_basic(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfigModified(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -53,7 +54,7 @@ func TestAccAWSCloudTrail_enable_logging(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudTrailDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -64,7 +65,7 @@ func TestAccAWSCloudTrail_enable_logging(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfigModified(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -73,7 +74,7 @@ func TestAccAWSCloudTrail_enable_logging(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -95,7 +96,7 @@ func TestAccAWSCloudTrail_is_multi_region(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudTrailDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -104,7 +105,7 @@ func TestAccAWSCloudTrail_is_multi_region(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfigMultiRegion(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -113,7 +114,7 @@ func TestAccAWSCloudTrail_is_multi_region(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -130,14 +131,12 @@ func TestAccAWSCloudTrail_logValidation(t *testing.T) {
var trail cloudtrail.Trail
cloudTrailRandInt := acctest.RandInt()
// TODO: Add test for KMS Key ID
// once https://github.com/hashicorp/terraform/pull/3928 is merged
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudTrailDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig_logValidation(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -147,7 +146,7 @@ func TestAccAWSCloudTrail_logValidation(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig_logValidationModified(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -161,6 +160,30 @@ func TestAccAWSCloudTrail_logValidation(t *testing.T) {
})
}
func TestAccAWSCloudTrail_kmsKey(t *testing.T) {
var trail cloudtrail.Trail
cloudTrailRandInt := acctest.RandInt()
keyRegex := regexp.MustCompile("^arn:aws:([a-zA-Z0-9\\-])+:([a-z]{2}-[a-z]+-\\d{1})?:(\\d{12})?:(.*)$")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudTrailDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudTrailConfig_kmsKey(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "s3_key_prefix", ""),
resource.TestCheckResourceAttr("aws_cloudtrail.foobar", "include_global_service_events", "true"),
testAccCheckCloudTrailLogValidationEnabled("aws_cloudtrail.foobar", false, &trail),
resource.TestMatchResourceAttr("aws_cloudtrail.foobar", "kms_key_id", keyRegex),
),
},
},
})
}
func TestAccAWSCloudTrail_tags(t *testing.T) {
var trail cloudtrail.Trail
var trailTags []*cloudtrail.Tag
@ -172,7 +195,7 @@ func TestAccAWSCloudTrail_tags(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSCloudTrailDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig_tags(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -183,7 +206,7 @@ func TestAccAWSCloudTrail_tags(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig_tagsModified(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -194,7 +217,7 @@ func TestAccAWSCloudTrail_tags(t *testing.T) {
testAccCheckCloudTrailKmsKeyIdEquals("aws_cloudtrail.foobar", "", &trail),
),
},
resource.TestStep{
{
Config: testAccAWSCloudTrailConfig_tagsModifiedAgain(cloudTrailRandInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudTrailExists("aws_cloudtrail.foobar", &trail),
@ -577,6 +600,69 @@ POLICY
`, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
}
func testAccAWSCloudTrailConfig_kmsKey(cloudTrailRandInt int) string {
return fmt.Sprintf(`
resource "aws_kms_key" "foo" {
description = "Terraform acc test %d"
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "kms-tf-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
POLICY
}
resource "aws_cloudtrail" "foobar" {
name = "tf-acc-trail-log-validation-test-%d"
s3_bucket_name = "${aws_s3_bucket.foo.id}"
include_global_service_events = true
kms_key_id = "${aws_kms_key.foo.arn}"
}
resource "aws_s3_bucket" "foo" {
bucket = "tf-test-trail-%d"
force_destroy = true
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AWSCloudTrailAclCheck",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetBucketAcl",
"Resource": "arn:aws:s3:::tf-test-trail-%d"
},
{
"Sid": "AWSCloudTrailWrite",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::tf-test-trail-%d/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}
POLICY
}
`, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt, cloudTrailRandInt)
}
var testAccAWSCloudTrailConfig_tags_tpl = `
resource "aws_cloudtrail" "foobar" {
name = "tf-acc-trail-log-validation-test-%d"

View File

@ -26,32 +26,32 @@ func resourceAwsDbInstance() *schema.Resource {
},
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"arn": &schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"username": &schema.Schema{
"username": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"password": &schema.Schema{
"password": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
},
"engine": &schema.Schema{
"engine": {
Type: schema.TypeString,
Optional: true,
Computed: true,
@ -62,38 +62,38 @@ func resourceAwsDbInstance() *schema.Resource {
},
},
"engine_version": &schema.Schema{
"engine_version": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"character_set_name": &schema.Schema{
"character_set_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"storage_encrypted": &schema.Schema{
"storage_encrypted": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
},
"allocated_storage": &schema.Schema{
"allocated_storage": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"storage_type": &schema.Schema{
"storage_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"identifier": &schema.Schema{
"identifier": {
Type: schema.TypeString,
Optional: true,
Computed: true,
@ -101,42 +101,42 @@ func resourceAwsDbInstance() *schema.Resource {
ValidateFunc: validateRdsId,
},
"instance_class": &schema.Schema{
"instance_class": {
Type: schema.TypeString,
Required: true,
},
"availability_zone": &schema.Schema{
"availability_zone": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"backup_retention_period": &schema.Schema{
"backup_retention_period": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"backup_window": &schema.Schema{
"backup_window": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"iops": &schema.Schema{
"iops": {
Type: schema.TypeInt,
Optional: true,
},
"license_model": &schema.Schema{
"license_model": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"maintenance_window": &schema.Schema{
"maintenance_window": {
Type: schema.TypeString,
Optional: true,
Computed: true,
@ -149,25 +149,25 @@ func resourceAwsDbInstance() *schema.Resource {
},
},
"multi_az": &schema.Schema{
"multi_az": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"port": &schema.Schema{
"port": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"publicly_accessible": &schema.Schema{
"publicly_accessible": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"vpc_security_group_ids": &schema.Schema{
"vpc_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
@ -175,14 +175,14 @@ func resourceAwsDbInstance() *schema.Resource {
Set: schema.HashString,
},
"security_group_names": &schema.Schema{
"security_group_names": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"final_snapshot_identifier": &schema.Schema{
"final_snapshot_identifier": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
@ -201,47 +201,47 @@ func resourceAwsDbInstance() *schema.Resource {
},
},
"skip_final_snapshot": &schema.Schema{
"skip_final_snapshot": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"copy_tags_to_snapshot": &schema.Schema{
"copy_tags_to_snapshot": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"db_subnet_group_name": &schema.Schema{
"db_subnet_group_name": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"parameter_group_name": &schema.Schema{
"parameter_group_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"address": &schema.Schema{
"address": {
Type: schema.TypeString,
Computed: true,
},
"endpoint": &schema.Schema{
"endpoint": {
Type: schema.TypeString,
Computed: true,
},
"hosted_zone_id": &schema.Schema{
"hosted_zone_id": {
Type: schema.TypeString,
Computed: true,
},
"status": &schema.Schema{
"status": {
Type: schema.TypeString,
Computed: true,
},
@ -249,24 +249,24 @@ func resourceAwsDbInstance() *schema.Resource {
// apply_immediately is used to determine when the update modifications
// take place.
// See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html
"apply_immediately": &schema.Schema{
"apply_immediately": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"replicate_source_db": &schema.Schema{
"replicate_source_db": {
Type: schema.TypeString,
Optional: true,
},
"replicas": &schema.Schema{
"replicas": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"snapshot_identifier": &schema.Schema{
"snapshot_identifier": {
Type: schema.TypeString,
Computed: false,
Optional: true,
@ -274,41 +274,42 @@ func resourceAwsDbInstance() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
},
"auto_minor_version_upgrade": &schema.Schema{
"auto_minor_version_upgrade": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"allow_major_version_upgrade": &schema.Schema{
"allow_major_version_upgrade": {
Type: schema.TypeBool,
Computed: false,
Optional: true,
},
"monitoring_role_arn": &schema.Schema{
"monitoring_role_arn": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"monitoring_interval": &schema.Schema{
"monitoring_interval": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
},
"option_group_name": &schema.Schema{
"option_group_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"kms_key_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validateArn,
},
"tags": tagsSchema(),

View File

@ -25,42 +25,43 @@ func resourceAwsEbsVolume() *schema.Resource {
},
Schema: map[string]*schema.Schema{
"availability_zone": &schema.Schema{
"availability_zone": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"encrypted": &schema.Schema{
"encrypted": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
ForceNew: true,
},
"iops": &schema.Schema{
"iops": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: true,
},
"kms_key_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validateArn,
},
"size": &schema.Schema{
"size": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ForceNew: true,
},
"snapshot_id": &schema.Schema{
"snapshot_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"type": &schema.Schema{
"type": {
Type: schema.TypeString,
Optional: true,
Computed: true,

View File

@ -6,8 +6,10 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"regexp"
)
func TestAccAWSEBSVolume_basic(t *testing.T) {
@ -17,7 +19,7 @@ func TestAccAWSEBSVolume_basic(t *testing.T) {
IDRefreshName: "aws_ebs_volume.test",
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAwsEbsVolumeConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckVolumeExists("aws_ebs_volume.test", &v),
@ -27,13 +29,36 @@ func TestAccAWSEBSVolume_basic(t *testing.T) {
})
}
func TestAccAWSEBSVolume_kmsKey(t *testing.T) {
var v ec2.Volume
ri := acctest.RandInt()
config := fmt.Sprintf(testAccAwsEbsVolumeConfigWithKmsKey, ri)
keyRegex := regexp.MustCompile("^arn:aws:([a-zA-Z0-9\\-])+:([a-z]{2}-[a-z]+-\\d{1})?:(\\d{12})?:(.*)$")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: "aws_ebs_volume.test",
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckVolumeExists("aws_ebs_volume.test", &v),
resource.TestCheckResourceAttr("aws_ebs_volume.test", "encrypted", "true"),
resource.TestMatchResourceAttr("aws_ebs_volume.test", "kms_key_id", keyRegex),
),
},
},
})
}
func TestAccAWSEBSVolume_NoIops(t *testing.T) {
var v ec2.Volume
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAwsEbsVolumeConfigWithNoIops,
Check: resource.ComposeTestCheckFunc(
testAccCheckVolumeExists("aws_ebs_volume.iops_test", &v),
@ -50,7 +75,7 @@ func TestAccAWSEBSVolume_withTags(t *testing.T) {
IDRefreshName: "aws_ebs_volume.tags_test",
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAwsEbsVolumeConfigWithTags,
Check: resource.ComposeTestCheckFunc(
testAccCheckVolumeExists("aws_ebs_volume.tags_test", &v),
@ -90,29 +115,59 @@ func testAccCheckVolumeExists(n string, v *ec2.Volume) resource.TestCheckFunc {
const testAccAwsEbsVolumeConfig = `
resource "aws_ebs_volume" "test" {
availability_zone = "us-west-2a"
size = 1
availability_zone = "us-west-2a"
size = 1
}
`
const testAccAwsEbsVolumeConfigWithKmsKey = `
resource "aws_kms_key" "foo" {
description = "Terraform acc test %d"
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "kms-tf-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
POLICY
}
resource "aws_ebs_volume" "test" {
availability_zone = "us-west-2a"
size = 1
encrypted = true
kms_key_id = "${aws_kms_key.foo.arn}"
}
`
const testAccAwsEbsVolumeConfigWithTags = `
resource "aws_ebs_volume" "tags_test" {
availability_zone = "us-west-2a"
size = 1
tags {
Name = "TerraformTest"
}
availability_zone = "us-west-2a"
size = 1
tags {
Name = "TerraformTest"
}
}
`
const testAccAwsEbsVolumeConfigWithNoIops = `
resource "aws_ebs_volume" "iops_test" {
availability_zone = "us-west-2a"
size = 10
availability_zone = "us-west-2a"
size = 10
type = "gp2"
iops = 0
tags {
Name = "TerraformTest"
}
iops = 0
tags {
Name = "TerraformTest"
}
}
`

View File

@ -20,18 +20,19 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
Delete: resourceAwsElasticTranscoderPipelineDelete,
Schema: map[string]*schema.Schema{
"arn": &schema.Schema{
"arn": {
Type: schema.TypeString,
Computed: true,
},
"aws_kms_key_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
"aws_kms_key_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},
// ContentConfig also requires ThumbnailConfig
"content_config": &schema.Schema{
"content_config": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
@ -39,13 +40,13 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
Elem: &schema.Resource{
// elastictranscoder.PipelineOutputConfig
Schema: map[string]*schema.Schema{
"bucket": &schema.Schema{
"bucket": {
Type: schema.TypeString,
Optional: true,
// AWS may insert the bucket name here taken from output_bucket
Computed: true,
},
"storage_class": &schema.Schema{
"storage_class": {
Type: schema.TypeString,
Optional: true,
},
@ -53,21 +54,21 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
},
},
"content_config_permissions": &schema.Schema{
"content_config_permissions": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"access": &schema.Schema{
"access": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"grantee": &schema.Schema{
"grantee": {
Type: schema.TypeString,
Optional: true,
},
"grantee_type": &schema.Schema{
"grantee_type": {
Type: schema.TypeString,
Optional: true,
},
@ -75,12 +76,12 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
},
},
"input_bucket": &schema.Schema{
"input_bucket": {
Type: schema.TypeString,
Required: true,
},
"name": &schema.Schema{
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
@ -98,25 +99,25 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
},
},
"notifications": &schema.Schema{
"notifications": {
Type: schema.TypeSet,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"completed": &schema.Schema{
"completed": {
Type: schema.TypeString,
Optional: true,
},
"error": &schema.Schema{
"error": {
Type: schema.TypeString,
Optional: true,
},
"progressing": &schema.Schema{
"progressing": {
Type: schema.TypeString,
Optional: true,
},
"warning": &schema.Schema{
"warning": {
Type: schema.TypeString,
Optional: true,
},
@ -128,18 +129,18 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
// and thumbnail_config.bucket.
// This is set as Computed, because the API may or may not return
// this as set based on the other 2 configurations.
"output_bucket": &schema.Schema{
"output_bucket": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"role": &schema.Schema{
"role": {
Type: schema.TypeString,
Required: true,
},
"thumbnail_config": &schema.Schema{
"thumbnail_config": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
@ -147,13 +148,13 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
Elem: &schema.Resource{
// elastictranscoder.PipelineOutputConfig
Schema: map[string]*schema.Schema{
"bucket": &schema.Schema{
"bucket": {
Type: schema.TypeString,
Optional: true,
// AWS may insert the bucket name here taken from output_bucket
Computed: true,
},
"storage_class": &schema.Schema{
"storage_class": {
Type: schema.TypeString,
Optional: true,
},
@ -161,21 +162,21 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource {
},
},
"thumbnail_config_permissions": &schema.Schema{
"thumbnail_config_permissions": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"access": &schema.Schema{
"access": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"grantee": &schema.Schema{
"grantee": {
Type: schema.TypeString,
Optional: true,
},
"grantee_type": &schema.Schema{
"grantee_type": {
Type: schema.TypeString,
Optional: true,
},

View File

@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"regexp"
)
func TestAccAWSElasticTranscoderPipeline_basic(t *testing.T) {
@ -23,7 +24,7 @@ func TestAccAWSElasticTranscoderPipeline_basic(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckElasticTranscoderPipelineDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: awsElasticTranscoderPipelineConfigBasic,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticTranscoderPipelineExists("aws_elastictranscoder_pipeline.bar", pipeline),
@ -33,6 +34,29 @@ func TestAccAWSElasticTranscoderPipeline_basic(t *testing.T) {
})
}
func TestAccAWSElasticTranscoderPipeline_kmsKey(t *testing.T) {
pipeline := &elastictranscoder.Pipeline{}
ri := acctest.RandInt()
config := fmt.Sprintf(awsElasticTranscoderPipelineConfigKmsKey, ri)
keyRegex := regexp.MustCompile("^arn:aws:([a-zA-Z0-9\\-])+:([a-z]{2}-[a-z]+-\\d{1})?:(\\d{12})?:(.*)$")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
IDRefreshName: "aws_elastictranscoder_pipeline.bar",
Providers: testAccProviders,
CheckDestroy: testAccCheckElasticTranscoderPipelineDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticTranscoderPipelineExists("aws_elastictranscoder_pipeline.bar", pipeline),
resource.TestMatchResourceAttr("aws_elastictranscoder_pipeline.bar", "aws_kms_key_arn", keyRegex),
),
},
},
})
}
func TestAccAWSElasticTranscoderPipeline_notifications(t *testing.T) {
pipeline := elastictranscoder.Pipeline{}
@ -44,7 +68,7 @@ func TestAccAWSElasticTranscoderPipeline_notifications(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckElasticTranscoderPipelineDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: awsElasticTranscoderNotifications(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticTranscoderPipelineExists("aws_elastictranscoder_pipeline.bar", &pipeline),
@ -107,13 +131,13 @@ func TestAccAWSElasticTranscoderPipeline_withContentConfig(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckElasticTranscoderPipelineDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: awsElasticTranscoderPipelineWithContentConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticTranscoderPipelineExists("aws_elastictranscoder_pipeline.bar", pipeline),
),
},
resource.TestStep{
{
Config: awsElasticTranscoderPipelineWithContentConfigUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticTranscoderPipelineExists("aws_elastictranscoder_pipeline.bar", pipeline),
@ -132,7 +156,7 @@ func TestAccAWSElasticTranscoderPipeline_withPermissions(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckElasticTranscoderPipelineDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: awsElasticTranscoderPipelineWithPerms,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticTranscoderPipelineExists("aws_elastictranscoder_pipeline.baz", pipeline),
@ -234,6 +258,62 @@ resource "aws_s3_bucket" "test_bucket" {
}
`
const awsElasticTranscoderPipelineConfigKmsKey = `
resource "aws_kms_key" "foo" {
description = "Terraform acc test %d"
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "kms-tf-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
POLICY
}
resource "aws_elastictranscoder_pipeline" "bar" {
input_bucket = "${aws_s3_bucket.test_bucket.bucket}"
output_bucket = "${aws_s3_bucket.test_bucket.bucket}"
name = "aws_elastictranscoder_pipeline_tf_test_"
role = "${aws_iam_role.test_role.arn}"
aws_kms_key_arn = "${aws_kms_key.foo.arn}"
}
resource "aws_iam_role" "test_role" {
name = "aws_elastictranscoder_pipeline_tf_test_role_"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_s3_bucket" "test_bucket" {
bucket = "aws-elasticencoder-pipeline-tf-test-bucket"
acl = "private"
}
`
const awsElasticTranscoderPipelineWithContentConfig = `
resource "aws_elastictranscoder_pipeline" "bar" {
input_bucket = "${aws_s3_bucket.content_bucket.bucket}"

View File

@ -150,8 +150,9 @@ func resourceAwsKinesisFirehoseDeliveryStream() *schema.Resource {
},
"kms_key_arn": {
Type: schema.TypeString,
Optional: true,
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},
"role_arn": {

View File

@ -26,7 +26,7 @@ func resourceAwsRDSCluster() *schema.Resource {
Schema: map[string]*schema.Schema{
"availability_zones": &schema.Schema{
"availability_zones": {
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
@ -35,14 +35,14 @@ func resourceAwsRDSCluster() *schema.Resource {
Set: schema.HashString,
},
"cluster_identifier": &schema.Schema{
"cluster_identifier": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateRdsId,
},
"cluster_members": &schema.Schema{
"cluster_members": {
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
@ -50,14 +50,14 @@ func resourceAwsRDSCluster() *schema.Resource {
Set: schema.HashString,
},
"database_name": &schema.Schema{
"database_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"db_subnet_group_name": &schema.Schema{
"db_subnet_group_name": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
@ -67,42 +67,42 @@ func resourceAwsRDSCluster() *schema.Resource {
// TODO: remove parameter_group_name
// See https://github.com/hashicorp/terraform/issues/7046
// Likely need migration to remove from state
"parameter_group_name": &schema.Schema{
"parameter_group_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Deprecated: "Use db_cluster_parameter_group_name instead. This attribute will be removed in a future version",
},
"db_cluster_parameter_group_name": &schema.Schema{
"db_cluster_parameter_group_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"endpoint": &schema.Schema{
"endpoint": {
Type: schema.TypeString,
Computed: true,
},
"reader_endpoint": &schema.Schema{
"reader_endpoint": {
Type: schema.TypeString,
Computed: true,
},
"engine": &schema.Schema{
"engine": {
Type: schema.TypeString,
Computed: true,
},
"storage_encrypted": &schema.Schema{
"storage_encrypted": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: true,
},
"final_snapshot_identifier": &schema.Schema{
"final_snapshot_identifier": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: func(v interface{}, k string) (ws []string, es []error) {
@ -121,32 +121,32 @@ func resourceAwsRDSCluster() *schema.Resource {
},
},
"skip_final_snapshot": &schema.Schema{
"skip_final_snapshot": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"master_username": &schema.Schema{
"master_username": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ForceNew: true,
},
"master_password": &schema.Schema{
"master_password": {
Type: schema.TypeString,
Optional: true,
},
"snapshot_identifier": &schema.Schema{
"snapshot_identifier": {
Type: schema.TypeString,
Computed: false,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"port": &schema.Schema{
"port": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
@ -155,13 +155,13 @@ func resourceAwsRDSCluster() *schema.Resource {
// apply_immediately is used to determine when the update modifications
// take place.
// See http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html
"apply_immediately": &schema.Schema{
"apply_immediately": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"vpc_security_group_ids": &schema.Schema{
"vpc_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
@ -169,13 +169,13 @@ func resourceAwsRDSCluster() *schema.Resource {
Set: schema.HashString,
},
"preferred_backup_window": &schema.Schema{
"preferred_backup_window": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"preferred_maintenance_window": &schema.Schema{
"preferred_maintenance_window": {
Type: schema.TypeString,
Optional: true,
Computed: true,
@ -187,7 +187,7 @@ func resourceAwsRDSCluster() *schema.Resource {
},
},
"backup_retention_period": &schema.Schema{
"backup_retention_period": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
@ -201,11 +201,12 @@ func resourceAwsRDSCluster() *schema.Resource {
},
},
"kms_key_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validateArn,
},
"tags": tagsSchema(),

View File

@ -22,7 +22,7 @@ func TestAccAWSRDSCluster_basic(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSClusterConfig(acctest.RandInt()),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
@ -47,7 +47,7 @@ func TestAccAWSRDSCluster_updateTags(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSClusterConfig(ri),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
@ -55,7 +55,7 @@ func TestAccAWSRDSCluster_updateTags(t *testing.T) {
"aws_rds_cluster.default", "tags.%", "1"),
),
},
resource.TestStep{
{
Config: testAccAWSClusterConfigUpdatedTags(ri),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
@ -76,7 +76,7 @@ func TestAccAWSRDSCluster_kmsKey(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSClusterConfig_kmsKey(acctest.RandInt()),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
@ -96,7 +96,7 @@ func TestAccAWSRDSCluster_encrypted(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSClusterConfig_encrypted(acctest.RandInt()),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),
@ -119,7 +119,7 @@ func TestAccAWSRDSCluster_backupsUpdate(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: testAccAWSClusterConfig_backups(ri),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSClusterExists("aws_rds_cluster.default", &v),

View File

@ -25,44 +25,44 @@ func resourceAwsRedshiftCluster() *schema.Resource {
},
Schema: map[string]*schema.Schema{
"database_name": &schema.Schema{
"database_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validateRedshiftClusterDbName,
},
"cluster_identifier": &schema.Schema{
"cluster_identifier": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateRedshiftClusterIdentifier,
},
"cluster_type": &schema.Schema{
"cluster_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"node_type": &schema.Schema{
"node_type": {
Type: schema.TypeString,
Required: true,
},
"master_username": &schema.Schema{
"master_username": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateRedshiftClusterMasterUsername,
},
"master_password": &schema.Schema{
"master_password": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
ValidateFunc: validateRedshiftClusterMasterPassword,
},
"cluster_security_groups": &schema.Schema{
"cluster_security_groups": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
@ -70,7 +70,7 @@ func resourceAwsRedshiftCluster() *schema.Resource {
Set: schema.HashString,
},
"vpc_security_group_ids": &schema.Schema{
"vpc_security_group_ids": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
@ -78,20 +78,20 @@ func resourceAwsRedshiftCluster() *schema.Resource {
Set: schema.HashString,
},
"cluster_subnet_group_name": &schema.Schema{
"cluster_subnet_group_name": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
},
"availability_zone": &schema.Schema{
"availability_zone": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"preferred_maintenance_window": &schema.Schema{
"preferred_maintenance_window": {
Type: schema.TypeString,
Optional: true,
Computed: true,
@ -103,13 +103,13 @@ func resourceAwsRedshiftCluster() *schema.Resource {
},
},
"cluster_parameter_group_name": &schema.Schema{
"cluster_parameter_group_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"automated_snapshot_retention_period": &schema.Schema{
"automated_snapshot_retention_period": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
@ -123,91 +123,92 @@ func resourceAwsRedshiftCluster() *schema.Resource {
},
},
"port": &schema.Schema{
"port": {
Type: schema.TypeInt,
Optional: true,
Default: 5439,
},
"cluster_version": &schema.Schema{
"cluster_version": {
Type: schema.TypeString,
Optional: true,
Default: "1.0",
},
"allow_version_upgrade": &schema.Schema{
"allow_version_upgrade": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"number_of_nodes": &schema.Schema{
"number_of_nodes": {
Type: schema.TypeInt,
Optional: true,
Default: 1,
},
"publicly_accessible": &schema.Schema{
"publicly_accessible": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"encrypted": &schema.Schema{
"encrypted": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"enhanced_vpc_routing": &schema.Schema{
"enhanced_vpc_routing": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"kms_key_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ValidateFunc: validateArn,
},
"elastic_ip": &schema.Schema{
"elastic_ip": {
Type: schema.TypeString,
Optional: true,
},
"final_snapshot_identifier": &schema.Schema{
"final_snapshot_identifier": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateRedshiftClusterFinalSnapshotIdentifier,
},
"skip_final_snapshot": &schema.Schema{
"skip_final_snapshot": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"endpoint": &schema.Schema{
"endpoint": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"cluster_public_key": &schema.Schema{
"cluster_public_key": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"cluster_revision_number": &schema.Schema{
"cluster_revision_number": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"iam_roles": &schema.Schema{
"iam_roles": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
@ -233,12 +234,12 @@ func resourceAwsRedshiftCluster() *schema.Resource {
Computed: true,
},
"snapshot_identifier": &schema.Schema{
"snapshot_identifier": {
Type: schema.TypeString,
Optional: true,
},
"snapshot_cluster_identifier": &schema.Schema{
"snapshot_cluster_identifier": {
Type: schema.TypeString,
Optional: true,
},

View File

@ -11,6 +11,7 @@ import (
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"regexp"
)
func TestValidateRedshiftClusterDbName(t *testing.T) {
@ -60,7 +61,7 @@ func TestAccAWSRedshiftCluster_basic(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -74,6 +75,33 @@ func TestAccAWSRedshiftCluster_basic(t *testing.T) {
})
}
func TestAccAWSRedshiftCluster_kmsKey(t *testing.T) {
var v redshift.Cluster
ri := rand.New(rand.NewSource(time.Now().UnixNano())).Int()
config := fmt.Sprintf(testAccAWSRedshiftClusterConfig_kmsKey, ri, ri)
keyRegex := regexp.MustCompile("^arn:aws:([a-zA-Z0-9\\-])+:([a-z]{2}-[a-z]+-\\d{1})?:(\\d{12})?:(.*)$")
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
resource.TestCheckResourceAttr(
"aws_redshift_cluster.default", "cluster_type", "single-node"),
resource.TestCheckResourceAttr(
"aws_redshift_cluster.default", "publicly_accessible", "true"),
resource.TestMatchResourceAttr("aws_redshift_cluster.default", "kms_key_id", keyRegex),
),
},
},
})
}
func TestAccAWSRedshiftCluster_enhancedVpcRoutingEnabled(t *testing.T) {
var v redshift.Cluster
@ -86,7 +114,7 @@ func TestAccAWSRedshiftCluster_enhancedVpcRoutingEnabled(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -94,7 +122,7 @@ func TestAccAWSRedshiftCluster_enhancedVpcRoutingEnabled(t *testing.T) {
"aws_redshift_cluster.default", "enhanced_vpc_routing", "true"),
),
},
resource.TestStep{
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -118,7 +146,7 @@ func TestAccAWSRedshiftCluster_loggingEnabled(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -129,7 +157,7 @@ func TestAccAWSRedshiftCluster_loggingEnabled(t *testing.T) {
),
},
resource.TestStep{
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -153,7 +181,7 @@ func TestAccAWSRedshiftCluster_iamRoles(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -162,7 +190,7 @@ func TestAccAWSRedshiftCluster_iamRoles(t *testing.T) {
),
},
resource.TestStep{
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -186,7 +214,7 @@ func TestAccAWSRedshiftCluster_publiclyAccessible(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -195,7 +223,7 @@ func TestAccAWSRedshiftCluster_publiclyAccessible(t *testing.T) {
),
},
resource.TestStep{
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -219,7 +247,7 @@ func TestAccAWSRedshiftCluster_updateNodeCount(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -228,7 +256,7 @@ func TestAccAWSRedshiftCluster_updateNodeCount(t *testing.T) {
),
},
resource.TestStep{
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -252,7 +280,7 @@ func TestAccAWSRedshiftCluster_tags(t *testing.T) {
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRedshiftClusterDestroy,
Steps: []resource.TestStep{
resource.TestStep{
{
Config: preConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -262,7 +290,7 @@ func TestAccAWSRedshiftCluster_tags(t *testing.T) {
),
},
resource.TestStep{
{
Config: postConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSRedshiftClusterExists("aws_redshift_cluster.default", &v),
@ -502,6 +530,41 @@ resource "aws_redshift_cluster" "default" {
allow_version_upgrade = false
}`
var testAccAWSRedshiftClusterConfig_kmsKey = `
resource "aws_kms_key" "foo" {
description = "Terraform acc test %d"
policy = <<POLICY
{
"Version": "2012-10-17",
"Id": "kms-tf-1",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "kms:*",
"Resource": "*"
}
]
}
POLICY
}
resource "aws_redshift_cluster" "default" {
cluster_identifier = "tf-redshift-cluster-%d"
availability_zone = "us-west-2a"
database_name = "mydb"
master_username = "foo_test"
master_password = "Mustbe8characters"
node_type = "dc1.large"
automated_snapshot_retention_period = 0
allow_version_upgrade = false
kms_key_id = "${aws_kms_key.foo.arn}"
encrypted = true
}`
var testAccAWSRedshiftClusterConfig_enhancedVpcRoutingEnabled = `
resource "aws_redshift_cluster" "default" {
cluster_identifier = "tf-redshift-cluster-%d"

View File

@ -25,76 +25,77 @@ func resourceAwsS3BucketObject() *schema.Resource {
Delete: resourceAwsS3BucketObjectDelete,
Schema: map[string]*schema.Schema{
"bucket": &schema.Schema{
"bucket": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"acl": &schema.Schema{
"acl": {
Type: schema.TypeString,
Default: "private",
Optional: true,
ValidateFunc: validateS3BucketObjectAclType,
},
"cache_control": &schema.Schema{
"cache_control": {
Type: schema.TypeString,
Optional: true,
},
"content_disposition": &schema.Schema{
"content_disposition": {
Type: schema.TypeString,
Optional: true,
},
"content_encoding": &schema.Schema{
"content_encoding": {
Type: schema.TypeString,
Optional: true,
},
"content_language": &schema.Schema{
"content_language": {
Type: schema.TypeString,
Optional: true,
},
"content_type": &schema.Schema{
"content_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"key": &schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"source": &schema.Schema{
"source": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"content"},
},
"content": &schema.Schema{
"content": {
Type: schema.TypeString,
Optional: true,
ConflictsWith: []string{"source"},
},
"storage_class": &schema.Schema{
"storage_class": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validateS3BucketObjectStorageClassType,
},
"kms_key_id": &schema.Schema{
Type: schema.TypeString,
Optional: true,
"kms_key_id": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},
"etag": &schema.Schema{
"etag": {
Type: schema.TypeString,
// This will conflict with SSE-C and SSE-KMS encryption and multi-part upload
// if/when it's actually implemented. The Etag then won't match raw-file MD5.
@ -104,7 +105,7 @@ func resourceAwsS3BucketObject() *schema.Resource {
ConflictsWith: []string{"kms_key_id"},
},
"version_id": &schema.Schema{
"version_id": {
Type: schema.TypeString,
Computed: true,
},

View File

@ -21,64 +21,64 @@ func resourceAwsSesReceiptRule() *schema.Resource {
Delete: resourceAwsSesReceiptRuleDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"rule_set_name": &schema.Schema{
"rule_set_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"after": &schema.Schema{
"after": {
Type: schema.TypeString,
Optional: true,
},
"enabled": &schema.Schema{
"enabled": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"recipients": &schema.Schema{
"recipients": {
Type: schema.TypeSet,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Set: schema.HashString,
},
"scan_enabled": &schema.Schema{
"scan_enabled": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"tls_policy": &schema.Schema{
"tls_policy": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"add_header_action": &schema.Schema{
"add_header_action": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"header_name": &schema.Schema{
"header_name": {
Type: schema.TypeString,
Required: true,
},
"header_value": &schema.Schema{
"header_value": {
Type: schema.TypeString,
Required: true,
},
"position": &schema.Schema{
"position": {
Type: schema.TypeInt,
Required: true,
},
@ -95,37 +95,37 @@ func resourceAwsSesReceiptRule() *schema.Resource {
},
},
"bounce_action": &schema.Schema{
"bounce_action": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"message": &schema.Schema{
"message": {
Type: schema.TypeString,
Required: true,
},
"sender": &schema.Schema{
"sender": {
Type: schema.TypeString,
Required: true,
},
"smtp_reply_code": &schema.Schema{
"smtp_reply_code": {
Type: schema.TypeString,
Required: true,
},
"status_code": &schema.Schema{
"status_code": {
Type: schema.TypeString,
Optional: true,
},
"topic_arn": &schema.Schema{
"topic_arn": {
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
"position": {
Type: schema.TypeInt,
Required: true,
},
@ -152,28 +152,28 @@ func resourceAwsSesReceiptRule() *schema.Resource {
},
},
"lambda_action": &schema.Schema{
"lambda_action": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"function_arn": &schema.Schema{
"function_arn": {
Type: schema.TypeString,
Required: true,
},
"invocation_type": &schema.Schema{
"invocation_type": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"topic_arn": &schema.Schema{
"topic_arn": {
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
"position": {
Type: schema.TypeInt,
Required: true,
},
@ -198,32 +198,33 @@ func resourceAwsSesReceiptRule() *schema.Resource {
},
},
"s3_action": &schema.Schema{
"s3_action": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"bucket_name": &schema.Schema{
"bucket_name": {
Type: schema.TypeString,
Required: true,
},
"kms_key_arn": &schema.Schema{
"kms_key_arn": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateArn,
},
"object_key_prefix": {
Type: schema.TypeString,
Optional: true,
},
"object_key_prefix": &schema.Schema{
"topic_arn": {
Type: schema.TypeString,
Optional: true,
},
"topic_arn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
"position": {
Type: schema.TypeInt,
Required: true,
},
@ -252,17 +253,17 @@ func resourceAwsSesReceiptRule() *schema.Resource {
},
},
"sns_action": &schema.Schema{
"sns_action": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"topic_arn": &schema.Schema{
"topic_arn": {
Type: schema.TypeString,
Required: true,
},
"position": &schema.Schema{
"position": {
Type: schema.TypeInt,
Required: true,
},
@ -278,22 +279,22 @@ func resourceAwsSesReceiptRule() *schema.Resource {
},
},
"stop_action": &schema.Schema{
"stop_action": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"scope": &schema.Schema{
"scope": {
Type: schema.TypeString,
Required: true,
},
"topic_arn": &schema.Schema{
"topic_arn": {
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
"position": {
Type: schema.TypeInt,
Required: true,
},
@ -314,22 +315,22 @@ func resourceAwsSesReceiptRule() *schema.Resource {
},
},
"workmail_action": &schema.Schema{
"workmail_action": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"organization_arn": &schema.Schema{
"organization_arn": {
Type: schema.TypeString,
Required: true,
},
"topic_arn": &schema.Schema{
"topic_arn": {
Type: schema.TypeString,
Optional: true,
},
"position": &schema.Schema{
"position": {
Type: schema.TypeInt,
Required: true,
},

View File

@ -55,8 +55,8 @@ The following arguments are supported:
* `identifier` - (Optional) The name of the RDS instance, if omitted, Terraform will assign a random, unique name
* `instance_class` - (Required) The instance type of the RDS instance.
* `storage_type` - (Optional) One of "standard" (magnetic), "gp2" (general
purpose SSD), or "io1" (provisioned IOPS SSD). The default is "io1" if
`iops` is specified, "standard" if not.
purpose SSD), or "io1" (provisioned IOPS SSD). The default is "io1" if
`iops` is specified, "standard" if not.
* `final_snapshot_identifier` - (Optional) The name of your final DB snapshot
when this DB instance is deleted. If omitted, no final snapshot will be
made.

View File

@ -34,7 +34,7 @@ The following arguments are supported:
* `size` - (Optional) The size of the drive in GiBs.
* `snapshot_id` (Optional) A snapshot to base the EBS volume off of.
* `type` - (Optional) The type of EBS volume. Can be "standard", "gp2", "io1", or "st1" (Default: "standard").
* `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying `kms_key_id`, `encrypted` needs to be set to true
* `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying `kms_key_id`, `encrypted` needs to be set to true.
* `tags` - (Optional) A mapping of tags to assign to the resource.
## Attributes Reference

View File

@ -135,7 +135,7 @@ The `s3_configuration` object supports the following:
We recommend setting SizeInMBs to a value greater than the amount of data you typically ingest into the delivery stream in 10 seconds. For example, if you typically ingest data at 1 MB/sec set SizeInMBs to be 10 MB or higher.
* `buffer_interval` - (Optional) Buffer incoming data for the specified period of time, in seconds, before delivering it to the destination. The default value is 300.
* `compression_format` - (Optional) The compression format. If no value is specified, the default is UNCOMPRESSED. Other supported values are GZIP, ZIP & Snappy. If the destination is redshift you cannot use ZIP or Snappy.
* `kms_key_arn` - (Optional) If set, the stream will encrypt data using the key in KMS, otherwise, no encryption will
* `kms_key_arn` - (Optional) Specifies the KMS key ARN the stream will use to encrypt data. If not set, no encryption will
be used.
* `cloudwatch_logging_options` - (Optional) The CloudWatch Logging Options for the delivery stream. More details are given below

View File

@ -79,7 +79,7 @@ Default: A 30-minute window selected at random from an 8-hour block of time per
`false`. See [Amazon RDS Documentation for more information.](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html)
* `db_subnet_group_name` - (Optional) A DB subnet group to associate with this DB instance. **NOTE:** This must match the `db_subnet_group_name` specified on every [`aws_rds_cluster_instance`](/docs/providers/aws/r/rds_cluster_instance.html) in the cluster.
* `db_cluster_parameter_group_name` - (Optional) A cluster parameter group to associate with the cluster.
* `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying `kms_key_id`, `storage_encrypted` needs to be set to true
* `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying `kms_key_id`, `storage_encrypted` needs to be set to true.
## Attributes Reference

View File

@ -55,7 +55,7 @@ string.
* `publicly_accessible` - (Optional) If true, the cluster can be accessed from a public network. Default is `true`.
* `encrypted` - (Optional) If true , the data in the cluster is encrypted at rest.
* `enhanced_vpc_routing` - (Optional) If true , enhanced VPC routing is enabled.
* `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying `kms_key_id`, `encrypted` needs to be set to true
* `kms_key_id` - (Optional) The ARN for the KMS encryption key. When specifying `kms_key_id`, `encrypted` needs to be set to true.
* `elastic_ip` - (Optional) The Elastic IP (EIP) address for the cluster.
* `skip_final_snapshot` - (Optional) Determines whether a final snapshot of the cluster is created before Amazon Redshift deletes the cluster. If true , a final cluster snapshot is not created. If false , a final cluster snapshot is created before the cluster is deleted. Default is true.
* `final_snapshot_identifier` - (Optional) The identifier of the final snapshot that is to be created immediately before deleting the cluster. If this parameter is provided, `skip_final_snapshot` must be false.

View File

@ -61,8 +61,8 @@ The following arguments are supported:
* `storage_class` - (Optional) Specifies the desired [Storage Class](http://docs.aws.amazon.com/AmazonS3/latest/dev/storage-class-intro.html)
for the object. Can be either "`STANDARD`", "`REDUCED_REDUNDANCY`", or "`STANDARD_IA`". Defaults to "`STANDARD`".
* `etag` - (Optional) Used to trigger updates. The only meaningful value is `${md5(file("path/to/file"))}`.
This attribute is not compatible with `kms_key_id`
* `kms_key_id` - (Optional) Specifies the AWS KMS Key ID to use for object encryption.
This attribute is not compatible with `kms_key_id`.
* `kms_key_id` - (Optional) Specifies the AWS KMS Key ARN to use for object encryption.
This value is a fully qualified **ARN** of the KMS Key. If using `aws_kms_key`,
use the exported `arn` attribute:
`kms_key_id = "${aws_kms_key.foo.arn}"`