Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow importing of aws_iam_role, aws_iam_role_policy, aws_iam_policy and aws_iam_instance_profile. #9398

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions builtin/providers/aws/import_aws_iam_instance_profile_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package aws

import (
"testing"

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccAWSIAMInstanceProfile_importBasic(t *testing.T) {
resourceName := "aws_iam_instance_profile.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSInstanceProfileDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAwsIamInstanceProfileConfig,
},

resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
88 changes: 88 additions & 0 deletions builtin/providers/aws/import_aws_iam_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package aws

import (
"fmt"
"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 testAccAwsIamPolicyConfig(suffix string) string {
return fmt.Sprintf(`
resource "aws_iam_policy" "test_%[1]s" {
name = "test_policy_%[1]s"
path = "/"
description = "My test policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"ec2:Describe*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
EOF
}
`, suffix)
}

func TestAccAWSIAMPolicy_importBasic(t *testing.T) {
suffix := randomString(10)
resourceName := fmt.Sprintf("aws_iam_policy.test_%s", suffix)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSPolicyDestroy,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should jsut use the same Destroy method as defined in iam_user_test.go testAccCheckAWSUserDestroy

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one destroys aws_iam_policy, whereas the function you refer to destroys aws_iam_user.

Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAwsIamPolicyConfig(suffix),
},

resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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 group
_, err := iamconn.GetPolicy(&iam.GetPolicyInput{
PolicyArn: aws.String(rs.Primary.ID),
})
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
}
55 changes: 55 additions & 0 deletions builtin/providers/aws/import_aws_iam_role_policy_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package aws

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/resource"
)

func testAccAwsIamRolePolicyConfig(suffix string) string {
return fmt.Sprintf(`
resource "aws_iam_role" "role_%[1]s" {
name = "tf_test_role_test_%[1]s"
path = "/"
assume_role_policy = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"ec2.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does a heredoc affect how the import works here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not; would you like me to make this a heredoc?

}

resource "aws_iam_role_policy" "foo_%[1]s" {
name = "tf_test_policy_test_%[1]s"
role = "${aws_iam_role.role_%[1]s.name}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
}
EOF
}
`, suffix)
}

func TestAccAWSIAMRolePolicy_importBasic(t *testing.T) {
suffix := randomString(10)
resourceName := fmt.Sprintf("aws_iam_role_policy.foo_%s", suffix)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckIAMRolePolicyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAwsIamRolePolicyConfig(suffix),
},

resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
28 changes: 28 additions & 0 deletions builtin/providers/aws/import_aws_iam_role_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package aws

import (
"testing"

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccAWSIAMRole_importBasic(t *testing.T) {
resourceName := "aws_iam_role.role"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSRoleDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSRoleConfig,
},

resource.TestStep{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}
3 changes: 3 additions & 0 deletions builtin/providers/aws/resource_aws_iam_instance_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ func resourceAwsIamInstanceProfile() *schema.Resource {
Read: resourceAwsIamInstanceProfileRead,
Update: resourceAwsIamInstanceProfileUpdate,
Delete: resourceAwsIamInstanceProfileDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"arn": &schema.Schema{
Expand Down
47 changes: 36 additions & 11 deletions builtin/providers/aws/resource_aws_iam_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package aws

import (
"fmt"
"net/url"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
Expand All @@ -16,6 +17,9 @@ func resourceAwsIamPolicy() *schema.Resource {
Read: resourceAwsIamPolicyRead,
Update: resourceAwsIamPolicyUpdate,
Delete: resourceAwsIamPolicyDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"description": &schema.Schema{
Expand All @@ -30,8 +34,9 @@ func resourceAwsIamPolicy() *schema.Resource {
ForceNew: true,
},
"policy": &schema.Schema{
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},
"name": &schema.Schema{
Type: schema.TypeString,
Expand Down Expand Up @@ -68,11 +73,11 @@ func resourceAwsIamPolicyCreate(d *schema.ResourceData, meta interface{}) error
func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error {
iamconn := meta.(*AWSClient).iamconn

request := &iam.GetPolicyInput{
getPolicyRequest := &iam.GetPolicyInput{
PolicyArn: aws.String(d.Id()),
}

response, err := iamconn.GetPolicy(request)
getPolicyResponse, err := iamconn.GetPolicy(getPolicyRequest)
if err != nil {
if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
d.SetId("")
Expand All @@ -81,7 +86,29 @@ func resourceAwsIamPolicyRead(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("Error reading IAM policy %s: %s", d.Id(), err)
}

return readIamPolicy(d, response.Policy)
getPolicyVersionRequest := &iam.GetPolicyVersionInput{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we looking for a specific policy version? This is a new code path that wasn't in use before

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're looking for the DefaulVersionId from the response to GetPolicy.

PolicyArn: aws.String(d.Id()),
VersionId: getPolicyResponse.Policy.DefaultVersionId,
}

getPolicyVersionResponse, err := iamconn.GetPolicyVersion(getPolicyVersionRequest)
if err != nil {
if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
d.SetId("")
return nil
}
return fmt.Errorf("Error reading IAM policy version %s: %s", d.Id(), err)
}

policy, err := url.QueryUnescape(*getPolicyVersionResponse.PolicyVersion.Document)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why queryunescape? What is this doing for us?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err != nil {
return err
}
if err := d.Set("policy", policy); err != nil {
return err
}

return readIamPolicy(d, getPolicyResponse.Policy)
}

func resourceAwsIamPolicyUpdate(d *schema.ResourceData, meta interface{}) error {
Expand Down Expand Up @@ -208,20 +235,18 @@ func readIamPolicy(d *schema.ResourceData, policy *iam.Policy) error {
d.SetId(*policy.Arn)
if policy.Description != nil {
// the description isn't present in the response to CreatePolicy.
if err := d.Set("description", *policy.Description); err != nil {
if err := d.Set("description", policy.Description); err != nil {
return err
}
}
if err := d.Set("path", *policy.Path); err != nil {
if err := d.Set("path", policy.Path); err != nil {
return err
}
if err := d.Set("name", *policy.PolicyName); err != nil {
if err := d.Set("name", policy.PolicyName); err != nil {
return err
}
if err := d.Set("arn", *policy.Arn); err != nil {
if err := d.Set("arn", policy.Arn); err != nil {
return err
}
// TODO: set policy

return nil
}
16 changes: 14 additions & 2 deletions builtin/providers/aws/resource_aws_iam_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package aws

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

Expand All @@ -19,6 +20,9 @@ func resourceAwsIamRole() *schema.Resource {
Read: resourceAwsIamRoleRead,
Update: resourceAwsIamRoleUpdate,
Delete: resourceAwsIamRoleDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"arn": &schema.Schema{
Expand Down Expand Up @@ -79,8 +83,9 @@ func resourceAwsIamRole() *schema.Resource {
},

"assume_role_policy": &schema.Schema{
Type: schema.TypeString,
Required: true,
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: suppressEquivalentAwsPolicyDiffs,
},
},
}
Expand Down Expand Up @@ -174,6 +179,13 @@ func resourceAwsIamRoleReadResult(d *schema.ResourceData, role *iam.Role) error
if err := d.Set("unique_id", role.RoleId); err != nil {
return err
}
assumRolePolicy, err := url.QueryUnescape(*role.AssumeRolePolicyDocument)
if err != nil {
return err
}
if err := d.Set("assume_role_policy", assumRolePolicy); err != nil {
return err
}
return nil
}

Expand Down
Loading