github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/aws/resource_aws_iam_role.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  
     7  	"github.com/aws/aws-sdk-go/aws"
     8  	"github.com/aws/aws-sdk-go/aws/awserr"
     9  	"github.com/aws/aws-sdk-go/service/iam"
    10  
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func resourceAwsIamRole() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceAwsIamRoleCreate,
    17  		Read:   resourceAwsIamRoleRead,
    18  		Update: resourceAwsIamRoleUpdate,
    19  		Delete: resourceAwsIamRoleDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"arn": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Computed: true,
    25  			},
    26  			"unique_id": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Computed: true,
    29  			},
    30  			"name": &schema.Schema{
    31  				Type:     schema.TypeString,
    32  				Required: true,
    33  				ForceNew: true,
    34  				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    35  					// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8329-L8334
    36  					value := v.(string)
    37  					if len(value) > 64 {
    38  						errors = append(errors, fmt.Errorf(
    39  							"%q cannot be longer than 64 characters", k))
    40  					}
    41  					if !regexp.MustCompile("^[\\w+=,.@-]*$").MatchString(value) {
    42  						errors = append(errors, fmt.Errorf(
    43  							"%q must match [\\w+=,.@-]", k))
    44  					}
    45  					return
    46  				},
    47  			},
    48  			"path": &schema.Schema{
    49  				Type:     schema.TypeString,
    50  				Optional: true,
    51  				Default:  "/",
    52  				ForceNew: true,
    53  			},
    54  			"assume_role_policy": &schema.Schema{
    55  				Type:     schema.TypeString,
    56  				Required: true,
    57  			},
    58  		},
    59  	}
    60  }
    61  
    62  func resourceAwsIamRoleCreate(d *schema.ResourceData, meta interface{}) error {
    63  	iamconn := meta.(*AWSClient).iamconn
    64  	name := d.Get("name").(string)
    65  
    66  	request := &iam.CreateRoleInput{
    67  		Path:                     aws.String(d.Get("path").(string)),
    68  		RoleName:                 aws.String(name),
    69  		AssumeRolePolicyDocument: aws.String(d.Get("assume_role_policy").(string)),
    70  	}
    71  
    72  	createResp, err := iamconn.CreateRole(request)
    73  	if err != nil {
    74  		return fmt.Errorf("Error creating IAM Role %s: %s", name, err)
    75  	}
    76  	return resourceAwsIamRoleReadResult(d, createResp.Role)
    77  }
    78  
    79  func resourceAwsIamRoleRead(d *schema.ResourceData, meta interface{}) error {
    80  	iamconn := meta.(*AWSClient).iamconn
    81  
    82  	request := &iam.GetRoleInput{
    83  		RoleName: aws.String(d.Id()),
    84  	}
    85  
    86  	getResp, err := iamconn.GetRole(request)
    87  	if err != nil {
    88  		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" { // XXX test me
    89  			d.SetId("")
    90  			return nil
    91  		}
    92  		return fmt.Errorf("Error reading IAM Role %s: %s", d.Id(), err)
    93  	}
    94  	return resourceAwsIamRoleReadResult(d, getResp.Role)
    95  }
    96  func resourceAwsIamRoleUpdate(d *schema.ResourceData, meta interface{}) error {
    97  	iamconn := meta.(*AWSClient).iamconn
    98  
    99  	if d.HasChange("assume_role_policy") {
   100  		assumeRolePolicyInput := &iam.UpdateAssumeRolePolicyInput{
   101  			RoleName:       aws.String(d.Id()),
   102  			PolicyDocument: aws.String(d.Get("assume_role_policy").(string)),
   103  		}
   104  		_, err := iamconn.UpdateAssumeRolePolicy(assumeRolePolicyInput)
   105  		if err != nil {
   106  			if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
   107  				d.SetId("")
   108  				return nil
   109  			}
   110  			return fmt.Errorf("Error Updating IAM Role (%s) Assume Role Policy: %s", d.Id(), err)
   111  		}
   112  	}
   113  
   114  	return nil
   115  }
   116  
   117  func resourceAwsIamRoleReadResult(d *schema.ResourceData, role *iam.Role) error {
   118  	d.SetId(*role.RoleName)
   119  	if err := d.Set("name", role.RoleName); err != nil {
   120  		return err
   121  	}
   122  	if err := d.Set("arn", role.Arn); err != nil {
   123  		return err
   124  	}
   125  	if err := d.Set("path", role.Path); err != nil {
   126  		return err
   127  	}
   128  	if err := d.Set("unique_id", role.RoleId); err != nil {
   129  		return err
   130  	}
   131  	return nil
   132  }
   133  
   134  func resourceAwsIamRoleDelete(d *schema.ResourceData, meta interface{}) error {
   135  	iamconn := meta.(*AWSClient).iamconn
   136  
   137  	// Roles cannot be destroyed when attached to an existing Instance Profile
   138  	resp, err := iamconn.ListInstanceProfilesForRole(&iam.ListInstanceProfilesForRoleInput{
   139  		RoleName: aws.String(d.Id()),
   140  	})
   141  	if err != nil {
   142  		return fmt.Errorf("Error listing Profiles for IAM Role (%s) when trying to delete: %s", d.Id(), err)
   143  	}
   144  
   145  	// Loop and remove this Role from any Profiles
   146  	if len(resp.InstanceProfiles) > 0 {
   147  		for _, i := range resp.InstanceProfiles {
   148  			_, err := iamconn.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
   149  				InstanceProfileName: i.InstanceProfileName,
   150  				RoleName:            aws.String(d.Id()),
   151  			})
   152  			if err != nil {
   153  				return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err)
   154  			}
   155  		}
   156  	}
   157  
   158  	request := &iam.DeleteRoleInput{
   159  		RoleName: aws.String(d.Id()),
   160  	}
   161  
   162  	if _, err := iamconn.DeleteRole(request); err != nil {
   163  		return fmt.Errorf("Error deleting IAM Role %s: %s", d.Id(), err)
   164  	}
   165  	return nil
   166  }