Skip to content

Commit

Permalink
Add name_prefix to aws_iam_policy
Browse files Browse the repository at this point in the history
This is intended to behave the same way as name_prefix does in
aws_iam_role.

Fixes hashicorp#10176
  • Loading branch information
2rs2ts committed Nov 16, 2016
1 parent 81125f6 commit 253d169
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 3 deletions.
47 changes: 45 additions & 2 deletions builtin/providers/aws/resource_aws_iam_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package aws

import (
"fmt"
"regexp"

"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 @@ -34,9 +36,42 @@ func resourceAwsIamPolicy() *schema.Resource {
Required: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
ConflictsWith: []string{"name_prefix"},
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8329-L8334
value := v.(string)
if len(value) > 128 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 128 characters", k))
}
if !regexp.MustCompile("^[\\w+=,.@-]*$").MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q must match [\\w+=,.@-]", k))
}
return
},
},
"name_prefix": {
Type: schema.TypeString,
Required: true,
Optional: true,
ForceNew: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8329-L8334
value := v.(string)
if len(value) > 96 {
errors = append(errors, fmt.Errorf(
"%q cannot be longer than 96 characters, name is limited to 128", k))
}
if !regexp.MustCompile("^[\\w+=,.@-]*$").MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q must match [\\w+=,.@-]", k))
}
return
},
},
"arn": &schema.Schema{
Type: schema.TypeString,
Expand All @@ -48,7 +83,15 @@ func resourceAwsIamPolicy() *schema.Resource {

func resourceAwsIamPolicyCreate(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn
name := d.Get("name").(string)

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

request := &iam.CreatePolicyInput{
Description: aws.String(d.Get("description").(string)),
Expand Down
125 changes: 125 additions & 0 deletions builtin/providers/aws/resource_aws_iam_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package aws

import (
"fmt"
"strings"
"testing"

"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/terraform"
)

func TestAWSPolicy_namePrefix(t *testing.T) {
var out iam.GetPolicyOutput

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSPolicyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSPolicyPrefixNameConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSPolicyExists("aws_iam_policy.policy", &out),
testAccCheckAWSPolicyGeneratedNamePrefix(
"aws_iam_policy.policy", "test-policy-"),
),
},
},
})
}

func testAccCheckAWSPolicyDestroy(s *terraform.State) error {
iamconn := testAccProvider.Meta().(*AWSClient).iamconn

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

// Try to get policy
_, err := iamconn.GetPolicy(&iam.GetPolicyInput{
PolicyArn: aws.String(rs.Primary.Attributes["arn"]),
})
if err == nil {
return fmt.Errorf("still exist.")
}

// Verify the error is what we want
ec2err, ok := err.(awserr.Error)
if !ok {
return err
}
if ec2err.Code() != "NoSuchEntity" {
return err
}
}

return nil
}

func testAccCheckAWSPolicyExists(resource string, res *iam.GetPolicyOutput) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resource]
if !ok {
return fmt.Errorf("Not found: %s", resource)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No Policy name is set")
}

iamconn := testAccProvider.Meta().(*AWSClient).iamconn

resp, err := iamconn.GetPolicy(&iam.GetPolicyInput{
PolicyArn: aws.String(rs.Primary.Attributes["arn"]),
})
if err != nil {
return err
}

*res = *resp

return nil
}
}

func testAccCheckAWSPolicyGeneratedNamePrefix(resource, prefix string) resource.TestCheckFunc {
return func(s *terraform.State) error {
r, ok := s.RootModule().Resources[resource]
if !ok {
return fmt.Errorf("Resource not found")
}
name, ok := r.Primary.Attributes["name"]
if !ok {
return fmt.Errorf("Name attr not found: %#v", r.Primary.Attributes)
}
if !strings.HasPrefix(name, prefix) {
return fmt.Errorf("Name: %q, does not have prefix: %q", name, prefix)
}
return nil
}
}

const testAccAWSPolicyPrefixNameConfig = `
resource "aws_iam_policy" "policy" {
name-prefix = "test-policy-"
path = "/"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
`
4 changes: 3 additions & 1 deletion website/source/docs/providers/aws/r/iam_policy.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ EOF
The following arguments are supported:

* `description` - (Optional) Description of the IAM policy.
* `name` - (Optional, Forces new resource) The name of the policy.
* `name_prefix` - (Optional, Forces new resource) Creates a unique name beginning with the specified prefix. Conflicts with `name`.
* `path` - (Optional, default "/") Path in which to create the policy.
See [IAM Identifiers](https://docs.aws.amazon.com/IAM/latest/UserGuide/Using_Identifiers.html) for more information.
* `policy` - (Required) The policy document. This is a JSON formatted string.
The heredoc syntax, `file` function, or the [`aws_iam_policy_document` data
source](/docs/providers/aws/d/iam_policy_document.html)
are all helpful here.
* `name` (Required) - The name of the policy.

## Attributes Reference

Expand Down

0 comments on commit 253d169

Please sign in to comment.