github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/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 }