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