state: remove deprecated state package (#25490)
Most of the state package has been deprecated by the states package. This PR replaces all the references to the old state package that can be done simply - the low-hanging fruit. * states: move state.Locker to statemgr The state.Locker interface was a wrapper around a statemgr.Full, so moving this was relatively straightforward. * command: remove unnecessary use of state package for writing local terraform state files * move state.LocalState into terraform package state.LocalState is responsible for managing terraform.States, so it made sense (to me) to move it into the terraform package. * slight change of heart: move state.LocalState into clistate instead of terraform
This commit is contained in:
parent
adf5cde180
commit
6621501ae3
|
@ -7,13 +7,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs/configschema"
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/mitchellh/colorstring"
|
"github.com/mitchellh/colorstring"
|
||||||
|
@ -171,7 +171,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return backend.ErrWorkspacesNotSupported
|
return backend.ErrWorkspacesNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
if name != backend.DefaultStateName {
|
if name != backend.DefaultStateName {
|
||||||
return nil, backend.ErrWorkspacesNotSupported
|
return nil, backend.ErrWorkspacesNotSupported
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"github.com/hashicorp/go-cleanhttp"
|
"github.com/hashicorp/go-cleanhttp"
|
||||||
"github.com/hashicorp/go-retryablehttp"
|
"github.com/hashicorp/go-retryablehttp"
|
||||||
"github.com/hashicorp/go-rootcerts"
|
"github.com/hashicorp/go-rootcerts"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/helper/acctest"
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ type Operation struct {
|
||||||
UIOut terraform.UIOutput
|
UIOut terraform.UIOutput
|
||||||
|
|
||||||
// If LockState is true, the Operation must Lock any
|
// If LockState is true, the Operation must Lock any
|
||||||
// state.Lockers for its duration, and Unlock when complete.
|
// statemgr.Lockers for its duration, and Unlock when complete.
|
||||||
LockState bool
|
LockState bool
|
||||||
|
|
||||||
// StateLocker is used to lock the state while providing UI feedback to the
|
// StateLocker is used to lock the state while providing UI feedback to the
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// StateHook is a hook that continuously updates the state by calling
|
// StateHook is a hook that continuously updates the state by calling
|
||||||
// WriteState on a state.State.
|
// WriteState on a statemgr.Full.
|
||||||
type StateHook struct {
|
type StateHook struct {
|
||||||
terraform.NilHook
|
terraform.NilHook
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
|
@ -3,7 +3,6 @@ package local
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +15,7 @@ func TestStateHook(t *testing.T) {
|
||||||
is := statemgr.NewTransientInMemory(nil)
|
is := statemgr.NewTransientInMemory(nil)
|
||||||
var hook terraform.Hook = &StateHook{StateMgr: is}
|
var hook terraform.Hook = &StateHook{StateMgr: is}
|
||||||
|
|
||||||
s := state.TestStateInitial()
|
s := statemgr.TestFullInitialState()
|
||||||
action, err := hook.PostStateUpdate(s)
|
action, err := hook.PostStateUpdate(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
|
artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ func (b *Backend) DeleteWorkspace(string) error {
|
||||||
return backend.ErrWorkspacesNotSupported
|
return backend.ErrWorkspacesNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
if name != backend.DefaultStateName {
|
if name != backend.DefaultStateName {
|
||||||
return nil, backend.ErrWorkspacesNotSupported
|
return nil, backend.ErrWorkspacesNotSupported
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
|
artifactory "github.com/lusis/go-artifactory/src/artifactory.v401"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
|
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
|
||||||
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
|
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/containers"
|
||||||
)
|
)
|
||||||
|
@ -78,7 +78,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
blobClient, err := b.armClient.getBlobClient(ctx)
|
blobClient, err := b.armClient.getBlobClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -99,7 +99,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
//it's listed by States.
|
//it's listed by States.
|
||||||
if name != backend.DefaultStateName {
|
if name != backend.DefaultStateName {
|
||||||
// take a lock on this state while we write it
|
// take a lock on this state while we write it
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := client.Lock(lockInfo)
|
lockId, err := client.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
"github.com/hashicorp/go-uuid"
|
"github.com/hashicorp/go-uuid"
|
||||||
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
|
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -116,7 +116,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
stateName := fmt.Sprintf("%s/%s", c.containerName, c.keyName)
|
stateName := fmt.Sprintf("%s/%s", c.containerName, c.keyName)
|
||||||
info.Path = stateName
|
info.Path = stateName
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
err = multierror.Append(err, infoErr)
|
err = multierror.Append(err, infoErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &state.LockError{
|
return &statemgr.LockError{
|
||||||
Err: err,
|
Err: err,
|
||||||
Info: lockInfo,
|
Info: lockInfo,
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
return info.ID, nil
|
return info.ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||||
options := blobs.GetPropertiesInput{}
|
options := blobs.GetPropertiesInput{}
|
||||||
if c.leaseID != "" {
|
if c.leaseID != "" {
|
||||||
options.LeaseID = &c.leaseID
|
options.LeaseID = &c.leaseID
|
||||||
|
@ -209,7 +209,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
lockInfo := &state.LockInfo{}
|
lockInfo := &statemgr.LockInfo{}
|
||||||
err = json.Unmarshal(data, lockInfo)
|
err = json.Unmarshal(data, lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -219,7 +219,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// writes info to blob meta data, deletes metadata entry if info is nil
|
// writes info to blob meta data, deletes metadata entry if info is nil
|
||||||
func (c *RemoteClient) writeLockInfo(info *state.LockInfo) error {
|
func (c *RemoteClient) writeLockInfo(info *statemgr.LockInfo) error {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
blob, err := c.giovanniBlobClient.GetProperties(ctx, c.accountName, c.containerName, c.keyName, blobs.GetPropertiesInput{LeaseID: &c.leaseID})
|
blob, err := c.giovanniBlobClient.GetProperties(ctx, c.accountName, c.containerName, c.keyName, blobs.GetPropertiesInput{LeaseID: &c.leaseID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -246,7 +246,7 @@ func (c *RemoteClient) writeLockInfo(info *state.LockInfo) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Unlock(id string) error {
|
func (c *RemoteClient) Unlock(id string) error {
|
||||||
lockErr := &state.LockError{}
|
lockErr := &statemgr.LockError{}
|
||||||
|
|
||||||
lockInfo, err := c.getLockInfo()
|
lockInfo, err := c.getLockInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/helper/acctest"
|
"github.com/hashicorp/terraform/helper/acctest"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
|
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -93,7 +92,7 @@ func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
// Grab a lock, we use this to write an empty state if one doesn't
|
// Grab a lock, we use this to write an empty state if one doesn't
|
||||||
// exist already. We have to write an empty state as a sentinel value
|
// exist already. We have to write an empty state as a sentinel value
|
||||||
// so States() knows it exists.
|
// so States() knows it exists.
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := stateMgr.Lock(lockInfo)
|
lockId, err := stateMgr.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -14,8 +14,8 @@ import (
|
||||||
|
|
||||||
consulapi "github.com/hashicorp/consul/api"
|
consulapi "github.com/hashicorp/consul/api"
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -54,7 +54,7 @@ type RemoteClient struct {
|
||||||
consulLock *consulapi.Lock
|
consulLock *consulapi.Lock
|
||||||
lockCh <-chan struct{}
|
lockCh <-chan struct{}
|
||||||
|
|
||||||
info *state.LockInfo
|
info *statemgr.LockInfo
|
||||||
|
|
||||||
// cancel our goroutine which is monitoring the lock to automatically
|
// cancel our goroutine which is monitoring the lock to automatically
|
||||||
// reacquire it when possible.
|
// reacquire it when possible.
|
||||||
|
@ -161,7 +161,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) putLockInfo(info *state.LockInfo) error {
|
func (c *RemoteClient) putLockInfo(info *statemgr.LockInfo) error {
|
||||||
info.Path = c.Path
|
info.Path = c.Path
|
||||||
info.Created = time.Now().UTC()
|
info.Created = time.Now().UTC()
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ func (c *RemoteClient) putLockInfo(info *state.LockInfo) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||||
path := c.Path + lockInfoSuffix
|
path := c.Path + lockInfoSuffix
|
||||||
pair, _, err := c.Client.KV().Get(path, nil)
|
pair, _, err := c.Client.KV().Get(path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -184,7 +184,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
li := &state.LockInfo{}
|
li := &statemgr.LockInfo{}
|
||||||
err = json.Unmarshal(pair.Value, li)
|
err = json.Unmarshal(pair.Value, li)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error unmarshaling lock info: %s", err)
|
return nil, fmt.Errorf("error unmarshaling lock info: %s", err)
|
||||||
|
@ -193,7 +193,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
return li, nil
|
return li, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ func (c *RemoteClient) lock() (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{}
|
lockErr := &statemgr.LockError{}
|
||||||
|
|
||||||
lockCh, err := c.consulLock.Lock(make(chan struct{}))
|
lockCh, err := c.consulLock.Lock(make(chan struct{}))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,8 +9,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
@ -109,7 +109,7 @@ func TestConsul_destroyLock(t *testing.T) {
|
||||||
|
|
||||||
c := s.(*remote.State).Client.(*RemoteClient)
|
c := s.(*remote.State).Client.(*RemoteClient)
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
id, err := c.Lock(info)
|
id, err := c.Lock(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -151,7 +151,7 @@ func TestConsul_lostLock(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
info.Operation = "test-lost-lock"
|
info.Operation = "test-lost-lock"
|
||||||
id, err := sA.Lock(info)
|
id, err := sA.Lock(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -200,7 +200,7 @@ func TestConsul_lostLockConnection(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
info.Operation = "test-lost-lock-connection"
|
info.Operation = "test-lost-lock-connection"
|
||||||
id, err := s.Lock(info)
|
id, err := s.Lock(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,9 +8,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/likexian/gokit/assert"
|
"github.com/likexian/gokit/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// StateMgr manage the state, if the named state not exists, a new file will created
|
// StateMgr manage the state, if the named state not exists, a new file will created
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
log.Printf("[DEBUG] state manager, current workspace: %v", name)
|
log.Printf("[DEBUG] state manager, current workspace: %v", name)
|
||||||
|
|
||||||
c, err := b.client(name)
|
c, err := b.client(name)
|
||||||
|
@ -92,7 +92,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
log.Printf("[DEBUG] workspace %v not exists", name)
|
log.Printf("[DEBUG] workspace %v not exists", name)
|
||||||
|
|
||||||
// take a lock on this state while we write it
|
// take a lock on this state while we write it
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := c.Lock(lockInfo)
|
lockId, err := c.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/likexian/gokit/assert"
|
"github.com/likexian/gokit/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
|
tag "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/tag/v20180813"
|
||||||
"github.com/tencentyun/cos-go-sdk-v5"
|
"github.com/tencentyun/cos-go-sdk-v5"
|
||||||
)
|
)
|
||||||
|
@ -72,7 +72,7 @@ func (c *remoteClient) Delete() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock lock remote state file for writing
|
// Lock lock remote state file for writing
|
||||||
func (c *remoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *remoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
log.Printf("[DEBUG] lock remote state file %s", c.lockFile)
|
log.Printf("[DEBUG] lock remote state file %s", c.lockFile)
|
||||||
|
|
||||||
err := c.cosLock(c.bucket, c.lockFile)
|
err := c.cosLock(c.bucket, c.lockFile)
|
||||||
|
@ -126,11 +126,11 @@ func (c *remoteClient) Unlock(check string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// lockError returns state.LockError
|
// lockError returns statemgr.LockError
|
||||||
func (c *remoteClient) lockError(err error) *state.LockError {
|
func (c *remoteClient) lockError(err error) *statemgr.LockError {
|
||||||
log.Printf("[DEBUG] failed to lock or unlock %s: %v", c.lockFile, err)
|
log.Printf("[DEBUG] failed to lock or unlock %s: %v", c.lockFile, err)
|
||||||
|
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ func (c *remoteClient) lockError(err error) *state.LockError {
|
||||||
}
|
}
|
||||||
|
|
||||||
// lockInfo returns LockInfo from lock file
|
// lockInfo returns LockInfo from lock file
|
||||||
func (c *remoteClient) lockInfo() (*state.LockInfo, error) {
|
func (c *remoteClient) lockInfo() (*statemgr.LockInfo, error) {
|
||||||
exists, data, checksum, err := c.getObject(c.lockFile)
|
exists, data, checksum, err := c.getObject(c.lockFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -155,7 +155,7 @@ func (c *remoteClient) lockInfo() (*state.LockInfo, error) {
|
||||||
return nil, fmt.Errorf("lock file %s not exists", c.lockFile)
|
return nil, fmt.Errorf("lock file %s not exists", c.lockFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
info := &state.LockInfo{}
|
info := &statemgr.LockInfo{}
|
||||||
if err := json.Unmarshal(data, info); err != nil {
|
if err := json.Unmarshal(data, info); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ import (
|
||||||
etcdapi "github.com/coreos/etcd/client"
|
etcdapi "github.com/coreos/etcd/client"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New() backend.Backend {
|
func New() backend.Backend {
|
||||||
|
@ -83,7 +83,7 @@ func (b *Backend) DeleteWorkspace(string) error {
|
||||||
return backend.ErrWorkspacesNotSupported
|
return backend.ErrWorkspacesNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
if name != backend.DefaultStateName {
|
if name != backend.DefaultStateName {
|
||||||
return nil, backend.ErrWorkspacesNotSupported
|
return nil, backend.ErrWorkspacesNotSupported
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
etcdapi "github.com/coreos/etcd/client"
|
etcdapi "github.com/coreos/etcd/client"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EtcdClient is a remote client that stores data in etcd.
|
// EtcdClient is a remote client that stores data in etcd.
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
etcdv3 "github.com/coreos/etcd/clientv3"
|
etcdv3 "github.com/coreos/etcd/clientv3"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) Workspaces() ([]string, error) {
|
func (b *Backend) Workspaces() ([]string, error) {
|
||||||
|
@ -41,8 +41,8 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
var stateMgr state.State = &remote.State{
|
var stateMgr statemgr.Full = &remote.State{
|
||||||
Client: &RemoteClient{
|
Client: &RemoteClient{
|
||||||
Client: b.client,
|
Client: b.client,
|
||||||
DoLock: b.lock,
|
DoLock: b.lock,
|
||||||
|
@ -51,10 +51,10 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !b.lock {
|
if !b.lock {
|
||||||
stateMgr = &state.LockDisabled{Inner: stateMgr}
|
stateMgr = &statemgr.LockDisabled{Inner: stateMgr}
|
||||||
}
|
}
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := stateMgr.Lock(lockInfo)
|
lockId, err := stateMgr.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
etcdv3 "github.com/coreos/etcd/clientv3"
|
etcdv3 "github.com/coreos/etcd/clientv3"
|
||||||
etcdv3sync "github.com/coreos/etcd/clientv3/concurrency"
|
etcdv3sync "github.com/coreos/etcd/clientv3/concurrency"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -28,7 +28,7 @@ type RemoteClient struct {
|
||||||
|
|
||||||
etcdMutex *etcdv3sync.Mutex
|
etcdMutex *etcdv3sync.Mutex
|
||||||
etcdSession *etcdv3sync.Session
|
etcdSession *etcdv3sync.Session
|
||||||
info *state.LockInfo
|
info *statemgr.LockInfo
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
modRevision int64
|
modRevision int64
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||||
return c.unlock(id)
|
return c.unlock(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) deleteLockInfo(info *state.LockInfo) error {
|
func (c *RemoteClient) deleteLockInfo(info *statemgr.LockInfo) error {
|
||||||
res, err := c.Client.KV.Delete(context.TODO(), c.Key+lockInfoSuffix)
|
res, err := c.Client.KV.Delete(context.TODO(), c.Key+lockInfoSuffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -129,7 +129,7 @@ func (c *RemoteClient) deleteLockInfo(info *state.LockInfo) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||||
res, err := c.Client.KV.Get(context.TODO(), c.Key+lockInfoSuffix)
|
res, err := c.Client.KV.Get(context.TODO(), c.Key+lockInfoSuffix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -138,7 +138,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
li := &state.LockInfo{}
|
li := &statemgr.LockInfo{}
|
||||||
err = json.Unmarshal(res.Kvs[0].Value, li)
|
err = json.Unmarshal(res.Kvs[0].Value, li)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error unmarshaling lock info: %s.", err)
|
return nil, fmt.Errorf("Error unmarshaling lock info: %s.", err)
|
||||||
|
@ -147,7 +147,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
return li, nil
|
return li, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) putLockInfo(info *state.LockInfo) error {
|
func (c *RemoteClient) putLockInfo(info *statemgr.LockInfo) error {
|
||||||
c.info.Path = c.etcdMutex.Key()
|
c.info.Path = c.etcdMutex.Key()
|
||||||
c.info.Created = time.Now().UTC()
|
c.info.Created = time.Now().UTC()
|
||||||
|
|
||||||
|
@ -168,9 +168,9 @@ func (c *RemoteClient) lock() (string, error) {
|
||||||
if err1 := mutex.Lock(ctx); err1 != nil {
|
if err1 := mutex.Lock(ctx); err1 != nil {
|
||||||
lockInfo, err2 := c.getLockInfo()
|
lockInfo, err2 := c.getLockInfo()
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return "", &state.LockError{Err: err2}
|
return "", &statemgr.LockError{Err: err2}
|
||||||
}
|
}
|
||||||
return "", &state.LockError{Info: lockInfo, Err: err1}
|
return "", &statemgr.LockError{Info: lockInfo, Err: err1}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.etcdMutex = mutex
|
c.etcdMutex = mutex
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
@ -83,7 +83,7 @@ func TestEtcdv3_destroyLock(t *testing.T) {
|
||||||
|
|
||||||
c := s.(*remote.State).Client.(*RemoteClient)
|
c := s.(*remote.State).Client.(*RemoteClient)
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
id, err := c.Lock(info)
|
id, err := c.Lock(info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
"google.golang.org/api/iterator"
|
"google.golang.org/api/iterator"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -86,7 +86,7 @@ func (b *Backend) client(name string) (*remoteClient, error) {
|
||||||
|
|
||||||
// StateMgr reads and returns the named state from GCS. If the named state does
|
// StateMgr reads and returns the named state from GCS. If the named state does
|
||||||
// not yet exist, a new state file is created.
|
// not yet exist, a new state file is created.
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
c, err := b.client(name)
|
c, err := b.client(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -102,7 +102,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
// If we have no state, we have to create an empty state
|
// If we have no state, we have to create an empty state
|
||||||
if v := st.State(); v == nil {
|
if v := st.State(); v == nil {
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockID, err := st.Lock(lockInfo)
|
lockID, err := st.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
|
|
||||||
"cloud.google.com/go/storage"
|
"cloud.google.com/go/storage"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -8,8 +8,8 @@ import (
|
||||||
|
|
||||||
"cloud.google.com/go/storage"
|
"cloud.google.com/go/storage"
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ func (c *remoteClient) Delete() error {
|
||||||
|
|
||||||
// Lock writes to a lock file, ensuring file creation. Returns the generation
|
// Lock writes to a lock file, ensuring file creation. Returns the generation
|
||||||
// number, which must be passed to Unlock().
|
// number, which must be passed to Unlock().
|
||||||
func (c *remoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *remoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
// update the path we're using
|
// update the path we're using
|
||||||
// we can't set the ID until the info is written
|
// we can't set the ID until the info is written
|
||||||
info.Path = c.lockFileURL()
|
info.Path = c.lockFileURL()
|
||||||
|
@ -120,8 +120,8 @@ func (c *remoteClient) Unlock(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *remoteClient) lockError(err error) *state.LockError {
|
func (c *remoteClient) lockError(err error) *statemgr.LockError {
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ func (c *remoteClient) lockError(err error) *state.LockError {
|
||||||
|
|
||||||
// lockInfo reads the lock file, parses its contents and returns the parsed
|
// lockInfo reads the lock file, parses its contents and returns the parsed
|
||||||
// LockInfo struct.
|
// LockInfo struct.
|
||||||
func (c *remoteClient) lockInfo() (*state.LockInfo, error) {
|
func (c *remoteClient) lockInfo() (*statemgr.LockInfo, error) {
|
||||||
r, err := c.lockFile().NewReader(c.storageContext)
|
r, err := c.lockFile().NewReader(c.storageContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -148,7 +148,7 @@ func (c *remoteClient) lockInfo() (*state.LockInfo, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := &state.LockInfo{}
|
info := &statemgr.LockInfo{}
|
||||||
if err := json.Unmarshal(rawData, info); err != nil {
|
if err := json.Unmarshal(rawData, info); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"github.com/hashicorp/go-retryablehttp"
|
"github.com/hashicorp/go-retryablehttp"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func New() backend.Backend {
|
func New() backend.Backend {
|
||||||
|
@ -175,7 +175,7 @@ func (b *Backend) configure(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
if name != backend.DefaultStateName {
|
if name != backend.DefaultStateName {
|
||||||
return nil, backend.ErrWorkspacesNotSupported
|
return nil, backend.ErrWorkspacesNotSupported
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
"github.com/hashicorp/go-retryablehttp"
|
"github.com/hashicorp/go-retryablehttp"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// httpClient is a remote client that stores data in Consul or HTTP REST.
|
// httpClient is a remote client that stores data in Consul or HTTP REST.
|
||||||
|
@ -74,7 +74,7 @@ func (c *httpClient) httpRequest(method string, url *url.URL, data *[]byte, what
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *httpClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
if c.LockURL == nil {
|
if c.LockURL == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ func (c *httpClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("HTTP remote state already locked, failed to read body")
|
return "", fmt.Errorf("HTTP remote state already locked, failed to read body")
|
||||||
}
|
}
|
||||||
existing := state.LockInfo{}
|
existing := statemgr.LockInfo{}
|
||||||
err = json.Unmarshal(body, &existing)
|
err = json.Unmarshal(body, &existing)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("HTTP remote state already locked, failed to unmarshal body")
|
return "", fmt.Errorf("HTTP remote state already locked, failed to unmarshal body")
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/go-retryablehttp"
|
"github.com/hashicorp/go-retryablehttp"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHTTPClient_impl(t *testing.T) {
|
func TestHTTPClient_impl(t *testing.T) {
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
statespkg "github.com/hashicorp/terraform/states"
|
statespkg "github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// we keep the states and locks in package-level variables, so that they can be
|
// we keep the states and locks in package-level variables, so that they can be
|
||||||
|
@ -36,7 +36,7 @@ func Reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
locks = lockMap{
|
locks = lockMap{
|
||||||
m: map[string]*state.LockInfo{},
|
m: map[string]*statemgr.LockInfo{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ func (b *Backend) configure(ctx context.Context) error {
|
||||||
// set the default client lock info per the test config
|
// set the default client lock info per the test config
|
||||||
data := schema.FromContextBackendConfig(ctx)
|
data := schema.FromContextBackendConfig(ctx)
|
||||||
if v, ok := data.GetOk("lock_id"); ok && v.(string) != "" {
|
if v, ok := data.GetOk("lock_id"); ok && v.(string) != "" {
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
info.ID = v.(string)
|
info.ID = v.(string)
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Info = "test config"
|
info.Info = "test config"
|
||||||
|
@ -113,7 +113,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
states.Lock()
|
states.Lock()
|
||||||
defer states.Unlock()
|
defer states.Unlock()
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
|
|
||||||
// to most closely replicate other implementations, we are going to
|
// to most closely replicate other implementations, we are going to
|
||||||
// take a lock and create a new state if it doesn't exist.
|
// take a lock and create a new state if it doesn't exist.
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockID, err := s.Lock(lockInfo)
|
lockID, err := s.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -158,16 +158,16 @@ type stateMap struct {
|
||||||
// Global level locks for inmem backends.
|
// Global level locks for inmem backends.
|
||||||
type lockMap struct {
|
type lockMap struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
m map[string]*state.LockInfo
|
m map[string]*statemgr.LockInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lockMap) lock(name string, info *state.LockInfo) (string, error) {
|
func (l *lockMap) lock(name string, info *statemgr.LockInfo) (string, error) {
|
||||||
l.Lock()
|
l.Lock()
|
||||||
defer l.Unlock()
|
defer l.Unlock()
|
||||||
|
|
||||||
lockInfo := l.m[name]
|
lockInfo := l.m[name]
|
||||||
if lockInfo != nil {
|
if lockInfo != nil {
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Info: lockInfo,
|
Info: lockInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,8 +193,8 @@ func (l *lockMap) unlock(name, id string) error {
|
||||||
return errors.New("state not locked")
|
return errors.New("state not locked")
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Info: &state.LockInfo{},
|
Info: &statemgr.LockInfo{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if id != lockInfo.ID {
|
if id != lockInfo.ID {
|
||||||
|
|
|
@ -11,8 +11,8 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/helper/logging"
|
"github.com/hashicorp/terraform/helper/logging"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
statespkg "github.com/hashicorp/terraform/states"
|
statespkg "github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -3,8 +3,8 @@ package inmem
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RemoteClient is a remote client that stores data in memory for testing.
|
// RemoteClient is a remote client that stores data in memory for testing.
|
||||||
|
@ -39,7 +39,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
return locks.lock(c.Name, info)
|
return locks.lock(c.Name, info)
|
||||||
}
|
}
|
||||||
func (c *RemoteClient) Unlock(id string) error {
|
func (c *RemoteClient) Unlock(id string) error {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/v2"
|
"github.com/hashicorp/hcl/v2"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
|
|
@ -6,9 +6,9 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return client.Delete()
|
return client.Delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
c, err := b.remoteClient(name)
|
c, err := b.remoteClient(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -87,7 +87,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
// If we have no state, we have to create an empty state
|
// If we have no state, we have to create an empty state
|
||||||
if v := stateMgr.State(); v == nil {
|
if v := stateMgr.State(); v == nil {
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockID, err := stateMgr.Lock(lockInfo)
|
lockID, err := stateMgr.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
@ -100,7 +99,7 @@ func TestBackendLocksSoak(t *testing.T) {
|
||||||
go func(locker statemgr.Locker, n int) {
|
go func(locker statemgr.Locker, n int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
li := state.NewLockInfo()
|
li := statemgr.NewLockInfo()
|
||||||
li.Operation = "test"
|
li.Operation = "test"
|
||||||
li.Who = fmt.Sprintf("client-%v", n)
|
li.Who = fmt.Sprintf("client-%v", n)
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
@ -143,7 +143,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
leaseName, err := c.createLeaseName()
|
leaseName, err := c.createLeaseName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -187,7 +187,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Info: currentLockInfo,
|
Info: currentLockInfo,
|
||||||
Err: errors.New("the state is already locked by another terraform client"),
|
Err: errors.New("the state is already locked by another terraform client"),
|
||||||
}
|
}
|
||||||
|
@ -224,7 +224,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{Info: lockInfo}
|
lockErr := &statemgr.LockError{Info: lockInfo}
|
||||||
if *lease.Spec.HolderIdentity != id {
|
if *lease.Spec.HolderIdentity != id {
|
||||||
lockErr.Err = fmt.Errorf("lock id %q does not match existing lock", id)
|
lockErr.Err = fmt.Errorf("lock id %q does not match existing lock", id)
|
||||||
return lockErr
|
return lockErr
|
||||||
|
@ -242,13 +242,13 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo(lease *coordinationv1.Lease) (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo(lease *coordinationv1.Lease) (*statemgr.LockInfo, error) {
|
||||||
lockData, ok := getLockInfo(lease)
|
lockData, ok := getLockInfo(lease)
|
||||||
if len(lockData) == 0 || !ok {
|
if len(lockData) == 0 || !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lockInfo := &state.LockInfo{}
|
lockInfo := &statemgr.LockInfo{}
|
||||||
err := json.Unmarshal(lockData, lockInfo)
|
err := json.Unmarshal(lockData, lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -4,8 +4,8 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
@ -72,7 +72,7 @@ func TestForceUnlock(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Who = "clientA"
|
info.Who = "clientA"
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ func TestForceUnlock(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info = state.NewLockInfo()
|
info = statemgr.NewLockInfo()
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Who = "clientA"
|
info.Who = "clientA"
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ import (
|
||||||
"github.com/joyent/triton-go/storage"
|
"github.com/joyent/triton-go/storage"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) Workspaces() ([]string, error) {
|
func (b *Backend) Workspaces() ([]string, error) {
|
||||||
|
@ -64,7 +64,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil, errors.New("missing state name")
|
return nil, errors.New("missing state name")
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
//it's listed by States.
|
//it's listed by States.
|
||||||
if name != backend.DefaultStateName {
|
if name != backend.DefaultStateName {
|
||||||
// take a lock on this state while we write it
|
// take a lock on this state while we write it
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := client.Lock(lockInfo)
|
lockId, err := client.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,8 +10,8 @@ import (
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
uuid "github.com/hashicorp/go-uuid"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
tritonErrors "github.com/joyent/triton-go/errors"
|
tritonErrors "github.com/joyent/triton-go/errors"
|
||||||
"github.com/joyent/triton-go/storage"
|
"github.com/joyent/triton-go/storage"
|
||||||
)
|
)
|
||||||
|
@ -86,7 +86,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
//At Joyent, we want to make sure that the State directory exists before we interact with it
|
//At Joyent, we want to make sure that the State directory exists before we interact with it
|
||||||
//We don't expect users to have to create it in advance
|
//We don't expect users to have to create it in advance
|
||||||
//The order of operations of Backend State as follows:
|
//The order of operations of Backend State as follows:
|
||||||
|
@ -103,7 +103,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//firstly we want to check that a lock doesn't already exist
|
//firstly we want to check that a lock doesn't already exist
|
||||||
lockErr := &state.LockError{}
|
lockErr := &statemgr.LockError{}
|
||||||
lockInfo, err := c.getLockInfo()
|
lockInfo, err := c.getLockInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !tritonErrors.IsResourceNotFound(err) {
|
if !tritonErrors.IsResourceNotFound(err) {
|
||||||
|
@ -113,7 +113,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if lockInfo != nil {
|
if lockInfo != nil {
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Err: fmt.Errorf("A lock is already acquired"),
|
Err: fmt.Errorf("A lock is already acquired"),
|
||||||
Info: lockInfo,
|
Info: lockInfo,
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Unlock(id string) error {
|
func (c *RemoteClient) Unlock(id string) error {
|
||||||
lockErr := &state.LockError{}
|
lockErr := &statemgr.LockError{}
|
||||||
|
|
||||||
lockInfo, err := c.getLockInfo()
|
lockInfo, err := c.getLockInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -175,7 +175,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||||
output, err := c.storageClient.Objects().Get(context.Background(), &storage.GetObjectInput{
|
output, err := c.storageClient.Objects().Get(context.Background(), &storage.GetObjectInput{
|
||||||
ObjectPath: path.Join(mantaDefaultRootStore, c.directoryName, lockFileName),
|
ObjectPath: path.Join(mantaDefaultRootStore, c.directoryName, lockFileName),
|
||||||
})
|
})
|
||||||
|
@ -190,7 +190,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
return nil, fmt.Errorf("Failed to read lock info: %s", err)
|
return nil, fmt.Errorf("Failed to read lock info: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lockInfo := &state.LockInfo{}
|
lockInfo := &statemgr.LockInfo{}
|
||||||
err = json.Unmarshal(buf.Bytes(), lockInfo)
|
err = json.Unmarshal(buf.Bytes(), lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
|
|
@ -8,9 +8,9 @@ import (
|
||||||
|
|
||||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
|
|
||||||
"log"
|
"log"
|
||||||
"path"
|
"path"
|
||||||
|
@ -95,7 +95,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return client.Delete()
|
return client.Delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
client, err := b.remoteClient(name)
|
client, err := b.remoteClient(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -120,7 +120,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
// We need to create the object so it's listed by States.
|
// We need to create the object so it's listed by States.
|
||||||
if !exists {
|
if !exists {
|
||||||
// take a lock on this state while we write it
|
// take a lock on this state while we write it
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := client.Lock(lockInfo)
|
lockId, err := client.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -16,8 +16,8 @@ import (
|
||||||
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
|
"github.com/aliyun/aliyun-tablestore-go-sdk/tablestore"
|
||||||
"github.com/hashicorp/go-multierror"
|
"github.com/hashicorp/go-multierror"
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
uuid "github.com/hashicorp/go-uuid"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ type RemoteClient struct {
|
||||||
lockFile string
|
lockFile string
|
||||||
serverSideEncryption bool
|
serverSideEncryption bool
|
||||||
acl string
|
acl string
|
||||||
info *state.LockInfo
|
info *statemgr.LockInfo
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
otsTable string
|
otsTable string
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
if c.otsTable == "" {
|
if c.otsTable == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
log.Printf("[WARN] Error getting lock info: %#v", err)
|
log.Printf("[WARN] Error getting lock info: %#v", err)
|
||||||
err = multierror.Append(err, infoErr)
|
err = multierror.Append(err, infoErr)
|
||||||
}
|
}
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Err: err,
|
Err: err,
|
||||||
Info: lockInfo,
|
Info: lockInfo,
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ func (c *RemoteClient) deleteMD5() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||||
getParams := &tablestore.SingleRowQueryCriteria{
|
getParams := &tablestore.SingleRowQueryCriteria{
|
||||||
TableName: c.otsTable,
|
TableName: c.otsTable,
|
||||||
PrimaryKey: &tablestore.PrimaryKey{
|
PrimaryKey: &tablestore.PrimaryKey{
|
||||||
|
@ -352,7 +352,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
if v, ok := object.GetColumnMap().Columns["Info"]; ok && len(v) > 0 {
|
if v, ok := object.GetColumnMap().Columns["Info"]; ok && len(v) > 0 {
|
||||||
infoData = v[0].Value.(string)
|
infoData = v[0].Value.(string)
|
||||||
}
|
}
|
||||||
lockInfo := &state.LockInfo{}
|
lockInfo := &statemgr.LockInfo{}
|
||||||
err = json.Unmarshal([]byte(infoData), lockInfo)
|
err = json.Unmarshal([]byte(infoData), lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -364,7 +364,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{}
|
lockErr := &statemgr.LockError{}
|
||||||
|
|
||||||
lockInfo, err := c.getLockInfo()
|
lockInfo, err := c.getLockInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,9 +10,9 @@ import (
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states/statefile"
|
"github.com/hashicorp/terraform/states/statefile"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NOTE: Before running this testcase, please create a OTS instance called 'tf-oss-remote'
|
// NOTE: Before running this testcase, please create a OTS instance called 'tf-oss-remote'
|
||||||
|
@ -117,7 +117,7 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := s1.Lock(state.NewLockInfo()); err != nil {
|
if _, err := s1.Lock(statemgr.NewLockInfo()); err != nil {
|
||||||
t.Fatal("failed to get lock for s1:", err)
|
t.Fatal("failed to get lock for s1:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ func TestRemoteClientLocks_multipleStates(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if _, err := s2.Lock(state.NewLockInfo()); err != nil {
|
if _, err := s2.Lock(statemgr.NewLockInfo()); err != nil {
|
||||||
t.Fatal("failed to get lock for s2:", err)
|
t.Fatal("failed to get lock for s2:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Who = "clientA"
|
info.Who = "clientA"
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ func TestRemoteForceUnlock(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info = state.NewLockInfo()
|
info = statemgr.NewLockInfo()
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Who = "clientA"
|
info.Who = "clientA"
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
|
||||||
client1 := s1.(*remote.State).Client
|
client1 := s1.(*remote.State).Client
|
||||||
|
|
||||||
// create an old and new state version to persist
|
// create an old and new state version to persist
|
||||||
s := state.TestStateInitial()
|
s := statemgr.TestFullInitialState()
|
||||||
sf := &statefile.File{State: s}
|
sf := &statefile.File{State: s}
|
||||||
var oldState bytes.Buffer
|
var oldState bytes.Buffer
|
||||||
if err := statefile.Write(sf, &oldState); err != nil {
|
if err := statefile.Write(sf, &oldState); err != nil {
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) Workspaces() ([]string, error) {
|
func (b *Backend) Workspaces() ([]string, error) {
|
||||||
|
@ -47,9 +47,9 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
// Build the state client
|
// Build the state client
|
||||||
var stateMgr state.State = &remote.State{
|
var stateMgr statemgr.Full = &remote.State{
|
||||||
Client: &RemoteClient{
|
Client: &RemoteClient{
|
||||||
Client: b.db,
|
Client: b.db,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -77,7 +77,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
// exist already. We have to write an empty state as a sentinel value
|
// exist already. We have to write an empty state as a sentinel value
|
||||||
// so Workspaces() knows it exists.
|
// so Workspaces() knows it exists.
|
||||||
if !exists {
|
if !exists {
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := stateMgr.Lock(lockInfo)
|
lockId, err := stateMgr.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
uuid "github.com/hashicorp/go-uuid"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ type RemoteClient struct {
|
||||||
Name string
|
Name string
|
||||||
SchemaName string
|
SchemaName string
|
||||||
|
|
||||||
info *state.LockInfo
|
info *statemgr.LockInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Get() (*remote.Payload, error) {
|
func (c *RemoteClient) Get() (*remote.Payload, error) {
|
||||||
|
@ -60,7 +60,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
var lockID string
|
var lockID string
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
var didUnlock []byte
|
var didUnlock []byte
|
||||||
err := row.Scan(&didUnlock)
|
err := row.Scan(&didUnlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &state.LockError{Info: info, Err: err}
|
return &statemgr.LockError{Info: info, Err: err}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -97,22 +97,22 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
var innerDidLock []byte
|
var innerDidLock []byte
|
||||||
err := innerRow.Scan(&innerDidLock)
|
err := innerRow.Scan(&innerDidLock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", &state.LockError{Info: info, Err: err}
|
return "", &statemgr.LockError{Info: info, Err: err}
|
||||||
}
|
}
|
||||||
if string(innerDidLock) == "false" {
|
if string(innerDidLock) == "false" {
|
||||||
return "", &state.LockError{Info: info, Err: fmt.Errorf("Already locked for workspace creation: %s", c.Name)}
|
return "", &statemgr.LockError{Info: info, Err: fmt.Errorf("Already locked for workspace creation: %s", c.Name)}
|
||||||
}
|
}
|
||||||
info.Path = "-1"
|
info.Path = "-1"
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return "", &state.LockError{Info: info, Err: err}
|
return "", &statemgr.LockError{Info: info, Err: err}
|
||||||
case string(didLock) == "false":
|
case string(didLock) == "false":
|
||||||
// Existing workspace is already locked. Release the attempted creation lock.
|
// Existing workspace is already locked. Release the attempted creation lock.
|
||||||
lockUnlock("-1")
|
lockUnlock("-1")
|
||||||
return "", &state.LockError{Info: info, Err: fmt.Errorf("Workspace is already locked: %s", c.Name)}
|
return "", &statemgr.LockError{Info: info, Err: fmt.Errorf("Workspace is already locked: %s", c.Name)}
|
||||||
case string(didLockForCreate) == "false":
|
case string(didLockForCreate) == "false":
|
||||||
// Someone has the creation lock already. Release the existing workspace because it might not be safe to touch.
|
// Someone has the creation lock already. Release the existing workspace because it might not be safe to touch.
|
||||||
lockUnlock(string(pgLockId))
|
lockUnlock(string(pgLockId))
|
||||||
return "", &state.LockError{Info: info, Err: fmt.Errorf("Cannot lock workspace; already locked for workspace creation: %s", c.Name)}
|
return "", &statemgr.LockError{Info: info, Err: fmt.Errorf("Cannot lock workspace; already locked for workspace creation: %s", c.Name)}
|
||||||
default:
|
default:
|
||||||
// Existing workspace is now locked. Release the attempted creation lock.
|
// Existing workspace is now locked. Release the attempted creation lock.
|
||||||
lockUnlock("-1")
|
lockUnlock("-1")
|
||||||
|
@ -123,7 +123,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
return info.ID, nil
|
return info.ID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||||
return c.info, nil
|
return c.info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||||
var didUnlock []byte
|
var didUnlock []byte
|
||||||
err := row.Scan(&didUnlock)
|
err := row.Scan(&didUnlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &state.LockError{Info: c.info, Err: err}
|
return &statemgr.LockError{Info: c.info, Err: err}
|
||||||
}
|
}
|
||||||
c.info = nil
|
c.info = nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
|
|
@ -12,9 +12,9 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *Backend) Workspaces() ([]string, error) {
|
func (b *Backend) Workspaces() ([]string, error) {
|
||||||
|
@ -124,7 +124,7 @@ func (b *Backend) remoteClient(name string) (*RemoteClient, error) {
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
client, err := b.remoteClient(name)
|
client, err := b.remoteClient(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -155,7 +155,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
// We need to create the object so it's listed by States.
|
// We need to create the object so it's listed by States.
|
||||||
if !exists {
|
if !exists {
|
||||||
// take a lock on this state while we write it
|
// take a lock on this state while we write it
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := client.Lock(lockInfo)
|
lockId, err := client.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -14,8 +14,8 @@ import (
|
||||||
awsbase "github.com/hashicorp/aws-sdk-go-base"
|
awsbase "github.com/hashicorp/aws-sdk-go-base"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs/hcl2shim"
|
"github.com/hashicorp/terraform/configs/hcl2shim"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -18,8 +18,8 @@ import (
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
uuid "github.com/hashicorp/go-uuid"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Store the last saved serial in dynamo with this suffix for consistency checks.
|
// Store the last saved serial in dynamo with this suffix for consistency checks.
|
||||||
|
@ -211,7 +211,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
if c.ddbTable == "" {
|
if c.ddbTable == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
@ -243,7 +243,7 @@ func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||||
err = multierror.Append(err, infoErr)
|
err = multierror.Append(err, infoErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Err: err,
|
Err: err,
|
||||||
Info: lockInfo,
|
Info: lockInfo,
|
||||||
}
|
}
|
||||||
|
@ -328,7 +328,7 @@ func (c *RemoteClient) deleteMD5() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
|
||||||
getParams := &dynamodb.GetItemInput{
|
getParams := &dynamodb.GetItemInput{
|
||||||
Key: map[string]*dynamodb.AttributeValue{
|
Key: map[string]*dynamodb.AttributeValue{
|
||||||
"LockID": {S: aws.String(c.lockPath())},
|
"LockID": {S: aws.String(c.lockPath())},
|
||||||
|
@ -348,7 +348,7 @@ func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||||
infoData = *v.S
|
infoData = *v.S
|
||||||
}
|
}
|
||||||
|
|
||||||
lockInfo := &state.LockInfo{}
|
lockInfo := &statemgr.LockInfo{}
|
||||||
err = json.Unmarshal([]byte(infoData), lockInfo)
|
err = json.Unmarshal([]byte(infoData), lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -362,7 +362,7 @@ func (c *RemoteClient) Unlock(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{}
|
lockErr := &statemgr.LockError{}
|
||||||
|
|
||||||
// TODO: store the path and lock ID in separate fields, and have proper
|
// TODO: store the path and lock ID in separate fields, and have proper
|
||||||
// projection expression only delete the lock if both match, rather than
|
// projection expression only delete the lock if both match, rather than
|
||||||
|
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states/statefile"
|
"github.com/hashicorp/terraform/states/statefile"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
@ -109,7 +109,7 @@ func TestForceUnlock(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Who = "clientA"
|
info.Who = "clientA"
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ func TestForceUnlock(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
info = state.NewLockInfo()
|
info = statemgr.NewLockInfo()
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Who = "clientA"
|
info.Who = "clientA"
|
||||||
|
|
||||||
|
@ -227,7 +227,7 @@ func TestRemoteClient_stateChecksum(t *testing.T) {
|
||||||
client1 := s1.(*remote.State).Client
|
client1 := s1.(*remote.State).Client
|
||||||
|
|
||||||
// create an old and new state version to persist
|
// create an old and new state version to persist
|
||||||
s := state.TestStateInitial()
|
s := statemgr.TestFullInitialState()
|
||||||
sf := &statefile.File{State: s}
|
sf := &statefile.File{State: s}
|
||||||
var oldState bytes.Buffer
|
var oldState bytes.Buffer
|
||||||
if err := statefile.Write(sf, &oldState); err != nil {
|
if err := statefile.Write(sf, &oldState); err != nil {
|
||||||
|
|
|
@ -5,9 +5,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -91,7 +91,7 @@ func (b *Backend) DeleteWorkspace(name string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) StateMgr(name string) (state.State, error) {
|
func (b *Backend) StateMgr(name string) (statemgr.Full, error) {
|
||||||
if name == "" {
|
if name == "" {
|
||||||
return nil, fmt.Errorf("missing state name")
|
return nil, fmt.Errorf("missing state name")
|
||||||
}
|
}
|
||||||
|
@ -106,11 +106,11 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
lockState: b.lock,
|
lockState: b.lock,
|
||||||
}
|
}
|
||||||
|
|
||||||
var stateMgr state.State = &remote.State{Client: client}
|
var stateMgr statemgr.Full = &remote.State{Client: client}
|
||||||
|
|
||||||
// If we're not locking, disable it
|
// If we're not locking, disable it
|
||||||
if !b.lock {
|
if !b.lock {
|
||||||
stateMgr = &state.LockDisabled{Inner: stateMgr}
|
stateMgr = &statemgr.LockDisabled{Inner: stateMgr}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to see if this state already exists.
|
// Check to see if this state already exists.
|
||||||
|
@ -144,7 +144,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
|
||||||
// Grab a lock, we use this to write an empty state if one doesn't
|
// Grab a lock, we use this to write an empty state if one doesn't
|
||||||
// exist already. We have to write an empty state as a sentinel value
|
// exist already. We have to write an empty state as a sentinel value
|
||||||
// so States() knows it exists.
|
// so States() knows it exists.
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = "init"
|
lockInfo.Operation = "init"
|
||||||
lockId, err := stateMgr.Lock(lockInfo)
|
lockId, err := stateMgr.Lock(lockInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -14,8 +14,8 @@ import (
|
||||||
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers"
|
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers"
|
||||||
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
|
"github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects"
|
||||||
"github.com/gophercloud/gophercloud/pagination"
|
"github.com/gophercloud/gophercloud/pagination"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -53,7 +53,7 @@ type RemoteClient struct {
|
||||||
// lockState is true if we're using locks
|
// lockState is true if we're using locks
|
||||||
lockState bool
|
lockState bool
|
||||||
|
|
||||||
info *state.LockInfo
|
info *statemgr.LockInfo
|
||||||
|
|
||||||
// lockCancel cancels the Context use for lockRenewPeriodic, and is
|
// lockCancel cancels the Context use for lockRenewPeriodic, and is
|
||||||
// called when unlocking, or before creating a new lock if the lock is
|
// called when unlocking, or before creating a new lock if the lock is
|
||||||
|
@ -124,7 +124,7 @@ func (c *RemoteClient) Delete() error {
|
||||||
return c.delete(c.objectName)
|
return c.delete(c.objectName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
defer c.mu.Unlock()
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ func (c *RemoteClient) delete(object string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) writeLockInfo(info *state.LockInfo, deleteAfter time.Duration, ifNoneMatch string) error {
|
func (c *RemoteClient) writeLockInfo(info *statemgr.LockInfo, deleteAfter time.Duration, ifNoneMatch string) error {
|
||||||
err := c.put(c.lockFilePath(), info.Marshal(), int(deleteAfter.Seconds()), ifNoneMatch)
|
err := c.put(c.lockFilePath(), info.Marshal(), int(deleteAfter.Seconds()), ifNoneMatch)
|
||||||
|
|
||||||
if httpErr, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok && httpErr.Actual == 412 {
|
if httpErr, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok && httpErr.Actual == 412 {
|
||||||
|
@ -405,8 +405,8 @@ func (c *RemoteClient) writeLockInfo(info *state.LockInfo, deleteAfter time.Dura
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) lockError(err error, conflictingLock *state.LockInfo) *state.LockError {
|
func (c *RemoteClient) lockError(err error, conflictingLock *statemgr.LockInfo) *statemgr.LockError {
|
||||||
lockErr := &state.LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Err: err,
|
Err: err,
|
||||||
Info: conflictingLock,
|
Info: conflictingLock,
|
||||||
}
|
}
|
||||||
|
@ -416,13 +416,13 @@ func (c *RemoteClient) lockError(err error, conflictingLock *state.LockInfo) *st
|
||||||
|
|
||||||
// lockInfo reads the lock file, parses its contents and returns the parsed
|
// lockInfo reads the lock file, parses its contents and returns the parsed
|
||||||
// LockInfo struct.
|
// LockInfo struct.
|
||||||
func (c *RemoteClient) lockInfo() (*state.LockInfo, error) {
|
func (c *RemoteClient) lockInfo() (*statemgr.LockInfo, error) {
|
||||||
raw, err := c.get(c.lockFilePath())
|
raw, err := c.get(c.lockFilePath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := &state.LockInfo{}
|
info := &statemgr.LockInfo{}
|
||||||
|
|
||||||
if err := json.Unmarshal(raw.Data, info); err != nil {
|
if err := json.Unmarshal(raw.Data, info); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -431,7 +431,7 @@ func (c *RemoteClient) lockInfo() (*state.LockInfo, error) {
|
||||||
return info, nil
|
return info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RemoteClient) lockRenewPeriodic(ctx context.Context, info *state.LockInfo) error {
|
func (c *RemoteClient) lockRenewPeriodic(ctx context.Context, info *statemgr.LockInfo) error {
|
||||||
log.Printf("[DEBUG] Renew lock %v", info)
|
log.Printf("[DEBUG] Renew lock %v", info)
|
||||||
|
|
||||||
waitDur := lockRenewInterval
|
waitDur := lockRenewInterval
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRemoteClient_impl(t *testing.T) {
|
func TestRemoteClient_impl(t *testing.T) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"github.com/hashicorp/terraform-svchost/disco"
|
"github.com/hashicorp/terraform-svchost/disco"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs/configschema"
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
|
|
|
@ -8,14 +8,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
tfe "github.com/hashicorp/go-tfe"
|
tfe "github.com/hashicorp/go-tfe"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
|
||||||
"github.com/hashicorp/terraform/states/statefile"
|
"github.com/hashicorp/terraform/states/statefile"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
type remoteClient struct {
|
type remoteClient struct {
|
||||||
client *tfe.Client
|
client *tfe.Client
|
||||||
lockInfo *state.LockInfo
|
lockInfo *statemgr.LockInfo
|
||||||
organization string
|
organization string
|
||||||
runID string
|
runID string
|
||||||
stateUploadErr bool
|
stateUploadErr bool
|
||||||
|
@ -106,10 +106,10 @@ func (r *remoteClient) EnableForcePush() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock the remote state.
|
// Lock the remote state.
|
||||||
func (r *remoteClient) Lock(info *state.LockInfo) (string, error) {
|
func (r *remoteClient) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
lockErr := &state.LockError{Info: r.lockInfo}
|
lockErr := &statemgr.LockError{Info: r.lockInfo}
|
||||||
|
|
||||||
// Lock the workspace.
|
// Lock the workspace.
|
||||||
_, err := r.client.Workspaces.Lock(ctx, r.workspace.ID, tfe.WorkspaceLockOptions{
|
_, err := r.client.Workspaces.Lock(ctx, r.workspace.ID, tfe.WorkspaceLockOptions{
|
||||||
|
@ -139,7 +139,7 @@ func (r *remoteClient) Unlock(id string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &state.LockError{Info: r.lockInfo}
|
lockErr := &statemgr.LockError{Info: r.lockInfo}
|
||||||
|
|
||||||
// With lock info this should be treated as a normal unlock.
|
// With lock info this should be treated as a normal unlock.
|
||||||
if r.lockInfo != nil {
|
if r.lockInfo != nil {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/configs/configschema"
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
"github.com/hashicorp/terraform/httpclient"
|
"github.com/hashicorp/terraform/httpclient"
|
||||||
"github.com/hashicorp/terraform/providers"
|
"github.com/hashicorp/terraform/providers"
|
||||||
"github.com/hashicorp/terraform/state/remote"
|
"github.com/hashicorp/terraform/states/remote"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
"github.com/hashicorp/terraform/version"
|
"github.com/hashicorp/terraform/version"
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/configs/hcl2shim"
|
"github.com/hashicorp/terraform/configs/hcl2shim"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
|
@ -293,7 +292,7 @@ func testLocks(t *testing.T, b1, b2 Backend, testForceUnlock bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fast exit if this doesn't support locking at all
|
// Fast exit if this doesn't support locking at all
|
||||||
if _, ok := b1StateMgr.(state.Locker); !ok {
|
if _, ok := b1StateMgr.(statemgr.Locker); !ok {
|
||||||
t.Logf("TestBackend: backend %T doesn't support state locking, not testing", b1)
|
t.Logf("TestBackend: backend %T doesn't support state locking, not testing", b1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -309,14 +308,14 @@ func testLocks(t *testing.T, b1, b2 Backend, testForceUnlock bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reassign so its obvious whats happening
|
// Reassign so its obvious whats happening
|
||||||
lockerA := b1StateMgr.(state.Locker)
|
lockerA := b1StateMgr.(statemgr.Locker)
|
||||||
lockerB := b2StateMgr.(state.Locker)
|
lockerB := b2StateMgr.(statemgr.Locker)
|
||||||
|
|
||||||
infoA := state.NewLockInfo()
|
infoA := statemgr.NewLockInfo()
|
||||||
infoA.Operation = "test"
|
infoA.Operation = "test"
|
||||||
infoA.Who = "clientA"
|
infoA.Who = "clientA"
|
||||||
|
|
||||||
infoB := state.NewLockInfo()
|
infoB := statemgr.NewLockInfo()
|
||||||
infoB.Operation = "test"
|
infoB.Operation = "test"
|
||||||
infoB.Who = "clientB"
|
infoB.Who = "clientB"
|
||||||
|
|
||||||
|
@ -325,7 +324,7 @@ func testLocks(t *testing.T, b1, b2 Backend, testForceUnlock bool) {
|
||||||
t.Fatal("unable to get initial lock:", err)
|
t.Fatal("unable to get initial lock:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can still get the state.State from another instance even
|
// Make sure we can still get the statemgr.Full from another instance even
|
||||||
// when locked. This should only happen when a state is loaded via the
|
// when locked. This should only happen when a state is loaded via the
|
||||||
// backend, and as a remote state.
|
// backend, and as a remote state.
|
||||||
_, err = b2.StateMgr(DefaultStateName)
|
_, err = b2.StateMgr(DefaultStateName)
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"github.com/hashicorp/terraform/configs/configschema"
|
"github.com/hashicorp/terraform/configs/configschema"
|
||||||
"github.com/hashicorp/terraform/plans"
|
"github.com/hashicorp/terraform/plans"
|
||||||
"github.com/hashicorp/terraform/providers"
|
"github.com/hashicorp/terraform/providers"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -305,8 +304,8 @@ func TestApply_defaultState(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an existing state file
|
// create an existing state file
|
||||||
localState := &state.LocalState{Path: statePath}
|
localState := statemgr.NewFilesystem(statePath)
|
||||||
if err := localState.WriteState(terraform.NewState()); err != nil {
|
if err := localState.WriteState(states.NewState()); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package state
|
package clistate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -12,6 +12,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -172,7 +173,7 @@ func (s *LocalState) RefreshState() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock implements a local filesystem state.Locker.
|
// Lock implements a local filesystem state.Locker.
|
||||||
func (s *LocalState) Lock(info *LockInfo) (string, error) {
|
func (s *LocalState) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
|
@ -192,7 +193,7 @@ func (s *LocalState) Lock(info *LockInfo) (string, error) {
|
||||||
err = multierror.Append(err, infoErr)
|
err = multierror.Append(err, infoErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
lockErr := &LockError{
|
lockErr := &statemgr.LockError{
|
||||||
Info: info,
|
Info: info,
|
||||||
Err: err,
|
Err: err,
|
||||||
}
|
}
|
||||||
|
@ -219,7 +220,7 @@ func (s *LocalState) Unlock(id string) error {
|
||||||
idErr = multierror.Append(idErr, err)
|
idErr = multierror.Append(idErr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &LockError{
|
return &statemgr.LockError{
|
||||||
Err: idErr,
|
Err: idErr,
|
||||||
Info: info,
|
Info: info,
|
||||||
}
|
}
|
||||||
|
@ -284,14 +285,14 @@ func (s *LocalState) lockInfoPath() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// lockInfo returns the data in a lock info file
|
// lockInfo returns the data in a lock info file
|
||||||
func (s *LocalState) lockInfo() (*LockInfo, error) {
|
func (s *LocalState) lockInfo() (*statemgr.LockInfo, error) {
|
||||||
path := s.lockInfoPath()
|
path := s.lockInfoPath()
|
||||||
infoData, err := ioutil.ReadFile(path)
|
infoData, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
info := LockInfo{}
|
info := statemgr.LockInfo{}
|
||||||
err = json.Unmarshal(infoData, &info)
|
err = json.Unmarshal(infoData, &info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("state file %q locked, but could not unmarshal lock info: %s", s.Path, err)
|
return nil, fmt.Errorf("state file %q locked, but could not unmarshal lock info: %s", s.Path, err)
|
||||||
|
@ -300,7 +301,7 @@ func (s *LocalState) lockInfo() (*LockInfo, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// write a new lock info file
|
// write a new lock info file
|
||||||
func (s *LocalState) writeLockInfo(info *LockInfo) error {
|
func (s *LocalState) writeLockInfo(info *statemgr.LockInfo) error {
|
||||||
path := s.lockInfoPath()
|
path := s.lockInfoPath()
|
||||||
info.Path = s.Path
|
info.Path = s.Path
|
||||||
info.Created = time.Now().UTC()
|
info.Created = time.Now().UTC()
|
|
@ -1,6 +1,6 @@
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package state
|
package clistate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
|
@ -1,6 +1,6 @@
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package state
|
package clistate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
multierror "github.com/hashicorp/go-multierror"
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/helper/slowmessage"
|
"github.com/hashicorp/terraform/helper/slowmessage"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/mitchellh/colorstring"
|
"github.com/mitchellh/colorstring"
|
||||||
|
@ -51,15 +50,15 @@ that no one else is holding a lock.
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Locker allows for more convenient usage of the lower-level state.Locker
|
// Locker allows for more convenient usage of the lower-level statemgr.Locker
|
||||||
// implementations.
|
// implementations.
|
||||||
// The state.Locker API requires passing in a state.LockInfo struct. Locker
|
// The statemgr.Locker API requires passing in a statemgr.LockInfo struct. Locker
|
||||||
// implementations are expected to create the required LockInfo struct when
|
// implementations are expected to create the required LockInfo struct when
|
||||||
// Lock is called, populate the Operation field with the "reason" string
|
// Lock is called, populate the Operation field with the "reason" string
|
||||||
// provided, and pass that on to the underlying state.Locker.
|
// provided, and pass that on to the underlying statemgr.Locker.
|
||||||
// Locker implementations are also expected to store any state required to call
|
// Locker implementations are also expected to store any state required to call
|
||||||
// Unlock, which is at a minimum the LockID string returned by the
|
// Unlock, which is at a minimum the LockID string returned by the
|
||||||
// state.Locker.
|
// statemgr.Locker.
|
||||||
type Locker interface {
|
type Locker interface {
|
||||||
// Lock the provided state manager, storing the reason string in the LockInfo.
|
// Lock the provided state manager, storing the reason string in the LockInfo.
|
||||||
Lock(s statemgr.Locker, reason string) error
|
Lock(s statemgr.Locker, reason string) error
|
||||||
|
@ -110,7 +109,7 @@ func (l *locker) Lock(s statemgr.Locker, reason string) error {
|
||||||
ctx, cancel := context.WithTimeout(l.ctx, l.timeout)
|
ctx, cancel := context.WithTimeout(l.ctx, l.timeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
lockInfo := statemgr.NewLockInfo()
|
||||||
lockInfo.Operation = reason
|
lockInfo.Operation = reason
|
||||||
|
|
||||||
err := slowmessage.Do(LockThreshold, func() error {
|
err := slowmessage.Do(LockThreshold, func() error {
|
||||||
|
|
|
@ -17,12 +17,10 @@ import (
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/backend/local"
|
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/helper/copy"
|
"github.com/hashicorp/terraform/helper/copy"
|
||||||
"github.com/hashicorp/terraform/internal/getproviders"
|
"github.com/hashicorp/terraform/internal/getproviders"
|
||||||
"github.com/hashicorp/terraform/internal/providercache"
|
"github.com/hashicorp/terraform/internal/providercache"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -878,12 +876,7 @@ func TestInit_getProvider(t *testing.T) {
|
||||||
// state.
|
// state.
|
||||||
s := terraform.NewState()
|
s := terraform.NewState()
|
||||||
s.TFVersion = "100.1.0"
|
s.TFVersion = "100.1.0"
|
||||||
local := &state.LocalState{
|
testStateFileDefault(t, s)
|
||||||
Path: local.DefaultStateFilename,
|
|
||||||
}
|
|
||||||
if err := local.WriteState(s); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
m.Ui = ui
|
m.Ui = ui
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/plans"
|
"github.com/hashicorp/terraform/plans"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
@ -439,7 +439,7 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di
|
||||||
// if we're using a remote backend. This may not yet exist which means
|
// if we're using a remote backend. This may not yet exist which means
|
||||||
// we haven't used a non-local backend before. That is okay.
|
// we haven't used a non-local backend before. That is okay.
|
||||||
statePath := filepath.Join(m.DataDir(), DefaultStateFilename)
|
statePath := filepath.Join(m.DataDir(), DefaultStateFilename)
|
||||||
sMgr := &state.LocalState{Path: statePath}
|
sMgr := &clistate.LocalState{Path: statePath}
|
||||||
if err := sMgr.RefreshState(); err != nil {
|
if err := sMgr.RefreshState(); err != nil {
|
||||||
diags = diags.Append(fmt.Errorf("Failed to load state: %s", err))
|
diags = diags.Append(fmt.Errorf("Failed to load state: %s", err))
|
||||||
return nil, diags
|
return nil, diags
|
||||||
|
@ -572,7 +572,7 @@ func (m *Meta) backendFromState() (backend.Backend, tfdiags.Diagnostics) {
|
||||||
// if we're using a remote backend. This may not yet exist which means
|
// if we're using a remote backend. This may not yet exist which means
|
||||||
// we haven't used a non-local backend before. That is okay.
|
// we haven't used a non-local backend before. That is okay.
|
||||||
statePath := filepath.Join(m.DataDir(), DefaultStateFilename)
|
statePath := filepath.Join(m.DataDir(), DefaultStateFilename)
|
||||||
sMgr := &state.LocalState{Path: statePath}
|
sMgr := &clistate.LocalState{Path: statePath}
|
||||||
if err := sMgr.RefreshState(); err != nil {
|
if err := sMgr.RefreshState(); err != nil {
|
||||||
diags = diags.Append(fmt.Errorf("Failed to load state: %s", err))
|
diags = diags.Append(fmt.Errorf("Failed to load state: %s", err))
|
||||||
return nil, diags
|
return nil, diags
|
||||||
|
@ -649,7 +649,7 @@ func (m *Meta) backendFromState() (backend.Backend, tfdiags.Diagnostics) {
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
// Unconfiguring a backend (moving from backend => local).
|
// Unconfiguring a backend (moving from backend => local).
|
||||||
func (m *Meta) backend_c_r_S(c *configs.Backend, cHash int, sMgr *state.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_c_r_S(c *configs.Backend, cHash int, sMgr *clistate.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
s := sMgr.State()
|
s := sMgr.State()
|
||||||
|
|
||||||
// Get the backend type for output
|
// Get the backend type for output
|
||||||
|
@ -704,7 +704,7 @@ func (m *Meta) backend_c_r_S(c *configs.Backend, cHash int, sMgr *state.LocalSta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Legacy remote state
|
// Legacy remote state
|
||||||
func (m *Meta) backend_c_R_s(c *configs.Backend, sMgr *state.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_c_R_s(c *configs.Backend, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
||||||
|
@ -714,7 +714,7 @@ func (m *Meta) backend_c_R_s(c *configs.Backend, sMgr *state.LocalState) (backen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsetting backend, saved backend, legacy remote state
|
// Unsetting backend, saved backend, legacy remote state
|
||||||
func (m *Meta) backend_c_R_S(c *configs.Backend, cHash int, sMgr *state.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_c_R_S(c *configs.Backend, cHash int, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
||||||
|
@ -724,7 +724,7 @@ func (m *Meta) backend_c_R_S(c *configs.Backend, cHash int, sMgr *state.LocalSta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuring a backend for the first time with legacy remote state.
|
// Configuring a backend for the first time with legacy remote state.
|
||||||
func (m *Meta) backend_C_R_s(c *configs.Backend, sMgr *state.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_C_R_s(c *configs.Backend, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
||||||
|
@ -734,7 +734,7 @@ func (m *Meta) backend_C_R_s(c *configs.Backend, sMgr *state.LocalState) (backen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configuring a backend for the first time.
|
// Configuring a backend for the first time.
|
||||||
func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *state.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
// Get the backend
|
// Get the backend
|
||||||
b, configVal, diags := m.backendInitFromConfig(c)
|
b, configVal, diags := m.backendInitFromConfig(c)
|
||||||
if diags.HasErrors() {
|
if diags.HasErrors() {
|
||||||
|
@ -754,7 +754,7 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *state.LocalSta
|
||||||
return nil, diags
|
return nil, diags
|
||||||
}
|
}
|
||||||
|
|
||||||
var localStates []state.State
|
var localStates []statemgr.Full
|
||||||
for _, workspace := range workspaces {
|
for _, workspace := range workspaces {
|
||||||
localState, err := localB.StateMgr(workspace)
|
localState, err := localB.StateMgr(workspace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -861,7 +861,7 @@ func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *state.LocalSta
|
||||||
}
|
}
|
||||||
|
|
||||||
// Changing a previously saved backend.
|
// Changing a previously saved backend.
|
||||||
func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *state.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *clistate.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
if output {
|
if output {
|
||||||
// Notify the user
|
// Notify the user
|
||||||
m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
|
m.Ui.Output(m.Colorize().Color(fmt.Sprintf(
|
||||||
|
@ -946,7 +946,7 @@ func (m *Meta) backend_C_r_S_changed(c *configs.Backend, cHash int, sMgr *state.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiailizing an unchanged saved backend
|
// Initiailizing an unchanged saved backend
|
||||||
func (m *Meta) backend_C_r_S_unchanged(c *configs.Backend, cHash int, sMgr *state.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_C_r_S_unchanged(c *configs.Backend, cHash int, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
s := sMgr.State()
|
s := sMgr.State()
|
||||||
|
@ -1001,7 +1001,7 @@ func (m *Meta) backend_C_r_S_unchanged(c *configs.Backend, cHash int, sMgr *stat
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiailizing a changed saved backend with legacy remote state.
|
// Initiailizing a changed saved backend with legacy remote state.
|
||||||
func (m *Meta) backend_C_R_S_changed(c *configs.Backend, sMgr *state.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_C_R_S_changed(c *configs.Backend, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
||||||
|
@ -1011,7 +1011,7 @@ func (m *Meta) backend_C_R_S_changed(c *configs.Backend, sMgr *state.LocalState)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initiailizing an unchanged saved backend with legacy remote state.
|
// Initiailizing an unchanged saved backend with legacy remote state.
|
||||||
func (m *Meta) backend_C_R_S_unchanged(c *configs.Backend, sMgr *state.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) {
|
func (m *Meta) backend_C_R_S_unchanged(c *configs.Backend, sMgr *clistate.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) {
|
||||||
var diags tfdiags.Diagnostics
|
var diags tfdiags.Diagnostics
|
||||||
|
|
||||||
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n")
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -336,7 +335,7 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
|
||||||
two = stateTwo.State()
|
two = stateTwo.State()
|
||||||
}
|
}
|
||||||
|
|
||||||
var confirmFunc func(state.State, state.State, *backendMigrateOpts) (bool, error)
|
var confirmFunc func(statemgr.Full, statemgr.Full, *backendMigrateOpts) (bool, error)
|
||||||
switch {
|
switch {
|
||||||
// No migration necessary
|
// No migration necessary
|
||||||
case one.Empty() && two.Empty():
|
case one.Empty() && two.Empty():
|
||||||
|
@ -401,7 +400,7 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Meta) backendMigrateEmptyConfirm(one, two state.State, opts *backendMigrateOpts) (bool, error) {
|
func (m *Meta) backendMigrateEmptyConfirm(one, two statemgr.Full, opts *backendMigrateOpts) (bool, error) {
|
||||||
inputOpts := &terraform.InputOpts{
|
inputOpts := &terraform.InputOpts{
|
||||||
Id: "backend-migrate-copy-to-empty",
|
Id: "backend-migrate-copy-to-empty",
|
||||||
Query: "Do you want to copy existing state to the new backend?",
|
Query: "Do you want to copy existing state to the new backend?",
|
||||||
|
@ -414,7 +413,7 @@ func (m *Meta) backendMigrateEmptyConfirm(one, two state.State, opts *backendMig
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Meta) backendMigrateNonEmptyConfirm(
|
func (m *Meta) backendMigrateNonEmptyConfirm(
|
||||||
stateOne, stateTwo state.State, opts *backendMigrateOpts) (bool, error) {
|
stateOne, stateTwo statemgr.Full, opts *backendMigrateOpts) (bool, error) {
|
||||||
// We need to grab both states so we can write them to a file
|
// We need to grab both states so we can write them to a file
|
||||||
one := stateOne.State()
|
one := stateOne.State()
|
||||||
two := stateTwo.State()
|
two := stateTwo.State()
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/helper/copy"
|
"github.com/hashicorp/terraform/helper/copy"
|
||||||
"github.com/hashicorp/terraform/plans"
|
"github.com/hashicorp/terraform/plans"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statefile"
|
"github.com/hashicorp/terraform/states/statefile"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
|
@ -1795,10 +1794,7 @@ func TestMetaBackend_localDoesNotDeleteLocal(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := (&state.LocalState{Path: DefaultStateFilename}).WriteState(orig)
|
testStateFileDefault(t, orig)
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
m := testMetaBackend(t, nil)
|
m := testMetaBackend(t, nil)
|
||||||
m.forceInitCopy = true
|
m.forceInitCopy = true
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
|
@ -23,8 +22,8 @@ type StateMeta struct {
|
||||||
// the backend, but changes the way that backups are done. This configures
|
// the backend, but changes the way that backups are done. This configures
|
||||||
// backups to be timestamped rather than just the original state path plus a
|
// backups to be timestamped rather than just the original state path plus a
|
||||||
// backup path.
|
// backup path.
|
||||||
func (c *StateMeta) State() (state.State, error) {
|
func (c *StateMeta) State() (statemgr.Full, error) {
|
||||||
var realState state.State
|
var realState statemgr.Full
|
||||||
backupPath := c.backupPath
|
backupPath := c.backupPath
|
||||||
stateOutPath := c.statePath
|
stateOutPath := c.statePath
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -19,11 +20,11 @@ func main() {
|
||||||
log.Fatal(os.Args[0], "statefile")
|
log.Fatal(os.Args[0], "statefile")
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &state.LocalState{
|
s := &clistate.LocalState{
|
||||||
Path: os.Args[1],
|
Path: os.Args[1],
|
||||||
}
|
}
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
info := statemgr.NewLockInfo()
|
||||||
info.Operation = "test"
|
info.Operation = "test"
|
||||||
info.Info = "state locker"
|
info.Info = "state locker"
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/hashicorp/terraform/backend/local"
|
"github.com/hashicorp/terraform/backend/local"
|
||||||
"github.com/hashicorp/terraform/backend/remote-state/inmem"
|
"github.com/hashicorp/terraform/backend/remote-state/inmem"
|
||||||
"github.com/hashicorp/terraform/helper/copy"
|
"github.com/hashicorp/terraform/helper/copy"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -265,7 +264,7 @@ func TestWorkspace_createWithState(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
newPath := filepath.Join(local.DefaultWorkspaceDir, "test", DefaultStateFilename)
|
newPath := filepath.Join(local.DefaultWorkspaceDir, "test", DefaultStateFilename)
|
||||||
envState := state.LocalState{Path: newPath}
|
envState := statemgr.NewFilesystem(newPath)
|
||||||
err = envState.RefreshState()
|
err = envState.RefreshState()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -364,11 +363,14 @@ func TestWorkspace_deleteWithState(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
envStatePath := filepath.Join(local.DefaultWorkspaceDir, "test", DefaultStateFilename)
|
f, err := os.Create(filepath.Join(local.DefaultWorkspaceDir, "test", "terraform.tfstate"))
|
||||||
err := (&state.LocalState{Path: envStatePath}).WriteState(originalState)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if err := terraform.WriteState(originalState, f); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
delCmd := &WorkspaceDeleteCommand{
|
delCmd := &WorkspaceDeleteCommand{
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
package state
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/states"
|
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BackupState wraps a State that backs up the state on the first time that
|
|
||||||
// a WriteState or PersistState is called.
|
|
||||||
//
|
|
||||||
// If Path exists, it will be overwritten.
|
|
||||||
type BackupState struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
Real State
|
|
||||||
Path string
|
|
||||||
|
|
||||||
done bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BackupState) State() *states.State {
|
|
||||||
return s.Real.State()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BackupState) RefreshState() error {
|
|
||||||
return s.Real.RefreshState()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BackupState) WriteState(state *states.State) error {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
|
|
||||||
if !s.done {
|
|
||||||
if err := s.backup(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.Real.WriteState(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BackupState) PersistState() error {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
|
|
||||||
if !s.done {
|
|
||||||
if err := s.backup(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.Real.PersistState()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BackupState) Lock(info *LockInfo) (string, error) {
|
|
||||||
return s.Real.Lock(info)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BackupState) Unlock(id string) error {
|
|
||||||
return s.Real.Unlock(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *BackupState) backup() error {
|
|
||||||
state := s.Real.State()
|
|
||||||
if state == nil {
|
|
||||||
if err := s.Real.RefreshState(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
state = s.Real.State()
|
|
||||||
}
|
|
||||||
|
|
||||||
// LocalState.WriteState ensures that a file always exists for locking
|
|
||||||
// purposes, but we don't need a backup or lock if the state is empty, so
|
|
||||||
// skip this with a nil state.
|
|
||||||
if state != nil {
|
|
||||||
ls := statemgr.NewFilesystem(s.Path)
|
|
||||||
if err := ls.WriteState(state); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.done = true
|
|
||||||
return nil
|
|
||||||
}
|
|
108
state/inmem.go
108
state/inmem.go
|
@ -1,108 +0,0 @@
|
||||||
package state
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
|
||||||
)
|
|
||||||
|
|
||||||
// InmemState is an in-memory state storage.
|
|
||||||
type InmemState struct {
|
|
||||||
mu sync.Mutex
|
|
||||||
state *terraform.State
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InmemState) State() *terraform.State {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
|
|
||||||
return s.state.DeepCopy()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InmemState) RefreshState() error {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InmemState) WriteState(state *terraform.State) error {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
|
|
||||||
state = state.DeepCopy()
|
|
||||||
|
|
||||||
if s.state != nil {
|
|
||||||
state.Serial = s.state.Serial
|
|
||||||
|
|
||||||
if !s.state.MarshalEqual(state) {
|
|
||||||
state.Serial++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.state = state
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InmemState) PersistState() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InmemState) Lock(*LockInfo) (string, error) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InmemState) Unlock(string) error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// inmemLocker is an in-memory State implementation for testing locks.
|
|
||||||
type inmemLocker struct {
|
|
||||||
*InmemState
|
|
||||||
|
|
||||||
mu sync.Mutex
|
|
||||||
lockInfo *LockInfo
|
|
||||||
// count the calls to Lock
|
|
||||||
lockCounter int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *inmemLocker) Lock(info *LockInfo) (string, error) {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
s.lockCounter++
|
|
||||||
|
|
||||||
lockErr := &LockError{
|
|
||||||
Info: &LockInfo{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.lockInfo != nil {
|
|
||||||
lockErr.Err = errors.New("state locked")
|
|
||||||
*lockErr.Info = *s.lockInfo
|
|
||||||
return "", lockErr
|
|
||||||
}
|
|
||||||
|
|
||||||
info.Created = time.Now().UTC()
|
|
||||||
s.lockInfo = info
|
|
||||||
return s.lockInfo.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *inmemLocker) Unlock(id string) error {
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
|
|
||||||
lockErr := &LockError{
|
|
||||||
Info: &LockInfo{},
|
|
||||||
}
|
|
||||||
|
|
||||||
if id != s.lockInfo.ID {
|
|
||||||
lockErr.Err = errors.New("invalid lock id")
|
|
||||||
*lockErr.Info = *s.lockInfo
|
|
||||||
return lockErr
|
|
||||||
}
|
|
||||||
|
|
||||||
s.lockInfo = nil
|
|
||||||
return nil
|
|
||||||
}
|
|
104
state/state.go
104
state/state.go
|
@ -1,104 +0,0 @@
|
||||||
package state
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
|
||||||
"github.com/hashicorp/terraform/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
// State is a deprecated alias for statemgr.Full
|
|
||||||
type State = statemgr.Full
|
|
||||||
|
|
||||||
// StateReader is a deprecated alias for statemgr.Reader
|
|
||||||
type StateReader = statemgr.Reader
|
|
||||||
|
|
||||||
// StateWriter is a deprecated alias for statemgr.Writer
|
|
||||||
type StateWriter = statemgr.Writer
|
|
||||||
|
|
||||||
// StateRefresher is a deprecated alias for statemgr.Refresher
|
|
||||||
type StateRefresher = statemgr.Refresher
|
|
||||||
|
|
||||||
// StatePersister is a deprecated alias for statemgr.Persister
|
|
||||||
type StatePersister = statemgr.Persister
|
|
||||||
|
|
||||||
// Locker is a deprecated alias for statemgr.Locker
|
|
||||||
type Locker = statemgr.Locker
|
|
||||||
|
|
||||||
// test hook to verify that LockWithContext has attempted a lock
|
|
||||||
var postLockHook func()
|
|
||||||
|
|
||||||
// Lock the state, using the provided context for timeout and cancellation.
|
|
||||||
// This backs off slightly to an upper limit.
|
|
||||||
func LockWithContext(ctx context.Context, s State, info *LockInfo) (string, error) {
|
|
||||||
delay := time.Second
|
|
||||||
maxDelay := 16 * time.Second
|
|
||||||
for {
|
|
||||||
id, err := s.Lock(info)
|
|
||||||
if err == nil {
|
|
||||||
return id, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
le, ok := err.(*LockError)
|
|
||||||
if !ok {
|
|
||||||
// not a lock error, so we can't retry
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if le == nil || le.Info == nil || le.Info.ID == "" {
|
|
||||||
// If we dont' have a complete LockError, there's something wrong with the lock
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if postLockHook != nil {
|
|
||||||
postLockHook()
|
|
||||||
}
|
|
||||||
|
|
||||||
// there's an existing lock, wait and try again
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
// return the last lock error with the info
|
|
||||||
return "", err
|
|
||||||
case <-time.After(delay):
|
|
||||||
if delay < maxDelay {
|
|
||||||
delay *= 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a LockInfo structure, populating the required fields.
|
|
||||||
func NewLockInfo() *LockInfo {
|
|
||||||
id, err := uuid.GenerateUUID()
|
|
||||||
if err != nil {
|
|
||||||
// this of course shouldn't happen
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't error out on user and hostname, as we don't require them
|
|
||||||
userName := ""
|
|
||||||
if userInfo, err := user.Current(); err == nil {
|
|
||||||
userName = userInfo.Username
|
|
||||||
}
|
|
||||||
host, _ := os.Hostname()
|
|
||||||
|
|
||||||
info := &LockInfo{
|
|
||||||
ID: id,
|
|
||||||
Who: fmt.Sprintf("%s@%s", userName, host),
|
|
||||||
Version: version.Version,
|
|
||||||
Created: time.Now().UTC(),
|
|
||||||
}
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
// LockInfo is a deprecated lias for statemgr.LockInfo
|
|
||||||
type LockInfo = statemgr.LockInfo
|
|
||||||
|
|
||||||
// LockError is a deprecated alias for statemgr.LockError
|
|
||||||
type LockError = statemgr.LockError
|
|
|
@ -1,52 +0,0 @@
|
||||||
package state
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/logging"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
|
||||||
flag.Parse()
|
|
||||||
if testing.Verbose() {
|
|
||||||
// if we're verbose, use the logging requested by TF_LOG
|
|
||||||
logging.SetOutput()
|
|
||||||
} else {
|
|
||||||
// otherwise silence all logs
|
|
||||||
log.SetOutput(ioutil.Discard)
|
|
||||||
}
|
|
||||||
os.Exit(m.Run())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewLockInfo(t *testing.T) {
|
|
||||||
info1 := NewLockInfo()
|
|
||||||
info2 := NewLockInfo()
|
|
||||||
|
|
||||||
if info1.ID == "" {
|
|
||||||
t.Fatal("LockInfo missing ID")
|
|
||||||
}
|
|
||||||
|
|
||||||
if info1.Version == "" {
|
|
||||||
t.Fatal("LockInfo missing version")
|
|
||||||
}
|
|
||||||
|
|
||||||
if info1.Created.IsZero() {
|
|
||||||
t.Fatal("LockInfo missing Created")
|
|
||||||
}
|
|
||||||
|
|
||||||
if info1.ID == info2.ID {
|
|
||||||
t.Fatal("multiple LockInfo with identical IDs")
|
|
||||||
}
|
|
||||||
|
|
||||||
// test the JSON output is valid
|
|
||||||
newInfo := &LockInfo{}
|
|
||||||
err := json.Unmarshal(info1.Marshal(), newInfo)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Attempt to open and lock a terraform state file.
|
|
||||||
// Lock failure exits with 0 and writes "lock failed" to stderr.
|
|
||||||
func main() {
|
|
||||||
if len(os.Args) != 2 {
|
|
||||||
log.Fatal(os.Args[0], "statefile")
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &state.LocalState{
|
|
||||||
Path: os.Args[1],
|
|
||||||
}
|
|
||||||
|
|
||||||
info := state.NewLockInfo()
|
|
||||||
info.Operation = "test"
|
|
||||||
info.Info = "state locker"
|
|
||||||
|
|
||||||
_, err := s.Lock(info)
|
|
||||||
if err != nil {
|
|
||||||
io.WriteString(os.Stderr, "lock failed")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
package state
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/states"
|
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestState is a helper for testing state implementations. It is expected
|
|
||||||
// that the given implementation is pre-loaded with the TestStateInitial
|
|
||||||
// state.
|
|
||||||
func TestState(t *testing.T, s State) {
|
|
||||||
t.Helper()
|
|
||||||
statemgr.TestFull(t, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestStateInitial is the initial state that a State should have
|
|
||||||
// for TestState.
|
|
||||||
func TestStateInitial() *states.State {
|
|
||||||
return statemgr.TestFullInitialState()
|
|
||||||
}
|
|
|
@ -3,7 +3,7 @@ package remote
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is the interface that must be implemented for a remote state
|
// Client is the interface that must be implemented for a remote state
|
||||||
|
@ -27,7 +27,7 @@ type ClientForcePusher interface {
|
||||||
// backend to enable state lock/unlock.
|
// backend to enable state lock/unlock.
|
||||||
type ClientLocker interface {
|
type ClientLocker interface {
|
||||||
Client
|
Client
|
||||||
state.Locker
|
statemgr.Locker
|
||||||
}
|
}
|
||||||
|
|
||||||
// Payload is the return value from the remote state storage.
|
// Payload is the return value from the remote state storage.
|
|
@ -6,14 +6,14 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states/statefile"
|
"github.com/hashicorp/terraform/states/statefile"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testClient is a generic function to test any client.
|
// testClient is a generic function to test any client.
|
||||||
func testClient(t *testing.T, c Client) {
|
func testClient(t *testing.T, c Client) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
s := state.TestStateInitial()
|
s := statemgr.TestFullInitialState()
|
||||||
sf := &statefile.File{State: s}
|
sf := &statefile.File{State: s}
|
||||||
if err := statefile.Write(sf, &buf); err != nil {
|
if err := statefile.Write(sf, &buf); err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
uuid "github.com/hashicorp/go-uuid"
|
uuid "github.com/hashicorp/go-uuid"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states/statefile"
|
"github.com/hashicorp/terraform/states/statefile"
|
||||||
"github.com/hashicorp/terraform/states/statemgr"
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
|
@ -196,7 +195,7 @@ func (s *State) PersistState() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock calls the Client's Lock method if it's implemented.
|
// Lock calls the Client's Lock method if it's implemented.
|
||||||
func (s *State) Lock(info *state.LockInfo) (string, error) {
|
func (s *State) Lock(info *statemgr.LockInfo) (string, error) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
|
@ -4,14 +4,14 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/states/statefile"
|
"github.com/hashicorp/terraform/states/statefile"
|
||||||
|
"github.com/hashicorp/terraform/states/statemgr"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestClient is a generic function to test any client.
|
// TestClient is a generic function to test any client.
|
||||||
func TestClient(t *testing.T, c Client) {
|
func TestClient(t *testing.T, c Client) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
s := state.TestStateInitial()
|
s := statemgr.TestFullInitialState()
|
||||||
sf := statefile.New(s, "stub-lineage", 2)
|
sf := statefile.New(s, "stub-lineage", 2)
|
||||||
err := statefile.Write(sf, &buf)
|
err := statefile.Write(sf, &buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -49,21 +49,21 @@ func TestClient(t *testing.T, c Client) {
|
||||||
// clients since some implementations may tie the client to the lock, or may
|
// clients since some implementations may tie the client to the lock, or may
|
||||||
// have reentrant locks.
|
// have reentrant locks.
|
||||||
func TestRemoteLocks(t *testing.T, a, b Client) {
|
func TestRemoteLocks(t *testing.T, a, b Client) {
|
||||||
lockerA, ok := a.(state.Locker)
|
lockerA, ok := a.(statemgr.Locker)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("client A not a state.Locker")
|
t.Fatal("client A not a statemgr.Locker")
|
||||||
}
|
}
|
||||||
|
|
||||||
lockerB, ok := b.(state.Locker)
|
lockerB, ok := b.(statemgr.Locker)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Fatal("client B not a state.Locker")
|
t.Fatal("client B not a statemgr.Locker")
|
||||||
}
|
}
|
||||||
|
|
||||||
infoA := state.NewLockInfo()
|
infoA := statemgr.NewLockInfo()
|
||||||
infoA.Operation = "test"
|
infoA.Operation = "test"
|
||||||
infoA.Who = "clientA"
|
infoA.Who = "clientA"
|
||||||
|
|
||||||
infoB := state.NewLockInfo()
|
infoB := statemgr.NewLockInfo()
|
||||||
infoB.Operation = "test"
|
infoB.Operation = "test"
|
||||||
infoB.Who = "clientB"
|
infoB.Who = "clientB"
|
||||||
|
|
|
@ -44,7 +44,7 @@ type Filesystem struct {
|
||||||
stateFileOut *os.File
|
stateFileOut *os.File
|
||||||
|
|
||||||
// While the stateFileOut will correspond to the lock directly,
|
// While the stateFileOut will correspond to the lock directly,
|
||||||
// store and check the lock ID to maintain a strict state.Locker
|
// store and check the lock ID to maintain a strict statemgr.Locker
|
||||||
// implementation.
|
// implementation.
|
||||||
lockID string
|
lockID string
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package state
|
package statemgr
|
||||||
|
|
||||||
import (
|
import "github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/states"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LockDisabled implements State and Locker but disables state locking.
|
// LockDisabled implements State and Locker but disables state locking.
|
||||||
// If State doesn't support locking, this is a no-op. This is useful for
|
// If State doesn't support locking, this is a no-op. This is useful for
|
||||||
|
@ -10,7 +8,7 @@ import (
|
||||||
type LockDisabled struct {
|
type LockDisabled struct {
|
||||||
// We can't embed State directly since Go dislikes that a field is
|
// We can't embed State directly since Go dislikes that a field is
|
||||||
// State and State interface has a method State
|
// State and State interface has a method State
|
||||||
Inner State
|
Inner Full
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *LockDisabled) State() *states.State {
|
func (s *LockDisabled) State() *states.State {
|
|
@ -1,10 +1,10 @@
|
||||||
package state
|
package statemgr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLockDisabled_impl(t *testing.T) {
|
func TestLockDisabled_impl(t *testing.T) {
|
||||||
var _ State = new(LockDisabled)
|
var _ Full = new(LockDisabled)
|
||||||
var _ Locker = new(LockDisabled)
|
var _ Locker = new(LockDisabled)
|
||||||
}
|
}
|
Loading…
Reference in New Issue