// 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 }
// 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 }
func testReadPlan(t *testing.T, path string) *terraform.Plan { f, err := os.Open(path) if err != nil { t.Fatalf("err: %s", err) } defer f.Close() p, err := terraform.ReadPlan(f) if err != nil { t.Fatalf("err: %s", err) } return p }
// Plan plans the operation accoring to the given content func (c *KodingContext) Plan(content io.Reader, destroy bool) (*terraform.Plan, error) { cmd := &command.PlanCommand{ Meta: command.Meta{ ContextOpts: c.TerraformContextOpts(), Ui: c.ui, }, } paths, err := c.run(cmd, content, destroy, c.populatePlanArgs) if err != nil { return nil, err } planFile, err := os.Open(paths.planPath) if err != nil { return nil, err } defer planFile.Close() return terraform.ReadPlan(planFile) }
func TestPlan_outPath(t *testing.T) { tf, err := ioutil.TempFile("", "tf") if err != nil { t.Fatalf("err: %s", err) } outPath := tf.Name() os.Remove(tf.Name()) p := testProvider() ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ ContextOpts: testCtxConfig(p), Ui: ui, }, } p.DiffReturn = &terraform.ResourceDiff{ Destroy: true, } args := []string{ "-out", outPath, testFixturePath("plan"), } if code := c.Run(args); code != 0 { t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } f, err := os.Open(outPath) if err != nil { t.Fatalf("err: %s", err) } defer f.Close() if _, err := terraform.ReadPlan(f); err != nil { t.Fatalf("err: %s", err) } }
// 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 }
func (c *ShowCommand) Run(args []string) int { var moduleDepth int args = c.Meta.process(args, false) cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError) c.addModuleDepthFlag(cmdFlags, &moduleDepth) cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } if err := cmdFlags.Parse(args); err != nil { return 1 } args = cmdFlags.Args() if len(args) > 1 { c.Ui.Error( "The show command expects at most one argument with the path\n" + "to a Terraform state or plan file.\n") cmdFlags.Usage() return 1 } var planErr, stateErr error var path string var plan *terraform.Plan var state *terraform.State if len(args) > 0 { path = args[0] f, err := os.Open(path) if err != nil { c.Ui.Error(fmt.Sprintf("Error loading file: %s", err)) return 1 } defer f.Close() plan, err = terraform.ReadPlan(f) if err != nil { if _, err := f.Seek(0, 0); err != nil { c.Ui.Error(fmt.Sprintf("Error reading file: %s", err)) return 1 } plan = nil planErr = err } if plan == nil { state, err = terraform.ReadState(f) if err != nil { stateErr = err } } } else { stateOpts := c.StateOpts() stateOpts.RemoteCacheOnly = true result, err := State(stateOpts) if err != nil { c.Ui.Error(fmt.Sprintf("Error reading state: %s", err)) return 1 } state = result.State.State() if state == nil { c.Ui.Output("No state.") return 0 } } if plan == nil && state == nil { c.Ui.Error(fmt.Sprintf( "Terraform couldn't read the given file as a state or plan file.\n"+ "The errors while attempting to read the file as each format are\n"+ "shown below.\n\n"+ "State read error: %s\n\nPlan read error: %s", stateErr, planErr)) return 1 } if plan != nil { c.Ui.Output(FormatPlan(&FormatPlanOpts{ Plan: plan, Color: c.Colorize(), ModuleDepth: moduleDepth, })) return 0 } c.Ui.Output(FormatState(&FormatStateOpts{ State: state, Color: c.Colorize(), ModuleDepth: moduleDepth, })) return 0 }
// 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 }
func (c *ShowCommand) Run(args []string) int { args = c.Meta.process(args) cmdFlags := flag.NewFlagSet("show", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } if err := cmdFlags.Parse(args); err != nil { return 1 } args = cmdFlags.Args() if len(args) != 1 { c.Ui.Error( "The show command expects exactly one argument with the path\n" + "to a Terraform state or plan file.\n") cmdFlags.Usage() return 1 } path := args[0] var plan *terraform.Plan var state *terraform.State f, err := os.Open(path) if err != nil { c.Ui.Error(fmt.Sprintf("Error loading file: %s", err)) return 1 } var planErr, stateErr error plan, err = terraform.ReadPlan(f) if err != nil { if _, err := f.Seek(0, 0); err != nil { c.Ui.Error(fmt.Sprintf("Error reading file: %s", err)) return 1 } plan = nil planErr = err } if plan == nil { state, err = terraform.ReadState(f) if err != nil { stateErr = err } } if plan == nil && state == nil { c.Ui.Error(fmt.Sprintf( "Terraform couldn't read the given file as a state or plan file.\n"+ "The errors while attempting to read the file as each format are\n"+ "shown below.\n\n"+ "State read error: %s\n\nPlan read error: %s", stateErr, planErr)) return 1 } if plan != nil { c.Ui.Output(FormatPlan(plan, c.Colorize())) return 0 } c.Ui.Output(FormatState(state, c.Colorize())) return 0 }