Skip to content

Commit

Permalink
Merge pull request #5884 from terraform-providers/b-aws_iam_policy-de…
Browse files Browse the repository at this point in the history
…scription-on-creation

resource/aws_iam_policy: Ensure description is properly read during creation
  • Loading branch information
bflad authored Sep 14, 2018
2 parents da9d1fd + d149602 commit ba4ed34
Show file tree
Hide file tree
Showing 4 changed files with 286 additions and 192 deletions.
88 changes: 0 additions & 88 deletions aws/import_aws_iam_policy_test.go

This file was deleted.

13 changes: 13 additions & 0 deletions aws/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@ func testAccCheckResourceAttrRegionalARN(resourceName, attributeName, arnService
}
}

// testAccCheckResourceAttrGlobalARN ensures the Terraform state exactly matches a formatted ARN without region
func testAccCheckResourceAttrGlobalARN(resourceName, attributeName, arnService, arnResource string) resource.TestCheckFunc {
return func(s *terraform.State) error {
attributeValue := arn.ARN{
AccountID: testAccGetAccountID(),
Partition: testAccGetPartition(),
Resource: arnResource,
Service: arnService,
}.String()
return resource.TestCheckResourceAttr(resourceName, attributeName, attributeValue)(s)
}
}

// testAccGetAccountID returns the account ID of testAccProvider
// Must be used returned within a resource.TestCheckFunc
func testAccGetAccountID() string {
Expand Down
123 changes: 82 additions & 41 deletions aws/resource_aws_iam_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ package aws

import (
"fmt"
"log"
"net/url"
"regexp"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/iam"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
Expand Down Expand Up @@ -112,7 +112,9 @@ func resourceAwsIamPolicyCreate(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("Error creating IAM policy %s: %s", name, err)
}

return readIamPolicy(d, response.Policy)
d.SetId(*response.Policy.Arn)

return resourceAwsIamPolicyRead(d, meta)
}

func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error {
Expand All @@ -121,39 +123,93 @@ func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error {
getPolicyRequest := &iam.GetPolicyInput{
PolicyArn: aws.String(d.Id()),
}
log.Printf("[DEBUG] Getting IAM Policy: %s", getPolicyRequest)

getPolicyResponse, err := iamconn.GetPolicy(getPolicyRequest)
if err != nil {
if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
d.SetId("")
return nil
// Handle IAM eventual consistency
var getPolicyResponse *iam.GetPolicyOutput
err := resource.Retry(1*time.Minute, func() *resource.RetryError {
var err error
getPolicyResponse, err = iamconn.GetPolicy(getPolicyRequest)

if d.IsNewResource() && isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
return resource.RetryableError(err)
}

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})

if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
log.Printf("[WARN] IAM Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

if err != nil {
return fmt.Errorf("Error reading IAM policy %s: %s", d.Id(), err)
}

if getPolicyResponse == nil || getPolicyResponse.Policy == nil {
log.Printf("[WARN] IAM Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

d.Set("arn", getPolicyResponse.Policy.Arn)
d.Set("description", getPolicyResponse.Policy.Description)
d.Set("name", getPolicyResponse.Policy.PolicyName)
d.Set("path", getPolicyResponse.Policy.Path)

// Retrieve policy

getPolicyVersionRequest := &iam.GetPolicyVersionInput{
PolicyArn: aws.String(d.Id()),
VersionId: getPolicyResponse.Policy.DefaultVersionId,
}
log.Printf("[DEBUG] Getting IAM Policy Version: %s", getPolicyVersionRequest)

getPolicyVersionResponse, err := iamconn.GetPolicyVersion(getPolicyVersionRequest)
if err != nil {
if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
d.SetId("")
return nil
// Handle IAM eventual consistency
var getPolicyVersionResponse *iam.GetPolicyVersionOutput
err = resource.Retry(1*time.Minute, func() *resource.RetryError {
var err error
getPolicyVersionResponse, err = iamconn.GetPolicyVersion(getPolicyVersionRequest)

if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
return resource.RetryableError(err)
}
return fmt.Errorf("Error reading IAM policy version %s: %s", d.Id(), err)

if err != nil {
return resource.NonRetryableError(err)
}

return nil
})

if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
log.Printf("[WARN] IAM Policy (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

policy, err := url.QueryUnescape(*getPolicyVersionResponse.PolicyVersion.Document)
if err != nil {
return err
return fmt.Errorf("Error reading IAM policy version %s: %s", d.Id(), err)
}
if err := d.Set("policy", policy); err != nil {
return err

policy := ""
if getPolicyVersionResponse != nil && getPolicyVersionResponse.PolicyVersion != nil {
var err error
policy, err = url.QueryUnescape(aws.StringValue(getPolicyVersionResponse.PolicyVersion.Document))
if err != nil {
return fmt.Errorf("error parsing policy: %s", err)
}
}

return readIamPolicy(d, getPolicyResponse.Policy)
d.Set("policy", policy)

return nil
}

func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
Expand All @@ -163,9 +219,6 @@ func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error
return err
}

if !d.HasChange("policy") {
return nil
}
request := &iam.CreatePolicyVersionInput{
PolicyArn: aws.String(d.Id()),
PolicyDocument: aws.String(d.Get("policy").(string)),
Expand All @@ -175,7 +228,8 @@ func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error
if _, err := iamconn.CreatePolicyVersion(request); err != nil {
return fmt.Errorf("Error updating IAM policy %s: %s", d.Id(), err)
}
return nil

return resourceAwsIamPolicyRead(d, meta)
}

func resourceAwsIamPolicyDelete(d *schema.ResourceData, meta interface{}) error {
Expand All @@ -190,12 +244,14 @@ func resourceAwsIamPolicyDelete(d *schema.ResourceData, meta interface{}) error
}

_, err := iamconn.DeletePolicy(request)
if isAWSErr(err, iam.ErrCodeNoSuchEntityException, "") {
return nil
}

if err != nil {
if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
return nil
}
return fmt.Errorf("Error deleting IAM policy %s: %#v", d.Id(), err)
}

return nil
}

Expand Down Expand Up @@ -275,18 +331,3 @@ func iamPolicyListVersions(arn string, iamconn *iam.IAM) ([]*iam.PolicyVersion,
}
return response.Versions, nil
}

func readIamPolicy(d *schema.ResourceData, policy *iam.Policy) error {
d.SetId(*policy.Arn)
d.Set("description", policy.Description)
if err := d.Set("path", policy.Path); err != nil {
return err
}
if err := d.Set("name", policy.PolicyName); err != nil {
return err
}
if err := d.Set("arn", policy.Arn); err != nil {
return err
}
return nil
}
Loading

0 comments on commit ba4ed34

Please sign in to comment.