terraform/config/raw_config.go

90 lines
2.7 KiB
Go

package config
import (
"github.com/mitchellh/copystructure"
"github.com/mitchellh/reflectwalk"
)
// UnknownVariableValue is a sentinel value that can be used
// to denote that the value of a variable is unknown at this time.
// RawConfig uses this information to build up data about
// unknown keys.
const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66"
// RawConfig is a structure that holds a piece of configuration
// where te overall structure is unknown since it will be used
// to configure a plugin or some other similar external component.
//
// RawConfigs can be interpolated with variables that come from
// other resources, user variables, etc.
//
// RawConfig supports a query-like interface to request
// information from deep within the structure.
type RawConfig struct {
Raw map[string]interface{}
Variables map[string]InterpolatedVariable
config map[string]interface{}
unknownKeys []string
}
// NewRawConfig creates a new RawConfig structure and populates the
// publicly readable struct fields.
func NewRawConfig(raw map[string]interface{}) (*RawConfig, error) {
walker := new(variableDetectWalker)
if err := reflectwalk.Walk(raw, walker); err != nil {
return nil, err
}
return &RawConfig{
Raw: raw,
Variables: walker.Variables,
config: raw,
}, nil
}
// Config returns the entire configuration with the variables
// interpolated from any call to Interpolate.
//
// If any interpolated variables are unknown (value set to
// UnknownVariableValue), the first non-container (map, slice, etc.) element
// will be removed from the config. The keys of unknown variables
// can be found using the UnknownKeys function.
//
// By pruning out unknown keys from the configuration, the raw
// structure will always successfully decode into its ultimate
// structure using something like mapstructure.
func (r *RawConfig) Config() map[string]interface{} {
return r.config
}
// Interpolate uses the given mapping of variable values and uses
// those as the values to replace any variables in this raw
// configuration.
//
// Any prior calls to Interpolate are replaced with this one.
//
// If a variable key is missing, this will panic.
func (r *RawConfig) Interpolate(vs map[string]string) error {
config, err := copystructure.Copy(r.Raw)
if err != nil {
return err
}
w := &variableReplaceWalker{Values: vs}
r.config = config.(map[string]interface{})
err = reflectwalk.Walk(r.config, w)
if err != nil {
return err
}
r.unknownKeys = w.UnknownKeys
return nil
}
// UnknownKeys returns the keys of the configuration that are unknown
// because they had interpolated variables that must be computed.
func (r *RawConfig) UnknownKeys() []string {
return r.unknownKeys
}