mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Use single state.LockInfo struct
Remove redundant structures
This commit is contained in:
parent
9b76f6e138
commit
14d965722e
@ -4,12 +4,12 @@ import (
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/errwrap"
|
||||
multierror "github.com/hashicorp/go-multierror"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/state/remote"
|
||||
)
|
||||
|
||||
@ -18,12 +18,6 @@ const (
|
||||
lockInfoSuffix = "/.lockinfo"
|
||||
)
|
||||
|
||||
// TODO: use single LockInfo struct
|
||||
type lockInfo struct {
|
||||
Created time.Time
|
||||
Info string
|
||||
}
|
||||
|
||||
// RemoteClient is a remote client that stores data in Consul.
|
||||
type RemoteClient struct {
|
||||
Client *consulapi.Client
|
||||
@ -65,7 +59,8 @@ func (c *RemoteClient) Delete() error {
|
||||
}
|
||||
|
||||
func (c *RemoteClient) putLockInfo(info string) error {
|
||||
li := &lockInfo{
|
||||
li := &state.LockInfo{
|
||||
Path: c.Path,
|
||||
Created: time.Now().UTC(),
|
||||
Info: info,
|
||||
}
|
||||
@ -84,7 +79,7 @@ func (c *RemoteClient) putLockInfo(info string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *RemoteClient) getLockInfo() (*lockInfo, error) {
|
||||
func (c *RemoteClient) getLockInfo() (*state.LockInfo, error) {
|
||||
path := c.Path + lockInfoSuffix
|
||||
pair, _, err := c.Client.KV().Get(path, nil)
|
||||
if err != nil {
|
||||
@ -94,7 +89,7 @@ func (c *RemoteClient) getLockInfo() (*lockInfo, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
li := &lockInfo{}
|
||||
li := &state.LockInfo{}
|
||||
err = json.Unmarshal(pair.Value, li)
|
||||
if err != nil {
|
||||
return nil, errwrap.Wrapf("error unmarshaling lock info: {{err}}", err)
|
||||
@ -144,8 +139,7 @@ func (c *RemoteClient) Lock(info string) error {
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
return fmt.Errorf("state locked: created:%s, info:%q",
|
||||
lockInfo.Created, lockInfo.Info)
|
||||
return lockInfo.Err()
|
||||
}
|
||||
|
||||
c.lockCh = lockCh
|
||||
|
@ -14,19 +14,27 @@ import (
|
||||
)
|
||||
|
||||
// lock metadata structure for local locks
|
||||
type lockInfo struct {
|
||||
type LockInfo struct {
|
||||
// Path to the state file
|
||||
Path string
|
||||
// The time the lock was taken
|
||||
Created time.Time
|
||||
// Extra info passed to State.Lock
|
||||
Reason string
|
||||
Info string
|
||||
}
|
||||
|
||||
// return the lock info formatted in an error
|
||||
func (l *lockInfo) Err() error {
|
||||
return fmt.Errorf("state file %q locked. created:%s, reason:%s",
|
||||
l.Path, l.Created, l.Reason)
|
||||
func (l *LockInfo) Err() error {
|
||||
return fmt.Errorf("state locked. path:%q, created:%s, info:%q",
|
||||
l.Path, l.Created, l.Info)
|
||||
}
|
||||
|
||||
func (l *LockInfo) String() string {
|
||||
js, err := json.Marshal(l)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(js)
|
||||
}
|
||||
|
||||
// LocalState manages a state storage that is local to the filesystem.
|
||||
@ -224,14 +232,14 @@ func (s *LocalState) lockInfoPath() string {
|
||||
}
|
||||
|
||||
// lockInfo returns the data in a lock info file
|
||||
func (s *LocalState) lockInfo() (*lockInfo, error) {
|
||||
func (s *LocalState) lockInfo() (*LockInfo, error) {
|
||||
path := s.lockInfoPath()
|
||||
infoData, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := lockInfo{}
|
||||
info := LockInfo{}
|
||||
err = json.Unmarshal(infoData, &info)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("state file %q locked, but could not unmarshal lock info: %s", s.Path, err)
|
||||
@ -240,13 +248,13 @@ func (s *LocalState) lockInfo() (*lockInfo, error) {
|
||||
}
|
||||
|
||||
// write a new lock info file
|
||||
func (s *LocalState) writeLockInfo(reason string) error {
|
||||
func (s *LocalState) writeLockInfo(info string) error {
|
||||
path := s.lockInfoPath()
|
||||
|
||||
lockInfo := &lockInfo{
|
||||
lockInfo := &LockInfo{
|
||||
Path: s.Path,
|
||||
Created: time.Now().UTC(),
|
||||
Reason: reason,
|
||||
Info: info,
|
||||
}
|
||||
|
||||
infoData, err := json.Marshal(lockInfo)
|
||||
|
@ -40,7 +40,7 @@ func TestLocalStateLocks(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if lockInfo.Reason != "test" {
|
||||
if lockInfo.Info != "test" {
|
||||
t.Fatalf("invalid lock info %#v\n", lockInfo)
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package remote
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
@ -17,6 +18,7 @@ import (
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
"github.com/hashicorp/go-multierror"
|
||||
terraformAws "github.com/hashicorp/terraform/builtin/providers/aws"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
)
|
||||
|
||||
func s3Factory(conf map[string]string) (Client, error) {
|
||||
@ -196,18 +198,22 @@ func (c *S3Client) Delete() error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *S3Client) Lock(reason string) error {
|
||||
func (c *S3Client) Lock(info string) error {
|
||||
if c.lockTable == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
stateName := fmt.Sprintf("%s/%s", c.bucketName, c.keyName)
|
||||
lockInfo := &state.LockInfo{
|
||||
Path: stateName,
|
||||
Created: time.Now().UTC(),
|
||||
Info: info,
|
||||
}
|
||||
|
||||
putParams := &dynamodb.PutItemInput{
|
||||
Item: map[string]*dynamodb.AttributeValue{
|
||||
"LockID": {S: aws.String(stateName)},
|
||||
"Created": {S: aws.String(time.Now().UTC().Format(time.RFC3339))},
|
||||
"Info": {S: aws.String(reason)},
|
||||
"LockID": {S: aws.String(stateName)},
|
||||
"Info": {S: aws.String(lockInfo.String())},
|
||||
},
|
||||
TableName: aws.String(c.lockTable),
|
||||
ConditionExpression: aws.String("attribute_not_exists(LockID)"),
|
||||
@ -225,20 +231,21 @@ func (c *S3Client) Lock(reason string) error {
|
||||
|
||||
resp, err := c.dynClient.GetItem(getParams)
|
||||
if err != nil {
|
||||
return fmt.Errorf("s3 state file %q locked, cfailed to retrive info: %s", stateName, err)
|
||||
return fmt.Errorf("s3 state file %q locked, failed to retrive info: %s", stateName, err)
|
||||
}
|
||||
|
||||
var created, info string
|
||||
if v, ok := resp.Item["Created"]; ok && v.S != nil {
|
||||
created = *v.S
|
||||
}
|
||||
var infoData string
|
||||
if v, ok := resp.Item["Info"]; ok && v.S != nil {
|
||||
info = *v.S
|
||||
infoData = *v.S
|
||||
}
|
||||
|
||||
return fmt.Errorf("state file %q locked. created:%s, reason:%s",
|
||||
stateName, created, info)
|
||||
lockInfo = &state.LockInfo{}
|
||||
err = json.Unmarshal([]byte(infoData), lockInfo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("s3 state file %q locked, failed get lock info: %s", stateName, err)
|
||||
}
|
||||
|
||||
return lockInfo.Err()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user