diff --git a/.changelog/13973.txt b/.changelog/13973.txt new file mode 100644 index 00000000000..d36e47fcfeb --- /dev/null +++ b/.changelog/13973.txt @@ -0,0 +1,5 @@ +```release-note:enhancement +resource/aws_elastictranscoder_pipeline: Add plan time validations to `content_config.storage_class`, `content_config_permissions.access`, `content_config_permissions.grantee_type`, +`notifications.completed`, `notifications.error`, `notifications.progressing`, `notifications.warning`, +`thumbnail_config.storage_class`, `thumbnail_config_permissions.access`, `thumbnail_config_permissions.grantee_type` +``` \ No newline at end of file diff --git a/aws/resource_aws_elastic_transcoder_pipeline.go b/aws/resource_aws_elastic_transcoder_pipeline.go index 64df5e9d8a9..0c998576cb3 100644 --- a/aws/resource_aws_elastic_transcoder_pipeline.go +++ b/aws/resource_aws_elastic_transcoder_pipeline.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/service/elastictranscoder" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func resourceAwsElasticTranscoderPipeline() *schema.Resource { @@ -51,6 +52,10 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { "storage_class": { Type: schema.TypeString, Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Standard", + "ReducedRedundancy", + }, false), }, }, }, @@ -64,7 +69,15 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { "access": { Type: schema.TypeList, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "Read", + "ReadAcp", + "WriteAcp", + "FullControl", + }, false), + }, }, "grantee": { Type: schema.TypeString, @@ -73,6 +86,11 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { "grantee_type": { Type: schema.TypeString, Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Canonical", + "Email", + "Group", + }, false), }, }, }, @@ -88,17 +106,11 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { Optional: true, Computed: true, ForceNew: true, - ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { - value := v.(string) - if !regexp.MustCompile(`^[.0-9A-Za-z-_]+$`).MatchString(value) { - errors = append(errors, fmt.Errorf( - "only alphanumeric characters, hyphens, underscores, and periods allowed in %q", k)) - } - if len(value) > 40 { - errors = append(errors, fmt.Errorf("%q cannot be longer than 40 characters", k)) - } - return - }, + ValidateFunc: validation.All( + validation.StringMatch(regexp.MustCompile(`^[.0-9A-Za-z-_]+$`), + "only alphanumeric characters, hyphens, underscores, and periods allowed"), + validation.StringLenBetween(1, 40), + ), }, "notifications": { @@ -108,20 +120,24 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "completed": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, }, "error": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, }, "progressing": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, }, "warning": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateArn, }, }, }, @@ -160,6 +176,10 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { "storage_class": { Type: schema.TypeString, Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Standard", + "ReducedRedundancy", + }, false), }, }, }, @@ -173,7 +193,15 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { "access": { Type: schema.TypeList, Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "Read", + "ReadAcp", + "WriteAcp", + "FullControl", + }, false), + }, }, "grantee": { Type: schema.TypeString, @@ -182,6 +210,11 @@ func resourceAwsElasticTranscoderPipeline() *schema.Resource { "grantee_type": { Type: schema.TypeString, Optional: true, + ValidateFunc: validation.StringInSlice([]string{ + "Canonical", + "Email", + "Group", + }, false), }, }, }, @@ -408,7 +441,8 @@ func resourceAwsElasticTranscoderPipelineUpdate(d *schema.ResourceData, meta int } for _, w := range output.Warnings { - log.Printf("[WARN] Elastic Transcoder Pipeline %v: %v", *w.Code, *w.Message) + log.Printf("[WARN] Elastic Transcoder Pipeline %v: %v", aws.StringValue(w.Code), + aws.StringValue(w.Message)) } return resourceAwsElasticTranscoderPipelineRead(d, meta) diff --git a/aws/resource_aws_elastic_transcoder_pipeline_test.go b/aws/resource_aws_elastic_transcoder_pipeline_test.go index 95d4daa1510..3e4991912b8 100644 --- a/aws/resource_aws_elastic_transcoder_pipeline_test.go +++ b/aws/resource_aws_elastic_transcoder_pipeline_test.go @@ -3,11 +3,11 @@ package aws import ( "fmt" "reflect" + "regexp" "sort" "testing" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" "github.com/aws/aws-sdk-go/service/elastictranscoder" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -29,6 +29,7 @@ func TestAccAWSElasticTranscoderPipeline_basic(t *testing.T) { Config: awsElasticTranscoderPipelineConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticTranscoderPipelineExists(resourceName, pipeline), + testAccMatchResourceAttrRegionalARN(resourceName, "arn", "elastictranscoder", regexp.MustCompile(`pipeline/.+`)), ), }, { @@ -110,16 +111,16 @@ func testAccCheckAWSElasticTranscoderPipeline_notifications( return func(s *terraform.State) error { var notes []string - if p.Notifications.Completed != nil && *p.Notifications.Completed != "" { + if aws.StringValue(p.Notifications.Completed) != "" { notes = append(notes, "completed") } - if p.Notifications.Error != nil && *p.Notifications.Error != "" { + if aws.StringValue(p.Notifications.Error) != "" { notes = append(notes, "error") } - if p.Notifications.Progressing != nil && *p.Notifications.Progressing != "" { + if aws.StringValue(p.Notifications.Progressing) != "" { notes = append(notes, "progressing") } - if p.Notifications.Warning != nil && *p.Notifications.Warning != "" { + if aws.StringValue(p.Notifications.Warning) != "" { notes = append(notes, "warning") } @@ -212,7 +213,7 @@ func TestAccAWSElasticTranscoderPipeline_disappears(t *testing.T) { Config: awsElasticTranscoderPipelineConfigBasic(rName), Check: resource.ComposeTestCheckFunc( testAccCheckAWSElasticTranscoderPipelineExists(resourceName, pipeline), - testAccCheckAWSElasticTranscoderPipelineDisappears(pipeline), + testAccCheckResourceDisappears(testAccProvider, resourceAwsElasticTranscoderPipeline(), resourceName), ), ExpectNonEmptyPlan: true, }, @@ -247,18 +248,6 @@ func testAccCheckAWSElasticTranscoderPipelineExists(n string, res *elastictransc } } -func testAccCheckAWSElasticTranscoderPipelineDisappears(res *elastictranscoder.Pipeline) resource.TestCheckFunc { - return func(s *terraform.State) error { - conn := testAccProvider.Meta().(*AWSClient).elastictranscoderconn - - _, err := conn.DeletePipeline(&elastictranscoder.DeletePipelineInput{ - Id: res.Id, - }) - - return err - } -} - func testAccCheckElasticTranscoderPipelineDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*AWSClient).elastictranscoderconn @@ -270,22 +259,16 @@ func testAccCheckElasticTranscoderPipelineDestroy(s *terraform.State) error { out, err := conn.ReadPipeline(&elastictranscoder.ReadPipelineInput{ Id: aws.String(rs.Primary.ID), }) - - if err == nil { - if out.Pipeline != nil && *out.Pipeline.Id == rs.Primary.ID { - return fmt.Errorf("Elastic Transcoder Pipeline still exists") - } + if isAWSErr(err, elastictranscoder.ErrCodeResourceNotFoundException, "") { + continue } - - awsErr, ok := err.(awserr.Error) - if !ok { - return err + if err != nil { + return fmt.Errorf("unexpected error: %w", err) } - if awsErr.Code() != "ResourceNotFoundException" { - return fmt.Errorf("unexpected error: %s", awsErr) + if out.Pipeline != nil && aws.StringValue(out.Pipeline.Id) == rs.Primary.ID { + return fmt.Errorf("Elastic Transcoder Pipeline still exists") } - } return nil } diff --git a/website/docs/r/elastictranscoder_pipeline.html.markdown b/website/docs/r/elastictranscoder_pipeline.html.markdown index 9d0fb4a8b5c..ab5238b5a3d 100644 --- a/website/docs/r/elastictranscoder_pipeline.html.markdown +++ b/website/docs/r/elastictranscoder_pipeline.html.markdown @@ -57,11 +57,11 @@ you specify values for `content_config`, you must also specify values for The `content_config` object supports the following: * `bucket` - The Amazon S3 bucket in which you want Elastic Transcoder to save transcoded files and playlists. -* `storage_class` - The Amazon S3 storage class, Standard or ReducedRedundancy, that you want Elastic Transcoder to assign to the files and playlists that it stores in your Amazon S3 bucket. +* `storage_class` - The Amazon S3 storage class, `Standard` or `ReducedRedundancy`, that you want Elastic Transcoder to assign to the files and playlists that it stores in your Amazon S3 bucket. The `content_config_permissions` object supports the following: -* `access` - The permission that you want to give to the AWS user that you specified in `content_config_permissions.grantee` +* `access` - The permission that you want to give to the AWS user that you specified in `content_config_permissions.grantee`. Valid values are `Read`, `ReadAcp`, `WriteAcp` or `FullControl`. * `grantee` - The AWS user or group that you want to have access to transcoded files and playlists. * `grantee_type` - Specify the type of value that appears in the `content_config_permissions.grantee` object. Valid values are `Canonical`, `Email` or `Group`. @@ -90,9 +90,16 @@ The `thumbnail_config` object supports the following: The `thumbnail_config_permissions` object supports the following: -* `access` - The permission that you want to give to the AWS user that you specified in `thumbnail_config_permissions.grantee`. +* `access` - The permission that you want to give to the AWS user that you specified in `thumbnail_config_permissions.grantee`. Valid values are `Read`, `ReadAcp`, `WriteAcp` or `FullControl`. * `grantee` - The AWS user or group that you want to have access to thumbnail files. -* `grantee_type` - Specify the type of value that appears in the `thumbnail_config_permissions.grantee` object. +* `grantee_type` - Specify the type of value that appears in the `thumbnail_config_permissions.grantee` object. Valid values are `Canonical`, `Email` or `Group`. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - The ID of the Elastictranscoder pipeline. +* `arn` - The ARN of the Elastictranscoder pipeline. ## Import