github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/builtin/providers/aws/resource_aws_iam_instance_profile.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 resourceAwsIamInstanceProfile() *schema.Resource {
    15  	return &schema.Resource{
    16  		Create: resourceAwsIamInstanceProfileCreate,
    17  		Read:   resourceAwsIamInstanceProfileRead,
    18  		Update: resourceAwsIamInstanceProfileUpdate,
    19  		Delete: resourceAwsIamInstanceProfileDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"arn": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Computed: true,
    25  			},
    26  			"create_date": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Computed: true,
    29  			},
    30  			"unique_id": &schema.Schema{
    31  				Type:     schema.TypeString,
    32  				Computed: true,
    33  			},
    34  			"name": &schema.Schema{
    35  				Type:     schema.TypeString,
    36  				Required: true,
    37  				ForceNew: true,
    38  				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    39  					// https://github.com/boto/botocore/blob/2485f5c/botocore/data/iam/2010-05-08/service-2.json#L8196-L8201
    40  					value := v.(string)
    41  					if len(value) > 128 {
    42  						errors = append(errors, fmt.Errorf(
    43  							"%q cannot be longer than 128 characters", k))
    44  					}
    45  					if !regexp.MustCompile("^[\\w+=,.@-]+$").MatchString(value) {
    46  						errors = append(errors, fmt.Errorf(
    47  							"%q must match [\\w+=,.@-]", k))
    48  					}
    49  					return
    50  				},
    51  			},
    52  			"path": &schema.Schema{
    53  				Type:     schema.TypeString,
    54  				Optional: true,
    55  				Default:  "/",
    56  				ForceNew: true,
    57  			},
    58  			"roles": &schema.Schema{
    59  				Type:     schema.TypeSet,
    60  				Required: true,
    61  				Elem:     &schema.Schema{Type: schema.TypeString},
    62  				Set:      schema.HashString,
    63  			},
    64  		},
    65  	}
    66  }
    67  
    68  func resourceAwsIamInstanceProfileCreate(d *schema.ResourceData, meta interface{}) error {
    69  	iamconn := meta.(*AWSClient).iamconn
    70  	name := d.Get("name").(string)
    71  
    72  	request := &iam.CreateInstanceProfileInput{
    73  		InstanceProfileName: aws.String(name),
    74  		Path:                aws.String(d.Get("path").(string)),
    75  	}
    76  
    77  	var err error
    78  	response, err := iamconn.CreateInstanceProfile(request)
    79  	if err == nil {
    80  		err = instanceProfileReadResult(d, response.InstanceProfile)
    81  	}
    82  	if err != nil {
    83  		return fmt.Errorf("Error creating IAM instance profile %s: %s", name, err)
    84  	}
    85  
    86  	return instanceProfileSetRoles(d, iamconn)
    87  }
    88  
    89  func instanceProfileAddRole(iamconn *iam.IAM, profileName, roleName string) error {
    90  	request := &iam.AddRoleToInstanceProfileInput{
    91  		InstanceProfileName: aws.String(profileName),
    92  		RoleName:            aws.String(roleName),
    93  	}
    94  
    95  	_, err := iamconn.AddRoleToInstanceProfile(request)
    96  	return err
    97  }
    98  
    99  func instanceProfileRemoveRole(iamconn *iam.IAM, profileName, roleName string) error {
   100  	request := &iam.RemoveRoleFromInstanceProfileInput{
   101  		InstanceProfileName: aws.String(profileName),
   102  		RoleName:            aws.String(roleName),
   103  	}
   104  
   105  	_, err := iamconn.RemoveRoleFromInstanceProfile(request)
   106  	if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
   107  		return nil
   108  	}
   109  	return err
   110  }
   111  
   112  func instanceProfileSetRoles(d *schema.ResourceData, iamconn *iam.IAM) error {
   113  	oldInterface, newInterface := d.GetChange("roles")
   114  	oldRoles := oldInterface.(*schema.Set)
   115  	newRoles := newInterface.(*schema.Set)
   116  
   117  	currentRoles := schema.CopySet(oldRoles)
   118  
   119  	d.Partial(true)
   120  
   121  	for _, role := range oldRoles.Difference(newRoles).List() {
   122  		err := instanceProfileRemoveRole(iamconn, d.Id(), role.(string))
   123  		if err != nil {
   124  			return fmt.Errorf("Error removing role %s from IAM instance profile %s: %s", role, d.Id(), err)
   125  		}
   126  		currentRoles.Remove(role)
   127  		d.Set("roles", currentRoles)
   128  		d.SetPartial("roles")
   129  	}
   130  
   131  	for _, role := range newRoles.Difference(oldRoles).List() {
   132  		err := instanceProfileAddRole(iamconn, d.Id(), role.(string))
   133  		if err != nil {
   134  			return fmt.Errorf("Error adding role %s to IAM instance profile %s: %s", role, d.Id(), err)
   135  		}
   136  		currentRoles.Add(role)
   137  		d.Set("roles", currentRoles)
   138  		d.SetPartial("roles")
   139  	}
   140  
   141  	d.Partial(false)
   142  
   143  	return nil
   144  }
   145  
   146  func instanceProfileRemoveAllRoles(d *schema.ResourceData, iamconn *iam.IAM) error {
   147  	for _, role := range d.Get("roles").(*schema.Set).List() {
   148  		err := instanceProfileRemoveRole(iamconn, d.Id(), role.(string))
   149  		if err != nil {
   150  			return fmt.Errorf("Error removing role %s from IAM instance profile %s: %s", role, d.Id(), err)
   151  		}
   152  	}
   153  	return nil
   154  }
   155  
   156  func resourceAwsIamInstanceProfileUpdate(d *schema.ResourceData, meta interface{}) error {
   157  	iamconn := meta.(*AWSClient).iamconn
   158  
   159  	if !d.HasChange("roles") {
   160  		return nil
   161  	}
   162  
   163  	return instanceProfileSetRoles(d, iamconn)
   164  }
   165  
   166  func resourceAwsIamInstanceProfileRead(d *schema.ResourceData, meta interface{}) error {
   167  	iamconn := meta.(*AWSClient).iamconn
   168  
   169  	request := &iam.GetInstanceProfileInput{
   170  		InstanceProfileName: aws.String(d.Id()),
   171  	}
   172  
   173  	result, err := iamconn.GetInstanceProfile(request)
   174  	if err != nil {
   175  		if iamerr, ok := err.(awserr.Error); ok && iamerr.Code() == "NoSuchEntity" {
   176  			d.SetId("")
   177  			return nil
   178  		}
   179  		return fmt.Errorf("Error reading IAM instance profile %s: %s", d.Id(), err)
   180  	}
   181  
   182  	return instanceProfileReadResult(d, result.InstanceProfile)
   183  }
   184  
   185  func resourceAwsIamInstanceProfileDelete(d *schema.ResourceData, meta interface{}) error {
   186  	iamconn := meta.(*AWSClient).iamconn
   187  
   188  	if err := instanceProfileRemoveAllRoles(d, iamconn); err != nil {
   189  		return err
   190  	}
   191  
   192  	request := &iam.DeleteInstanceProfileInput{
   193  		InstanceProfileName: aws.String(d.Id()),
   194  	}
   195  	_, err := iamconn.DeleteInstanceProfile(request)
   196  	if err != nil {
   197  		return fmt.Errorf("Error deleting IAM instance profile %s: %s", d.Id(), err)
   198  	}
   199  	d.SetId("")
   200  	return nil
   201  }
   202  
   203  func instanceProfileReadResult(d *schema.ResourceData, result *iam.InstanceProfile) error {
   204  	d.SetId(*result.InstanceProfileName)
   205  	if err := d.Set("name", result.InstanceProfileName); err != nil {
   206  		return err
   207  	}
   208  	if err := d.Set("arn", result.Arn); err != nil {
   209  		return err
   210  	}
   211  	if err := d.Set("path", result.Path); err != nil {
   212  		return err
   213  	}
   214  
   215  	roles := &schema.Set{F: schema.HashString}
   216  	for _, role := range result.Roles {
   217  		roles.Add(*role.RoleName)
   218  	}
   219  	if err := d.Set("roles", roles); err != nil {
   220  		return err
   221  	}
   222  
   223  	return nil
   224  }