Exemple #1
0
func TestAtlasClient_NoConflict(t *testing.T) {
	fakeAtlas := newFakeAtlas(t, testStateSimple)
	srv := fakeAtlas.Server()
	defer srv.Close()
	client, err := atlasFactory(map[string]string{
		"access_token": "sometoken",
		"name":         "someuser/some-test-remote-state",
		"address":      srv.URL,
	})
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	state, err := terraform.ReadState(bytes.NewReader(testStateSimple))
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	fakeAtlas.NoConflictAllowed(true)

	var stateJson bytes.Buffer
	if err := terraform.WriteState(state, &stateJson); err != nil {
		t.Fatalf("err: %s", err)
	}

	if err := client.Put(stateJson.Bytes()); err != nil {
		t.Fatalf("err: %s", err)
	}
}
Exemple #2
0
func TestAtlasClient_LegitimateConflict(t *testing.T) {
	fakeAtlas := newFakeAtlas(t, testStateSimple)
	srv := fakeAtlas.Server()
	defer srv.Close()
	client, err := atlasFactory(map[string]string{
		"access_token": "sometoken",
		"name":         "someuser/some-test-remote-state",
		"address":      srv.URL,
	})
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	state, err := terraform.ReadState(bytes.NewReader(testStateSimple))
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	// Changing the state but not the serial. Should generate a conflict.
	state.RootModule().Outputs["drift"] = &terraform.OutputState{
		Type:      "string",
		Sensitive: false,
		Value:     "happens",
	}

	var stateJson bytes.Buffer
	if err := terraform.WriteState(state, &stateJson); err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := client.Put(stateJson.Bytes()); err == nil {
		t.Fatal("Expected error from state conflict, got none.")
	}
}
Exemple #3
0
func (f *fakeAtlas) CurrentState() *terraform.State {
	currentState, err := terraform.ReadState(bytes.NewReader(f.state))
	if err != nil {
		f.t.Fatalf("err: %s", err)
	}
	return currentState
}
func TestRefresh_cwd(t *testing.T) {
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := os.Chdir(testFixturePath("refresh")); err != nil {
		t.Fatalf("err: %s", err)
	}
	defer os.Chdir(cwd)

	state := &terraform.State{
		Resources: map[string]*terraform.ResourceState{
			"test_instance.foo": &terraform.ResourceState{
				ID:   "bar",
				Type: "test_instance",
			},
		},
	}
	statePath := testStateFile(t, state)

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

	p.RefreshFn = nil
	p.RefreshReturn = &terraform.ResourceState{ID: "yes"}

	args := []string{
		"-state", statePath,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if !p.RefreshCalled {
		t.Fatal("refresh should be called")
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	newState, err := terraform.ReadState(f)
	f.Close()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	actual := newState.Resources["test_instance.foo"]
	expected := p.RefreshReturn
	if !reflect.DeepEqual(actual, expected) {
		t.Fatalf("bad: %#v", actual)
	}
}
Exemple #5
0
// StateRefresher impl.
func (s *LocalState) RefreshState() error {
	// If we've never loaded before, read from Path, otherwise we
	// read from PathOut.
	path := s.Path
	if s.written && s.PathOut != "" {
		path = s.PathOut
	}

	f, err := os.Open(path)
	if err != nil {
		// It is okay if the file doesn't exist, we treat that as a nil state
		if !os.IsNotExist(err) {
			return err
		}

		f = nil
	}

	var state *terraform.State
	if f != nil {
		defer f.Close()
		state, err = terraform.ReadState(f)
		if err != nil {
			return err
		}
	}

	s.state = state
	s.readState = state
	return nil
}
Exemple #6
0
func (f *fakeAtlas) handler(resp http.ResponseWriter, req *http.Request) {
	switch req.Method {
	case "GET":
		// Respond with the current stored state.
		resp.Header().Set("Content-Type", "application/json")
		resp.Write(f.state)
	case "PUT":
		var buf bytes.Buffer
		buf.ReadFrom(req.Body)
		sum := md5.Sum(buf.Bytes())
		state, err := terraform.ReadState(&buf)
		if err != nil {
			f.t.Fatalf("err: %s", err)
		}
		conflict := f.CurrentSerial() == state.Serial && f.CurrentSum() != sum
		conflict = conflict || f.alwaysConflict
		if conflict {
			if f.noConflictAllowed {
				f.t.Fatal("Got conflict when NoConflictAllowed was set.")
			}
			http.Error(resp, "Conflict", 409)
		} else {
			f.state = buf.Bytes()
			resp.WriteHeader(200)
		}
	}
}
Exemple #7
0
func TestPlan_destroy(t *testing.T) {
	originalState := &terraform.State{
		Resources: map[string]*terraform.ResourceState{
			"test_instance.foo": &terraform.ResourceState{
				ID:   "bar",
				Type: "test_instance",
			},
		},
	}

	outPath := testTempFile(t)
	statePath := testStateFile(t, originalState)

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

	args := []string{
		"-destroy",
		"-out", outPath,
		"-state", statePath,
		testFixturePath("plan"),
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if !p.RefreshCalled {
		t.Fatal("refresh should be called")
	}

	plan := testReadPlan(t, outPath)
	for _, r := range plan.Diff.Resources {
		if !r.Destroy {
			t.Fatalf("bad: %#v", r)
		}
	}

	f, err := os.Open(statePath + DefaultBackupExtention)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	backupState, err := terraform.ReadState(f)
	f.Close()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	if !reflect.DeepEqual(backupState, originalState) {
		t.Fatalf("bad: %#v", backupState)
	}
}
Exemple #8
0
func ReadState(path string) (*terraform.State, error) {
	if f, err := os.Open(path); err != nil {
		return nil, err
	} else {
		defer f.Close()
		state, _ := terraform.ReadState(f)
		return state, nil
	}
}
Exemple #9
0
func readState(path string) (*terraform.State, error) {
	f, err := os.Open(path)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	return terraform.ReadState(f)
}
Exemple #10
0
func readState(path string) *terraform.State {
	f, _ := os.Open(path)
	if f != nil {
		defer f.Close()
		state, _ := terraform.ReadState(f)
		return state
	}
	return nil
}
func TestApply_planWithVarFile(t *testing.T) {
	varFileDir := testTempDir(t)
	varFilePath := filepath.Join(varFileDir, "terraform.tfvars")
	if err := ioutil.WriteFile(varFilePath, []byte(applyVarFile), 0644); err != nil {
		t.Fatalf("err: %s", err)
	}

	planPath := testPlanFile(t, &terraform.Plan{
		Module: testModule(t, "apply"),
	})
	statePath := testTempFile(t)

	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := os.Chdir(varFileDir); err != nil {
		t.Fatalf("err: %s", err)
	}
	defer os.Chdir(cwd)

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

	args := []string{
		"-state", statePath,
		planPath,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if _, err := os.Stat(statePath); err != nil {
		t.Fatalf("err: %s", err)
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer f.Close()

	state, err := terraform.ReadState(f)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if state == nil {
		t.Fatal("state should not be nil")
	}
}
Exemple #12
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
}
Exemple #13
0
func (c *OutputCommand) Run(args []string) int {
	var statePath string

	args = c.Meta.process(args, false)

	cmdFlags := flag.NewFlagSet("output", flag.ContinueOnError)
	cmdFlags.StringVar(&statePath, "state", DefaultStateFilename, "path")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	args = cmdFlags.Args()
	if len(args) != 1 || args[0] == "" {
		c.Ui.Error(
			"The output command expects exactly one argument with the name\n" +
				"of an output variable.\n")
		cmdFlags.Usage()
		return 1
	}
	name := args[0]

	f, err := os.Open(statePath)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error loading file: %s", err))
		return 1
	}

	state, err := terraform.ReadState(f)
	f.Close()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Error reading state: %s", err))
		return 1
	}

	if len(state.Outputs) == 0 {
		c.Ui.Error(fmt.Sprintf(
			"The state file has no outputs defined. Define an output\n" +
				"in your configuration with the `output` directive and re-run\n" +
				"`terraform apply` for it to become available."))
		return 1
	}
	v, ok := state.Outputs[name]
	if !ok {
		c.Ui.Error(fmt.Sprintf(
			"The output variable requested could not be found in the state\n" +
				"file. If you recently added this to your configuration, be\n" +
				"sure to run `terraform apply`, since the state won't be updated\n" +
				"with new output variables until that command is run."))
		return 1
	}

	c.Ui.Output(v)
	return 0
}
Exemple #14
0
// laodState is used to load the Terraform state. We give precedence
// to a remote state if enabled, and then check the normal state path.
func (m *Meta) loadState() (*terraform.State, error) {
	// Check if we remote state is enabled
	localCache, _, err := remote.ReadLocalState()
	if err != nil {
		return nil, fmt.Errorf("Error loading state: %s", err)
	}

	// Set the state if enabled
	var state *terraform.State
	if localCache != nil {
		// Refresh the state
		log.Printf("[INFO] Refreshing local state...")
		changes, err := remote.RefreshState(localCache.Remote)
		if err != nil {
			return nil, fmt.Errorf("Failed to refresh state: %v", err)
		}
		switch changes {
		case remote.StateChangeNoop:
		case remote.StateChangeInit:
		case remote.StateChangeLocalNewer:
		case remote.StateChangeUpdateLocal:
			// Reload the state since we've udpated
			localCache, _, err = remote.ReadLocalState()
			if err != nil {
				return nil, fmt.Errorf("Error loading state: %s", err)
			}
		default:
			return nil, fmt.Errorf("%s", changes)
		}

		state = localCache
		m.useRemoteState = true
	}

	// Load up the state
	if m.statePath != "" {
		f, err := os.Open(m.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 m.useRemoteState && err == nil {
			err = fmt.Errorf("Remote state enabled, but state file '%s' also present.", m.statePath)
			f.Close()
		} else if err == nil {
			state, err = terraform.ReadState(f)
			f.Close()
		}
		if err != nil {
			return nil, fmt.Errorf("Error loading state: %s", err)
		}
	}
	return state, nil
}
Exemple #15
0
// Atlas returns an HTTP 409 - Conflict if the pushed state reports the same
// Serial number but the checksum of the raw content differs. This can
// sometimes happen when Terraform changes state representation internally
// between versions in a way that's semantically neutral but affects the JSON
// output and therefore the checksum.
//
// Here we detect and handle this situation by ticking the serial and retrying
// iff for the previous state and the proposed state:
//
//   * the serials match
//   * the parsed states are Equal (semantically equivalent)
//
// In other words, in this situation Terraform can override Atlas's detected
// conflict by asserting that the state it is pushing is indeed correct.
func (c *AtlasClient) handleConflict(msg string, state []byte) error {
	log.Printf("[DEBUG] Handling Atlas conflict response: %s", msg)

	if c.conflictHandlingAttempted {
		log.Printf("[DEBUG] Already attempted conflict resolution; returning conflict.")
	} else {
		c.conflictHandlingAttempted = true
		log.Printf("[DEBUG] Atlas reported conflict, checking for equivalent states.")

		payload, err := c.Get()
		if err != nil {
			return conflictHandlingError(err)
		}

		currentState, err := terraform.ReadState(bytes.NewReader(payload.Data))
		if err != nil {
			return conflictHandlingError(err)
		}

		proposedState, err := terraform.ReadState(bytes.NewReader(state))
		if err != nil {
			return conflictHandlingError(err)
		}

		if statesAreEquivalent(currentState, proposedState) {
			log.Printf("[DEBUG] States are equivalent, incrementing serial and retrying.")
			proposedState.Serial++
			var buf bytes.Buffer
			if err := terraform.WriteState(proposedState, &buf); err != nil {
				return conflictHandlingError(err)

			}
			return c.Put(buf.Bytes())
		} else {
			log.Printf("[DEBUG] States are not equivalent, returning conflict.")
		}
	}

	return fmt.Errorf(
		"Atlas detected a remote state conflict.\n\nMessage: %s", msg)
}
Exemple #16
0
func TestRefresh_cwd(t *testing.T) {
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := os.Chdir(testFixturePath("refresh")); err != nil {
		t.Fatalf("err: %s", err)
	}
	defer os.Chdir(cwd)

	state := testState()
	statePath := testStateFile(t, state)

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

	p.RefreshFn = nil
	p.RefreshReturn = &terraform.InstanceState{ID: "yes"}

	args := []string{
		"-state", statePath,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if !p.RefreshCalled {
		t.Fatal("refresh should be called")
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	newState, err := terraform.ReadState(f)
	f.Close()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	actual := strings.TrimSpace(newState.String())
	expected := strings.TrimSpace(testRefreshCwdStr)
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}
// Test disabling remote management
func TestRemoteConfig_disable(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

	// Write the state
	statePath := filepath.Join(tmp, DefaultDataDir, DefaultStateFilename)
	state := &state.LocalState{Path: statePath}
	if err := state.WriteState(s); err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := state.PersistState(); err != nil {
		t.Fatalf("err: %s", err)
	}

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

	// Local state file should be removed and the local cache should exist
	testRemoteLocal(t, true)
	testRemoteLocalCache(t, false)

	// 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 updated
	if newState.Remote != nil {
		t.Fatalf("remote configuration not removed")
	}
}
func TestApply_plan(t *testing.T) {
	// Disable test mode so input would be asked
	test = false
	defer func() { test = true }()

	// Set some default reader/writers for the inputs
	defaultInputReader = new(bytes.Buffer)
	defaultInputWriter = new(bytes.Buffer)

	planPath := testPlanFile(t, &terraform.Plan{
		Module: testModule(t, "apply"),
	})
	statePath := testTempFile(t)

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

	args := []string{
		"-state", statePath,
		planPath,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if p.InputCalled {
		t.Fatalf("input should not be called for plans")
	}

	if _, err := os.Stat(statePath); err != nil {
		t.Fatalf("err: %s", err)
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer f.Close()

	state, err := terraform.ReadState(f)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if state == nil {
		t.Fatal("state should not be nil")
	}
}
Exemple #19
0
// Function fetchState takes a directory name (a string) and returns
// an instance of *terraform.State based on what it finds in that
// directory and an error.
func fetchState(dir string) (*terraform.State, error) {
	src, err := openState(dir)
	if err != nil {
		return nil, err
	}
	defer src.Close()

	state, err := terraform.ReadState(src)
	if err != nil {
		return nil, errors.New(fmt.Sprintf("Unable to read state from src"))
	}
	return state, nil
}
Exemple #20
0
func TestRefresh_futureState(t *testing.T) {
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := os.Chdir(testFixturePath("refresh")); err != nil {
		t.Fatalf("err: %s", err)
	}
	defer os.Chdir(cwd)

	state := testState()
	state.TFVersion = "99.99.99"
	statePath := testStateFile(t, state)

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

	args := []string{
		"-state", statePath,
	}
	if code := c.Run(args); code == 0 {
		t.Fatal("should fail")
	}

	if p.RefreshCalled {
		t.Fatal("refresh should not be called")
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	newState, err := terraform.ReadState(f)
	f.Close()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	actual := strings.TrimSpace(newState.String())
	expected := strings.TrimSpace(state.String())
	if actual != expected {
		t.Fatalf("bad:\n\n%s", actual)
	}
}
Exemple #21
0
func TestApply_defaultState(t *testing.T) {
	td, err := ioutil.TempDir("", "tf")
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	statePath := filepath.Join(td, DefaultStateFilename)

	// Change to the temporary directory
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := os.Chdir(filepath.Dir(statePath)); err != nil {
		t.Fatalf("err: %s", err)
	}
	defer os.Chdir(cwd)

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

	args := []string{
		testFixturePath("apply"),
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if _, err := os.Stat(statePath); err != nil {
		t.Fatalf("err: %s", err)
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer f.Close()

	state, err := terraform.ReadState(f)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if state == nil {
		t.Fatal("state should not be nil")
	}
}
Exemple #22
0
func TestPersist(t *testing.T) {
	tmp, cwd := testDir(t)
	defer testFixCwd(tmp, cwd)

	EnsureDirectory()

	// Place old state file, should backup
	old := filepath.Join(tmp, LocalDirectory, HiddenStateFile)
	ioutil.WriteFile(old, []byte("test"), 0777)

	remote := &terraform.RemoteState{
		Type: "http",
		Config: map[string]string{
			"address": "http://foo.com/",
		},
	}
	blank, _ := blankState(remote)
	if err := Persist(bytes.NewReader(blank)); err != nil {
		t.Fatalf("err: %v", err)
	}

	// Check for backup
	backup := filepath.Join(tmp, LocalDirectory, BackupHiddenStateFile)
	out, err := ioutil.ReadFile(backup)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	if string(out) != "test" {
		t.Fatalf("bad: %v", out)
	}

	// Read the state
	out, err = ioutil.ReadFile(old)
	if err != nil {
		t.Fatalf("Err: %v", err)
	}
	s, err := terraform.ReadState(bytes.NewReader(out))
	if err != nil {
		t.Fatalf("Err: %v", err)
	}

	// Check the remote
	if !remote.Equals(s.Remote) {
		t.Fatalf("remote mismatch")
	}
}
Exemple #23
0
func TestApply_noArgs(t *testing.T) {
	cwd, err := os.Getwd()
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if err := os.Chdir(testFixturePath("plan")); err != nil {
		t.Fatalf("err: %s", err)
	}
	defer os.Chdir(cwd)

	statePath := testTempFile(t)

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

	args := []string{
		"-state", statePath,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if _, err := os.Stat(statePath); err != nil {
		t.Fatalf("err: %s", err)
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer f.Close()

	state, err := terraform.ReadState(f)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if state == nil {
		t.Fatal("state should not be nil")
	}
}
Exemple #24
0
// StateRefresher impl.
func (s *State) RefreshState() error {
	payload, err := s.Client.Get()
	if err != nil {
		return err
	}

	var state *terraform.State
	if payload != nil {
		state, err = terraform.ReadState(bytes.NewReader(payload.Data))
		if err != nil {
			return err
		}
	}

	s.state = state
	s.readState = state
	return nil
}
Exemple #25
0
// testStateOutput tests that the state at the given path contains
// the expected state string.
func testStateOutput(t *testing.T, path string, expected string) {
	f, err := os.Open(path)
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	newState, err := terraform.ReadState(f)
	f.Close()
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	actual := strings.TrimSpace(newState.String())
	expected = strings.TrimSpace(expected)
	if actual != expected {
		t.Fatalf("expected:\n%s\nactual:\n%s", expected, actual)
	}
}
Exemple #26
0
// testReadLocal is used to just get the local state
func testReadLocal(t *testing.T) *terraform.State {
	path, err := HiddenStatePath()
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	raw, err := ioutil.ReadFile(path)
	if err != nil && !os.IsNotExist(err) {
		t.Fatalf("err: %v", err)
	}
	if raw == nil {
		return nil
	}
	s, err := terraform.ReadState(bytes.NewReader(raw))
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	return s
}
Exemple #27
0
func TestBlankState(t *testing.T) {
	remote := &terraform.RemoteState{
		Type: "http",
		Config: map[string]string{
			"address": "http://foo.com/",
		},
	}
	r, err := blankState(remote)
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	s, err := terraform.ReadState(bytes.NewReader(r))
	if err != nil {
		t.Fatalf("err: %v", err)
	}
	if !remote.Equals(s.Remote) {
		t.Fatalf("remote mismatch")
	}
}
Exemple #28
0
// StateRefresher impl.
func (s *State) RefreshState() error {
	payload, err := s.Client.Get()
	if err != nil {
		return err
	}

	// no remote state is OK
	if payload == nil {
		return nil
	}

	state, err := terraform.ReadState(bytes.NewReader(payload.Data))
	if err != nil {
		return err
	}

	s.state = state
	s.readState = state
	return nil
}
Exemple #29
0
func TestApply_plan(t *testing.T) {
	planPath := testPlanFile(t, &terraform.Plan{
		Config: new(config.Config),
	})
	statePath := testTempFile(t)

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

	args := []string{
		"-state", statePath,
		planPath,
	}
	if code := c.Run(args); code != 0 {
		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
	}

	if _, err := os.Stat(statePath); err != nil {
		t.Fatalf("err: %s", err)
	}

	f, err := os.Open(statePath)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	defer f.Close()

	state, err := terraform.ReadState(f)
	if err != nil {
		t.Fatalf("err: %s", err)
	}
	if state == nil {
		t.Fatal("state should not be nil")
	}
}
Exemple #30
0
func TestAtlasClient_UnresolvableConflict(t *testing.T) {
	fakeAtlas := newFakeAtlas(t, testStateSimple)

	// Something unexpected causes Atlas to conflict in a way that we can't fix.
	fakeAtlas.AlwaysConflict(true)

	srv := fakeAtlas.Server()
	defer srv.Close()
	client, err := atlasFactory(map[string]string{
		"access_token": "sometoken",
		"name":         "someuser/some-test-remote-state",
		"address":      srv.URL,
	})
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	state, err := terraform.ReadState(bytes.NewReader(testStateSimple))
	if err != nil {
		t.Fatalf("err: %s", err)
	}

	var stateJson bytes.Buffer
	if err := terraform.WriteState(state, &stateJson); err != nil {
		t.Fatalf("err: %s", err)
	}
	doneCh := make(chan struct{})
	go func() {
		defer close(doneCh)
		if err := client.Put(stateJson.Bytes()); err == nil {
			t.Fatal("Expected error from state conflict, got none.")
		}
	}()

	select {
	case <-doneCh:
		// OK
	case <-time.After(500 * time.Millisecond):
		t.Fatalf("Timed out after 500ms, probably because retrying infinitely.")
	}
}