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:
parent
73e191442d
commit
c77ed69a4e
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue