state/remote/swift: Add support for versioning state file in swift, and expiring object after period of time.

Update website docs with changes
This commit is contained in:
Gavin Williams 2016-11-11 15:13:10 +00:00
parent 73e191442d
commit c77ed69a4e
2 changed files with 79 additions and 17 deletions

View File

@ -11,6 +11,8 @@ import (
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
@ -22,21 +24,24 @@ const TFSTATE_NAME = "tfstate.tf"
// SwiftClient implements the Client interface for an Openstack Swift server.
type SwiftClient struct {
client *gophercloud.ServiceClient
authurl string
cacert string
cert string
domainid string
domainname string
insecure bool
key string
password string
path string
region string
tenantid string
tenantname string
userid string
username string
client *gophercloud.ServiceClient
authurl string
cacert string
cert string
domainid string
domainname string
insecure bool
key string
password string
path string
region string
tenantid string
tenantname string
userid string
username string
archive bool
archivepath string
expireSecs int
}
func swiftFactory(conf map[string]string) (Client, error) {
@ -131,6 +136,35 @@ func (c *SwiftClient) validateConfig(conf map[string]string) (err error) {
}
c.path = path
if archivepath, ok := conf["archive_path"]; ok {
log.Printf("[DEBUG] Archivepath set, enabling object versioning")
c.archive = true
c.archivepath = archivepath
}
if expire, ok := conf["expire_after"]; ok {
log.Printf("[DEBUG] Requested that remote state expires after %s", expire)
if strings.HasSuffix(expire, "d") {
log.Printf("[DEBUG] Got a days expire after duration. Converting to hours")
days, err := strconv.Atoi(expire[:len(expire)-1])
if err != nil {
return fmt.Errorf("Error converting expire_after value %s to int: %s", expire, err)
}
expire = fmt.Sprintf("%dh", days*24)
log.Printf("[DEBUG] Expire after %s hours", expire)
}
expireDur, err := time.ParseDuration(expire)
if err != nil {
log.Printf("[DEBUG] Error parsing duration %s: %s", expire, err)
return fmt.Errorf("Error parsing expire_after duration '%s': %s", expire, err)
}
log.Printf("[DEBUG] Seconds duration = %d", int(expireDur.Seconds()))
c.expireSecs = int(expireDur.Seconds())
}
c.insecure = false
raw, ok := conf["insecure"]
if !ok {
@ -252,10 +286,17 @@ func (c *SwiftClient) Put(data []byte) error {
return err
}
log.Printf("[DEBUG] Creating object %s at path %s", TFSTATE_NAME, c.path)
reader := bytes.NewReader(data)
createOpts := objects.CreateOpts{
Content: reader,
}
if c.expireSecs != 0 {
log.Printf("[DEBUG] ExpireSecs = %d", c.expireSecs)
createOpts.DeleteAfter = c.expireSecs
}
result := objects.Create(c.client, c.path, TFSTATE_NAME, createOpts)
return result.Err
@ -267,7 +308,22 @@ func (c *SwiftClient) Delete() error {
}
func (c *SwiftClient) ensureContainerExists() error {
result := containers.Create(c.client, c.path, nil)
containerOpts := &containers.CreateOpts{}
if c.archive {
log.Printf("[DEBUG] Creating container %s", c.archivepath)
result := containers.Create(c.client, c.archivepath, nil)
if result.Err != nil {
log.Printf("[DEBUG] Error creating container %s: %s", c.archivepath, result.Err)
return result.Err
}
log.Printf("[DEBUG] Enabling Versioning on container %s", c.path)
containerOpts.VersionsLocation = c.archivepath
}
log.Printf("[DEBUG] Creating container %s", c.path)
result := containers.Create(c.client, c.path, containerOpts)
if result.Err != nil {
return result.Err
}

View File

@ -80,4 +80,10 @@ The following configuration options are supported:
authentication. If omitted the `OS_CERT` environment variable is used.
* `key` - (Optional) Specify client private key file for SSL client
authentication. If omitted the `OS_KEY` environment variable is used.
authentication. If omitted the `OS_KEY` environment variable is used.
* `archive_path` - (Optional) The path to store archived copied of `terraform.tfstate`.
If specified, Swift object versioning is enabled on the container created at `path`.
* `expire_after` - (Optional) How long should the `terraform.tfstate` created at `path`
be retained for? Supported durations: `m` - Minutes, `h` - Hours, `d` - Days.