Example #1
0
func TestMeta_persistLocal(t *testing.T) {
	tmp, cwd := testCwd(t)
	defer testFixCwd(t, tmp, cwd)

	m := new(Meta)
	s := terraform.NewState()
	if err := m.persistLocalState(s); err != nil {
		t.Fatalf("err: %v", err)
	}

	exists, err := remote.ExistsFile(m.stateOutPath)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if !exists {
		t.Fatalf("state should exist")
	}

	// Write again, shoudl backup
	if err := m.persistLocalState(s); err != nil {
		t.Fatalf("err: %v", err)
	}

	exists, err = remote.ExistsFile(m.backupPath)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if !exists {
		t.Fatalf("backup should exist")
	}
}
Example #2
0
func TestMeta_persistRemote(t *testing.T) {
	tmp, cwd := testCwd(t)
	defer testFixCwd(t, tmp, cwd)

	err := remote.EnsureDirectory()
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	s := terraform.NewState()
	conf, srv := testRemoteState(t, s, 200)
	s.Remote = conf
	defer srv.Close()

	m := new(Meta)
	if err := m.persistRemoteState(s); err != nil {
		t.Fatalf("err: %v", err)
	}

	local, _, err := remote.ReadLocalState()
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if local == nil {
		t.Fatalf("state should exist")
	}

	if err := m.persistRemoteState(s); err != nil {
		t.Fatalf("err: %v", err)
	}

	backup := remote.LocalDirectory + "/" + remote.BackupHiddenStateFile
	exists, err := remote.ExistsFile(backup)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if !exists {
		t.Fatalf("backup should exist")
	}
}
Example #3
0
// Test enabling remote state
func TestRemote_enableRemote(t *testing.T) {
	tmp, cwd := testCwd(t)
	defer testFixCwd(t, tmp, cwd)

	// Create a non-remote enabled state
	s := terraform.NewState()
	s.Serial = 5

	// Add the state at the default path
	fh, err := os.Create(DefaultStateFilename)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	err = terraform.WriteState(s, fh)
	fh.Close()
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	ui := new(cli.MockUi)
	c := &RemoteCommand{
		Meta: Meta{
			ContextOpts: testCtxConfig(testProvider()),
			Ui:          ui,
		},
	}

	args := []string{
		"-backend=http",
		"-address",
		"http://example.com",
		"-access-token=test",
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
	}

	local, _, err := remote.ReadLocalState()
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	if local.Remote.Type != "http" {
		t.Fatalf("Bad: %#v", local.Remote)
	}
	if local.Remote.Config["address"] != "http://example.com" {
		t.Fatalf("Bad: %#v", local.Remote)
	}
	if local.Remote.Config["access_token"] != "test" {
		t.Fatalf("Bad: %#v", local.Remote)
	}

	// Backup file should exist
	exist, err := remote.ExistsFile(DefaultStateFilename + DefaultBackupExtention)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if !exist {
		t.Fatalf("backup should exist")
	}

	// State file should not
	exist, err = remote.ExistsFile(DefaultStateFilename)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if exist {
		t.Fatalf("state file should not exist")
	}
}
Example #4
0
// Test disabling remote management without pulling
func TestRemote_disable_noPull(t *testing.T) {
	tmp, cwd := testCwd(t)
	defer testFixCwd(t, tmp, cwd)

	// Create remote state file, this should be pulled
	s := terraform.NewState()
	s.Serial = 10
	conf, srv := testRemoteState(t, s, 200)
	defer srv.Close()

	// Persist local remote state
	s = terraform.NewState()
	s.Serial = 5
	s.Remote = conf
	if err := remote.EnsureDirectory(); err != nil {
		t.Fatalf("err: %v", err)
	}
	if err := remote.PersistState(s); err != nil {
		t.Fatalf("err: %v", err)
	}

	ui := new(cli.MockUi)
	c := &RemoteCommand{
		Meta: Meta{
			ContextOpts: testCtxConfig(testProvider()),
			Ui:          ui,
		},
	}
	args := []string{"-disable", "-pull=false"}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
	}

	// Local state file should be removed
	haveLocal, err := remote.HaveLocalState()
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if haveLocal {
		t.Fatalf("should be disabled")
	}

	// New state file should be installed
	exists, err := remote.ExistsFile(DefaultStateFilename)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if !exists {
		t.Fatalf("failed to make state file")
	}

	// Check that the state file was updated
	raw, _ := ioutil.ReadFile(DefaultStateFilename)
	newState, err := terraform.ReadState(bytes.NewReader(raw))
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	// Ensure we DIDNT updated
	// TODO: Should be 5, but WriteState currently increments
	// this which is incorrect.
	if newState.Serial != 7 {
		t.Fatalf("state file updated: %#v", newState)
	}
	if newState.Remote != nil {
		t.Fatalf("remote configuration not removed")
	}
}
Example #5
0
func (c *RemoteCommand) Run(args []string) int {
	args = c.Meta.process(args, false)
	var address, accessToken, name, path string
	cmdFlags := flag.NewFlagSet("remote", flag.ContinueOnError)
	cmdFlags.BoolVar(&c.conf.disableRemote, "disable", false, "")
	cmdFlags.BoolVar(&c.conf.pullOnDisable, "pull", true, "")
	cmdFlags.StringVar(&c.conf.statePath, "state", DefaultStateFilename, "path")
	cmdFlags.StringVar(&c.conf.backupPath, "backup", "", "path")
	cmdFlags.StringVar(&c.remoteConf.Type, "backend", "atlas", "")
	cmdFlags.StringVar(&address, "address", "", "")
	cmdFlags.StringVar(&accessToken, "access-token", "", "")
	cmdFlags.StringVar(&name, "name", "", "")
	cmdFlags.StringVar(&path, "path", "", "")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	// Show help if given no inputs
	if !c.conf.disableRemote && c.remoteConf.Type == "atlas" &&
		name == "" && accessToken == "" {
		cmdFlags.Usage()
		return 1
	}

	// Populate the various configurations
	c.remoteConf.Config = map[string]string{
		"address":      address,
		"access_token": accessToken,
		"name":         name,
		"path":         path,
	}

	// Check if have an existing local state file
	haveLocal, err := remote.HaveLocalState()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to check for local state: %v", err))
		return 1
	}

	// Check if we have the non-managed state file
	haveNonManaged, err := remote.ExistsFile(c.conf.statePath)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to check for state file: %v", err))
		return 1
	}

	// Check if remote state is being disabled
	if c.conf.disableRemote {
		if !haveLocal {
			c.Ui.Error(fmt.Sprintf("Remote state management not enabled! Aborting."))
			return 1
		}
		if haveNonManaged {
			c.Ui.Error(fmt.Sprintf("State file already exists at '%s'. Aborting.",
				c.conf.statePath))
			return 1
		}
		return c.disableRemoteState()
	}

	// Ensure there is no conflict
	switch {
	case haveLocal && haveNonManaged:
		c.Ui.Error(fmt.Sprintf("Remote state is enabled, but non-managed state file '%s' is also present!",
			c.conf.statePath))
		return 1

	case !haveLocal && !haveNonManaged:
		// If we don't have either state file, initialize a blank state file
		return c.initBlankState()

	case haveLocal && !haveNonManaged:
		// Update the remote state target potentially
		return c.updateRemoteConfig()

	case !haveLocal && haveNonManaged:
		// Enable remote state management
		return c.enableRemoteState()

	default:
		panic("unhandled case")
	}
	return 0
}