command/remote: no more remote package
This commit is contained in:
parent
3bf59183b8
commit
2c2b560d7f
|
@ -24,6 +24,7 @@ type Meta struct {
|
|||
// State read when calling `Context`. This is available after calling
|
||||
// `Context`.
|
||||
state state.State
|
||||
stateResult *StateResult
|
||||
|
||||
// This can be set by the command itself to provide extra hooks.
|
||||
extraHooks []terraform.Hook
|
||||
|
@ -174,25 +175,45 @@ func (m *Meta) State() (state.State, error) {
|
|||
return m.state, nil
|
||||
}
|
||||
|
||||
result, err := State(m.StateOpts())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.state = result.State
|
||||
m.stateOutPath = result.StatePath
|
||||
m.stateResult = result
|
||||
return m.state, nil
|
||||
}
|
||||
|
||||
// StateRaw is used to setup the state manually.
|
||||
func (m *Meta) StateRaw(opts *StateOpts) (*StateResult, error) {
|
||||
result, err := State(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.state = result.State
|
||||
m.stateOutPath = result.StatePath
|
||||
m.stateResult = result
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// StateOpts returns the default state options
|
||||
func (m *Meta) StateOpts() *StateOpts {
|
||||
localPath := m.statePath
|
||||
if localPath == "" {
|
||||
localPath = DefaultStateFilename
|
||||
}
|
||||
remotePath := filepath.Join(DefaultDataDir, DefaultStateFilename)
|
||||
|
||||
state, statePath, err := State(&StateOpts{
|
||||
return &StateOpts{
|
||||
LocalPath: localPath,
|
||||
LocalPathOut: m.stateOutPath,
|
||||
RemotePath: remotePath,
|
||||
RemoteRefresh: true,
|
||||
BackupPath: m.backupPath,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
m.state = state
|
||||
m.stateOutPath = statePath
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// UIInput returns a UIInput object to be used for asking for input.
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/terraform/remote"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
|
@ -55,6 +54,9 @@ func (c *RemoteCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
// Set the local state path
|
||||
c.statePath = c.conf.statePath
|
||||
|
||||
// Populate the various configurations
|
||||
c.remoteConf.Config = map[string]string{
|
||||
"address": address,
|
||||
|
@ -63,50 +65,56 @@ func (c *RemoteCommand) Run(args []string) int {
|
|||
"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))
|
||||
// Get the state information. We specifically request the cache only
|
||||
// for the remote state here because it is possible the remote state
|
||||
// is invalid and we don't want to error.
|
||||
stateOpts := c.StateOpts()
|
||||
stateOpts.RemoteCacheOnly = true
|
||||
if _, err := c.StateRaw(stateOpts); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error loading local state: %s", 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
|
||||
// Get the local and remote [cached] state
|
||||
localState := c.stateResult.Local.State()
|
||||
var remoteState *terraform.State
|
||||
if remote := c.stateResult.Remote; remote != nil {
|
||||
remoteState = remote.State()
|
||||
}
|
||||
|
||||
// Check if remote state is being disabled
|
||||
if c.conf.disableRemote {
|
||||
if !haveLocal {
|
||||
if !remoteState.IsRemote() {
|
||||
c.Ui.Error(fmt.Sprintf("Remote state management not enabled! Aborting."))
|
||||
return 1
|
||||
}
|
||||
if haveNonManaged {
|
||||
if !localState.Empty() {
|
||||
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
|
||||
haveCache := !remoteState.Empty()
|
||||
haveLocal := !localState.Empty()
|
||||
switch {
|
||||
case haveLocal && haveNonManaged:
|
||||
case haveCache && haveLocal:
|
||||
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:
|
||||
case !haveCache && !haveLocal:
|
||||
// If we don't have either state file, initialize a blank state file
|
||||
return c.initBlankState()
|
||||
|
||||
case haveLocal && !haveNonManaged:
|
||||
case haveCache && !haveLocal:
|
||||
// Update the remote state target potentially
|
||||
return c.updateRemoteConfig()
|
||||
|
||||
case !haveLocal && haveNonManaged:
|
||||
case !haveCache && haveLocal:
|
||||
// Enable remote state management
|
||||
return c.enableRemoteState()
|
||||
}
|
||||
|
@ -117,71 +125,66 @@ func (c *RemoteCommand) Run(args []string) int {
|
|||
// 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))
|
||||
if c.stateResult == nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Internal error. State() must be called internally before remote\n" +
|
||||
"state can be disabled. Please report this as a bug."))
|
||||
return 1
|
||||
}
|
||||
if !c.stateResult.State.State().IsRemote() {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Remote state is not enabled. Can't disable remote state."))
|
||||
return 1
|
||||
}
|
||||
local := c.stateResult.Local
|
||||
remote := c.stateResult.Remote
|
||||
|
||||
// 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 {
|
||||
if err := remote.RefreshState(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Failed to refresh from remote state: %v", err))
|
||||
"Failed to refresh from remote state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Exit if we were unable to update
|
||||
if !change.SuccessfulPull() {
|
||||
if change := remote.RefreshResult(); !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",
|
||||
newState := remote.State()
|
||||
newState.Remote = nil
|
||||
if err := local.WriteState(newState); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to encode state file '%s': %s",
|
||||
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",
|
||||
if err := local.PersistState(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to encode state file '%s': %s",
|
||||
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 {
|
||||
if err := os.Remove(c.stateResult.RemotePath); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to remove the local state file: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// validateRemoteConfig is used to verify that the remote configuration
|
||||
// we have is valid
|
||||
func (c *RemoteCommand) validateRemoteConfig() error {
|
||||
err := remote.ValidConfig(&c.remoteConf)
|
||||
conf := c.remoteConf
|
||||
_, err := remote.NewClient(conf.Type, conf.Config)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("%s", err))
|
||||
}
|
||||
|
@ -196,18 +199,17 @@ func (c *RemoteCommand) initBlankState() int {
|
|||
return 1
|
||||
}
|
||||
|
||||
// Make the hidden directory
|
||||
if err := remote.EnsureDirectory(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("%s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Make a blank state, attach the remote configuration
|
||||
blank := terraform.NewState()
|
||||
blank.Remote = &c.remoteConf
|
||||
|
||||
// Persist the state
|
||||
if err := remote.PersistState(blank); err != nil {
|
||||
remote := &state.LocalState{Path: c.stateResult.RemotePath}
|
||||
if err := remote.WriteState(blank); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to initialize state file: %v", err))
|
||||
return 1
|
||||
}
|
||||
if err := remote.PersistState(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to initialize state file: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
@ -225,16 +227,17 @@ func (c *RemoteCommand) updateRemoteConfig() int {
|
|||
return 1
|
||||
}
|
||||
|
||||
// Read in the local state
|
||||
local, _, err := remote.ReadLocalState()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to read local state: %v", err))
|
||||
return 1
|
||||
}
|
||||
// Read in the local state, which is just the cache of the remote state
|
||||
remote := c.stateResult.Remote.Cache
|
||||
|
||||
// Update the configuration
|
||||
local.Remote = &c.remoteConf
|
||||
if err := remote.PersistState(local); err != nil {
|
||||
state := remote.State()
|
||||
state.Remote = &c.remoteConf
|
||||
if err := remote.WriteState(state); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("%s", err))
|
||||
return 1
|
||||
}
|
||||
if err := remote.PersistState(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("%s", err))
|
||||
return 1
|
||||
}
|
||||
|
@ -252,21 +255,10 @@ func (c *RemoteCommand) enableRemoteState() int {
|
|||
return 1
|
||||
}
|
||||
|
||||
// Make the hidden directory
|
||||
if err := remote.EnsureDirectory(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("%s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Read the provided state file
|
||||
raw, err := ioutil.ReadFile(c.conf.statePath)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to read '%s': %v", c.conf.statePath, err))
|
||||
return 1
|
||||
}
|
||||
state, err := terraform.ReadState(bytes.NewReader(raw))
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to decode '%s': %v", c.conf.statePath, err))
|
||||
// Read the local state
|
||||
local := c.stateResult.Local
|
||||
if err := local.RefreshState(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to read local state: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -279,25 +271,31 @@ func (c *RemoteCommand) enableRemoteState() int {
|
|||
}
|
||||
|
||||
log.Printf("[INFO] Writing backup state to: %s", backupPath)
|
||||
f, err := os.Create(backupPath)
|
||||
if err == nil {
|
||||
err = terraform.WriteState(state, f)
|
||||
f.Close()
|
||||
backup := &state.LocalState{Path: backupPath}
|
||||
if err := backup.WriteState(local.State()); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing backup state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
if err != nil {
|
||||
if err := backup.PersistState(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error writing backup state file: %s", err))
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
// Update the local configuration, move into place
|
||||
state := local.State()
|
||||
state.Remote = &c.remoteConf
|
||||
if err := remote.PersistState(state); err != nil {
|
||||
remote := c.stateResult.Remote
|
||||
if err := remote.WriteState(state); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("%s", err))
|
||||
return 1
|
||||
}
|
||||
if err := remote.PersistState(); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("%s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Remove the state file
|
||||
// Remove the original, local state file
|
||||
log.Printf("[INFO] Removing state file: %s", c.conf.statePath)
|
||||
if err := os.Remove(c.conf.statePath); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Failed to remove state file '%s': %v",
|
||||
|
|
|
@ -4,9 +4,11 @@ import (
|
|||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/remote"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
@ -71,11 +73,6 @@ func TestRemote_disable(t *testing.T) {
|
|||
}
|
||||
|
||||
// Ensure we updated
|
||||
// TODO: Should be 10, but WriteState currently
|
||||
// increments incorrectly
|
||||
if newState.Serial != 11 {
|
||||
t.Fatalf("state file not updated: %#v", newState)
|
||||
}
|
||||
if newState.Remote != nil {
|
||||
t.Fatalf("remote configuration not removed")
|
||||
}
|
||||
|
@ -96,11 +93,15 @@ func TestRemote_disable_noPull(t *testing.T) {
|
|||
s = terraform.NewState()
|
||||
s.Serial = 5
|
||||
s.Remote = conf
|
||||
if err := remote.EnsureDirectory(); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
|
||||
// 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 := remote.PersistState(s); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
if err := state.PersistState(); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
|
@ -140,12 +141,6 @@ func TestRemote_disable_noPull(t *testing.T) {
|
|||
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")
|
||||
}
|
||||
|
|
114
command/state.go
114
command/state.go
|
@ -21,7 +21,12 @@ type StateOpts struct {
|
|||
LocalPathOut string
|
||||
|
||||
// RemotePath is the path where the remote state cache would be.
|
||||
//
|
||||
// RemoteCache, if true, will set the result to only be the cache
|
||||
// and not backed by any real durable storage.
|
||||
RemotePath string
|
||||
RemoteCacheOnly bool
|
||||
RemoteRefresh bool
|
||||
|
||||
// BackupPath is the path where the backup will be placed. If not set,
|
||||
// it is assumed to be the path where the state is stored locally
|
||||
|
@ -29,25 +34,74 @@ type StateOpts struct {
|
|||
BackupPath string
|
||||
}
|
||||
|
||||
// StateResult is the result of calling State and holds various different
|
||||
// State implementations so they can be accessed directly.
|
||||
type StateResult struct {
|
||||
// State is the final outer state that should be used for all
|
||||
// _real_ reads/writes.
|
||||
//
|
||||
// StatePath is the local path where the state will be stored or
|
||||
// cached, no matter whether State is local or remote.
|
||||
State state.State
|
||||
StatePath string
|
||||
|
||||
// Local and Remote are the local/remote state implementations, raw
|
||||
// and unwrapped by any backups. The paths here are the paths where
|
||||
// these state files would be saved.
|
||||
Local *state.LocalState
|
||||
LocalPath string
|
||||
Remote *state.CacheState
|
||||
RemotePath string
|
||||
}
|
||||
|
||||
// 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) (state.State, string, error) {
|
||||
var result state.State
|
||||
var resultPath string
|
||||
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.
|
||||
result, err = remoteStateFromPath(opts.RemotePath)
|
||||
remote, err = remoteStateFromPath(
|
||||
opts.RemotePath,
|
||||
opts.RemoteRefresh)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
return nil, err
|
||||
}
|
||||
resultPath = opts.RemotePath
|
||||
}
|
||||
}
|
||||
|
||||
if remote != nil {
|
||||
result.State = remote
|
||||
result.StatePath = opts.RemotePath
|
||||
result.Remote = remote
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,22 +111,20 @@ func State(opts *StateOpts) (state.State, string, error) {
|
|||
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 {
|
||||
isNotExist := false
|
||||
errwrap.Walk(err, func(e error) {
|
||||
if !isNotExist && os.IsNotExist(e) {
|
||||
isNotExist = true
|
||||
}
|
||||
})
|
||||
if isNotExist {
|
||||
err = nil
|
||||
}
|
||||
} else {
|
||||
if result != nil {
|
||||
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(
|
||||
return nil, fmt.Errorf(
|
||||
"Remote state found, but state file '%s' also present.",
|
||||
opts.LocalPath)
|
||||
}
|
||||
|
@ -82,34 +134,34 @@ func State(opts *StateOpts) (state.State, string, error) {
|
|||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, "", errwrap.Wrapf(
|
||||
return nil, errwrap.Wrapf(
|
||||
"Error reading local state: {{err}}", err)
|
||||
}
|
||||
|
||||
if local != nil {
|
||||
result = local
|
||||
resultPath = opts.LocalPath
|
||||
result.State = local
|
||||
result.StatePath = opts.LocalPath
|
||||
if opts.LocalPathOut != "" {
|
||||
resultPath = opts.LocalPathOut
|
||||
result.StatePath = opts.LocalPathOut
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a result, make sure to back it up
|
||||
if result != nil {
|
||||
backupPath := resultPath + DefaultBackupExtention
|
||||
if result.State != nil {
|
||||
backupPath := result.StatePath + DefaultBackupExtention
|
||||
if opts.BackupPath != "" {
|
||||
backupPath = opts.BackupPath
|
||||
}
|
||||
|
||||
result = &state.BackupState{
|
||||
Real: result,
|
||||
result.State = &state.BackupState{
|
||||
Real: result.State,
|
||||
Path: backupPath,
|
||||
}
|
||||
}
|
||||
|
||||
// Return whatever state we have
|
||||
return result, resultPath, nil
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// StateFromPlan gets our state from the plan.
|
||||
|
@ -147,7 +199,7 @@ func StateFromPlan(
|
|||
|
||||
func remoteState(
|
||||
local *terraform.State,
|
||||
localPath string, refresh bool) (state.State, error) {
|
||||
localPath string, refresh bool) (*state.CacheState, error) {
|
||||
// If there is no remote settings, it is an error
|
||||
if local.Remote == nil {
|
||||
return nil, fmt.Errorf("Remote state cache has no remote info")
|
||||
|
@ -199,7 +251,7 @@ func remoteState(
|
|||
return cache, nil
|
||||
}
|
||||
|
||||
func remoteStateFromPath(path string) (state.State, error) {
|
||||
func remoteStateFromPath(path string, refresh bool) (*state.CacheState, error) {
|
||||
// First create the local state for the path
|
||||
local := &state.LocalState{Path: path}
|
||||
if err := local.RefreshState(); err != nil {
|
||||
|
@ -207,5 +259,5 @@ func remoteStateFromPath(path string) (state.State, error) {
|
|||
}
|
||||
localState := local.State()
|
||||
|
||||
return remoteState(localState, path, true)
|
||||
return remoteState(localState, path, refresh)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue