Пример #1
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
}
Пример #2
0
func (c *PullCommand) Run(args []string) int {
	args = c.Meta.process(args, false)
	cmdFlags := flag.NewFlagSet("pull", flag.ContinueOnError)
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		return 1
	}

	// Recover the local state if any
	local, _, err := remote.ReadLocalState()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("%s", err))
		return 1
	}
	if local == nil || local.Remote == nil {
		c.Ui.Error("Remote state not enabled!")
		return 1
	}

	// Attempt the state refresh
	change, err := remote.RefreshState(local.Remote)
	if err != nil {
		c.Ui.Error(fmt.Sprintf(
			"Failed to refresh from remote state: %v", err))
		return 1
	}

	// Use an error exit code if the update was not a success
	if !change.SuccessfulPull() {
		c.Ui.Error(fmt.Sprintf("%s", change))
		return 1
	} else {
		c.Ui.Output(fmt.Sprintf("%s", change))
	}
	return 0
}
Пример #3
0
// disableRemoteState is used to disable remote state management,
// and move the state file into place.
func (c *RemoteCommand) disableRemoteState() int {
	// Get the local state
	local, _, err := remote.ReadLocalState()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to read local state: %v", err))
		return 1
	}

	// Ensure we have the latest state before disabling
	if c.conf.pullOnDisable {
		log.Printf("[INFO] Refreshing local state from remote server")
		change, err := remote.RefreshState(local.Remote)
		if err != nil {
			c.Ui.Error(fmt.Sprintf(
				"Failed to refresh from remote state: %v", err))
			return 1
		}

		// Exit if we were unable to update
		if !change.SuccessfulPull() {
			c.Ui.Error(fmt.Sprintf("%s", change))
			return 1
		} else {
			log.Printf("[INFO] %s", change)
		}

		// Reload the local state after the refresh
		local, _, err = remote.ReadLocalState()
		if err != nil {
			c.Ui.Error(fmt.Sprintf("Failed to read local state: %v", err))
			return 1
		}
	}

	// Clear the remote management, and copy into place
	local.Remote = nil
	fh, err := os.Create(c.conf.statePath)
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to create state file '%s': %v",
			c.conf.statePath, err))
		return 1
	}
	defer fh.Close()
	if err := terraform.WriteState(local, fh); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to encode state file '%s': %v",
			c.conf.statePath, err))
		return 1
	}

	// Remove the old state file
	path, err := remote.HiddenStatePath()
	if err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to get local state path: %v", err))
		return 1
	}
	if err := os.Remove(path); err != nil {
		c.Ui.Error(fmt.Sprintf("Failed to remove the local state file: %v", err))
		return 1
	}
	return 0
}