func (provider) Transform(cfg map[string]interface{}) error {
	return config.ReplaceObjects(cfg, "abs", func(val map[string]interface{}) (interface{}, error) {
		p := val["$abs"].(string)
		result, err := filepath.Abs(filepath.FromSlash(p))
		if err != nil {
			return nil, fmt.Errorf("Unable to resolve absolute path for: %s, error: %s", p, err)
		}
		return result, nil
	})
}
func (provider) Transform(cfg map[string]interface{}) error {
	metaURL, ok := cfg["packetMetaDataUrl"].(string)
	if !ok {
		metaURL = defaultPacketMetaDataURL
	}

	var data metadata

	return config.ReplaceObjects(cfg, "packet", func(val map[string]interface{}) (interface{}, error) {
		// Fetch packet metadata, if not already done
		if data.InstanceID == "" {
			g := got.New()
			res, err := g.Get(metaURL).Send()
			if err != nil {
				return nil, fmt.Errorf("Failed to fetch packet metadata, error: %s", err)
			}
			err = json.Unmarshal(res.Body, &data)
			if err != nil {
				return nil, fmt.Errorf("Failed to parse packet metadata, error: %s", err)
			}
			if data.InstanceID == "" {
				return nil, errors.New("Packet metadata isn't valid missing 'id' property")
			}
		}

		key := val["$packet"].(string)
		switch key {
		case "instance-id":
			return data.InstanceID, nil
		case "hostname":
			return data.Hostname, nil
		case "facility":
			return data.Facility, nil
		case "instance-type":
			return data.InstanceType, nil
		case "public-ipv4":
			for _, addr := range data.Network.Addresses {
				if addr.Family == 4 && addr.Public {
					return addr.Address, nil
				}
			}
			return nil, ErrNoPublicIPv4Address
		case "public-ipv6":
			for _, addr := range data.Network.Addresses {
				if addr.Family == 6 && addr.Public {
					return addr.Address, nil
				}
			}
			return nil, ErrNoPublicIPv6Address
		default:
			return nil, fmt.Errorf("Unknown $packet variable: %s", key)
		}
	})
}
func (provider) Transform(cfg map[string]interface{}) error {
	c, ok := cfg["credentials"].(map[string]interface{})
	if !ok {
		return errors.New("Expected 'credentials' property to hold credentials")
	}
	creds := &tcclient.Credentials{}
	creds.ClientID, _ = c["clientId"].(string)
	creds.AccessToken, _ = c["accessToken"].(string)
	creds.Certificate, _ = c["certificate"].(string)
	if creds.ClientID == "" || creds.AccessToken == "" {
		return errors.New("Expected properties: credentials.clientId and credentials.accessToken")
	}

	// Create a secrets client
	s := secrets.New(creds)

	// Overwrite the baseUrl for secrets if one is given
	if baseURL, _ := cfg["secretsBaseUrl"].(string); baseURL != "" {
		s.BaseURL = baseURL
	}

	// Create a cache to avoid loading the same secret twice, we use the same
	// creds for all calls and we don't persistent the cache so there is no risk
	// of scope elevation here.
	cache := make(map[string]map[string]interface{})

	return config.ReplaceObjects(cfg, "secret", func(val map[string]interface{}) (interface{}, error) {
		name := val["$secret"].(string)
		key, ok := val["key"].(string)
		if !ok || len(val) != 2 {
			return nil, errors.New("{$secret: ..., key: ...} object is missing key property")
		}
		// If secret isn't in the cache we try to load it
		if _, ok := cache[name]; !ok {
			secret, err := s.Get(name)
			if err != nil {
				return nil, err
			}
			value := map[string]interface{}{}
			err = json.Unmarshal(secret.Secret, &value)
			if err != nil {
				return nil, fmt.Errorf("Failed to parse response from secret, error: %s", err)
			}
			cache[name] = value
		}
		// Get secret from cache
		return cache[name][key], nil
	})
}
func (provider) Transform(cfg map[string]interface{}) error {
	return config.ReplaceObjects(cfg, "env", func(val map[string]interface{}) (interface{}, error) {
		env := val["$env"].(string)
		value := os.Getenv(env)
		typ, ok := val["type"]
		if !ok {
			typ = "string"
		}
		t, ok := typ.(string)
		if !ok {
			return nil, errors.New("'type' property in {$env, type} is not a string")
		}
		switch t {
		case "string":
			return value, nil
		case "number":
			v, err := strconv.ParseFloat(value, 64)
			if err != nil {
				return nil, fmt.Errorf(
					"Error parsing number from {$env: '%s'}, error: %s", env, err,
				)
			}
			return v, nil
		case "json":
			var retval interface{}
			err := json.Unmarshal([]byte(value), &retval)
			if err != nil {
				return nil, fmt.Errorf(
					"Error parsing JSON from {$env: '%s'}, error: %s", env, err,
				)
			}
			return retval, nil
		case "bool":
			return strings.ToLower(value) == "true", nil
		case "list":
			parts := strings.Split(value, " ")
			retval := make([]interface{}, len(parts))
			for i, s := range parts {
				retval[i] = s
			}
			return retval, nil
		default:
			return nil, fmt.Errorf("Unsupported type: '%s' in {$env, type}", t)
		}
	})
}