func resource_aws_route_table_association_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	rs := s.MergeDiff(d)
	log.Printf(
		"[INFO] Replacing route table association: %s => %s",
		rs.Attributes["subnet_id"],
		rs.Attributes["route_table_id"])
	resp, err := ec2conn.ReassociateRouteTable(
		rs.ID,
		rs.Attributes["route_table_id"])
	if err != nil {
		ec2err, ok := err.(*ec2.Error)
		if ok && ec2err.Code == "InvalidAssociationID.NotFound" {
			// Not found, so just create a new one
			return resource_aws_route_table_association_create(s, d, meta)
		}

		return s, err
	}

	// Update the ID
	rs.ID = resp.AssociationId
	log.Printf("[INFO] Association ID: %s", rs.ID)

	rs.Dependencies = []terraform.ResourceDependency{
		terraform.ResourceDependency{ID: rs.Attributes["route_table_id"]},
	}

	return rs, nil
}
func resource_aws_instance_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn
	rs := s.MergeDiff(d)

	modify := false
	opts := new(ec2.ModifyInstance)

	if attr, ok := d.Attributes["source_dest_check"]; ok {
		modify = true
		opts.SourceDestCheck = attr.New != "" && attr.New != "false"
		opts.SetSourceDestCheck = true
		rs.Attributes["source_dest_check"] = strconv.FormatBool(
			opts.SourceDestCheck)
	}

	if modify {
		log.Printf("[INFO] Modifing instance %s: %#v", s.ID, opts)
		if _, err := ec2conn.ModifyInstance(s.ID, opts); err != nil {
			return s, err
		}

		// TODO(mitchellh): wait for the attributes we modified to
		// persist the change...
	}

	return rs, nil
}
func resource_heroku_addon_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client
	rs := s.MergeDiff(d)

	app := rs.Attributes["app"]

	if attr, ok := d.Attributes["plan"]; ok {
		ad, err := client.AddonUpdate(
			app, rs.ID,
			attr.New)

		if err != nil {
			return s, err
		}

		// Store the new ID
		rs.ID = ad.Id
	}

	addon, err := resource_heroku_addon_retrieve(app, rs.ID, client)

	if err != nil {
		return rs, err
	}

	return resource_heroku_addon_update_state(rs, addon)
}
func resource_heroku_domain_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	app := rs.Attributes["app"]
	hostname := rs.Attributes["hostname"]

	log.Printf("[DEBUG] Domain create configuration: %#v, %#v", app, hostname)

	do, err := client.DomainCreate(app, hostname)

	if err != nil {
		return s, err
	}

	rs.ID = do.Id
	rs.Attributes["hostname"] = do.Hostname
	rs.Attributes["cname"] = fmt.Sprintf("%s.herokuapp.com", app)

	log.Printf("[INFO] Domain ID: %s", rs.ID)

	return rs, nil
}
func resource_heroku_drain_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	app := rs.Attributes["app"]
	url := rs.Attributes["url"]

	log.Printf("[DEBUG] Drain create configuration: %#v, %#v", app, url)

	dr, err := client.LogDrainCreate(app, url)

	if err != nil {
		return s, err
	}

	rs.ID = dr.Id
	rs.Attributes["url"] = dr.URL
	rs.Attributes["token"] = dr.Token

	log.Printf("[INFO] Drain ID: %s", rs.ID)

	return rs, nil
}
func resource_digitalocean_domain_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client
	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	// Build up our creation options
	opts := digitalocean.CreateDomain{
		Name:      rs.Attributes["name"],
		IPAddress: rs.Attributes["ip_address"],
	}

	log.Printf("[DEBUG] Domain create configuration: %#v", opts)

	name, err := client.CreateDomain(&opts)
	if err != nil {
		return nil, fmt.Errorf("Error creating Domain: %s", err)
	}

	rs.ID = name
	log.Printf("[INFO] Domain Name: %s", name)

	return rs, nil
}
func resource_aws_s3_bucket_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	s3conn := p.s3conn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	// Get the bucket and optional acl
	bucket := rs.Attributes["bucket"]
	acl := "private"
	if other, ok := rs.Attributes["acl"]; ok {
		acl = other
	}

	log.Printf("[DEBUG] S3 bucket create: %s, ACL: %s", bucket, acl)
	s3Bucket := s3conn.Bucket(bucket)
	err := s3Bucket.PutBucket(s3.ACL(acl))
	if err != nil {
		return nil, fmt.Errorf("Error creating S3 bucket: %s", err)
	}

	// Assign the bucket name as the resource ID
	rs.ID = bucket
	return rs, nil
}
func resource_aws_route_table_association_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn
	rs := s.MergeDiff(d)

	log.Printf(
		"[INFO] Creating route table association: %s => %s",
		rs.Attributes["subnet_id"],
		rs.Attributes["route_table_id"])
	resp, err := ec2conn.AssociateRouteTable(
		rs.Attributes["route_table_id"],
		rs.Attributes["subnet_id"])
	if err != nil {
		return nil, err
	}

	// Set the ID and return
	rs.ID = resp.AssociationId
	log.Printf("[INFO] Association ID: %s", rs.ID)

	rs.Dependencies = []terraform.ResourceDependency{
		terraform.ResourceDependency{ID: rs.Attributes["route_table_id"]},
	}

	return rs, nil
}
func resource_digitalocean_record_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client
	rs := s.MergeDiff(d)

	updateRecord := digitalocean.UpdateRecord{}

	if attr, ok := d.Attributes["name"]; ok {
		updateRecord.Name = attr.New
	}

	log.Printf("[DEBUG] record update configuration: %#v", updateRecord)

	err := client.UpdateRecord(rs.Attributes["domain"], rs.ID, &updateRecord)
	if err != nil {
		return rs, fmt.Errorf("Failed to update record: %s", err)
	}

	record, err := resource_digitalocean_record_retrieve(rs.Attributes["domain"], rs.ID, client)
	if err != nil {
		return rs, fmt.Errorf("Couldn't find record: %s", err)
	}

	return resource_digitalocean_record_update_state(rs, record)
}
func resource_cloudflare_record_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client
	rs := s.MergeDiff(d)

	// Cloudflare requires we send all values
	// for an update request, so we just
	// merge out diff and send the current
	// state of affairs to them
	updateRecord := cloudflare.UpdateRecord{
		Name:     rs.Attributes["name"],
		Content:  rs.Attributes["value"],
		Type:     rs.Attributes["type"],
		Ttl:      rs.Attributes["ttl"],
		Priority: rs.Attributes["priority"],
	}

	log.Printf("[DEBUG] record update configuration: %#v", updateRecord)

	err := client.UpdateRecord(rs.Attributes["domain"], rs.ID, &updateRecord)
	if err != nil {
		return rs, fmt.Errorf("Failed to update record: %s", err)
	}

	record, err := resource_cloudflare_record_retrieve(rs.Attributes["domain"], rs.ID, client)
	if err != nil {
		return rs, fmt.Errorf("Couldn't find record: %s", err)
	}

	return resource_cloudflare_record_update_state(rs, record)
}
func resource_aws_subnet_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff so that we have all the proper attributes
	s = s.MergeDiff(d)

	// Create the Subnet
	createOpts := &ec2.CreateSubnet{
		AvailabilityZone: s.Attributes["availability_zone"],
		CidrBlock:        s.Attributes["cidr_block"],
		VpcId:            s.Attributes["vpc_id"],
	}
	log.Printf("[DEBUG] Subnet create config: %#v", createOpts)
	resp, err := ec2conn.CreateSubnet(createOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating subnet: %s", err)
	}

	// Get the ID and store it
	subnet := &resp.Subnet
	s.ID = subnet.SubnetId
	log.Printf("[INFO] Subnet ID: %s", s.ID)

	// Wait for the Subnet to become available
	log.Printf(
		"[DEBUG] Waiting for subnet (%s) to become available",
		s.ID)
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "available",
		Refresh: SubnetStateRefreshFunc(ec2conn, s.ID),
		Timeout: 10 * time.Minute,
	}
	subnetRaw, err := stateConf.WaitForState()
	if err != nil {
		return s, fmt.Errorf(
			"Error waiting for subnet (%s) to become available: %s",
			s.ID, err)
	}

	// Map public ip on launch must be set in another API call
	if attr := s.Attributes["map_public_ip_on_launch"]; attr == "true" {
		modifyOpts := &ec2.ModifySubnetAttribute{
			SubnetId:            s.ID,
			MapPublicIpOnLaunch: true,
		}
		log.Printf("[DEBUG] Subnet modify attributes: %#v", modifyOpts)
		_, err := ec2conn.ModifySubnetAttribute(modifyOpts)
		if err != nil {
			return nil, fmt.Errorf("Error modify subnet attributes: %s", err)
		}
	}

	// Update our attributes and return
	return resource_aws_subnet_update_state(s, subnetRaw.(*ec2.Subnet))
}
func resource_aws_internet_gateway_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff so we have the latest attributes
	rs := s.MergeDiff(d)

	// A note on the states below: the AWS docs (as of July, 2014) say
	// that the states would be: attached, attaching, detached, detaching,
	// but when running, I noticed that the state is usually "available" when
	// it is attached.

	// If we're already attached, detach it first
	if err := resource_aws_internet_gateway_detach(ec2conn, s); err != nil {
		return s, err
	}

	// Set the VPC ID to empty since we're detached at this point
	delete(rs.Attributes, "vpc_id")

	if attr, ok := d.Attributes["vpc_id"]; ok && attr.New != "" {
		err := resource_aws_internet_gateway_attach(ec2conn, s, attr.New)
		if err != nil {
			return rs, err
		}

		rs.Attributes["vpc_id"] = attr.New
	}

	return resource_aws_internet_gateway_update_state(rs, nil)
}
func resource_openstack_compute_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {

	p := meta.(*ResourceProvider)
	client := p.client

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	serversApi, err := gophercloud.ServersApi(client.AccessProvider, gophercloud.ApiCriteria{
		Name:      "nova",
		UrlChoice: gophercloud.PublicURL,
	})
	if err != nil {
		return nil, err
	}

	if attr, ok := d.Attributes["name"]; ok {
		_, err := serversApi.UpdateServer(rs.ID, gophercloud.NewServerSettings{
			Name: attr.New,
		})

		if err != nil {
			return nil, err
		}

		rs.Attributes["name"] = attr.New
	}

	if attr, ok := d.Attributes["flavor_ref"]; ok {
		err := serversApi.ResizeServer(rs.Attributes["id"], rs.Attributes["name"], attr.New, "")

		if err != nil {
			return nil, err
		}

		stateConf := &resource.StateChangeConf{
			Pending:    []string{"ACTIVE"},
			Target:     "VERIFY_RESIZE",
			Refresh:    WaitForServerState(serversApi, rs.Attributes["id"]),
			Timeout:    10 * time.Minute,
			Delay:      10 * time.Second,
			MinTimeout: 3 * time.Second,
		}

		_, err = stateConf.WaitForState()

		if err != nil {
			return nil, err
		}

		err = serversApi.ConfirmResize(rs.Attributes["id"])
	}

	return rs, nil
}
func resource_aws_launch_configuration_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	autoscalingconn := p.autoscalingconn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	var err error
	createLaunchConfigurationOpts := autoscaling.CreateLaunchConfiguration{}

	if rs.Attributes["image_id"] != "" {
		createLaunchConfigurationOpts.ImageId = rs.Attributes["image_id"]
	}

	if rs.Attributes["instance_type"] != "" {
		createLaunchConfigurationOpts.InstanceType = rs.Attributes["instance_type"]
	}

	if rs.Attributes["instance_id"] != "" {
		createLaunchConfigurationOpts.InstanceId = rs.Attributes["instance_id"]
	}

	if rs.Attributes["key_name"] != "" {
		createLaunchConfigurationOpts.KeyName = rs.Attributes["key_name"]
	}

	if err != nil {
		return nil, fmt.Errorf("Error parsing configuration: %s", err)
	}

	if _, ok := rs.Attributes["security_groups.#"]; ok {
		createLaunchConfigurationOpts.SecurityGroups = expandStringList(flatmap.Expand(
			rs.Attributes, "security_groups").([]interface{}))
	}

	createLaunchConfigurationOpts.Name = rs.Attributes["name"]

	log.Printf("[DEBUG] autoscaling create launch configuration: %#v", createLaunchConfigurationOpts)
	_, err = autoscalingconn.CreateLaunchConfiguration(&createLaunchConfigurationOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating launch configuration: %s", err)
	}

	rs.ID = rs.Attributes["name"]

	log.Printf("[INFO] launch configuration ID: %s", rs.ID)

	g, err := resource_aws_launch_configuration_retrieve(rs.ID, autoscalingconn)
	if err != nil {
		return rs, err
	}

	return resource_aws_launch_configuration_update_state(rs, g)
}
func resource_aws_r53_record_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	conn := p.route53

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	// Get the record
	rec, err := resource_aws_r53_build_record_set(rs)
	if err != nil {
		return rs, err
	}

	// Create the new records
	req := &route53.ChangeResourceRecordSetsRequest{
		Comment: "Managed by Terraform",
		Changes: []route53.Change{
			route53.Change{
				Action: "UPSERT",
				Record: *rec,
			},
		},
	}
	zone := rs.Attributes["zone_id"]
	log.Printf("[DEBUG] Creating resource records for zone: %s, name: %s",
		zone, rs.Attributes["name"])
	resp, err := conn.ChangeResourceRecordSets(zone, req)
	if err != nil {
		return rs, err
	}

	// Generate an ID
	rs.ID = fmt.Sprintf("%s_%s_%s", zone, rs.Attributes["name"], rs.Attributes["type"])
	rs.Dependencies = []terraform.ResourceDependency{
		terraform.ResourceDependency{ID: zone},
	}

	// Wait until we are done
	wait := resource.StateChangeConf{
		Delay:      30 * time.Second,
		Pending:    []string{"PENDING"},
		Target:     "INSYNC",
		Timeout:    10 * time.Minute,
		MinTimeout: 5 * time.Second,
		Refresh: func() (result interface{}, state string, err error) {
			return resource_aws_r53_wait(conn, resp.ChangeInfo.ID)
		},
	}
	_, err = wait.WaitForState()
	if err != nil {
		return rs, err
	}
	return rs, nil
}
func resource_heroku_app_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	// Build up our creation options
	opts := heroku.AppCreateOpts{}

	if attr := rs.Attributes["name"]; attr != "" {
		opts.Name = &attr
	}

	if attr := rs.Attributes["region"]; attr != "" {
		opts.Region = &attr
	}

	if attr := rs.Attributes["stack"]; attr != "" {
		opts.Stack = &attr
	}

	log.Printf("[DEBUG] App create configuration: %#v", opts)

	a, err := client.AppCreate(&opts)
	if err != nil {
		return s, err
	}

	rs.ID = a.Name
	log.Printf("[INFO] App ID: %s", rs.ID)

	if attr, ok := rs.Attributes["config_vars.#"]; ok && attr == "1" {
		vs := flatmap.Expand(
			rs.Attributes, "config_vars").([]interface{})

		err = update_config_vars(rs.ID, vs, client)
		if err != nil {
			return rs, err
		}
	}

	app, err := resource_heroku_app_retrieve(rs.ID, client)
	if err != nil {
		return rs, err
	}

	return resource_heroku_app_update_state(rs, app)
}
func resource_heroku_app_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client
	rs := s.MergeDiff(d)

	if attr, ok := d.Attributes["name"]; ok {
		opts := heroku.AppUpdateOpts{
			Name: &attr.New,
		}

		renamedApp, err := client.AppUpdate(rs.ID, &opts)

		if err != nil {
			return s, err
		}

		// Store the new ID
		rs.ID = renamedApp.Name
	}

	attr, ok := s.Attributes["config_vars.#"]

	// If the config var block was removed, nuke all config vars
	if ok && attr == "1" {
		vs := flatmap.Expand(
			rs.Attributes, "config_vars").([]interface{})

		err := update_config_vars(rs.ID, vs, client)
		if err != nil {
			return rs, err
		}
	} else if ok && attr == "0" {
		log.Println("[INFO] Config vars removed, removing all vars")

		err := update_config_vars(rs.ID, make([]interface{}, 0), client)

		if err != nil {
			return rs, err
		}
	}

	app, err := resource_heroku_app_retrieve(rs.ID, client)
	if err != nil {
		return rs, err
	}

	return resource_heroku_app_update_state(rs, app)
}
func resource_heroku_addon_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	addonLock.Lock()
	defer addonLock.Unlock()

	p := meta.(*ResourceProvider)
	client := p.client

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	app := rs.Attributes["app"]
	plan := rs.Attributes["plan"]
	opts := heroku.AddonCreateOpts{}

	if attr, ok := rs.Attributes["config.#"]; ok && attr == "1" {
		vs := flatmap.Expand(
			rs.Attributes, "config").([]interface{})

		config := make(map[string]string)
		for k, v := range vs[0].(map[string]interface{}) {
			config[k] = v.(string)
		}

		opts.Config = &config
	}

	log.Printf("[DEBUG] Addon create configuration: %#v, %#v, %#v", app, plan, opts)

	a, err := client.AddonCreate(app, plan, &opts)

	if err != nil {
		return s, err
	}

	rs.ID = a.Id
	log.Printf("[INFO] Addon ID: %s", rs.ID)

	addon, err := resource_heroku_addon_retrieve(app, rs.ID, client)
	if err != nil {
		return rs, err
	}

	return resource_heroku_addon_update_state(rs, addon)
}
func resource_aws_eip_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	// By default, we're not in a VPC
	vpc := false
	domainOpt := ""
	if rs.Attributes["vpc"] == "true" {
		vpc = true
		domainOpt = "vpc"
	}

	allocOpts := ec2.AllocateAddress{
		Domain: domainOpt,
	}

	log.Printf("[DEBUG] EIP create configuration: %#v", allocOpts)
	allocResp, err := ec2conn.AllocateAddress(&allocOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating EIP: %s", err)
	}

	// Assign the eips (unique) allocation id for use later
	// the EIP api has a conditional unique ID (really), so
	// if we're in a VPC we need to save the ID as such, otherwise
	// it defaults to using the public IP
	log.Printf("[DEBUG] EIP Allocate: %#v", allocResp)
	if allocResp.AllocationId != "" {
		rs.ID = allocResp.AllocationId
		rs.Attributes["vpc"] = "true"

	} else {
		rs.ID = allocResp.PublicIp
	}

	log.Printf("[INFO] EIP ID: %s (vpc: %v)", rs.ID, vpc)

	return resource_aws_eip_update(rs, d, meta)
}
func resource_aws_eip_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	vpc := strings.Contains(rs.ID, "eipalloc")

	// If we have an instance to register, do it
	instanceId := rs.Attributes["instance"]

	// Only register with an instance if we have one
	if instanceId != "" {
		assocOpts := ec2.AssociateAddress{
			InstanceId: instanceId,
			PublicIp:   rs.ID,
		}

		// more unique ID conditionals
		if vpc {
			assocOpts = ec2.AssociateAddress{
				InstanceId:   instanceId,
				AllocationId: rs.ID,
				PublicIp:     "",
			}
		}

		log.Printf("[DEBUG] EIP associate configuration: %#v (vpc: %v)", assocOpts, vpc)
		_, err := ec2conn.AssociateAddress(&assocOpts)
		if err != nil {
			return rs, fmt.Errorf("Failure associating instances: %s", err)
		}
	}

	address, err := resource_aws_eip_retrieve_address(rs.ID, vpc, ec2conn)
	if err != nil {
		return rs, err
	}

	return resource_aws_eip_update_state(rs, address)
}
func resource_aws_vpc_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff so that we have all the proper attributes
	s = s.MergeDiff(d)

	// Create the VPC
	createOpts := &ec2.CreateVpc{
		CidrBlock: s.Attributes["cidr_block"],
	}
	log.Printf("[DEBUG] VPC create config: %#v", createOpts)
	vpcResp, err := ec2conn.CreateVpc(createOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating VPC: %s", err)
	}

	// Get the ID and store it
	vpc := &vpcResp.VPC
	log.Printf("[INFO] VPC ID: %s", vpc.VpcId)
	s.ID = vpc.VpcId

	// Wait for the VPC to become available
	log.Printf(
		"[DEBUG] Waiting for VPC (%s) to become available",
		s.ID)
	stateConf := &resource.StateChangeConf{
		Pending: []string{"pending"},
		Target:  "available",
		Refresh: VPCStateRefreshFunc(ec2conn, s.ID),
		Timeout: 10 * time.Minute,
	}
	vpcRaw, err := stateConf.WaitForState()
	if err != nil {
		return s, fmt.Errorf(
			"Error waiting for VPC (%s) to become available: %s",
			s.ID, err)
	}

	// Update our attributes and return
	return resource_aws_vpc_update_state(s, vpcRaw.(*ec2.VPC))
}
func resource_aws_autoscaling_group_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	autoscalingconn := p.autoscalingconn
	rs := s.MergeDiff(d)

	opts := autoscaling.UpdateAutoScalingGroup{
		Name: rs.ID,
	}

	var err error

	if _, ok := d.Attributes["min_size"]; ok {
		opts.MinSize, err = strconv.Atoi(rs.Attributes["min_size"])
		opts.SetMinSize = true
	}

	if _, ok := d.Attributes["max_size"]; ok {
		opts.MaxSize, err = strconv.Atoi(rs.Attributes["max_size"])
		opts.SetMaxSize = true
	}

	if err != nil {
		return s, fmt.Errorf("Error parsing configuration: %s", err)
	}

	log.Printf("[DEBUG] AutoScaling Group update configuration: %#v", opts)

	_, err = autoscalingconn.UpdateAutoScalingGroup(&opts)

	if err != nil {
		return rs, fmt.Errorf("Error updating AutoScaling group: %s", err)
	}

	g, err := resource_aws_autoscaling_group_retrieve(rs.ID, autoscalingconn)

	if err != nil {
		return rs, err
	}

	return resource_aws_autoscaling_group_update_state(rs, g)
}
func resource_aws_r53_zone_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	r53 := p.route53

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	req := &route53.CreateHostedZoneRequest{
		Name:    rs.Attributes["name"],
		Comment: "Managed by Terraform",
	}
	log.Printf("[DEBUG] Creating Route53 hosted zone: %s", req.Name)
	resp, err := r53.CreateHostedZone(req)
	if err != nil {
		return rs, err
	}

	// Store the zone_id
	zone := route53.CleanZoneID(resp.HostedZone.ID)
	rs.ID = zone
	rs.Attributes["zone_id"] = zone

	// Wait until we are done initializing
	wait := resource.StateChangeConf{
		Delay:      30 * time.Second,
		Pending:    []string{"PENDING"},
		Target:     "INSYNC",
		Timeout:    10 * time.Minute,
		MinTimeout: 5 * time.Second,
		Refresh: func() (result interface{}, state string, err error) {
			return resource_aws_r53_wait(r53, resp.ChangeInfo.ID)
		},
	}
	_, err = wait.WaitForState()
	if err != nil {
		return rs, err
	}
	return rs, nil
}
Example #24
0
func resource_aws_vpc_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn
	rs := s.MergeDiff(d)

	log.Printf("[DEBUG] attributes: %#v", d.Attributes)

	if attr, ok := d.Attributes["enable_dns_support"]; ok {
		options := new(ec2.ModifyVpcAttribute)

		options.EnableDnsSupport = attr.New != "" && attr.New != "false"
		options.SetEnableDnsSupport = true

		rs.Attributes["enable_dns_support"] = strconv.FormatBool(options.EnableDnsSupport)

		log.Printf("[INFO] Modifying enable_dns_support vpc attribute for %s: %#v", s.ID, options)

		if _, err := ec2conn.ModifyVpcAttribute(s.ID, options); err != nil {
			return s, err
		}
	}

	if attr, ok := d.Attributes["enable_dns_hostnames"]; ok {
		options := new(ec2.ModifyVpcAttribute)

		options.EnableDnsHostnames = attr.New != "" && attr.New != "false"
		options.SetEnableDnsHostnames = true

		rs.Attributes["enable_dns_hostnames"] = strconv.FormatBool(options.EnableDnsHostnames)

		log.Printf("[INFO] Modifying enable_dns_hostnames vpc attribute for %s: %#v", s.ID, options)

		if _, err := ec2conn.ModifyVpcAttribute(s.ID, options); err != nil {
			return s, err
		}
	}

	return rs, nil
}
func resource_dnsimple_record_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	var err error

	newRecord := dnsimple.ChangeRecord{
		Name:  rs.Attributes["name"],
		Value: rs.Attributes["value"],
		Type:  rs.Attributes["type"],
	}

	if attr, ok := rs.Attributes["ttl"]; ok {
		newRecord.Ttl = attr
	}

	log.Printf("[DEBUG] record create configuration: %#v", newRecord)

	recId, err := client.CreateRecord(rs.Attributes["domain"], &newRecord)

	if err != nil {
		return nil, fmt.Errorf("Failed to create record: %s", err)
	}

	rs.ID = recId
	log.Printf("[INFO] record ID: %s", rs.ID)

	record, err := resource_dnsimple_record_retrieve(rs.Attributes["domain"], rs.ID, client)
	if err != nil {
		return nil, fmt.Errorf("Couldn't find record: %s", err)
	}

	return resource_dnsimple_record_update_state(rs, record)
}
func resource_digitalocean_record_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	client := p.client

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	var err error

	newRecord := digitalocean.CreateRecord{
		Type:     rs.Attributes["type"],
		Name:     rs.Attributes["name"],
		Data:     rs.Attributes["value"],
		Priority: rs.Attributes["priority"],
		Port:     rs.Attributes["port"],
		Weight:   rs.Attributes["weight"],
	}

	log.Printf("[DEBUG] record create configuration: %#v", newRecord)

	recId, err := client.CreateRecord(rs.Attributes["domain"], &newRecord)

	if err != nil {
		return nil, fmt.Errorf("Failed to create record: %s", err)
	}

	rs.ID = recId
	log.Printf("[INFO] Record ID: %s", rs.ID)

	record, err := resource_digitalocean_record_retrieve(rs.Attributes["domain"], rs.ID, client)
	if err != nil {
		return nil, fmt.Errorf("Couldn't find record: %s", err)
	}

	return resource_digitalocean_record_update_state(rs, record)
}
func resource_aws_security_group_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	ec2conn := p.ec2conn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	securityGroupOpts := ec2.SecurityGroup{
		Name: rs.Attributes["name"],
	}

	if rs.Attributes["vpc_id"] != "" {
		securityGroupOpts.VpcId = rs.Attributes["vpc_id"]
	}

	if rs.Attributes["description"] != "" {
		securityGroupOpts.Description = rs.Attributes["description"]
	}

	log.Printf("[DEBUG] Security Group create configuration: %#v", securityGroupOpts)
	createResp, err := ec2conn.CreateSecurityGroup(securityGroupOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating Security Group: %s", err)
	}

	rs.ID = createResp.Id
	group := createResp.SecurityGroup

	log.Printf("[INFO] Security Group ID: %s", rs.ID)

	// Wait for the security group to truly exist
	log.Printf(
		"[DEBUG] Waiting for SG (%s) to exist",
		s.ID)
	stateConf := &resource.StateChangeConf{
		Pending: []string{""},
		Target:  "exists",
		Refresh: SGStateRefreshFunc(ec2conn, rs.ID),
		Timeout: 1 * time.Minute,
	}
	if _, err := stateConf.WaitForState(); err != nil {
		return s, fmt.Errorf(
			"Error waiting for SG (%s) to become available: %s",
			rs.ID, err)
	}

	// Expand the "ingress" array to goamz compat []ec2.IPPerm
	ingressRules := []ec2.IPPerm{}
	v, ok := flatmap.Expand(rs.Attributes, "ingress").([]interface{})
	if ok {
		ingressRules, err = expandIPPerms(v)
		if err != nil {
			return rs, err
		}
	}

	if len(ingressRules) > 0 {
		_, err = ec2conn.AuthorizeSecurityGroup(group, ingressRules)
		if err != nil {
			return rs, fmt.Errorf("Error authorizing security group ingress rules: %s", err)
		}
	}

	return resource_aws_security_group_refresh(rs, meta)
}
func resource_aws_elb_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	elbconn := p.elbconn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	// The name specified for the ELB. This is also our unique ID
	// we save to state if the creation is successful (amazon verifies
	// it is unique)
	elbName := rs.Attributes["name"]

	// Expand the "listener" array to goamz compat []elb.Listener
	v := flatmap.Expand(rs.Attributes, "listener").([]interface{})
	listeners, err := expandListeners(v)
	if err != nil {
		return nil, err
	}

	// Provision the elb
	elbOpts := &elb.CreateLoadBalancer{
		LoadBalancerName: elbName,
		Listeners:        listeners,
	}

	if _, ok := rs.Attributes["availability_zones.#"]; ok {
		v = flatmap.Expand(rs.Attributes, "availability_zones").([]interface{})
		zones := expandStringList(v)
		elbOpts.AvailZone = zones
	}

	log.Printf("[DEBUG] ELB create configuration: %#v", elbOpts)

	_, err = elbconn.CreateLoadBalancer(elbOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating ELB: %s", err)
	}

	// Assign the elb's unique identifier for use later
	rs.ID = elbName
	log.Printf("[INFO] ELB ID: %s", elbName)

	if _, ok := rs.Attributes["instances.#"]; ok {
		// If we have any instances, we need to register them
		v = flatmap.Expand(rs.Attributes, "instances").([]interface{})
		instances := expandStringList(v)

		if len(instances) > 0 {
			registerInstancesOpts := elb.RegisterInstancesWithLoadBalancer{
				LoadBalancerName: elbName,
				Instances:        instances,
			}

			_, err := elbconn.RegisterInstancesWithLoadBalancer(&registerInstancesOpts)

			if err != nil {
				return rs, fmt.Errorf("Failure registering instances: %s", err)
			}
		}
	}

	if _, ok := rs.Attributes["health_check.#"]; ok {
		v := flatmap.Expand(rs.Attributes, "health_check").([]interface{})
		health_check := v[0].(map[string]interface{})
		healthyThreshold, err := strconv.ParseInt(health_check["healthy_threshold"].(string), 0, 0)
		unhealthyThreshold, err := strconv.ParseInt(health_check["unhealthy_threshold"].(string), 0, 0)
		interval, err := strconv.ParseInt(health_check["interval"].(string), 0, 0)
		timeout, err := strconv.ParseInt(health_check["timeout"].(string), 0, 0)

		if err != nil {
			return nil, err
		}

		configureHealthCheckOpts := elb.ConfigureHealthCheck{
			LoadBalancerName: elbName,
			Check: elb.HealthCheck{
				HealthyThreshold:   healthyThreshold,
				UnhealthyThreshold: unhealthyThreshold,
				Interval:           interval,
				Target:             health_check["target"].(string),
				Timeout:            timeout,
			},
		}

		_, err = elbconn.ConfigureHealthCheck(&configureHealthCheckOpts)
		if err != nil {
			return rs, fmt.Errorf("Failure configuring health check: %s", err)
		}
	}

	loadBalancer, err := resource_aws_elb_retrieve_balancer(rs.ID, elbconn)
	if err != nil {
		return rs, err
	}

	return resource_aws_elb_update_state(rs, loadBalancer)
}
func resource_aws_elb_update(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	elbconn := p.elbconn

	rs := s.MergeDiff(d)

	// If we currently have instances, or did have instances,
	// we want to figure out what to add and remove from the load
	// balancer
	if attr, ok := d.Attributes["instances.#"]; ok && attr.Old != "" {
		// The new state of instances merged with the diff
		mergedInstances := expandStringList(flatmap.Expand(
			rs.Attributes, "instances").([]interface{}))

		// The state before the diff merge
		previousInstances := expandStringList(flatmap.Expand(
			s.Attributes, "instances").([]interface{}))

		// keep track of what instances we are removing, and which
		// we are adding
		var toRemove []string
		var toAdd []string

		for _, instanceId := range mergedInstances {
			for _, prevId := range previousInstances {
				// If the merged instance ID existed
				// previously, we don't have to do anything
				if instanceId == prevId {
					continue
					// Otherwise, we need to add it to the load balancer
				} else {
					toAdd = append(toAdd, instanceId)
				}
			}
		}

		for i, instanceId := range toAdd {
			for _, prevId := range previousInstances {
				// If the instance ID we are adding existed
				// previously, we want to not add it, but rather remove
				// it
				if instanceId == prevId {
					toRemove = append(toRemove, instanceId)
					toAdd = append(toAdd[:i], toAdd[i+1:]...)
					// Otherwise, we continue adding it to the ELB
				} else {
					continue
				}
			}
		}

		if len(toAdd) > 0 {
			registerInstancesOpts := elb.RegisterInstancesWithLoadBalancer{
				LoadBalancerName: rs.ID,
				Instances:        toAdd,
			}

			_, err := elbconn.RegisterInstancesWithLoadBalancer(&registerInstancesOpts)

			if err != nil {
				return s, fmt.Errorf("Failure registering instances: %s", err)
			}
		}

		if len(toRemove) > 0 {
			deRegisterInstancesOpts := elb.DeregisterInstancesFromLoadBalancer{
				LoadBalancerName: rs.ID,
				Instances:        toRemove,
			}

			_, err := elbconn.DeregisterInstancesFromLoadBalancer(&deRegisterInstancesOpts)

			if err != nil {
				return s, fmt.Errorf("Failure deregistering instances: %s", err)
			}
		}
	}

	loadBalancer, err := resource_aws_elb_retrieve_balancer(rs.ID, elbconn)

	if err != nil {
		return s, err
	}

	return resource_aws_elb_update_state(rs, loadBalancer)
}
func resource_aws_autoscaling_group_create(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	autoscalingconn := p.autoscalingconn

	// Merge the diff into the state so that we have all the attributes
	// properly.
	rs := s.MergeDiff(d)

	var err error
	autoScalingGroupOpts := autoscaling.CreateAutoScalingGroup{}

	if rs.Attributes["min_size"] != "" {
		autoScalingGroupOpts.MinSize, err = strconv.Atoi(rs.Attributes["min_size"])
		autoScalingGroupOpts.SetMinSize = true
	}

	if rs.Attributes["max_size"] != "" {
		autoScalingGroupOpts.MaxSize, err = strconv.Atoi(rs.Attributes["max_size"])
		autoScalingGroupOpts.SetMaxSize = true
	}

	if rs.Attributes["default_cooldown"] != "" {
		autoScalingGroupOpts.DefaultCooldown, err = strconv.Atoi(rs.Attributes["default_cooldown"])
		autoScalingGroupOpts.SetDefaultCooldown = true
	}

	if rs.Attributes["desired_capacity"] != "" {
		autoScalingGroupOpts.DesiredCapacity, err = strconv.Atoi(rs.Attributes["desired_capacity"])
		autoScalingGroupOpts.SetDesiredCapacity = true
	}

	if rs.Attributes["health_check_grace_period"] != "" {
		autoScalingGroupOpts.HealthCheckGracePeriod, err = strconv.Atoi(rs.Attributes["health_check_grace_period"])
		autoScalingGroupOpts.SetHealthCheckGracePeriod = true
	}

	if err != nil {
		return nil, fmt.Errorf("Error parsing configuration: %s", err)
	}

	if _, ok := rs.Attributes["availability_zones.#"]; ok {
		autoScalingGroupOpts.AvailZone = expandStringList(flatmap.Expand(
			rs.Attributes, "availability_zones").([]interface{}))
	}

	if _, ok := rs.Attributes["load_balancers.#"]; ok {
		autoScalingGroupOpts.LoadBalancerNames = expandStringList(flatmap.Expand(
			rs.Attributes, "load_balancers").([]interface{}))
	}

	if _, ok := rs.Attributes["vpc_identifier.#"]; ok {
		autoScalingGroupOpts.VPCZoneIdentifier = expandStringList(flatmap.Expand(
			rs.Attributes, "vpc_identifier").([]interface{}))
	}

	autoScalingGroupOpts.Name = rs.Attributes["name"]
	autoScalingGroupOpts.HealthCheckType = rs.Attributes["health_check_type"]
	autoScalingGroupOpts.LaunchConfigurationName = rs.Attributes["launch_configuration"]

	log.Printf("[DEBUG] AutoScaling Group create configuration: %#v", autoScalingGroupOpts)
	_, err = autoscalingconn.CreateAutoScalingGroup(&autoScalingGroupOpts)
	if err != nil {
		return nil, fmt.Errorf("Error creating AutoScaling Group: %s", err)
	}

	rs.ID = rs.Attributes["name"]
	rs.Dependencies = []terraform.ResourceDependency{
		terraform.ResourceDependency{ID: rs.Attributes["launch_configuration"]},
	}

	log.Printf("[INFO] AutoScaling Group ID: %s", rs.ID)

	g, err := resource_aws_autoscaling_group_retrieve(rs.ID, autoscalingconn)
	if err != nil {
		return rs, err
	}

	return resource_aws_autoscaling_group_update_state(rs, g)
}