github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/aws/resource_aws_emr_instance_group.go (about)

     1  package aws
     2  
     3  import (
     4  	"errors"
     5  	"log"
     6  	"time"
     7  
     8  	"fmt"
     9  
    10  	"github.com/aws/aws-sdk-go/aws"
    11  	"github.com/aws/aws-sdk-go/service/emr"
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  )
    15  
    16  var emrInstanceGroupNotFound = errors.New("No matching EMR Instance Group")
    17  
    18  func resourceAwsEMRInstanceGroup() *schema.Resource {
    19  	return &schema.Resource{
    20  		Create: resourceAwsEMRInstanceGroupCreate,
    21  		Read:   resourceAwsEMRInstanceGroupRead,
    22  		Update: resourceAwsEMRInstanceGroupUpdate,
    23  		Delete: resourceAwsEMRInstanceGroupDelete,
    24  		Schema: map[string]*schema.Schema{
    25  			"cluster_id": &schema.Schema{
    26  				Type:     schema.TypeString,
    27  				Required: true,
    28  				ForceNew: true,
    29  			},
    30  			"instance_type": &schema.Schema{
    31  				Type:     schema.TypeString,
    32  				Required: true,
    33  				ForceNew: true,
    34  			},
    35  			"instance_count": &schema.Schema{
    36  				Type:     schema.TypeInt,
    37  				Optional: true,
    38  				Default:  0,
    39  			},
    40  			"running_instance_count": &schema.Schema{
    41  				Type:     schema.TypeInt,
    42  				Computed: true,
    43  			},
    44  			"status": &schema.Schema{
    45  				Type:     schema.TypeString,
    46  				Computed: true,
    47  			},
    48  			"name": &schema.Schema{
    49  				Type:     schema.TypeString,
    50  				Optional: true,
    51  				ForceNew: true,
    52  			},
    53  		},
    54  	}
    55  }
    56  
    57  func resourceAwsEMRInstanceGroupCreate(d *schema.ResourceData, meta interface{}) error {
    58  	conn := meta.(*AWSClient).emrconn
    59  
    60  	clusterId := d.Get("cluster_id").(string)
    61  	instanceType := d.Get("instance_type").(string)
    62  	instanceCount := d.Get("instance_count").(int)
    63  	groupName := d.Get("name").(string)
    64  
    65  	params := &emr.AddInstanceGroupsInput{
    66  		InstanceGroups: []*emr.InstanceGroupConfig{
    67  			{
    68  				InstanceRole:  aws.String("TASK"),
    69  				InstanceCount: aws.Int64(int64(instanceCount)),
    70  				InstanceType:  aws.String(instanceType),
    71  				Name:          aws.String(groupName),
    72  			},
    73  		},
    74  		JobFlowId: aws.String(clusterId),
    75  	}
    76  
    77  	log.Printf("[DEBUG] Creating EMR task group params: %s", params)
    78  	resp, err := conn.AddInstanceGroups(params)
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	log.Printf("[DEBUG] Created EMR task group finished: %#v", resp)
    84  	if resp == nil || len(resp.InstanceGroupIds) == 0 {
    85  		return fmt.Errorf("Error creating instance groups: no instance group returned")
    86  	}
    87  	d.SetId(*resp.InstanceGroupIds[0])
    88  
    89  	return nil
    90  }
    91  
    92  func resourceAwsEMRInstanceGroupRead(d *schema.ResourceData, meta interface{}) error {
    93  	group, err := fetchEMRInstanceGroup(meta, d.Get("cluster_id").(string), d.Id())
    94  	if err != nil {
    95  		switch err {
    96  		case emrInstanceGroupNotFound:
    97  			log.Printf("[DEBUG] EMR Instance Group (%s) not found, removing", d.Id())
    98  			d.SetId("")
    99  			return nil
   100  		default:
   101  			return err
   102  		}
   103  	}
   104  
   105  	// Guard against the chance of fetchEMRInstanceGroup returning nil group but
   106  	// not a emrInstanceGroupNotFound error
   107  	if group == nil {
   108  		log.Printf("[DEBUG] EMR Instance Group (%s) not found, removing", d.Id())
   109  		d.SetId("")
   110  		return nil
   111  	}
   112  
   113  	d.Set("name", group.Name)
   114  	d.Set("instance_count", group.RequestedInstanceCount)
   115  	d.Set("running_instance_count", group.RunningInstanceCount)
   116  	d.Set("instance_type", group.InstanceType)
   117  	if group.Status != nil && group.Status.State != nil {
   118  		d.Set("status", group.Status.State)
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  func fetchAllEMRInstanceGroups(meta interface{}, clusterId string) ([]*emr.InstanceGroup, error) {
   125  	conn := meta.(*AWSClient).emrconn
   126  	req := &emr.ListInstanceGroupsInput{
   127  		ClusterId: aws.String(clusterId),
   128  	}
   129  
   130  	var groups []*emr.InstanceGroup
   131  	marker := aws.String("intitial")
   132  	for marker != nil {
   133  		log.Printf("[DEBUG] EMR Cluster Instance Marker: %s", *marker)
   134  		respGrps, errGrps := conn.ListInstanceGroups(req)
   135  		if errGrps != nil {
   136  			return nil, fmt.Errorf("[ERR] Error reading EMR cluster (%s): %s", clusterId, errGrps)
   137  		}
   138  		if respGrps == nil {
   139  			return nil, fmt.Errorf("[ERR] Error reading EMR Instance Group for cluster (%s)", clusterId)
   140  		}
   141  
   142  		if respGrps.InstanceGroups != nil {
   143  			for _, g := range respGrps.InstanceGroups {
   144  				groups = append(groups, g)
   145  			}
   146  		} else {
   147  			log.Printf("[DEBUG] EMR Instance Group list was empty")
   148  		}
   149  		marker = respGrps.Marker
   150  	}
   151  
   152  	if len(groups) == 0 {
   153  		return nil, fmt.Errorf("[WARN] No instance groups found for EMR Cluster (%s)", clusterId)
   154  	}
   155  
   156  	return groups, nil
   157  }
   158  
   159  func fetchEMRInstanceGroup(meta interface{}, clusterId, groupId string) (*emr.InstanceGroup, error) {
   160  	groups, err := fetchAllEMRInstanceGroups(meta, clusterId)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	var group *emr.InstanceGroup
   166  	for _, ig := range groups {
   167  		if groupId == *ig.Id {
   168  			group = ig
   169  			break
   170  		}
   171  	}
   172  
   173  	if group != nil {
   174  		return group, nil
   175  	}
   176  
   177  	return nil, emrInstanceGroupNotFound
   178  }
   179  
   180  func resourceAwsEMRInstanceGroupUpdate(d *schema.ResourceData, meta interface{}) error {
   181  	conn := meta.(*AWSClient).emrconn
   182  
   183  	log.Printf("[DEBUG] Modify EMR task group")
   184  	instanceCount := d.Get("instance_count").(int)
   185  
   186  	params := &emr.ModifyInstanceGroupsInput{
   187  		InstanceGroups: []*emr.InstanceGroupModifyConfig{
   188  			{
   189  				InstanceGroupId: aws.String(d.Id()),
   190  				InstanceCount:   aws.Int64(int64(instanceCount)),
   191  			},
   192  		},
   193  	}
   194  
   195  	_, err := conn.ModifyInstanceGroups(params)
   196  	if err != nil {
   197  		return err
   198  	}
   199  
   200  	stateConf := &resource.StateChangeConf{
   201  		Pending:    []string{"PROVISIONING", "BOOTSTRAPPING", "RESIZING"},
   202  		Target:     []string{"RUNNING"},
   203  		Refresh:    instanceGroupStateRefresh(conn, d.Get("cluster_id").(string), d.Id()),
   204  		Timeout:    10 * time.Minute,
   205  		Delay:      10 * time.Second,
   206  		MinTimeout: 3 * time.Second,
   207  	}
   208  
   209  	_, err = stateConf.WaitForState()
   210  	if err != nil {
   211  		return fmt.Errorf(
   212  			"Error waiting for instance (%s) to terminate: %s", d.Id(), err)
   213  	}
   214  
   215  	return resourceAwsEMRInstanceGroupRead(d, meta)
   216  }
   217  
   218  func instanceGroupStateRefresh(meta interface{}, clusterID, igID string) resource.StateRefreshFunc {
   219  	return func() (interface{}, string, error) {
   220  		group, err := fetchEMRInstanceGroup(meta, clusterID, igID)
   221  		if err != nil {
   222  			return nil, "Not Found", err
   223  		}
   224  
   225  		if group.Status == nil || group.Status.State == nil {
   226  			log.Printf("[WARN] ERM Instance Group found, but without state")
   227  			return nil, "Undefined", fmt.Errorf("Undefined EMR Cluster Instance Group state")
   228  		}
   229  
   230  		return group, *group.Status.State, nil
   231  	}
   232  }
   233  
   234  func resourceAwsEMRInstanceGroupDelete(d *schema.ResourceData, meta interface{}) error {
   235  	log.Printf("[WARN] AWS EMR Instance Group does not support DELETE; resizing cluster to zero before removing from state")
   236  	conn := meta.(*AWSClient).emrconn
   237  	params := &emr.ModifyInstanceGroupsInput{
   238  		InstanceGroups: []*emr.InstanceGroupModifyConfig{
   239  			{
   240  				InstanceGroupId: aws.String(d.Id()),
   241  				InstanceCount:   aws.Int64(0),
   242  			},
   243  		},
   244  	}
   245  
   246  	_, err := conn.ModifyInstanceGroups(params)
   247  	if err != nil {
   248  		return err
   249  	}
   250  	return nil
   251  }