X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=vendor%2Fgithub.com%2Fhashicorp%2Fterraform%2Fterraform%2Feval_context_builtin.go;h=20b37933d0470bff15fbb25d90fbc0814b2e358f;hb=3cd2d4f34aefe6090b287b2b4c26049819414e46;hp=3dcfb2275bb975f323f685441ccef78bbf537e5a;hpb=21252084ae8c5f3321b45008fd5a6b162b293407;p=github%2Ffretlink%2Fterraform-provider-statuscake.git diff --git a/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go b/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go index 3dcfb22..20b3793 100644 --- a/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go +++ b/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go @@ -4,10 +4,22 @@ import ( "context" "fmt" "log" - "strings" "sync" - "github.com/hashicorp/terraform/config" + "github.com/hashicorp/terraform/plans" + "github.com/hashicorp/terraform/providers" + "github.com/hashicorp/terraform/provisioners" + "github.com/hashicorp/terraform/version" + + "github.com/hashicorp/terraform/states" + + "github.com/hashicorp/hcl2/hcl" + "github.com/hashicorp/terraform/configs/configschema" + "github.com/hashicorp/terraform/lang" + "github.com/hashicorp/terraform/tfdiags" + + "github.com/hashicorp/terraform/addrs" + "github.com/zclconf/go-cty/cty" ) // BuiltinEvalContext is an EvalContext implementation that is used by @@ -17,36 +29,47 @@ type BuiltinEvalContext struct { StopContext context.Context // PathValue is the Path that this context is operating within. - PathValue []string + PathValue addrs.ModuleInstance - // Interpolater setting below affect the interpolation of variables. + // Evaluator is used for evaluating expressions within the scope of this + // eval context. + Evaluator *Evaluator + + // Schemas is a repository of all of the schemas we should need to + // decode configuration blocks and expressions. This must be constructed by + // the caller to include schemas for all of the providers, resource types, + // data sources and provisioners used by the given configuration and + // state. // - // The InterpolaterVars are the exact value for ${var.foo} values. - // The map is shared between all contexts and is a mapping of - // PATH to KEY to VALUE. Because it is shared by all contexts as well - // as the Interpolater itself, it is protected by InterpolaterVarLock - // which must be locked during any access to the map. - Interpolater *Interpolater - InterpolaterVars map[string]map[string]interface{} - InterpolaterVarLock *sync.Mutex + // This must not be mutated during evaluation. + Schemas *Schemas + + // VariableValues contains the variable values across all modules. This + // structure is shared across the entire containing context, and so it + // may be accessed only when holding VariableValuesLock. + // The keys of the first level of VariableValues are the string + // representations of addrs.ModuleInstance values. The second-level keys + // are variable names within each module instance. + VariableValues map[string]map[string]cty.Value + VariableValuesLock *sync.Mutex Components contextComponentFactory Hooks []Hook InputValue UIInput - ProviderCache map[string]ResourceProvider - ProviderConfigCache map[string]*ResourceConfig - ProviderInputConfig map[string]map[string]interface{} + ProviderCache map[string]providers.Interface + ProviderInputConfig map[string]map[string]cty.Value ProviderLock *sync.Mutex - ProvisionerCache map[string]ResourceProvisioner + ProvisionerCache map[string]provisioners.Interface ProvisionerLock *sync.Mutex - DiffValue *Diff - DiffLock *sync.RWMutex - StateValue *State - StateLock *sync.RWMutex + ChangesValue *plans.ChangesSync + StateValue *states.SyncState once sync.Once } +// BuiltinEvalContext implements EvalContext +var _ EvalContext = (*BuiltinEvalContext)(nil) + func (ctx *BuiltinEvalContext) Stopped() <-chan struct{} { // This can happen during tests. During tests, we just block forever. if ctx.StopContext == nil { @@ -80,12 +103,13 @@ func (ctx *BuiltinEvalContext) Input() UIInput { return ctx.InputValue } -func (ctx *BuiltinEvalContext) InitProvider(n string) (ResourceProvider, error) { +func (ctx *BuiltinEvalContext) InitProvider(typeName string, addr addrs.ProviderConfig) (providers.Interface, error) { ctx.once.Do(ctx.init) + absAddr := addr.Absolute(ctx.Path()) // If we already initialized, it is an error - if p := ctx.Provider(n); p != nil { - return nil, fmt.Errorf("Provider '%s' already initialized", n) + if p := ctx.Provider(absAddr); p != nil { + return nil, fmt.Errorf("%s is already initialized", addr) } // Warning: make sure to acquire these locks AFTER the call to Provider @@ -93,139 +117,102 @@ func (ctx *BuiltinEvalContext) InitProvider(n string) (ResourceProvider, error) ctx.ProviderLock.Lock() defer ctx.ProviderLock.Unlock() - providerPath := make([]string, len(ctx.Path())+1) - copy(providerPath, ctx.Path()) - providerPath[len(providerPath)-1] = n - key := PathCacheKey(providerPath) + key := absAddr.String() - typeName := strings.SplitN(n, ".", 2)[0] p, err := ctx.Components.ResourceProvider(typeName, key) if err != nil { return nil, err } + log.Printf("[TRACE] BuiltinEvalContext: Initialized %q provider for %s", typeName, absAddr) ctx.ProviderCache[key] = p + return p, nil } -func (ctx *BuiltinEvalContext) Provider(n string) ResourceProvider { +func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface { ctx.once.Do(ctx.init) ctx.ProviderLock.Lock() defer ctx.ProviderLock.Unlock() - providerPath := make([]string, len(ctx.Path())+1) - copy(providerPath, ctx.Path()) - providerPath[len(providerPath)-1] = n + return ctx.ProviderCache[addr.String()] +} + +func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *ProviderSchema { + ctx.once.Do(ctx.init) - return ctx.ProviderCache[PathCacheKey(providerPath)] + return ctx.Schemas.ProviderSchema(addr.ProviderConfig.Type) } -func (ctx *BuiltinEvalContext) CloseProvider(n string) error { +func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.ProviderConfig) error { ctx.once.Do(ctx.init) ctx.ProviderLock.Lock() defer ctx.ProviderLock.Unlock() - providerPath := make([]string, len(ctx.Path())+1) - copy(providerPath, ctx.Path()) - providerPath[len(providerPath)-1] = n - - var provider interface{} - provider = ctx.ProviderCache[PathCacheKey(providerPath)] + key := addr.Absolute(ctx.Path()).String() + provider := ctx.ProviderCache[key] if provider != nil { - if p, ok := provider.(ResourceProviderCloser); ok { - delete(ctx.ProviderCache, PathCacheKey(providerPath)) - return p.Close() - } + delete(ctx.ProviderCache, key) + return provider.Close() } return nil } -func (ctx *BuiltinEvalContext) ConfigureProvider( - n string, cfg *ResourceConfig) error { - p := ctx.Provider(n) +func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.ProviderConfig, cfg cty.Value) tfdiags.Diagnostics { + var diags tfdiags.Diagnostics + absAddr := addr.Absolute(ctx.Path()) + p := ctx.Provider(absAddr) if p == nil { - return fmt.Errorf("Provider '%s' not initialized", n) + diags = diags.Append(fmt.Errorf("%s not initialized", addr)) + return diags } - if err := ctx.SetProviderConfig(n, cfg); err != nil { - return nil + providerSchema := ctx.ProviderSchema(absAddr) + if providerSchema == nil { + diags = diags.Append(fmt.Errorf("schema for %s is not available", absAddr)) + return diags } - return p.Configure(cfg) -} - -func (ctx *BuiltinEvalContext) SetProviderConfig( - n string, cfg *ResourceConfig) error { - providerPath := make([]string, len(ctx.Path())+1) - copy(providerPath, ctx.Path()) - providerPath[len(providerPath)-1] = n - - // Save the configuration - ctx.ProviderLock.Lock() - ctx.ProviderConfigCache[PathCacheKey(providerPath)] = cfg - ctx.ProviderLock.Unlock() + req := providers.ConfigureRequest{ + TerraformVersion: version.String(), + Config: cfg, + } - return nil + resp := p.Configure(req) + return resp.Diagnostics } -func (ctx *BuiltinEvalContext) ProviderInput(n string) map[string]interface{} { +func (ctx *BuiltinEvalContext) ProviderInput(pc addrs.ProviderConfig) map[string]cty.Value { ctx.ProviderLock.Lock() defer ctx.ProviderLock.Unlock() - // Make a copy of the path so we can safely edit it - path := ctx.Path() - pathCopy := make([]string, len(path)+1) - copy(pathCopy, path) - - // Go up the tree. - for i := len(path) - 1; i >= 0; i-- { - pathCopy[i+1] = n - k := PathCacheKey(pathCopy[:i+2]) - if v, ok := ctx.ProviderInputConfig[k]; ok { - return v - } + if !ctx.Path().IsRoot() { + // Only root module provider configurations can have input. + return nil } - return nil + return ctx.ProviderInputConfig[pc.String()] } -func (ctx *BuiltinEvalContext) SetProviderInput(n string, c map[string]interface{}) { - providerPath := make([]string, len(ctx.Path())+1) - copy(providerPath, ctx.Path()) - providerPath[len(providerPath)-1] = n +func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.ProviderConfig, c map[string]cty.Value) { + absProvider := pc.Absolute(ctx.Path()) + + if !ctx.Path().IsRoot() { + // Only root module provider configurations can have input. + log.Printf("[WARN] BuiltinEvalContext: attempt to SetProviderInput for non-root module") + return + } // Save the configuration ctx.ProviderLock.Lock() - ctx.ProviderInputConfig[PathCacheKey(providerPath)] = c + ctx.ProviderInputConfig[absProvider.String()] = c ctx.ProviderLock.Unlock() } -func (ctx *BuiltinEvalContext) ParentProviderConfig(n string) *ResourceConfig { - ctx.ProviderLock.Lock() - defer ctx.ProviderLock.Unlock() - - // Make a copy of the path so we can safely edit it - path := ctx.Path() - pathCopy := make([]string, len(path)+1) - copy(pathCopy, path) - - // Go up the tree. - for i := len(path) - 1; i >= 0; i-- { - pathCopy[i+1] = n - k := PathCacheKey(pathCopy[:i+2]) - if v, ok := ctx.ProviderConfigCache[k]; ok { - return v - } - } - - return nil -} - -func (ctx *BuiltinEvalContext) InitProvisioner( - n string) (ResourceProvisioner, error) { +func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface, error) { ctx.once.Do(ctx.init) // If we already initialized, it is an error @@ -238,10 +225,7 @@ func (ctx *BuiltinEvalContext) InitProvisioner( ctx.ProvisionerLock.Lock() defer ctx.ProvisionerLock.Unlock() - provPath := make([]string, len(ctx.Path())+1) - copy(provPath, ctx.Path()) - provPath[len(provPath)-1] = n - key := PathCacheKey(provPath) + key := PathObjectCacheKey(ctx.Path(), n) p, err := ctx.Components.ResourceProvisioner(n, key) if err != nil { @@ -249,20 +233,24 @@ func (ctx *BuiltinEvalContext) InitProvisioner( } ctx.ProvisionerCache[key] = p + return p, nil } -func (ctx *BuiltinEvalContext) Provisioner(n string) ResourceProvisioner { +func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface { ctx.once.Do(ctx.init) ctx.ProvisionerLock.Lock() defer ctx.ProvisionerLock.Unlock() - provPath := make([]string, len(ctx.Path())+1) - copy(provPath, ctx.Path()) - provPath[len(provPath)-1] = n + key := PathObjectCacheKey(ctx.Path(), n) + return ctx.ProvisionerCache[key] +} + +func (ctx *BuiltinEvalContext) ProvisionerSchema(n string) *configschema.Block { + ctx.once.Do(ctx.init) - return ctx.ProvisionerCache[PathCacheKey(provPath)] + return ctx.Schemas.ProvisionerConfig(n) } func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error { @@ -271,76 +259,70 @@ func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error { ctx.ProvisionerLock.Lock() defer ctx.ProvisionerLock.Unlock() - provPath := make([]string, len(ctx.Path())+1) - copy(provPath, ctx.Path()) - provPath[len(provPath)-1] = n + key := PathObjectCacheKey(ctx.Path(), n) - var prov interface{} - prov = ctx.ProvisionerCache[PathCacheKey(provPath)] + prov := ctx.ProvisionerCache[key] if prov != nil { - if p, ok := prov.(ResourceProvisionerCloser); ok { - delete(ctx.ProvisionerCache, PathCacheKey(provPath)) - return p.Close() - } + return prov.Close() } return nil } -func (ctx *BuiltinEvalContext) Interpolate( - cfg *config.RawConfig, r *Resource) (*ResourceConfig, error) { - if cfg != nil { - scope := &InterpolationScope{ - Path: ctx.Path(), - Resource: r, - } +func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) { + var diags tfdiags.Diagnostics + scope := ctx.EvaluationScope(self, keyData) + body, evalDiags := scope.ExpandBlock(body, schema) + diags = diags.Append(evalDiags) + val, evalDiags := scope.EvalBlock(body, schema) + diags = diags.Append(evalDiags) + return val, body, diags +} - vs, err := ctx.Interpolater.Values(scope, cfg.Variables) - if err != nil { - return nil, err - } +func (ctx *BuiltinEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) { + scope := ctx.EvaluationScope(self, EvalDataForNoInstanceKey) + return scope.EvalExpr(expr, wantType) +} - // Do the interpolation - if err := cfg.Interpolate(vs); err != nil { - return nil, err - } +func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope { + data := &evaluationStateData{ + Evaluator: ctx.Evaluator, + ModulePath: ctx.PathValue, + InstanceKeyData: keyData, + Operation: ctx.Evaluator.Operation, } - - result := NewResourceConfig(cfg) - result.interpolateForce() - return result, nil + return ctx.Evaluator.Scope(data, self) } -func (ctx *BuiltinEvalContext) Path() []string { +func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance { return ctx.PathValue } -func (ctx *BuiltinEvalContext) SetVariables(n string, vs map[string]interface{}) { - ctx.InterpolaterVarLock.Lock() - defer ctx.InterpolaterVarLock.Unlock() +func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance, vals map[string]cty.Value) { + ctx.VariableValuesLock.Lock() + defer ctx.VariableValuesLock.Unlock() - path := make([]string, len(ctx.Path())+1) - copy(path, ctx.Path()) - path[len(path)-1] = n - key := PathCacheKey(path) + childPath := n.ModuleInstance(ctx.PathValue) + key := childPath.String() - vars := ctx.InterpolaterVars[key] - if vars == nil { - vars = make(map[string]interface{}) - ctx.InterpolaterVars[key] = vars + args := ctx.VariableValues[key] + if args == nil { + args = make(map[string]cty.Value) + ctx.VariableValues[key] = vals + return } - for k, v := range vs { - vars[k] = v + for k, v := range vals { + args[k] = v } } -func (ctx *BuiltinEvalContext) Diff() (*Diff, *sync.RWMutex) { - return ctx.DiffValue, ctx.DiffLock +func (ctx *BuiltinEvalContext) Changes() *plans.ChangesSync { + return ctx.ChangesValue } -func (ctx *BuiltinEvalContext) State() (*State, *sync.RWMutex) { - return ctx.StateValue, ctx.StateLock +func (ctx *BuiltinEvalContext) State() *states.SyncState { + return ctx.StateValue } func (ctx *BuiltinEvalContext) init() {