Add inmem remote backend
Add an Inmem remote state backend. The only config option right now is a lock_id, which will instantiate the backend in a locked state for testing.
This commit is contained in:
parent
3127998ecd
commit
2392455a67
|
@ -0,0 +1,41 @@
|
|||
package inmem
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/backend/remote-state"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
)
|
||||
|
||||
// New creates a new backend for Inmem remote state.
|
||||
func New() backend.Backend {
|
||||
return &remotestate.Backend{
|
||||
ConfigureFunc: configure,
|
||||
|
||||
// Set the schema
|
||||
Backend: &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"lock_id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Description: "initializes the state in a locked configuration",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func configure(ctx context.Context) (remote.Client, error) {
|
||||
data := schema.FromContextBackendConfig(ctx)
|
||||
if v, ok := data.GetOk("lock_id"); ok && v.(string) != "" {
|
||||
info := state.NewLockInfo()
|
||||
info.ID = v.(string)
|
||||
info.Operation = "test"
|
||||
info.Info = "test config"
|
||||
return &RemoteClient{LockInfo: info}, nil
|
||||
}
|
||||
return &RemoteClient{}, nil
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package inmem
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
)
|
||||
|
||||
// RemoteClient is a remote client that stores data in memory for testing.
|
||||
type RemoteClient struct {
|
||||
Data []byte
|
||||
MD5 []byte
|
||||
|
||||
LockInfo *state.LockInfo
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Get() (*remote.Payload, error) {
|
||||
if c.Data == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return &remote.Payload{
|
||||
Data: c.Data,
|
||||
MD5: c.MD5,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Put(data []byte) error {
|
||||
md5 := md5.Sum(data)
|
||||
|
||||
c.Data = data
|
||||
c.MD5 = md5[:]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Delete() error {
|
||||
c.Data = nil
|
||||
c.MD5 = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Lock(info *state.LockInfo) (string, error) {
|
||||
lockErr := &state.LockError{
|
||||
Info: &state.LockInfo{},
|
||||
}
|
||||
|
||||
if c.LockInfo != nil {
|
||||
lockErr.Err = errors.New("state locked")
|
||||
// make a copy of the lock info to avoid any testing shenanigans
|
||||
*lockErr.Info = *c.LockInfo
|
||||
return "", lockErr
|
||||
}
|
||||
|
||||
info.Created = time.Now().UTC()
|
||||
c.LockInfo = info
|
||||
|
||||
return c.LockInfo.ID, nil
|
||||
}
|
||||
|
||||
func (c *RemoteClient) Unlock(id string) error {
|
||||
if c.LockInfo == nil {
|
||||
return errors.New("state not locked")
|
||||
}
|
||||
|
||||
lockErr := &state.LockError{
|
||||
Info: &state.LockInfo{},
|
||||
}
|
||||
if id != c.LockInfo.ID {
|
||||
lockErr.Err = errors.New("invalid lock id")
|
||||
*lockErr.Info = *c.LockInfo
|
||||
return lockErr
|
||||
}
|
||||
|
||||
c.LockInfo = nil
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package inmem
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
remotestate "github.com/hashicorp/terraform/backend/remote-state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
)
|
||||
|
||||
func TestRemoteClient_impl(t *testing.T) {
|
||||
var _ remote.Client = new(RemoteClient)
|
||||
var _ remote.ClientLocker = new(RemoteClient)
|
||||
}
|
||||
|
||||
func TestRemoteClient(t *testing.T) {
|
||||
b := backend.TestBackendConfig(t, New(), nil)
|
||||
remotestate.TestClient(t, b)
|
||||
}
|
||||
|
||||
func TestInmemLocks(t *testing.T) {
|
||||
s, err := backend.TestBackendConfig(t, New(), nil).State()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
remote.TestRemoteLocks(t, s.(*remote.State).Client, s.(*remote.State).Client)
|
||||
}
|
Loading…
Reference in New Issue