示例#1
0
// 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
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 {
			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
0
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
}
示例#4
0
文件: plan.go 项目: koding/koding
// 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)
}
示例#5
0
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)
	}
}
示例#6
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
			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
}
示例#7
0
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
}
示例#8
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
}
示例#9
0
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
}