func (c *Context) Apply() (*states.State, tfdiags.Diagnostics) {
	defer c.acquireRun("apply")()
	c.state = c.state.DeepCopy()
	graph, diags := c.Graph(GraphTypeApply, nil)
	if diags.HasErrors() {
		return nil, diags
	}
	operation := walkApply
	if c.destroy {
		operation = walkDestroy
	}
	walker, walkDiags := c.walk(graph, operation)
	diags = diags.Append(walker.NonFatalDiagnostics)
	diags = diags.Append(walkDiags)
	if c.destroy && !diags.HasErrors() {
		c.state.PruneResourceHusks()
	}
	return c.state, diags
}
Apply applies the changes represented by this context and returns
the resulting state.

Even in the case an error is returned, the state may be returned and will
potentially be partially updated.  In addition to returning the resulting
state, this context is updated with the latest state.

If the state is required after an error, the caller should call
Context.State, rather than rely on the return value.

TODO: Apply and Refresh should either always return a state, or rely on the
State() method. Currently the helper/resource testing framework relies
on the absence of a returned state to determine if Destroy can be
called, so that will need to be refactored before this can be changed.
package terraform
import (
	"bytes"
	"context"
	"fmt"
	"log"
	"strings"
	"sync"
	"github.com/hashicorp/hcl"
	"github.com/zclconf/go-cty/cty"
	"github.com/hashicorp/terraform/addrs"
	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/configs"
	"github.com/hashicorp/terraform/lang"
	"github.com/hashicorp/terraform/plans"
	"github.com/hashicorp/terraform/providers"
	"github.com/hashicorp/terraform/provisioners"
	"github.com/hashicorp/terraform/states"
	"github.com/hashicorp/terraform/states/statefile"
	"github.com/hashicorp/terraform/tfdiags"
)
type InputMode byte
const (
	InputModeVar InputMode = 1 << iota
	InputModeVarUnset
	InputModeProvider
	InputModeStd = InputModeVar | InputModeProvider
)
var (
	contextFailOnShadowError = false
	contextTestDeepCopyOnPlan = false
)
type ContextOpts struct {
	Config    *configs.Config
	Changes   *plans.Changes
	State     *states.State
	Targets   []addrs.Targetable
	Variables InputValues
	Meta      *ContextMeta
	Destroy   bool
	Hooks            []Hook
	Parallelism      int
	ProviderResolver providers.Resolver
	Provisioners     map[string]ProvisionerFactory
	ProviderSHA256s    map[string][]byte
	SkipProviderVerify bool
	UIInput UIInput
}
type ContextMeta struct {
	Env string  
}
type Context struct {
	config    *configs.Config
	changes   *plans.Changes
	state     *states.State
	targets   []addrs.Targetable
	variables InputValues
	meta      *ContextMeta
	destroy   bool
	hooks      []Hook
	components contextComponentFactory
	schemas    *Schemas
	sh         *stopHook
	uiInput    UIInput
	l                   sync.Mutex  
	parallelSem         Semaphore
	providerInputConfig map[string]map[string]cty.Value
	providerSHA256s     map[string][]byte
	runLock             sync.Mutex
	runCond             *sync.Cond
	runContext          context.Context
	runContextCancel    context.CancelFunc
	shadowErr           error
}
func NewContext(opts *ContextOpts) (*Context, tfdiags.Diagnostics) {
	log.Printf("[TRACE] terraform.NewContext: starting")
	diags := CheckCoreVersionRequirements(opts.Config)
	if diags.HasErrors() {
		return nil, diags
	}
	sh := new(stopHook)
	hooks := make([]Hook, len(opts.Hooks)+1)
	copy(hooks, opts.Hooks)
	hooks[len(opts.Hooks)] = sh
	state := opts.State
	if state == nil {
		state = states.NewState()
	}
	par := opts.Parallelism
	if par == 0 {
		par = 10
	}
	var variables InputValues
	if opts.Config != nil {
		variables = DefaultVariableValues(opts.Config.Module.Variables)
	}
	variables = variables.Override(opts.Variables)
	var providerFactories map[string]providers.Factory
	if opts.ProviderResolver != nil {
		deps := ConfigTreeDependencies(opts.Config, state)
		reqd := deps.AllPluginRequirements()
		if opts.ProviderSHA256s != nil && !opts.SkipProviderVerify {
			reqd.LockExecutables(opts.ProviderSHA256s)
		}
		log.Printf("[TRACE] terraform.NewContext: resolving provider version selections")
		var providerDiags tfdiags.Diagnostics
		providerFactories, providerDiags = resourceProviderFactories(opts.ProviderResolver, reqd)
		diags = diags.Append(providerDiags)
		if diags.HasErrors() {
			return nil, diags
		}
	} else {
		providerFactories = make(map[string]providers.Factory)
	}
	components := &basicComponentFactory{
		providers:    providerFactories,
		provisioners: opts.Provisioners,
	}
	log.Printf("[TRACE] terraform.NewContext: loading provider schemas")
	schemas, err := LoadSchemas(opts.Config, opts.State, components)
	if err != nil {
		diags = diags.Append(err)
		return nil, diags
	}
	changes := opts.Changes
	if changes == nil {
		changes = plans.NewChanges()
	}
	config := opts.Config
	if config == nil {
		config = configs.NewEmptyConfig()
	}
	log.Printf("[TRACE] terraform.NewContext: complete")
	return &Context{
		components: components,
		schemas:    schemas,
		destroy:    opts.Destroy,
		changes:    changes,
		hooks:      hooks,
		meta:       opts.Meta,
		config:     config,
		state:      state,
		targets:    opts.Targets,
		uiInput:    opts.UIInput,
		variables:  variables,
		parallelSem:         NewSemaphore(par),
		providerInputConfig: make(map[string]map[string]cty.Value),
		providerSHA256s:     opts.ProviderSHA256s,
		sh:                  sh,
	}, nil
}
func (c *Context) Schemas() *Schemas {
	return c.schemas
}
type ContextGraphOpts struct {
	Validate bool
	Verbose bool
}
func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, tfdiags.Diagnostics) {
	if opts == nil {
		opts = &ContextGraphOpts{Validate: true}
	}
	log.Printf("[INFO] terraform: building graph: %s", typ)
	switch typ {
	case GraphTypeApply:
		return (&ApplyGraphBuilder{
			Config:     c.config,
			Changes:    c.changes,
			State:      c.state,
			Components: c.components,
			Schemas:    c.schemas,
			Targets:    c.targets,
			Destroy:    c.destroy,
			Validate:   opts.Validate,
		}).Build(addrs.RootModuleInstance)
	case GraphTypeValidate:
		fallthrough
	case GraphTypePlan:
		p := &PlanGraphBuilder{
			Config:     c.config,
			State:      c.state,
			Components: c.components,
			Schemas:    c.schemas,
			Targets:    c.targets,
			Validate:   opts.Validate,
		}
		var b GraphBuilder = p
		switch typ {
		case GraphTypeValidate:
			b = ValidateGraphBuilder(p)
		}
		return b.Build(addrs.RootModuleInstance)
	case GraphTypePlanDestroy:
		return (&DestroyPlanGraphBuilder{
			Config:     c.config,
			State:      c.state,
			Components: c.components,
			Schemas:    c.schemas,
			Targets:    c.targets,
			Validate:   opts.Validate,
		}).Build(addrs.RootModuleInstance)
	case GraphTypeRefresh:
		return (&RefreshGraphBuilder{
			Config:     c.config,
			State:      c.state,
			Components: c.components,
			Schemas:    c.schemas,
			Targets:    c.targets,
			Validate:   opts.Validate,
		}).Build(addrs.RootModuleInstance)
	case GraphTypeEval:
		return (&EvalGraphBuilder{
			Config:     c.config,
			State:      c.state,
			Components: c.components,
			Schemas:    c.schemas,
		}).Build(addrs.RootModuleInstance)
	default:
		panic(fmt.Errorf("unsupported graph type %s", typ))
	}
}
func (c *Context) ShadowError() error {
	return c.shadowErr
}
func (c *Context) State() *states.State {
	return c.state.DeepCopy()
}
func (c *Context) Eval(path addrs.ModuleInstance) (*lang.Scope, tfdiags.Diagnostics) {
	var diags tfdiags.Diagnostics
	defer c.acquireRun("eval")()
	c.state = c.state.DeepCopy()
	var walker *ContextGraphWalker
	graph, graphDiags := c.Graph(GraphTypeEval, nil)
	diags = diags.Append(graphDiags)
	if !diags.HasErrors() {
		var walkDiags tfdiags.Diagnostics
		walker, walkDiags = c.walk(graph, walkEval)
		diags = diags.Append(walker.NonFatalDiagnostics)
		diags = diags.Append(walkDiags)
	}
	if walker == nil {
		walker = c.graphWalker(walkEval)
	}
	evalCtx := walker.EnterPath(path)
	return evalCtx.EvaluationScope(nil, EvalDataForNoInstanceKey), diags
}
func (c *Context) Interpolater() *Interpolater {
	return &Interpolater{}
}