func (c *Context) Module() *module.Tree {
	return c.module
}
Module returns the module tree associated with this context.
package terraform
import (
	"context"
	"fmt"
	"log"
	"sort"
	"strings"
	"sync"
	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/hcl"
	"github.com/hashicorp/terraform/config"
	"github.com/hashicorp/terraform/config/module"
	"github.com/hashicorp/terraform/helper/experiment"
)
type InputMode byte
const (
	InputModeVar InputMode = 1 << iota
	InputModeVarUnset
	InputModeProvider
	InputModeStd = InputModeVar | InputModeProvider
)
var (
	contextFailOnShadowError = false
	contextTestDeepCopyOnPlan = false
)
type ContextOpts struct {
	Meta               *ContextMeta
	Destroy            bool
	Diff               *Diff
	Hooks              []Hook
	Module             *module.Tree
	Parallelism        int
	State              *State
	StateFutureAllowed bool
	Providers          map[string]ResourceProviderFactory
	Provisioners       map[string]ResourceProvisionerFactory
	Shadow             bool
	Targets            []string
	Variables          map[string]interface{}
	UIInput UIInput
}
type ContextMeta struct {
	Env string  
}
type Context struct {
	components contextComponentFactory
	destroy    bool
	diff       *Diff
	diffLock   sync.RWMutex
	hooks      []Hook
	meta       *ContextMeta
	module     *module.Tree
	sh         *stopHook
	shadow     bool
	state      *State
	stateLock  sync.RWMutex
	targets    []string
	uiInput    UIInput
	variables  map[string]interface{}
	l                   sync.Mutex  
	parallelSem         Semaphore
	providerInputConfig map[string]map[string]interface{}
	runLock             sync.Mutex
	runCond             *sync.Cond
	runContext          context.Context
	runContextCancel    context.CancelFunc
	shadowErr           error
}
func NewContext(opts *ContextOpts) (*Context, error) {
	if opts.Module != nil {
		if err := checkRequiredVersion(opts.Module); err != nil {
			return nil, err
		}
	}
	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 = new(State)
		state.init()
	}
	if !opts.StateFutureAllowed && state.FromFutureTerraform() {
		return nil, fmt.Errorf(
			"Terraform doesn't allow running any operations against a state\n"+
				"that was written by a future Terraform version. The state is\n"+
				"reporting it is written by Terraform '%s'.\n\n"+
				"Please run at least that version of Terraform to continue.",
			state.TFVersion)
	}
	state.TFVersion = Version
	par := opts.Parallelism
	if par == 0 {
		par = 10
	}
	variables := make(map[string]interface{})
	if opts.Module != nil {
		var err error
		variables, err = Variables(opts.Module, opts.Variables)
		if err != nil {
			return nil, err
		}
	}
	diff := opts.Diff
	if diff == nil {
		diff = &Diff{}
	}
	return &Context{
		components: &basicComponentFactory{
			providers:    opts.Providers,
			provisioners: opts.Provisioners,
		},
		destroy:   opts.Destroy,
		diff:      diff,
		hooks:     hooks,
		meta:      opts.Meta,
		module:    opts.Module,
		shadow:    opts.Shadow,
		state:     state,
		targets:   opts.Targets,
		uiInput:   opts.UIInput,
		variables: variables,
		parallelSem:         NewSemaphore(par),
		providerInputConfig: make(map[string]map[string]interface{}),
		sh:                  sh,
	}, nil
}
type ContextGraphOpts struct {
	Validate bool
	Verbose bool
}
func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, error) {
	if opts == nil {
		opts = &ContextGraphOpts{Validate: true}
	}
	log.Printf("[INFO] terraform: building graph: %s", typ)
	switch typ {
	case GraphTypeApply:
		return (&ApplyGraphBuilder{
			Module:       c.module,
			Diff:         c.diff,
			State:        c.state,
			Providers:    c.components.ResourceProviders(),
			Provisioners: c.components.ResourceProvisioners(),
			Targets:      c.targets,
			Destroy:      c.destroy,
			Validate:     opts.Validate,
		}).Build(RootModulePath)
	case GraphTypeInput:
		fallthrough
	case GraphTypeValidate:
		fallthrough
	case GraphTypePlan:
		p := &PlanGraphBuilder{
			Module:    c.module,
			State:     c.state,
			Providers: c.components.ResourceProviders(),
			Targets:   c.targets,
			Validate:  opts.Validate,
		}
		var b GraphBuilder = p
		switch typ {
		case GraphTypeInput:
			b = InputGraphBuilder(p)
		case GraphTypeValidate:
			p.Provisioners = c.components.ResourceProvisioners()
			b = ValidateGraphBuilder(p)
		}
		return b.Build(RootModulePath)
	case GraphTypePlanDestroy:
		return (&DestroyPlanGraphBuilder{
			Module:   c.module,
			State:    c.state,
			Targets:  c.targets,
			Validate: opts.Validate,
		}).Build(RootModulePath)
	case GraphTypeRefresh:
		return (&RefreshGraphBuilder{
			Module:    c.module,
			State:     c.state,
			Providers: c.components.ResourceProviders(),
			Targets:   c.targets,
			Validate:  opts.Validate,
		}).Build(RootModulePath)
	}
	return nil, fmt.Errorf("unknown graph type: %s", typ)
}
func (c *Context) ShadowError() error {
	return c.shadowErr
}
func (c *Context) State() *State {
	return c.state.DeepCopy()
}
func (c *Context) Interpolater() *Interpolater {
	var varLock sync.Mutex
	var stateLock sync.RWMutex
	return &Interpolater{
		Operation:          walkApply,
		Meta:               c.meta,
		Module:             c.module,
		State:              c.state.DeepCopy(),
		StateLock:          &stateLock,
		VariableValues:     c.variables,
		VariableValuesLock: &varLock,
	}
}
func (c *Context) Input(mode InputMode) error {
	defer c.acquireRun("input")()
	if mode&InputModeVar != 0 {
		rootConf := c.module.Config()
		names := make([]string, len(rootConf.Variables))
		m := make(map[string]*config.Variable)
		for i, v := range rootConf.Variables {
			names[i] = v.Name
			m[v.Name] = v
		}
		sort.Strings(names)
		for _, n := range names {
			if mode&InputModeVarUnset != 0 {
				if _, ok := c.variables[n]; ok {
					continue
				}
			}
			var valueType config.VariableType
			v := m[n]
			switch valueType = v.Type(); valueType {
			case config.VariableTypeUnknown:
				continue
			case config.VariableTypeMap:
			case config.VariableTypeList:
			case config.VariableTypeString:
			default:
				panic(fmt.Sprintf("Unknown variable type: %#v", v.Type()))
			}
			if _, ok := c.variables[n]; !ok {
				if v.Default != nil {
					c.variables[n] = v.Default.(string)
					continue
				}
			}
			if c.uiInput == nil {
				log.Println("[WARN] Content.uiInput is nil")
				continue
			}
			var value string
			retry := 0
			for {
				var err error
				value, err = c.uiInput.Input(&InputOpts{
					Id:          fmt.Sprintf("var.%s", n),
					Query:       fmt.Sprintf("var.%s", n),
					Description: v.Description,
				})
				if err != nil {
					return fmt.Errorf(
						"Error asking for %s: %s", n, err)
				}
				if value == "" && v.Required() {
					if retry > 2 {
						return fmt.Errorf("missing required value for %q", n)
					}
					retry++
					continue
				}
				break
			}
			if value == "" {
				continue
			}
			decoded, err := parseVariableAsHCL(n, value, valueType)
			if err != nil {
				return err
			}
			if decoded != nil {
				c.variables[n] = decoded
			}
		}
	}
	if mode&InputModeProvider != 0 {
		graph, err := c.Graph(GraphTypeInput, nil)
		if err != nil {
			return err
		}
		if _, err := c.walk(graph, nil, walkInput); err != nil {
			return err
		}
	}
	return nil
}
func (c *Context) Apply() (*State, error) {
	defer c.acquireRun("apply")()
	c.state = c.state.DeepCopy()
	graph, err := c.Graph(GraphTypeApply, nil)
	if err != nil {
		return nil, err
	}
	operation := walkApply
	if c.destroy {
		operation = walkDestroy
	}
	walker, err := c.walk(graph, graph, operation)
	if len(walker.ValidationErrors) > 0 {
		err = multierror.Append(err, walker.ValidationErrors...)
	}
	c.state.prune()
	return c.state, err
}
func (c *Context) Plan() (*Plan, error) {
	defer c.acquireRun("plan")()
	p := &Plan{
		Module:  c.module,
		Vars:    c.variables,
		State:   c.state,
		Targets: c.targets,
	}
	var operation walkOperation
	if c.destroy {
		operation = walkPlanDestroy
	} else {
		old := c.state
		if old == nil {
			c.state = &State{}
			c.state.init()
		} else {
			c.state = old.DeepCopy()
		}
		defer func() {
			c.state = old
		}()
		operation = walkPlan
	}
	c.diffLock.Lock()
	c.diff = new(Diff)
	c.diff.init()
	c.diffLock.Unlock()
	graphType := GraphTypePlan
	if c.destroy {
		graphType = GraphTypePlanDestroy
	}
	graph, err := c.Graph(graphType, nil)
	if err != nil {
		return nil, err
	}
	walker, err := c.walk(graph, graph, operation)
	if err != nil {
		return nil, err
	}
	p.Diff = c.diff
	if contextTestDeepCopyOnPlan {
		p.Diff.DeepCopy()
	}
	var errs error
	if len(walker.ValidationErrors) > 0 {
		errs = multierror.Append(errs, walker.ValidationErrors...)
	}
	return p, errs
}
func (c *Context) Refresh() (*State, error) {
	defer c.acquireRun("refresh")()
	c.state = c.state.DeepCopy()
	graph, err := c.Graph(GraphTypeRefresh, nil)
	if err != nil {
		return nil, err
	}
	if _, err := c.walk(graph, graph, walkRefresh); err != nil {
		return nil, err
	}
	c.state.prune()
	return c.state, nil
}
func (c *Context) Stop() {
	log.Printf("[WARN] terraform: Stop called, initiating interrupt sequence")
	c.l.Lock()
	defer c.l.Unlock()
	if c.runContextCancel != nil {
		log.Printf("[WARN] terraform: run context exists, stopping")
		c.sh.Stop()
		c.runContextCancel()
		c.runContextCancel = nil
	}
	if cond := c.runCond; cond != nil {
		cond.Wait()
	}
	log.Printf("[WARN] terraform: stop complete")
}
func (c *Context) Validate() ([]string, []error) {
	defer c.acquireRun("validate")()
	var errs error
	if err := c.module.Validate(); err != nil {
		errs = multierror.Append(errs, err)
	}
	if config := c.module.Config(); config != nil {
		if err := smcUserVariables(config, c.variables); len(err) > 0 {
			errs = multierror.Append(errs, err...)
		}
	}
	if errs != nil {
		return nil, []error{errs}
	}
	graph, err := c.Graph(GraphTypeValidate, nil)
	if err != nil {
		return nil, []error{err}
	}
	walker, err := c.walk(graph, graph, walkValidate)
	if err != nil {
		return nil, multierror.Append(errs, err).Errors
	}
	rerrs := multierror.Append(errs, walker.ValidationErrors...)
	sort.Strings(walker.ValidationWarnings)
	sort.Slice(rerrs.Errors, func(i, j int) bool {
		return rerrs.Errors[i].Error() < rerrs.Errors[j].Error()
	})
	return walker.ValidationWarnings, rerrs.Errors
}