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_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 (p *ResourceProvisioner) Apply(s *terraform.ResourceState,
	c *terraform.ResourceConfig) error {
	// Ensure the connection type is SSH
	if err := helper.VerifySSH(s); err != nil {
		return err
	}

	// Get the SSH configuration
	conf, err := helper.ParseSSHConfig(s)
	if err != nil {
		return err
	}

	// Collect the scripts
	scripts, err := p.collectScripts(c)
	if err != nil {
		return err
	}
	for _, s := range scripts {
		defer s.Close()
	}

	// Copy and execute each script
	if err := p.runScripts(conf, scripts); err != nil {
		return err
	}
	return 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_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_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_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_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_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_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_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_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_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_aws_security_group_update_state(
	s *terraform.ResourceState,
	sg *ec2.SecurityGroupInfo) (*terraform.ResourceState, error) {

	s.Attributes["description"] = sg.Description
	s.Attributes["name"] = sg.Name
	s.Attributes["vpc_id"] = sg.VpcId
	s.Attributes["owner_id"] = sg.OwnerId

	// Flatten our ingress values
	toFlatten := make(map[string]interface{})
	toFlatten["ingress"] = flattenIPPerms(sg.IPPerms)

	for k, v := range flatmap.Flatten(toFlatten) {
		s.Attributes[k] = v
	}

	s.Dependencies = nil
	if s.Attributes["vpc_id"] != "" {
		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: s.Attributes["vpc_id"]},
		)
	}

	return s, 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_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_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_instance_update_state(
	s *terraform.ResourceState,
	instance *ec2.Instance) (*terraform.ResourceState, error) {
	s.Attributes["availability_zone"] = instance.AvailZone
	s.Attributes["key_name"] = instance.KeyName
	s.Attributes["public_dns"] = instance.DNSName
	s.Attributes["public_ip"] = instance.PublicIpAddress
	s.Attributes["private_dns"] = instance.PrivateDNSName
	s.Attributes["private_ip"] = instance.PrivateIpAddress
	s.Attributes["subnet_id"] = instance.SubnetId
	s.Dependencies = nil

	// Extract the existing security groups
	useID := false
	if raw := flatmap.Expand(s.Attributes, "security_groups"); raw != nil {
		if sgs, ok := raw.([]interface{}); ok {
			for _, sg := range sgs {
				str, ok := sg.(string)
				if !ok {
					continue
				}

				if strings.HasPrefix(str, "sg-") {
					useID = true
					break
				}
			}
		}
	}

	// Build up the security groups
	sgs := make([]string, len(instance.SecurityGroups))
	for i, sg := range instance.SecurityGroups {
		if instance.SubnetId != "" && useID {
			sgs[i] = sg.Id
		} else {
			sgs[i] = sg.Name
		}

		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: sg.Id},
		)
	}
	flatmap.Map(s.Attributes).Merge(flatmap.Flatten(map[string]interface{}{
		"security_groups": sgs,
	}))

	if instance.SubnetId != "" {
		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: instance.SubnetId},
		)
	}

	return s, 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_aws_security_group_update_state(
	s *terraform.ResourceState,
	sg *ec2.SecurityGroupInfo) (*terraform.ResourceState, error) {

	s.Attributes["description"] = sg.Description
	s.Attributes["name"] = sg.Name
	s.Attributes["vpc_id"] = sg.VpcId
	s.Attributes["owner_id"] = sg.OwnerId

	// Flatten our ingress values
	toFlatten := make(map[string]interface{})

	ingressRules := make([]map[string]interface{}, 0, len(sg.IPPerms))
	for _, perm := range sg.IPPerms {
		n := make(map[string]interface{})
		n["from_port"] = perm.FromPort
		n["protocol"] = perm.Protocol
		n["to_port"] = perm.ToPort

		if len(perm.SourceIPs) > 0 {
			n["cidr_blocks"] = perm.SourceIPs
		}

		if len(perm.SourceGroups) > 0 {
			// We depend on other security groups
			for _, v := range perm.SourceGroups {
				s.Dependencies = append(s.Dependencies,
					terraform.ResourceDependency{ID: v.Id},
				)
			}
			n["security_groups"] = flattenSecurityGroups(perm.SourceGroups)
		}

		// Reverse the order, as Amazon sorts it the reverse of how we created
		// it.
		ingressRules = append([]map[string]interface{}{n}, ingressRules...)
	}

	toFlatten["ingress"] = ingressRules

	for k, v := range flatmap.Flatten(toFlatten) {
		s.Attributes[k] = v
	}

	if s.Attributes["vpc_id"] != "" {
		s.Dependencies = append(s.Dependencies,
			terraform.ResourceDependency{ID: s.Attributes["vpc_id"]},
		)
	}

	return s, nil
}
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)
}
Exemple #22
0
// Apply performs a create or update depending on the diff, and calls
// the proper function on the matching Resource.
func (m *Map) Apply(
	s *terraform.ResourceState,
	d *terraform.ResourceDiff,
	meta interface{}) (*terraform.ResourceState, error) {
	r, ok := m.Mapping[s.Type]
	if !ok {
		return nil, fmt.Errorf("Unknown resource type: %s", s.Type)
	}

	if d.Destroy || d.RequiresNew() {
		if s.ID != "" {
			// Destroy the resource if it is created
			err := r.Destroy(s, meta)
			if err != nil {
				return s, err
			}

			s.ID = ""
		}

		// If we're only destroying, and not creating, then return now.
		// Otherwise, we continue so that we can create a new resource.
		if !d.RequiresNew() {
			return nil, nil
		}
	}

	var result *terraform.ResourceState
	var err error
	if s.ID == "" {
		result, err = r.Create(s, d, meta)
	} else {
		if r.Update == nil {
			return s, fmt.Errorf(
				"Resource type '%s' doesn't support update",
				s.Type)
		}

		result, err = r.Update(s, d, meta)
	}
	if result != nil {
		if result.Attributes == nil {
			result.Attributes = make(map[string]string)
		}

		result.Attributes["id"] = result.ID
	}

	return result, err
}
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_r53_record_refresh(
	s *terraform.ResourceState,
	meta interface{}) (*terraform.ResourceState, error) {
	p := meta.(*ResourceProvider)
	conn := p.route53

	zone := s.Attributes["zone_id"]
	lopts := &route53.ListOpts{
		Name: s.Attributes["name"],
		Type: s.Attributes["type"],
	}
	resp, err := conn.ListResourceRecordSets(zone, lopts)
	if err != nil {
		return s, err
	}

	// Scan for a matching record
	found := false
	for _, record := range resp.Records {
		if route53.FQDN(record.Name) != route53.FQDN(lopts.Name) {
			continue
		}
		if strings.ToUpper(record.Type) != strings.ToUpper(lopts.Type) {
			continue
		}

		found = true
		resource_aws_r53_record_update_state(s, &record)
		break
	}
	if !found {
		s.ID = ""
	}
	return s, nil
}
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
}
Exemple #30
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
}