Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 18 additions & 12 deletions internal/backend/remote-state/azure/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

"github.com/hashicorp/terraform/internal/states/remote"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/hashicorp/terraform/internal/tfdiags"
)

const (
Expand All @@ -44,7 +45,8 @@ type RemoteClient struct {
snapshot bool
}

func (c *RemoteClient) Get() (*remote.Payload, error) {
func (c *RemoteClient) Get() (*remote.Payload, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
options := blobs.GetInput{}
if c.leaseID != "" {
options.LeaseID = &c.leaseID
Expand All @@ -56,11 +58,11 @@ func (c *RemoteClient) Get() (*remote.Payload, error) {
if response.WasNotFound(blob.HttpResponse) {
return nil, nil
}
return nil, err
return nil, diags.Append(err)
}

if blob.Contents == nil {
return nil, nil
return nil, diags
}

payload := &remote.Payload{
Expand All @@ -69,13 +71,15 @@ func (c *RemoteClient) Get() (*remote.Payload, error) {

// If there was no data, then return nil
if len(payload.Data) == 0 {
return nil, nil
return nil, diags
}

return payload, nil
return payload, diags
}

func (c *RemoteClient) Put(data []byte) error {
func (c *RemoteClient) Put(data []byte) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics

getOptions := blobs.GetPropertiesInput{}
setOptions := blobs.SetPropertiesInput{}
putOptions := blobs.PutBlockBlobInput{}
Expand All @@ -95,7 +99,7 @@ func (c *RemoteClient) Put(data []byte) error {

log.Printf("[DEBUG] Snapshotting existing Blob %q (Container %q / Account %q)", c.keyName, c.containerName, c.accountName)
if _, err := c.giovanniBlobClient.Snapshot(ctx, c.containerName, c.keyName, snapshotInput); err != nil {
return fmt.Errorf("error snapshotting Blob %q (Container %q / Account %q): %+v", c.keyName, c.containerName, c.accountName, err)
return diags.Append(fmt.Errorf("error snapshotting Blob %q (Container %q / Account %q): %+v", c.keyName, c.containerName, c.accountName, err))
}

log.Print("[DEBUG] Created blob snapshot")
Expand All @@ -104,7 +108,7 @@ func (c *RemoteClient) Put(data []byte) error {
blob, err := c.giovanniBlobClient.GetProperties(ctx, c.containerName, c.keyName, getOptions)
if err != nil {
if !response.WasNotFound(blob.HttpResponse) {
return err
return diags.Append(err)
}
}

Expand All @@ -114,10 +118,12 @@ func (c *RemoteClient) Put(data []byte) error {
putOptions.MetaData = blob.MetaData
_, err = c.giovanniBlobClient.PutBlockBlob(ctx, c.containerName, c.keyName, putOptions)

return err
return diags.Append(err)
}

func (c *RemoteClient) Delete() error {
func (c *RemoteClient) Delete() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics

options := blobs.DeleteInput{}

if c.leaseID != "" {
Expand All @@ -128,10 +134,10 @@ func (c *RemoteClient) Delete() error {
resp, err := c.giovanniBlobClient.Delete(ctx, c.containerName, c.keyName, options)
if err != nil {
if !response.WasNotFound(resp.HttpResponse) {
return err
return diags.Append(err)
}
}
return nil
return diags
}

func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
Expand Down
6 changes: 3 additions & 3 deletions internal/backend/remote-state/azure/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,9 @@ func TestPutMaintainsMetaData(t *testing.T) {
}

bytes := []byte(randString(20))
err = remoteClient.Put(bytes)
if err != nil {
t.Fatalf("Error putting data: %+v", err)
diags := remoteClient.Put(bytes)
if diags.HasErrors() {
t.Fatalf("Error putting data: %+v", diags.Err())
}

// Verify it still exists
Expand Down
44 changes: 25 additions & 19 deletions internal/backend/remote-state/consul/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/hashicorp/terraform/internal/states/remote"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/hashicorp/terraform/internal/tfdiags"
)

const (
Expand Down Expand Up @@ -71,18 +72,20 @@ type RemoteClient struct {
sessionCancel context.CancelFunc
}

func (c *RemoteClient) Get() (*remote.Payload, error) {
func (c *RemoteClient) Get() (*remote.Payload, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics

c.mu.Lock()
defer c.mu.Unlock()

kv := c.Client.KV()

chunked, hash, chunks, pair, err := c.chunkedMode()
if err != nil {
return nil, err
return nil, diags.Append(err)
}
if pair == nil {
return nil, nil
return nil, diags
}

c.modifyIndex = pair.ModifyIndex
Expand All @@ -92,10 +95,10 @@ func (c *RemoteClient) Get() (*remote.Payload, error) {
for _, c := range chunks {
pair, _, err := kv.Get(c, nil)
if err != nil {
return nil, err
return nil, diags.Append(err)
}
if pair == nil {
return nil, fmt.Errorf("Key %q could not be found", c)
return nil, diags.Append(fmt.Errorf("Key %q could not be found", c))
}
payload = append(payload, pair.Value[:]...)
}
Expand All @@ -107,23 +110,23 @@ func (c *RemoteClient) Get() (*remote.Payload, error) {
if len(payload) >= 1 && payload[0] == '\x1f' {
payload, err = uncompressState(payload)
if err != nil {
return nil, err
return nil, diags.Append(err)
}
}

md5 := md5.Sum(payload)

if hash != "" && fmt.Sprintf("%x", md5) != hash {
return nil, fmt.Errorf("The remote state does not match the expected hash")
return nil, diags.Append(fmt.Errorf("The remote state does not match the expected hash"))
}

return &remote.Payload{
Data: payload,
MD5: md5[:],
}, nil
}, diags
}

func (c *RemoteClient) Put(data []byte) error {
func (c *RemoteClient) Put(data []byte) tfdiags.Diagnostics {
// The state can be stored in 4 different ways, based on the payload size
// and whether the user enabled gzip:
// - single entry mode with plain JSON: a single JSON is stored at
Expand Down Expand Up @@ -161,6 +164,8 @@ func (c *RemoteClient) Put(data []byte) error {
// in chunked mode and we will need to remove the old chunks (whether or
// not we were using gzip does not matter in that case).

var diags tfdiags.Diagnostics

c.mu.Lock()
defer c.mu.Unlock()

Expand All @@ -169,7 +174,7 @@ func (c *RemoteClient) Put(data []byte) error {
// First we determine what mode we were using and to prepare the cleanup
chunked, hash, _, _, err := c.chunkedMode()
if err != nil {
return err
return diags.Append(err)
}
cleanupOldChunks := func() {}
if chunked {
Expand All @@ -188,7 +193,7 @@ func (c *RemoteClient) Put(data []byte) error {
if compressedState, err := compressState(data); err == nil {
payload = compressedState
} else {
return err
return diags.Append(err)
}
}

Expand Down Expand Up @@ -256,10 +261,10 @@ func (c *RemoteClient) Put(data []byte) error {

if err = store(payload); err == nil {
// The payload was small enough to be stored
return nil
return diags
} else if !strings.Contains(err.Error(), "too large") {
// We failed for some other reason, report this to the user
return err
return diags.Append(err)
}

// The payload was too large so we split it in multiple chunks
Expand All @@ -278,7 +283,7 @@ func (c *RemoteClient) Put(data []byte) error {
}, nil)

if err != nil {
return err
return diags.Append(err)
}
}

Expand All @@ -288,20 +293,21 @@ func (c *RemoteClient) Put(data []byte) error {
"chunks": chunkPaths,
})
if err != nil {
return err
return diags.Append(err)
}
return store(payload)
return diags.Append(store(payload))
}

func (c *RemoteClient) Delete() error {
func (c *RemoteClient) Delete() tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
c.mu.Lock()
defer c.mu.Unlock()

kv := c.Client.KV()

chunked, hash, _, _, err := c.chunkedMode()
if err != nil {
return err
return diags.Append(err)
}

_, err = kv.Delete(c.Path, nil)
Expand All @@ -312,7 +318,7 @@ func (c *RemoteClient) Delete() error {
kv.DeleteTree(path, nil)
}

return err
return diags.Append(err)
}

func (c *RemoteClient) lockPath() string {
Expand Down
18 changes: 9 additions & 9 deletions internal/backend/remote-state/consul/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ func TestConsul_largeState(t *testing.T) {
if err != nil {
t.Fatal(err)
}
err = c.Put(payload)
if err != nil {
t.Fatal("could not put payload", err)
diags := c.Put(payload)
if diags.HasErrors() {
t.Fatal("could not put payload", diags.Err())
}

remote, err := c.Get()
if err != nil {
t.Fatal(err)
remote, diags := c.Get()
if diags.HasErrors() {
t.Fatal(diags.Err())
}

if !bytes.Equal(payload, remote.Data) {
Expand Down Expand Up @@ -229,9 +229,9 @@ func TestConsul_largeState(t *testing.T) {
)

// Deleting the state should remove all chunks
err := c.Delete()
if err != nil {
t.Fatal(err)
dDiags := c.Delete()
if dDiags.HasErrors() {
t.Fatal(dDiags.Err())
}
testPaths(t, []string{})
}
Expand Down
20 changes: 12 additions & 8 deletions internal/backend/remote-state/cos/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/hashicorp/terraform/internal/states/remote"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/hashicorp/terraform/internal/tfdiags"
)

const (
Expand All @@ -41,38 +42,41 @@ type remoteClient struct {
}

// Get returns remote state file
func (c *remoteClient) Get() (*remote.Payload, error) {
func (c *remoteClient) Get() (*remote.Payload, tfdiags.Diagnostics) {
log.Printf("[DEBUG] get remote state file %s", c.stateFile)
var diags tfdiags.Diagnostics

exists, data, checksum, err := c.getObject(c.stateFile)
if err != nil {
return nil, err
return nil, diags.Append(err)
}

if !exists {
return nil, nil
return nil, diags
}

payload := &remote.Payload{
Data: data,
MD5: []byte(checksum),
}

return payload, nil
return payload, diags
}

// Put put state file to remote
func (c *remoteClient) Put(data []byte) error {
func (c *remoteClient) Put(data []byte) tfdiags.Diagnostics {
log.Printf("[DEBUG] put remote state file %s", c.stateFile)
var diags tfdiags.Diagnostics

return c.putObject(c.stateFile, data)
return diags.Append(c.putObject(c.stateFile, data))
}

// Delete delete remote state file
func (c *remoteClient) Delete() error {
func (c *remoteClient) Delete() tfdiags.Diagnostics {
log.Printf("[DEBUG] delete remote state file %s", c.stateFile)
var diags tfdiags.Diagnostics

return c.deleteObject(c.stateFile)
return diags.Append(c.deleteObject(c.stateFile))
}

// Lock lock remote state file for writing
Expand Down
Loading