Skip to content

Commit

Permalink
Merge pull request #5737 from saravanan30erd/cloudfront-pubkey
Browse files Browse the repository at this point in the history
New Resource: CloudFront Public Key
  • Loading branch information
bflad authored Sep 12, 2018
2 parents 13b35cb + 8f80721 commit ad83a91
Show file tree
Hide file tree
Showing 8 changed files with 464 additions and 0 deletions.
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ func Provider() terraform.ResourceProvider {
"aws_cloudformation_stack": resourceAwsCloudFormationStack(),
"aws_cloudfront_distribution": resourceAwsCloudFrontDistribution(),
"aws_cloudfront_origin_access_identity": resourceAwsCloudFrontOriginAccessIdentity(),
"aws_cloudfront_public_key": resourceAwsCloudFrontPublicKey(),
"aws_cloudtrail": resourceAwsCloudTrail(),
"aws_cloudwatch_event_permission": resourceAwsCloudWatchEventPermission(),
"aws_cloudwatch_event_rule": resourceAwsCloudWatchEventRule(),
Expand Down
170 changes: 170 additions & 0 deletions aws/resource_aws_cloudfront_public_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package aws

import (
"fmt"
"log"
"time"

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

func resourceAwsCloudFrontPublicKey() *schema.Resource {
return &schema.Resource{
Create: resourceAwsCloudFrontPublicKeyCreate,
Read: resourceAwsCloudFrontPublicKeyRead,
Update: resourceAwsCloudFrontPublicKeyUpdate,
Delete: resourceAwsCloudFrontPublicKeyDelete,

Schema: map[string]*schema.Schema{
"caller_reference": {
Type: schema.TypeString,
Computed: true,
},
"comment": {
Type: schema.TypeString,
Optional: true,
},
"encoded_key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"etag": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"name_prefix"},
ValidateFunc: validateCloudFrontPublicKeyName,
},
"name_prefix": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"name"},
ValidateFunc: validateCloudFrontPublicKeyNamePrefix,
},
},
}
}

func resourceAwsCloudFrontPublicKeyCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudfrontconn

if v, ok := d.GetOk("name"); ok {
d.Set("name", v.(string))
} else if v, ok := d.GetOk("name_prefix"); ok {
d.Set("name", resource.PrefixedUniqueId(v.(string)))
} else {
d.Set("name", resource.PrefixedUniqueId("tf-"))
}

request := &cloudfront.CreatePublicKeyInput{
PublicKeyConfig: expandPublicKeyConfig(d),
}

log.Println("[DEBUG] Create CloudFront PublicKey:", request)

output, err := conn.CreatePublicKey(request)
if err != nil {
return fmt.Errorf("error creating CloudFront PublicKey: %s", err)
}

d.SetId(aws.StringValue(output.PublicKey.Id))
return resourceAwsCloudFrontPublicKeyRead(d, meta)
}

func resourceAwsCloudFrontPublicKeyRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudfrontconn
request := &cloudfront.GetPublicKeyInput{
Id: aws.String(d.Id()),
}

output, err := conn.GetPublicKey(request)
if err != nil {
if isAWSErr(err, cloudfront.ErrCodeNoSuchPublicKey, "") {
log.Printf("[WARN] No PublicKey found: %s, removing from state", d.Id())
d.SetId("")
return nil
}
return err
}

if output == nil || output.PublicKey == nil || output.PublicKey.PublicKeyConfig == nil {
log.Printf("[WARN] No PublicKey found: %s, removing from state", d.Id())
d.SetId("")
return nil
}
publicKeyConfig := output.PublicKey.PublicKeyConfig

d.Set("encoded_key", publicKeyConfig.EncodedKey)
d.Set("name", publicKeyConfig.Name)
d.Set("comment", publicKeyConfig.Comment)
d.Set("caller_reference", publicKeyConfig.CallerReference)
d.Set("etag", output.ETag)

return nil
}

func resourceAwsCloudFrontPublicKeyUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudfrontconn

request := &cloudfront.UpdatePublicKeyInput{
Id: aws.String(d.Id()),
PublicKeyConfig: expandPublicKeyConfig(d),
IfMatch: aws.String(d.Get("etag").(string)),
}

_, err := conn.UpdatePublicKey(request)
if err != nil {
return fmt.Errorf("error updating CloudFront PublicKey (%s): %s", d.Id(), err)
}

return resourceAwsCloudFrontPublicKeyRead(d, meta)
}

func resourceAwsCloudFrontPublicKeyDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).cloudfrontconn

request := &cloudfront.DeletePublicKeyInput{
Id: aws.String(d.Id()),
IfMatch: aws.String(d.Get("etag").(string)),
}

_, err := conn.DeletePublicKey(request)
if err != nil {
if isAWSErr(err, cloudfront.ErrCodeNoSuchPublicKey, "") {
return nil
}
return err
}

return nil
}

func expandPublicKeyConfig(d *schema.ResourceData) *cloudfront.PublicKeyConfig {
publicKeyConfig := &cloudfront.PublicKeyConfig{
EncodedKey: aws.String(d.Get("encoded_key").(string)),
Name: aws.String(d.Get("name").(string)),
}

if v, ok := d.GetOk("comment"); ok {
publicKeyConfig.Comment = aws.String(v.(string))
}

if v, ok := d.GetOk("caller_reference"); ok {
publicKeyConfig.CallerReference = aws.String(v.(string))
} else {
publicKeyConfig.CallerReference = aws.String(time.Now().Format(time.RFC3339Nano))
}

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

import (
"fmt"
"regexp"
"testing"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/cloudfront"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccAWSCloudFrontPublicKey_basic(t *testing.T) {
rInt := acctest.RandInt()

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudFrontPublicKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudFrontPublicKeyConfig(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudFrontPublicKeyExistence("aws_cloudfront_public_key.example"),
resource.TestCheckResourceAttr("aws_cloudfront_public_key.example", "comment", "test key"),
resource.TestMatchResourceAttr("aws_cloudfront_public_key.example",
"caller_reference",
regexp.MustCompile("^20[0-9]{2}.*")),
resource.TestCheckResourceAttr("aws_cloudfront_public_key.example", "name", fmt.Sprintf("tf-acc-test-%d", rInt)),
),
},
},
})
}

func TestAccAWSCloudFrontPublicKey_namePrefix(t *testing.T) {
startsWithPrefix := regexp.MustCompile("^tf-acc-test-")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudFrontPublicKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudFrontPublicKeyConfig_namePrefix(),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudFrontPublicKeyExistence("aws_cloudfront_public_key.example"),
resource.TestMatchResourceAttr("aws_cloudfront_public_key.example", "name", startsWithPrefix),
),
},
},
})
}

func TestAccAWSCloudFrontPublicKey_update(t *testing.T) {
rInt := acctest.RandInt()

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckCloudFrontPublicKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSCloudFrontPublicKeyConfig(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudFrontPublicKeyExistence("aws_cloudfront_public_key.example"),
resource.TestCheckResourceAttr("aws_cloudfront_public_key.example", "comment", "test key"),
),
},
{
Config: testAccAWSCloudFrontPublicKeyConfigUpdate(rInt),
Check: resource.ComposeTestCheckFunc(
testAccCheckCloudFrontPublicKeyExistence("aws_cloudfront_public_key.example"),
resource.TestCheckResourceAttr("aws_cloudfront_public_key.example", "comment", "test key1"),
),
},
},
})
}

func testAccCheckCloudFrontPublicKeyExistence(r string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[r]
if !ok {
return fmt.Errorf("Not found: %s", r)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No Id is set")
}

conn := testAccProvider.Meta().(*AWSClient).cloudfrontconn

params := &cloudfront.GetPublicKeyInput{
Id: aws.String(rs.Primary.ID),
}

_, err := conn.GetPublicKey(params)
if err != nil {
return fmt.Errorf("Error retrieving CloudFront PublicKey: %s", err)
}
return nil
}
}

func testAccCheckCloudFrontPublicKeyDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).cloudfrontconn

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_cloudfront_public_key" {
continue
}

params := &cloudfront.GetPublicKeyInput{
Id: aws.String(rs.Primary.ID),
}

_, err := conn.GetPublicKey(params)
if isAWSErr(err, cloudfront.ErrCodeNoSuchPublicKey, "") {
continue
}
if err != nil {
return err
}
return fmt.Errorf("CloudFront PublicKey (%s) was not deleted", rs.Primary.ID)
}

return nil
}

func testAccAWSCloudFrontPublicKeyConfig(rInt int) string {
return fmt.Sprintf(`
resource "aws_cloudfront_public_key" "example" {
comment = "test key"
encoded_key = "${file("test-fixtures/cloudfront-public-key.pem")}"
name = "tf-acc-test-%d"
}
`, rInt)
}

func testAccAWSCloudFrontPublicKeyConfig_namePrefix() string {
return fmt.Sprintf(`
resource "aws_cloudfront_public_key" "example" {
comment = "test key"
encoded_key = "${file("test-fixtures/cloudfront-public-key.pem")}"
name_prefix = "tf-acc-test-"
}
`)
}

func testAccAWSCloudFrontPublicKeyConfigUpdate(rInt int) string {
return fmt.Sprintf(`
resource "aws_cloudfront_public_key" "example" {
comment = "test key1"
encoded_key = "${file("test-fixtures/cloudfront-public-key.pem")}"
name = "tf-acc-test-%d"
}
`, rInt)
}
9 changes: 9 additions & 0 deletions aws/test-fixtures/cloudfront-public-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtZCjGTEV/ttumSJBnsc2
SUzPY/wJjfNchT2mjWivg/S7HuwKp1tDHizxrXTVuZLdDKceVcSclS7otzwfmGxM
Gjk2/CM2hEMThT86q76TrbH6hvGa25n8piBOkhwbwdbvmg3DRJiLR9bqw+nAPt/n
1ggTcwazm1Bw7y112Ardop+buWirS3w2C6au2OdloaaLz5N1eHEHQuRpnmD+UoVR
OgGeaLaU7FxKkpOps4Giu4vgjcefGlM3MrqG4FAzDMtgGZdJm4U+bldYmk0+J1yv
JA0FGd9g9GhjHMT9UznxXccw7PhHQsXn4lQfOn47uO9KIq170t8FeHKEzbCMsmyA
2QIDAQAB
-----END PUBLIC KEY-----
27 changes: 27 additions & 0 deletions aws/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -2009,3 +2009,30 @@ func validateNeptuneEventSubscriptionNamePrefix(v interface{}, k string) (ws []s
}
return
}

func validateCloudFrontPublicKeyName(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, underscores and hyphens allowed in %q", k))
}
if len(value) > 128 {
errors = append(errors, fmt.Errorf(
"%q cannot be greater than 128 characters", k))
}
return
}

func validateCloudFrontPublicKeyNamePrefix(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, underscores and hyphens allowed in %q", k))
}
prefixMaxLength := 128 - resource.UniqueIDSuffixLength
if len(value) > prefixMaxLength {
errors = append(errors, fmt.Errorf(
"%q cannot be greater than %d characters", k, prefixMaxLength))
}
return
}
Loading

0 comments on commit ad83a91

Please sign in to comment.