本文整理匯總了Golang中github.com/hashicorp/terraform/terraform.NewContext函數的典型用法代碼示例。如果您正苦於以下問題:Golang NewContext函數的具體用法?Golang NewContext怎麽用?Golang NewContext使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了NewContext函數的12個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: Context
// Context returns a Terraform Context taking into account the context
// options used to initialize this meta configuration.
func (m *Meta) Context(path, statePath string) (*terraform.Context, bool, error) {
opts := m.contextOpts()
// First try to just read the plan directly from the path given.
f, err := os.Open(path)
if err == nil {
plan, err := terraform.ReadPlan(f)
f.Close()
if err == nil {
if len(m.variables) > 0 {
return nil, false, fmt.Errorf(
"You can't set variables with the '-var' or '-var-file' flag\n" +
"when you're applying a plan file. The variables used when\n" +
"the plan was created will be used. If you wish to use different\n" +
"variable values, create a new plan file.")
}
return plan.Context(opts), true, nil
}
}
// Load up the state
var state *terraform.State
if statePath != "" {
f, err := os.Open(statePath)
if err != nil && os.IsNotExist(err) {
// If the state file doesn't exist, it is okay, since it
// is probably a new infrastructure.
err = nil
} else if err == nil {
state, err = terraform.ReadState(f)
f.Close()
}
if err != nil {
return nil, false, fmt.Errorf("Error loading state: %s", err)
}
}
// Store the loaded state
m.state = state
config, err := config.LoadDir(path)
if err != nil {
return nil, false, fmt.Errorf("Error loading config: %s", err)
}
if err := config.Validate(); err != nil {
return nil, false, fmt.Errorf("Error validating config: %s", err)
}
opts.Config = config
opts.State = state
ctx := terraform.NewContext(opts)
return ctx, false, nil
}
示例2: Context
// Context returns a Terraform Context taking into account the context
// options used to initialize this meta configuration.
func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
opts := m.contextOpts()
// First try to just read the plan directly from the path given.
f, err := os.Open(copts.Path)
if err == nil {
plan, err := terraform.ReadPlan(f)
f.Close()
if err == nil {
if len(m.variables) > 0 {
return nil, false, fmt.Errorf(
"You can't set variables with the '-var' or '-var-file' flag\n" +
"when you're applying a plan file. The variables used when\n" +
"the plan was created will be used. If you wish to use different\n" +
"variable values, create a new plan file.")
}
return plan.Context(opts), true, nil
}
}
// Load the statePath if not given
if copts.StatePath != "" {
m.statePath = copts.StatePath
}
// Store the loaded state
state, err := m.loadState()
if err != nil {
return nil, false, err
}
m.state = state
// Load the root module
mod, err := module.NewTreeModule("", copts.Path)
if err != nil {
return nil, false, fmt.Errorf("Error loading config: %s", err)
}
dataDir := DefaultDataDirectory
if m.dataDir != "" {
dataDir = m.dataDir
}
err = mod.Load(m.moduleStorage(dataDir), copts.GetMode)
if err != nil {
return nil, false, fmt.Errorf("Error downloading modules: %s", err)
}
opts.Module = mod
opts.State = state
ctx := terraform.NewContext(opts)
return ctx, false, nil
}
示例3: testSession
func testSession(t *testing.T, test testSessionTest) {
// Build the TF context
ctx, err := terraform.NewContext(&terraform.ContextOpts{
State: test.State,
Module: module.NewEmptyTree(),
})
if err != nil {
t.Fatalf("err: %s", err)
}
// Build the session
s := &Session{
Interpolater: ctx.Interpolater(),
}
// Test the inputs. We purposely don't use subtests here because
// the inputs don't recognize subtests, but a sequence of stateful
// operations.
for _, input := range test.Inputs {
result, err := s.Handle(input.Input)
if (err != nil) != input.Error {
t.Fatalf("%q: err: %s", input.Input, err)
}
if err != nil {
if input.ErrorContains != "" {
if !strings.Contains(err.Error(), input.ErrorContains) {
t.Fatalf(
"%q: err should contain: %q\n\n%s",
input.Input, input.ErrorContains, err)
}
}
continue
}
if input.Output != "" && result != input.Output {
t.Fatalf(
"%q: expected:\n\n%s\n\ngot:\n\n%s",
input.Input, input.Output, result)
}
if input.OutputContains != "" && !strings.Contains(result, input.OutputContains) {
t.Fatalf(
"%q: expected contains:\n\n%s\n\ngot:\n\n%s",
input.Input, input.OutputContains, result)
}
}
}
示例4: Context
// Context returns a Terraform Context taking into account the context
// options used to initialize this meta configuration.
func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
opts := m.contextOpts()
// First try to just read the plan directly from the path given.
f, err := os.Open(copts.Path)
if err == nil {
plan, err := terraform.ReadPlan(f)
f.Close()
if err == nil {
// Setup our state
state, statePath, err := StateFromPlan(m.statePath, m.stateOutPath, plan)
if err != nil {
return nil, false, fmt.Errorf("Error loading plan: %s", err)
}
// Set our state
m.state = state
// this is used for printing the saved location later
if m.stateOutPath == "" {
m.stateOutPath = statePath
}
if len(m.variables) > 0 {
return nil, false, fmt.Errorf(
"You can't set variables with the '-var' or '-var-file' flag\n" +
"when you're applying a plan file. The variables used when\n" +
"the plan was created will be used. If you wish to use different\n" +
"variable values, create a new plan file.")
}
ctx, err := plan.Context(opts)
return ctx, true, err
}
}
// Load the statePath if not given
if copts.StatePath != "" {
m.statePath = copts.StatePath
}
// Tell the context if we're in a destroy plan / apply
opts.Destroy = copts.Destroy
// Store the loaded state
state, err := m.State()
if err != nil {
return nil, false, err
}
// Load the root module
var mod *module.Tree
if copts.Path != "" {
mod, err = module.NewTreeModule("", copts.Path)
if err != nil {
return nil, false, fmt.Errorf("Error loading config: %s", err)
}
} else {
mod = module.NewEmptyTree()
}
err = mod.Load(m.moduleStorage(m.DataDir()), copts.GetMode)
if err != nil {
return nil, false, fmt.Errorf("Error downloading modules: %s", err)
}
opts.Module = mod
opts.Parallelism = copts.Parallelism
opts.State = state.State()
ctx, err := terraform.NewContext(opts)
return ctx, false, err
}
示例5: testStep
func testStep(
opts terraform.ContextOpts,
state *terraform.State,
step TestStep) (*terraform.State, error) {
mod, err := testModule(opts, step)
if err != nil {
return state, err
}
// Build the context
opts.Module = mod
opts.State = state
opts.Destroy = step.Destroy
ctx := terraform.NewContext(&opts)
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
if len(es) > 0 {
estrs := make([]string, len(es))
for i, e := range es {
estrs[i] = e.Error()
}
return state, fmt.Errorf(
"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
ws, estrs)
}
log.Printf("[WARN] Config warnings: %#v", ws)
}
// Refresh!
state, err = ctx.Refresh()
if err != nil {
return state, fmt.Errorf(
"Error refreshing: %s", err)
}
// Plan!
if p, err := ctx.Plan(); err != nil {
return state, fmt.Errorf(
"Error planning: %s", err)
} else {
log.Printf("[WARN] Test: Step plan: %s", p)
}
// We need to keep a copy of the state prior to destroying
// such that destroy steps can verify their behaviour in the check
// function
stateBeforeApplication := state.DeepCopy()
// Apply!
state, err = ctx.Apply()
if err != nil {
return state, fmt.Errorf("Error applying: %s", err)
}
// Check! Excitement!
if step.Check != nil {
if step.Destroy {
if err := step.Check(stateBeforeApplication); err != nil {
return state, fmt.Errorf("Check failed: %s", err)
}
} else {
if err := step.Check(state); err != nil {
return state, fmt.Errorf("Check failed: %s", err)
}
}
}
// Now, verify that Plan is now empty and we don't have a perpetual diff issue
// We do this with TWO plans. One without a refresh.
var p *terraform.Plan
if p, err = ctx.Plan(); err != nil {
return state, fmt.Errorf("Error on follow-up plan: %s", err)
}
if p.Diff != nil && !p.Diff.Empty() {
if step.ExpectNonEmptyPlan {
log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
} else {
return state, fmt.Errorf(
"After applying this step, the plan was not empty:\n\n%s", p)
}
}
// And another after a Refresh.
state, err = ctx.Refresh()
if err != nil {
return state, fmt.Errorf(
"Error on follow-up refresh: %s", err)
}
if p, err = ctx.Plan(); err != nil {
return state, fmt.Errorf("Error on second follow-up plan: %s", err)
}
if p.Diff != nil && !p.Diff.Empty() {
if step.ExpectNonEmptyPlan {
log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
} else {
return state, fmt.Errorf(
"After applying this step and refreshing, "+
"the plan was not empty:\n\n%s", p)
}
}
//.........這裏部分代碼省略.........
示例6: testIDOnlyRefresh
func testIDOnlyRefresh(c TestCase, opts terraform.ContextOpts, step TestStep, r *terraform.ResourceState) error {
// TODO: We guard by this right now so master doesn't explode. We
// need to remove this eventually to make this part of the normal tests.
if os.Getenv("TF_ACC_IDONLY") == "" {
return nil
}
name := fmt.Sprintf("%s.foo", r.Type)
// Build the state. The state is just the resource with an ID. There
// are no attributes. We only set what is needed to perform a refresh.
state := terraform.NewState()
state.RootModule().Resources[name] = &terraform.ResourceState{
Type: r.Type,
Primary: &terraform.InstanceState{
ID: r.Primary.ID,
},
}
// Create the config module. We use the full config because Refresh
// doesn't have access to it and we may need things like provider
// configurations. The initial implementation of id-only checks used
// an empty config module, but that caused the aforementioned problems.
mod, err := testModule(opts, step)
if err != nil {
return err
}
// Initialize the context
opts.Module = mod
opts.State = state
ctx := terraform.NewContext(&opts)
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
if len(es) > 0 {
estrs := make([]string, len(es))
for i, e := range es {
estrs[i] = e.Error()
}
return fmt.Errorf(
"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
ws, estrs)
}
log.Printf("[WARN] Config warnings: %#v", ws)
}
// Refresh!
state, err = ctx.Refresh()
if err != nil {
return fmt.Errorf("Error refreshing: %s", err)
}
// Verify attribute equivalence.
actualR := state.RootModule().Resources[name]
if actualR == nil {
return fmt.Errorf("Resource gone!")
}
if actualR.Primary == nil {
return fmt.Errorf("Resource has no primary instance")
}
actual := actualR.Primary.Attributes
expected := r.Primary.Attributes
// Remove fields we're ignoring
for _, v := range c.IDRefreshIgnore {
delete(actual, v)
delete(expected, v)
}
if !reflect.DeepEqual(actual, expected) {
// Determine only the different attributes
for k, v := range expected {
if av, ok := actual[k]; ok && v == av {
delete(expected, k)
delete(actual, k)
}
}
spewConf := spew.NewDefaultConfig()
spewConf.SortKeys = true
return fmt.Errorf(
"Attributes not equivalent. Difference is shown below. Top is actual, bottom is expected."+
"\n\n%s\n\n%s",
spewConf.Sdump(actual), spewConf.Sdump(expected))
}
return nil
}
示例7: testStepImportState
// testStepImportState runs an imort state test step
func testStepImportState(
opts terraform.ContextOpts,
state *terraform.State,
step TestStep) (*terraform.State, error) {
// Determine the ID to import
importId := step.ImportStateId
if importId == "" {
resource, err := testResource(step, state)
if err != nil {
return state, err
}
importId = resource.Primary.ID
}
// Setup the context. We initialize with an empty state. We use the
// full config for provider configurations.
mod, err := testModule(opts, step)
if err != nil {
return state, err
}
opts.Module = mod
opts.State = terraform.NewState()
ctx, err := terraform.NewContext(&opts)
if err != nil {
return state, err
}
// Do the import!
newState, err := ctx.Import(&terraform.ImportOpts{
// Set the module so that any provider config is loaded
Module: mod,
Targets: []*terraform.ImportTarget{
&terraform.ImportTarget{
Addr: step.ResourceName,
ID: importId,
},
},
})
if err != nil {
log.Printf("[ERROR] Test: ImportState failure: %s", err)
return state, err
}
// Go through the new state and verify
if step.ImportStateCheck != nil {
var states []*terraform.InstanceState
for _, r := range newState.RootModule().Resources {
if r.Primary != nil {
states = append(states, r.Primary)
}
}
if err := step.ImportStateCheck(states); err != nil {
return state, err
}
}
// Verify that all the states match
if step.ImportStateVerify {
new := newState.RootModule().Resources
old := state.RootModule().Resources
for _, r := range new {
// Find the existing resource
var oldR *terraform.ResourceState
for _, r2 := range old {
if r2.Primary != nil && r2.Primary.ID == r.Primary.ID {
oldR = r2
break
}
}
if oldR == nil {
return state, fmt.Errorf(
"Failed state verification, resource with ID %s not found",
r.Primary.ID)
}
// Compare their attributes
actual := make(map[string]string)
for k, v := range r.Primary.Attributes {
actual[k] = v
}
expected := make(map[string]string)
for k, v := range oldR.Primary.Attributes {
expected[k] = v
}
// Remove fields we're ignoring
for _, v := range step.ImportStateVerifyIgnore {
for k, _ := range actual {
if strings.HasPrefix(k, v) {
delete(actual, k)
}
}
for k, _ := range expected {
if strings.HasPrefix(k, v) {
delete(expected, k)
}
//.........這裏部分代碼省略.........
示例8: testStep
func testStep(
opts terraform.ContextOpts,
state *terraform.State,
step TestStep) (*terraform.State, error) {
// Write the configuration
cfgF, err := ioutil.TempFile("", "tf-test")
if err != nil {
return state, fmt.Errorf(
"Error creating temporary file for config: %s", err)
}
cfgPath := cfgF.Name() + ".tf"
cfgF.Close()
os.Remove(cfgF.Name())
cfgF, err = os.Create(cfgPath)
if err != nil {
return state, fmt.Errorf(
"Error creating temporary file for config: %s", err)
}
defer os.Remove(cfgPath)
_, err = io.Copy(cfgF, strings.NewReader(step.Config))
cfgF.Close()
if err != nil {
return state, fmt.Errorf(
"Error creating temporary file for config: %s", err)
}
// Parse the configuration
config, err := config.Load(cfgPath)
if err != nil {
return state, fmt.Errorf(
"Error parsing configuration: %s", err)
}
// Build the context
opts.Config = config
opts.State = state
ctx := terraform.NewContext(&opts)
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
estrs := make([]string, len(es))
for i, e := range es {
estrs[i] = e.Error()
}
return state, fmt.Errorf(
"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
ws, estrs)
}
// Refresh!
state, err = ctx.Refresh()
if err != nil {
return state, fmt.Errorf(
"Error refreshing: %s", err)
}
// Plan!
if p, err := ctx.Plan(&terraform.PlanOpts{Destroy: step.Destroy}); err != nil {
return state, fmt.Errorf(
"Error planning: %s", err)
} else {
log.Printf("[WARN] Test: Step plan: %s", p)
}
// Apply!
state, err = ctx.Apply()
if err != nil {
return state, fmt.Errorf("Error applying: %s", err)
}
// Check! Excitement!
if step.Check != nil {
if err = step.Check(state); err != nil {
err = fmt.Errorf("Check failed: %s", err)
}
}
return state, err
}
示例9: testStep
func testStep(
opts terraform.ContextOpts,
state *terraform.State,
step TestStep) (*terraform.State, error) {
cfgPath, err := ioutil.TempDir("", "tf-test")
if err != nil {
return state, fmt.Errorf(
"Error creating temporary directory for config: %s", err)
}
defer os.RemoveAll(cfgPath)
// Write the configuration
cfgF, err := os.Create(filepath.Join(cfgPath, "main.tf"))
if err != nil {
return state, fmt.Errorf(
"Error creating temporary file for config: %s", err)
}
_, err = io.Copy(cfgF, strings.NewReader(step.Config))
cfgF.Close()
if err != nil {
return state, fmt.Errorf(
"Error creating temporary file for config: %s", err)
}
// Parse the configuration
mod, err := module.NewTreeModule("", cfgPath)
if err != nil {
return state, fmt.Errorf(
"Error loading configuration: %s", err)
}
// Load the modules
modStorage := &module.FolderStorage{
StorageDir: filepath.Join(cfgPath, ".tfmodules"),
}
err = mod.Load(modStorage, module.GetModeGet)
if err != nil {
return state, fmt.Errorf("Error downloading modules: %s", err)
}
// Build the context
opts.Module = mod
opts.State = state
opts.Destroy = step.Destroy
ctx := terraform.NewContext(&opts)
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
estrs := make([]string, len(es))
for i, e := range es {
estrs[i] = e.Error()
}
return state, fmt.Errorf(
"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
ws, estrs)
}
// Refresh!
state, err = ctx.Refresh()
if err != nil {
return state, fmt.Errorf(
"Error refreshing: %s", err)
}
// Plan!
if p, err := ctx.Plan(); err != nil {
return state, fmt.Errorf(
"Error planning: %s", err)
} else {
log.Printf("[WARN] Test: Step plan: %s", p)
}
// Apply!
state, err = ctx.Apply()
if err != nil {
return state, fmt.Errorf("Error applying: %s", err)
}
// Check! Excitement!
if step.Check != nil {
if err = step.Check(state); err != nil {
err = fmt.Errorf("Check failed: %s", err)
}
}
return state, err
}
示例10: Context
// Context returns a Terraform Context taking into account the context
// options used to initialize this meta configuration.
func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
opts := m.contextOpts()
// First try to just read the plan directly from the path given.
f, err := os.Open(copts.Path)
if err == nil {
plan, err := terraform.ReadPlan(f)
f.Close()
if err == nil {
// Setup our state, force it to use our plan's state
stateOpts := m.StateOpts()
if plan != nil {
stateOpts.ForceState = plan.State
}
// Get the state
result, err := State(stateOpts)
if err != nil {
return nil, false, fmt.Errorf("Error loading plan: %s", err)
}
// Set our state
m.state = result.State
// this is used for printing the saved location later
if m.stateOutPath == "" {
m.stateOutPath = result.StatePath
}
if len(m.variables) > 0 {
return nil, false, fmt.Errorf(
"You can't set variables with the '-var' or '-var-file' flag\n" +
"when you're applying a plan file. The variables used when\n" +
"the plan was created will be used. If you wish to use different\n" +
"variable values, create a new plan file.")
}
ctx, err := plan.Context(opts)
return ctx, true, err
}
}
// Load the statePath if not given
if copts.StatePath != "" {
m.statePath = copts.StatePath
}
// Tell the context if we're in a destroy plan / apply
opts.Destroy = copts.Destroy
// Store the loaded state
state, err := m.State()
if err != nil {
return nil, false, err
}
// Load the root module
var mod *module.Tree
if copts.Path != "" {
mod, err = module.NewTreeModule("", copts.Path)
// Check for the error where we have no config files but
// allow that. If that happens, clear the error.
if errwrap.ContainsType(err, new(config.ErrNoConfigsFound)) &&
copts.PathEmptyOk {
log.Printf(
"[WARN] Empty configuration dir, ignoring: %s", copts.Path)
err = nil
mod = module.NewEmptyTree()
}
if err != nil {
return nil, false, fmt.Errorf("Error loading config: %s", err)
}
} else {
mod = module.NewEmptyTree()
}
err = mod.Load(m.moduleStorage(m.DataDir()), copts.GetMode)
if err != nil {
return nil, false, fmt.Errorf("Error downloading modules: %s", err)
}
// Validate the module right away
if err := mod.Validate(); err != nil {
return nil, false, err
}
opts.Module = mod
opts.Parallelism = copts.Parallelism
opts.State = state.State()
ctx, err := terraform.NewContext(opts)
return ctx, false, err
}
示例11: testStep
func testStep(
opts terraform.ContextOpts,
state *terraform.State,
step TestStep) (*terraform.State, error) {
mod, err := testModule(opts, step)
if err != nil {
return state, err
}
// Build the context
opts.Module = mod
opts.State = state
opts.Destroy = step.Destroy
ctx, err := terraform.NewContext(&opts)
if err != nil {
return state, fmt.Errorf("Error initializing context: %s", err)
}
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
if len(es) > 0 {
estrs := make([]string, len(es))
for i, e := range es {
estrs[i] = e.Error()
}
return state, fmt.Errorf(
"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
ws, estrs)
}
log.Printf("[WARN] Config warnings: %#v", ws)
}
// Refresh!
state, err = ctx.Refresh()
if err != nil {
return state, fmt.Errorf(
"Error refreshing: %s", err)
}
// Plan!
if p, err := ctx.Plan(); err != nil {
return state, fmt.Errorf(
"Error planning: %s", err)
} else {
log.Printf("[WARN] Test: Step plan: %s", p)
}
// We need to keep a copy of the state prior to destroying
// such that destroy steps can verify their behaviour in the check
// function
stateBeforeApplication := state.DeepCopy()
// Apply!
state, err = ctx.Apply()
if err != nil {
return state, fmt.Errorf("Error applying: %s", err)
}
// Check! Excitement!
if step.Check != nil {
if step.Destroy {
if err := step.Check(stateBeforeApplication); err != nil {
return state, fmt.Errorf("Check failed: %s", err)
}
} else {
if err := step.Check(state); err != nil {
return state, fmt.Errorf("Check failed: %s", err)
}
}
}
// Now, verify that Plan is now empty and we don't have a perpetual diff issue
// We do this with TWO plans. One without a refresh.
var p *terraform.Plan
if p, err = ctx.Plan(); err != nil {
return state, fmt.Errorf("Error on follow-up plan: %s", err)
}
if p.Diff != nil && !p.Diff.Empty() {
if step.ExpectNonEmptyPlan {
log.Printf("[INFO] Got non-empty plan, as expected:\n\n%s", p)
} else {
return state, fmt.Errorf(
"After applying this step, the plan was not empty:\n\n%s", p)
}
}
// And another after a Refresh.
state, err = ctx.Refresh()
if err != nil {
return state, fmt.Errorf(
"Error on follow-up refresh: %s", err)
}
if p, err = ctx.Plan(); err != nil {
return state, fmt.Errorf("Error on second follow-up plan: %s", err)
}
empty := p.Diff == nil || p.Diff.Empty()
// Data resources are tricky because they legitimately get instantiated
// during refresh so that they will be already populated during the
// plan walk. Because of this, if we have any data resources in the
// config we'll end up wanting to destroy them again here. This is
// acceptable and expected, and we'll treat it as "empty" for the
//.........這裏部分代碼省略.........
示例12: testStep
func testStep(
opts terraform.ContextOpts,
state *terraform.State,
step TestStep) (*terraform.State, error) {
if step.PreConfig != nil {
step.PreConfig()
}
cfgPath, err := ioutil.TempDir("", "tf-test")
if err != nil {
return state, fmt.Errorf(
"Error creating temporary directory for config: %s", err)
}
defer os.RemoveAll(cfgPath)
// Write the configuration
cfgF, err := os.Create(filepath.Join(cfgPath, "main.tf"))
if err != nil {
return state, fmt.Errorf(
"Error creating temporary file for config: %s", err)
}
_, err = io.Copy(cfgF, strings.NewReader(step.Config))
cfgF.Close()
if err != nil {
return state, fmt.Errorf(
"Error creating temporary file for config: %s", err)
}
// Parse the configuration
mod, err := module.NewTreeModule("", cfgPath)
if err != nil {
return state, fmt.Errorf(
"Error loading configuration: %s", err)
}
// Load the modules
modStorage := &getter.FolderStorage{
StorageDir: filepath.Join(cfgPath, ".tfmodules"),
}
err = mod.Load(modStorage, module.GetModeGet)
if err != nil {
return state, fmt.Errorf("Error downloading modules: %s", err)
}
// Build the context
opts.Module = mod
opts.State = state
opts.Destroy = step.Destroy
ctx := terraform.NewContext(&opts)
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
if len(es) > 0 {
estrs := make([]string, len(es))
for i, e := range es {
estrs[i] = e.Error()
}
return state, fmt.Errorf(
"Configuration is invalid.\n\nWarnings: %#v\n\nErrors: %#v",
ws, estrs)
}
log.Printf("[WARN] Config warnings: %#v", ws)
}
// Refresh!
state, err = ctx.Refresh()
if err != nil {
return state, fmt.Errorf(
"Error refreshing: %s", err)
}
// Plan!
if p, err := ctx.Plan(); err != nil {
return state, fmt.Errorf(
"Error planning: %s", err)
} else {
log.Printf("[WARN] Test: Step plan: %s", p)
}
// We need to keep a copy of the state prior to destroying
// such that destroy steps can verify their behaviour in the check
// function
stateBeforeApplication := state.DeepCopy()
// Apply!
state, err = ctx.Apply()
if err != nil {
return state, fmt.Errorf("Error applying: %s", err)
}
// Check! Excitement!
if step.Check != nil {
if step.Destroy {
if err := step.Check(stateBeforeApplication); err != nil {
return state, fmt.Errorf("Check failed: %s", err)
}
} else {
if err := step.Check(state); err != nil {
return state, fmt.Errorf("Check failed: %s", err)
}
}
//.........這裏部分代碼省略.........