func (c *RemotePullCommand) 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 } // Read out our state s, err := c.State() if err != nil { c.Ui.Error(fmt.Sprintf("Failed to read state: %s", err)) return 1 } localState := s.State() // If remote state isn't enabled, it is a problem. if !localState.IsRemote() { c.Ui.Error("Remote state not enabled!") return 1 } // We need the CacheState structure in order to do anything var cache *state.CacheState if bs, ok := s.(*state.BackupState); ok { if cs, ok := bs.Real.(*state.CacheState); ok { cache = cs } } if cache == nil { c.Ui.Error(fmt.Sprintf( "Failed to extract internal CacheState from remote state.\n" + "This is an internal error, please report it as a bug.")) return 1 } // Refresh the state if err := cache.RefreshState(); err != nil { c.Ui.Error(fmt.Sprintf( "Failed to refresh from remote state: %s", err)) return 1 } // Use an error exit code if the update was not a success change := cache.RefreshResult() if !change.SuccessfulPull() { c.Ui.Error(fmt.Sprintf("%s", change)) return 1 } else { c.Ui.Output(c.Colorize().Color(fmt.Sprintf( "[reset][bold][green]%s", change))) } return 0 }
// State returns the proper state.State implementation to represent the // current environment. // // localPath is the path to where state would be if stored locally. // dataDir is the path to the local data directory where the remote state // cache would be stored. func State(opts *StateOpts) (*StateResult, error) { result := new(StateResult) // Get the remote state cache path if opts.RemotePath != "" { result.RemotePath = opts.RemotePath var remote *state.CacheState if opts.RemoteCacheOnly { // Setup the in-memory state ls := &state.LocalState{Path: opts.RemotePath} if err := ls.RefreshState(); err != nil { return nil, err } // If we have a forced state, set it if opts.ForceState != nil { ls.SetState(opts.ForceState) } is := &state.InmemState{} is.WriteState(ls.State()) // Setupt he remote state, cache-only, and refresh it so that // we have access to the state right away. remote = &state.CacheState{ Cache: ls, Durable: is, } if err := remote.RefreshState(); err != nil { return nil, err } } else { // If we have a forced state that is remote, then we load that if opts.ForceState != nil && opts.ForceState.Remote != nil && opts.ForceState.Remote.Type != "" { var err error remote, err = remoteState( opts.ForceState, opts.RemotePath, false) if err != nil { return nil, err } } else { // Only if we have no forced state, we check our normal // remote path. if _, err := os.Stat(opts.RemotePath); err == nil { // We have a remote state, initialize that. remote, err = remoteStateFromPath( opts.RemotePath, opts.RemoteRefresh) if err != nil { return nil, err } } } } if remote != nil { result.State = remote result.StatePath = opts.RemotePath result.Remote = remote } } // If we have a forced state and we were able to initialize that // into a remote state, we don't do any local state stuff. This is // because normally we're able to test whether we should do local vs. // remote by checking file existence. With ForceState, file existence // doesn't work because neither may exist, so we use state attributes. if opts.ForceState != nil && result.Remote != nil { opts.LocalPath = "" } // Do we have a local state? if opts.LocalPath != "" { local := &state.LocalState{ Path: opts.LocalPath, PathOut: opts.LocalPathOut, } // Always store it in the result even if we're not using it result.Local = local result.LocalPath = local.Path if local.PathOut != "" { result.LocalPath = local.PathOut } // If we're forcing, then set it if opts.ForceState != nil { local.SetState(opts.ForceState) } else { // If we're not forcing, then we load the state directly // from disk. err := local.RefreshState() if err == nil { if result.State != nil && !result.State.State().Empty() { if !local.State().Empty() { // We already have a remote state... that is an error. return nil, fmt.Errorf( "Remote state found, but state file '%s' also present.", opts.LocalPath) } // Empty state local = nil } } if err != nil { return nil, errwrap.Wrapf( "Error reading local state: {{err}}", err) } } if local != nil { result.State = local result.StatePath = opts.LocalPath if opts.LocalPathOut != "" { result.StatePath = opts.LocalPathOut } } } // If we have a result, make sure to back it up if result.State != nil { backupPath := result.StatePath + DefaultBackupExtension if opts.BackupPath != "" { backupPath = opts.BackupPath } if backupPath != "-" { result.State = &state.BackupState{ Real: result.State, Path: backupPath, } } } // Return whatever state we have return result, nil }
// State returns the proper state.State implementation to represent the // current environment. // // localPath is the path to where state would be if stored locally. // dataDir is the path to the local data directory where the remote state // cache would be stored. func State(opts *StateOpts) (*StateResult, error) { result := new(StateResult) // Get the remote state cache path if opts.RemotePath != "" { result.RemotePath = opts.RemotePath var remote *state.CacheState if opts.RemoteCacheOnly { // Setup the in-memory state ls := &state.LocalState{Path: opts.RemotePath} if err := ls.RefreshState(); err != nil { return nil, err } is := &state.InmemState{} is.WriteState(ls.State()) // Setupt he remote state, cache-only, and refresh it so that // we have access to the state right away. remote = &state.CacheState{ Cache: ls, Durable: is, } if err := remote.RefreshState(); err != nil { return nil, err } } else { if _, err := os.Stat(opts.RemotePath); err == nil { // We have a remote state, initialize that. remote, err = remoteStateFromPath( opts.RemotePath, opts.RemoteRefresh) if err != nil { return nil, err } } } if remote != nil { result.State = remote result.StatePath = opts.RemotePath result.Remote = remote } } // Do we have a local state? if opts.LocalPath != "" { local := &state.LocalState{ Path: opts.LocalPath, PathOut: opts.LocalPathOut, } // Always store it in the result even if we're not using it result.Local = local result.LocalPath = local.Path if local.PathOut != "" { result.LocalPath = local.PathOut } err := local.RefreshState() if err == nil { if result.State != nil && !result.State.State().Empty() { if !local.State().Empty() { // We already have a remote state... that is an error. return nil, fmt.Errorf( "Remote state found, but state file '%s' also present.", opts.LocalPath) } // Empty state local = nil } } if err != nil { return nil, errwrap.Wrapf( "Error reading local state: {{err}}", err) } if local != nil { result.State = local result.StatePath = opts.LocalPath if opts.LocalPathOut != "" { result.StatePath = opts.LocalPathOut } } } // If we have a result, make sure to back it up if result.State != nil { backupPath := result.StatePath + DefaultBackupExtention if opts.BackupPath != "" { backupPath = opts.BackupPath } if backupPath != "-" { result.State = &state.BackupState{ Real: result.State, Path: backupPath, } } } // Return whatever state we have return result, nil }