Skip to content

Commit

Permalink
Azure backend: support snapshots/versioning (#24069)
Browse files Browse the repository at this point in the history
* Azure backend: support snapshots/versioning

Co-authored-by: Reda Ahdjoudj <[email protected]>
Co-authored-by: Patrick F. Marques <[email protected]>

* Azure backend: Versioning -> Snapshot

Co-authored-by: Reda Ahdjoudj <[email protected]>
Co-authored-by: Patrick F. Marques <[email protected]>
  • Loading branch information
3 people authored Jun 25, 2020
1 parent f1ea705 commit 0f85b28
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 1 deletion.
9 changes: 9 additions & 0 deletions backend/remote-state/azure/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ func New() backend.Backend {
DefaultFunc: schema.EnvDefaultFunc("ARM_SAS_TOKEN", ""),
},

"snapshot": {
Type: schema.TypeBool,
Optional: true,
Description: "Enable/Disable automatic blob snapshotting",
DefaultFunc: schema.EnvDefaultFunc("ARM_SNAPSHOT", false),
},

"resource_group_name": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -150,6 +157,7 @@ type Backend struct {
containerName string
keyName string
accountName string
snapshot bool
}

type BackendConfig struct {
Expand Down Expand Up @@ -180,6 +188,7 @@ func (b *Backend) configure(ctx context.Context) error {
b.containerName = data.Get("container_name").(string)
b.accountName = data.Get("storage_account_name").(string)
b.keyName = data.Get("key").(string)
b.snapshot = data.Get("snapshot").(bool)

// support for previously deprecated fields
clientId := valueFromDeprecatedField(data, "client_id", "arm_client_id")
Expand Down
1 change: 1 addition & 0 deletions backend/remote-state/azure/backend_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func (b *Backend) StateMgr(name string) (state.State, error) {
containerName: b.containerName,
keyName: b.path(name),
accountName: b.accountName,
snapshot: b.snapshot,
}

stateMgr := &remote.State{Client: client}
Expand Down
4 changes: 4 additions & 0 deletions backend/remote-state/azure/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestBackendConfig(t *testing.T) {
"storage_account_name": "tfaccount",
"container_name": "tfcontainer",
"key": "state",
"snapshot": false,
// Access Key must be Base64
"access_key": "QUNDRVNTX0tFWQ0K",
}
Expand All @@ -33,6 +34,9 @@ func TestBackendConfig(t *testing.T) {
if b.keyName != "state" {
t.Fatalf("Incorrect keyName was populated")
}
if b.snapshot != false {
t.Fatalf("Incorrect snapshot was populated")
}
}

func TestBackendAccessKeyBasic(t *testing.T) {
Expand Down
18 changes: 17 additions & 1 deletion backend/remote-state/azure/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import (
"encoding/base64"
"encoding/json"
"fmt"
"log"

"github.com/hashicorp/go-multierror"
"github.com/hashicorp/go-uuid"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"

"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/state/remote"
"github.com/tombuildsstuff/giovanni/storage/2018-11-09/blob/blobs"
)

const (
Expand All @@ -24,6 +27,7 @@ type RemoteClient struct {
containerName string
keyName string
leaseID string
snapshot bool
}

func (c *RemoteClient) Get() (*remote.Payload, error) {
Expand Down Expand Up @@ -67,6 +71,18 @@ func (c *RemoteClient) Put(data []byte) error {
}

ctx := context.TODO()

if c.snapshot {
snapshotInput := blobs.SnapshotInput{LeaseID: options.LeaseID}

log.Printf("[DEBUG] Snapshotting existing Blob %q (Container %q / Account %q)", c.keyName, c.containerName, c.accountName)
if _, err := c.giovanniBlobClient.Snapshot(ctx, c.accountName, 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)
}

log.Print("[DEBUG] Created blob snapshot")
}

blob, err := c.giovanniBlobClient.GetProperties(ctx, c.accountName, c.containerName, c.keyName, getOptions)
if err != nil {
if blob.StatusCode != 404 {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/backends/types/azurerm.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ The following configuration options are supported:

* `environment` - (Optional) The Azure Environment which should be used. This can also be sourced from the `ARM_ENVIRONMENT` environment variable. Possible values are `public`, `china`, `german`, `stack` and `usgovernment`. Defaults to `public`.

* `snapshot` - (Optional) Should the Blob used to store the Terraform Statefile be snapshotted before use? Defaults to `false`. This value can also be sourced from the `ARM_SNAPSHOT` environment variable.

* `endpoint` - (Optional) The Custom Endpoint for Azure Resource Manager. This can also be sourced from the `ARM_ENDPOINT` environment variable.

~> **NOTE:** An `endpoint` should only be configured when using Azure Stack.
Expand Down

0 comments on commit 0f85b28

Please sign in to comment.