// 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 }
// 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 }
// 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 }
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 }
// 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") }
// 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 }