// Apply executes the remote exec provisioner
func (p *ResourceProvisioner) Apply(
	o terraform.UIOutput,
	s *terraform.InstanceState,
	c *terraform.ResourceConfig) error {
	// Get a new communicator
	comm, err := communicator.New(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(o, comm, scripts); err != nil {
		return err
	}
	return nil
}
func migrateVSphereVirtualMachineStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() || is.Attributes == nil {
		log.Println("[DEBUG] Empty VSphere Virtual Machine State; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)

	if is.Attributes["skip_customization"] == "" {
		is.Attributes["skip_customization"] = "false"
	}

	for k, _ := range is.Attributes {
		if strings.HasPrefix(k, "disk.") && strings.HasSuffix(k, ".size") {
			diskParts := strings.Split(k, ".")
			if len(diskParts) != 3 {
				continue
			}
			s := strings.Join([]string{diskParts[0], diskParts[1], "controller_type"}, ".")
			if _, ok := is.Attributes[s]; !ok {
				is.Attributes[s] = "scsi"
			}
		}
	}

	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
func (p *ResourceProvisioner) Apply(
	o terraform.UIOutput,
	s *terraform.InstanceState,
	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(o, conf, scripts); err != nil {
		return err
	}
	return nil
}
func resourceComputeInstanceMigrateState(
	v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	switch v {
	case 0:
		log.Println("[INFO] Found Compute Instance State v0; migrating to v1")
		is, err := migrateStateV0toV1(is)
		if err != nil {
			return is, err
		}
		fallthrough
	case 1:
		log.Println("[INFO] Found Compute Instance State v1; migrating to v2")
		is, err := migrateStateV1toV2(is)
		if err != nil {
			return is, err
		}
		return is, nil
	case 2:
		log.Println("[INFO] Found Compute Instance State v2; migrating to v3")
		is, err := migrateStateV2toV3(is)
		if err != nil {
			return is, err
		}
		return is, nil
	default:
		return is, fmt.Errorf("Unexpected schema version: %d", v)
	}
}
func migrateStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)

	// Delete old count
	delete(is.Attributes, "block_device.#")

	oldBds, err := readV0BlockDevices(is)
	if err != nil {
		return is, err
	}
	// seed count fields for new types
	is.Attributes["ebs_block_device.#"] = "0"
	is.Attributes["ephemeral_block_device.#"] = "0"
	// depending on if state was v0.3.7 or an earlier version, it might have
	// root_block_device defined already
	if _, ok := is.Attributes["root_block_device.#"]; !ok {
		is.Attributes["root_block_device.#"] = "0"
	}
	for _, oldBd := range oldBds {
		if err := writeV1BlockDevice(is, oldBd); err != nil {
			return is, err
		}
	}
	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
示例#6
0
// State returns the new InstanceState after the diff and any Set
// calls.
func (d *ResourceData) State() *terraform.InstanceState {
	var result terraform.InstanceState
	result.ID = d.Id()

	// If we have no ID, then this resource doesn't exist and we just
	// return nil.
	if result.ID == "" {
		return nil
	}

	// In order to build the final state attributes, we read the full
	// attribute set as a map[string]interface{}, write it to a MapFieldWriter,
	// and then use that map.
	rawMap := make(map[string]interface{})
	for k := range d.schema {
		source := getSourceSet
		if d.partial {
			source = getSourceState
			if _, ok := d.partialMap[k]; ok {
				source = getSourceSet
			}
		}

		raw := d.get([]string{k}, source)
		if raw.Exists && !raw.Computed {
			rawMap[k] = raw.Value
			if raw.ValueProcessed != nil {
				rawMap[k] = raw.ValueProcessed
			}
		}
	}
	mapW := &MapFieldWriter{Schema: d.schema}
	if err := mapW.WriteField(nil, rawMap); err != nil {
		return nil
	}

	result.Attributes = mapW.Map()
	result.Ephemeral.ConnInfo = d.ConnInfo()

	// TODO: This is hacky and we can remove this when we have a proper
	// state writer. We should instead have a proper StateFieldWriter
	// and use that.
	for k, schema := range d.schema {
		if schema.Type != TypeMap {
			continue
		}

		if result.Attributes[k] == "" {
			delete(result.Attributes, k)
		}
	}

	if v := d.Id(); v != "" {
		result.Attributes["id"] = d.Id()
	}

	return &result
}
func migrateRoute53RecordStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)
	newName := strings.TrimSuffix(is.Attributes["name"], ".")
	is.Attributes["name"] = newName
	log.Printf("[DEBUG] Attributes after migration: %#v, new name: %s", is.Attributes, newName)
	return is, nil
}
func migrateSpotFleetRequestV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty Spot Fleet Request State; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)

	is.Attributes["associate_public_ip_address"] = "false"

	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
示例#9
0
// Apply performs a create or update depending on the diff, and calls
// the proper function on the matching Resource.
func (m *Map) Apply(
	info *terraform.InstanceInfo,
	s *terraform.InstanceState,
	d *terraform.InstanceDiff,
	meta interface{}) (*terraform.InstanceState, error) {
	r, ok := m.Mapping[info.Type]
	if !ok {
		return nil, fmt.Errorf("Unknown resource type: %s", info.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.InstanceState
	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",
				info.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 migrateBeanstalkEnvironmentStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() || is.Attributes == nil {
		log.Println("[DEBUG] Empty Elastic Beanstalk Environment State; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)

	if is.Attributes["tier"] == "" {
		is.Attributes["tier"] = "WebServer"
	}

	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
func migrateKeyPairStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)

	// replace public_key with a stripped version, removing `\n` from the end
	// see https://github.com/hashicorp/terraform/issues/3455
	is.Attributes["public_key"] = strings.TrimSpace(is.Attributes["public_key"])

	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
示例#12
0
func (r *Resource) recordCurrentSchemaVersion(
	state *terraform.InstanceState) *terraform.InstanceState {
	if state != nil && r.SchemaVersion > 0 {
		if state.Meta == nil {
			state.Meta = make(map[string]string)
		}
		state.Meta["schema_version"] = strconv.Itoa(r.SchemaVersion)
	}
	return state
}
func migrateSGRuleStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	perm, err := migrateExpandIPPerm(is.Attributes)

	if err != nil {
		return nil, fmt.Errorf("[WARN] Error making new IP Permission in Security Group migration")
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)
	newID := ipPermissionIDHash(is.Attributes["security_group_id"], is.Attributes["type"], perm)
	is.Attributes["id"] = newID
	is.ID = newID
	log.Printf("[DEBUG] Attributes after migration: %#v, new id: %s", is.Attributes, newID)
	return is, nil
}
示例#14
0
// State returns the new InstanceState after the diff and any Set
// calls.
func (d *ResourceData) State() *terraform.InstanceState {
	var result terraform.InstanceState
	result.ID = d.Id()

	// If we have no ID, then this resource doesn't exist and we just
	// return nil.
	if result.ID == "" {
		return nil
	}

	result.Attributes = d.stateObject("", d.schema)
	result.Ephemeral.ConnInfo = d.ConnInfo()

	if v := d.Id(); v != "" {
		result.Attributes["id"] = d.Id()
	}

	return &result
}
func resourceVSphereVirtualMachineMigrateState(
	v int, is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	switch v {
	case 0:
		log.Println("[INFO] Found Compute Instance State v0; migrating to v1")
		is, err := migrateVSphereVirtualMachineStateV0toV1(is)
		if err != nil {
			return is, err
		}
		return is, nil
	default:
		return is, fmt.Errorf("Unexpected schema version: %d", v)
	}
}
func migrateRoute53RecordStateV1toV2(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}
	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)
	if is.Attributes["weight"] != "" && is.Attributes["weight"] != "-1" {
		is.Attributes["weighted_routing_policy.#"] = "1"
		key := fmt.Sprintf("weighted_routing_policy.0.weight")
		is.Attributes[key] = is.Attributes["weight"]
	}
	if is.Attributes["failover"] != "" {
		is.Attributes["failover_routing_policy.#"] = "1"
		key := fmt.Sprintf("failover_routing_policy.0.type")
		is.Attributes[key] = is.Attributes["failover"]
	}
	delete(is.Attributes, "weight")
	delete(is.Attributes, "failover")
	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
func migrateKinesisFirehoseV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty Kinesis Firehose Delivery State; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)

	// migrate flate S3 configuration to a s3_configuration block
	// grab initial values
	is.Attributes["s3_configuration.#"] = "1"
	// Required parameters
	is.Attributes["s3_configuration.0.role_arn"] = is.Attributes["role_arn"]
	is.Attributes["s3_configuration.0.bucket_arn"] = is.Attributes["s3_bucket_arn"]

	// Optional parameters
	if is.Attributes["s3_buffer_size"] != "" {
		is.Attributes["s3_configuration.0.buffer_size"] = is.Attributes["s3_buffer_size"]
	}
	if is.Attributes["s3_data_compression"] != "" {
		is.Attributes["s3_configuration.0.compression_format"] = is.Attributes["s3_data_compression"]
	}
	if is.Attributes["s3_buffer_interval"] != "" {
		is.Attributes["s3_configuration.0.buffer_interval"] = is.Attributes["s3_buffer_interval"]
	}
	if is.Attributes["s3_prefix"] != "" {
		is.Attributes["s3_configuration.0.prefix"] = is.Attributes["s3_prefix"]
	}

	delete(is.Attributes, "role_arn")
	delete(is.Attributes, "s3_bucket_arn")
	delete(is.Attributes, "s3_buffer_size")
	delete(is.Attributes, "s3_data_compression")
	delete(is.Attributes, "s3_buffer_interval")
	delete(is.Attributes, "s3_prefix")

	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
func resourceConsulKeysMigrateStateV0toV1(is *terraform.InstanceState) (*terraform.InstanceState, error) {
	if is.Empty() || is.Attributes == nil {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)

	res := resourceConsulKeys()
	keys, err := readV0Keys(is, res)
	if err != nil {
		return is, err
	}
	if err := clearV0Keys(is); err != nil {
		return is, err
	}
	if err := writeV1Keys(is, res, keys); err != nil {
		return is, err
	}

	log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
	return is, nil
}
func migrateCloudFlareRecordStateV0toV1(is *terraform.InstanceState, meta interface{}) (*terraform.InstanceState, error) {
	if is.Empty() {
		log.Println("[DEBUG] Empty InstanceState; nothing to migrate.")
		return is, nil
	}

	log.Printf("[DEBUG] Attributes before migration: %#v", is.Attributes)
	client := meta.(*cloudflare.API)

	// look up new id based on attributes
	domain := is.Attributes["domain"]
	zoneId, err := client.ZoneIDByName(domain)
	if err != nil {
		return is, fmt.Errorf("Error finding zone %q: %s", domain, err)
	}

	// all other information is ignored in the DNSRecords call
	searchRecord := cloudflare.DNSRecord{
		Type:    is.Attributes["type"],
		Name:    is.Attributes["hostname"],
		Content: is.Attributes["value"],
	}

	records, err := client.DNSRecords(zoneId, searchRecord)
	if err != nil {
		return is, err
	}

	for _, r := range records {
		if is.Attributes["ttl"] != "" {
			v, err := strconv.Atoi(is.Attributes["ttl"])
			if err != nil {
				return is, fmt.Errorf("Error converting ttl to int in CloudFlare Record Migration")
			}

			if v != r.TTL {
				continue
			}
		}

		if is.Attributes["proxied"] != "" {
			b, err := strconv.ParseBool(is.Attributes["proxied"])
			if err != nil {
				return is, fmt.Errorf("Error converting proxied to bool in CloudFlare Record Migration")
			}

			if b != r.Proxied {
				continue
			}
		}

		if is.Attributes["priority"] != "" {
			v, err := strconv.Atoi(is.Attributes["priority"])
			if err != nil {
				return is, fmt.Errorf("Error converting priority to int in CloudFlare Record Migration")
			}

			if v != r.Priority {
				continue
			}
		}

		// assume record found
		is.Attributes["id"] = r.ID
		is.ID = r.ID
		log.Printf("[DEBUG] Attributes after migration: %#v", is.Attributes)
		return is, nil
	}

	// assume no record found
	log.Printf("[DEBUG] Attributes after no migration: %#v", is.Attributes)
	return is, fmt.Errorf("No matching Record found")
}
示例#20
0
// State returns the new InstanceState after the diff and any Set
// calls.
func (d *ResourceData) State() *terraform.InstanceState {
	var result terraform.InstanceState
	result.ID = d.Id()
	result.Meta = d.meta

	// If we have no ID, then this resource doesn't exist and we just
	// return nil.
	if result.ID == "" {
		return nil
	}

	// Look for a magic key in the schema that determines we skip the
	// integrity check of fields existing in the schema, allowing dynamic
	// keys to be created.
	hasDynamicAttributes := false
	for k, _ := range d.schema {
		if k == "__has_dynamic_attributes" {
			hasDynamicAttributes = true
			log.Printf("[INFO] Resource %s has dynamic attributes", result.ID)
		}
	}

	// In order to build the final state attributes, we read the full
	// attribute set as a map[string]interface{}, write it to a MapFieldWriter,
	// and then use that map.
	rawMap := make(map[string]interface{})
	for k := range d.schema {
		source := getSourceSet
		if d.partial {
			source = getSourceState
			if _, ok := d.partialMap[k]; ok {
				source = getSourceSet
			}
		}

		raw := d.get([]string{k}, source)
		if raw.Exists && !raw.Computed {
			rawMap[k] = raw.Value
			if raw.ValueProcessed != nil {
				rawMap[k] = raw.ValueProcessed
			}
		}
	}

	mapW := &MapFieldWriter{Schema: d.schema}
	if err := mapW.WriteField(nil, rawMap); err != nil {
		return nil
	}

	result.Attributes = mapW.Map()

	if hasDynamicAttributes {
		// If we have dynamic attributes, just copy the attributes map
		// one for one into the result attributes.
		for k, v := range d.setWriter.Map() {
			// Don't clobber schema values. This limits usage of dynamic
			// attributes to names which _do not_ conflict with schema
			// keys!
			if _, ok := result.Attributes[k]; !ok {
				result.Attributes[k] = v
			}
		}
	}

	if d.newState != nil {
		result.Ephemeral = d.newState.Ephemeral
	}

	// TODO: This is hacky and we can remove this when we have a proper
	// state writer. We should instead have a proper StateFieldWriter
	// and use that.
	for k, schema := range d.schema {
		if schema.Type != TypeMap {
			continue
		}

		if result.Attributes[k] == "" {
			delete(result.Attributes, k)
		}
	}

	if v := d.Id(); v != "" {
		result.Attributes["id"] = d.Id()
	}

	if d.state != nil {
		result.Tainted = d.state.Tainted
	}

	return &result
}