github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/state/remote/swift.go (about)

     1  package remote
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/md5"
     6  	"fmt"
     7  	"os"
     8  	"strings"
     9  
    10  	"github.com/rackspace/gophercloud"
    11  	"github.com/rackspace/gophercloud/openstack"
    12  	"github.com/rackspace/gophercloud/openstack/objectstorage/v1/containers"
    13  	"github.com/rackspace/gophercloud/openstack/objectstorage/v1/objects"
    14  )
    15  
    16  const TFSTATE_NAME = "tfstate.tf"
    17  
    18  // SwiftClient implements the Client interface for an Openstack Swift server.
    19  type SwiftClient struct {
    20  	client *gophercloud.ServiceClient
    21  	path   string
    22  }
    23  
    24  func swiftFactory(conf map[string]string) (Client, error) {
    25  	client := &SwiftClient{}
    26  
    27  	if err := client.validateConfig(conf); err != nil {
    28  		return nil, err
    29  	}
    30  
    31  	return client, nil
    32  }
    33  
    34  func (c *SwiftClient) validateConfig(conf map[string]string) (err error) {
    35  	if val := os.Getenv("OS_AUTH_URL"); val == "" {
    36  		return fmt.Errorf("missing OS_AUTH_URL environment variable")
    37  	}
    38  	if val := os.Getenv("OS_USERNAME"); val == "" {
    39  		return fmt.Errorf("missing OS_USERNAME environment variable")
    40  	}
    41  	if val := os.Getenv("OS_TENANT_NAME"); val == "" {
    42  		return fmt.Errorf("missing OS_TENANT_NAME environment variable")
    43  	}
    44  	if val := os.Getenv("OS_PASSWORD"); val == "" {
    45  		return fmt.Errorf("missing OS_PASSWORD environment variable")
    46  	}
    47  	path, ok := conf["path"]
    48  	if !ok || path == "" {
    49  		return fmt.Errorf("missing 'path' configuration")
    50  	}
    51  
    52  	provider, err := openstack.AuthenticatedClient(gophercloud.AuthOptions{
    53  		IdentityEndpoint: os.Getenv("OS_AUTH_URL"),
    54  		Username:         os.Getenv("OS_USERNAME"),
    55  		TenantName:       os.Getenv("OS_TENANT_NAME"),
    56  		Password:         os.Getenv("OS_PASSWORD"),
    57  	})
    58  
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	c.path = path
    64  	c.client, err = openstack.NewObjectStorageV1(provider, gophercloud.EndpointOpts{
    65  		Region: os.Getenv("OS_REGION_NAME"),
    66  	})
    67  
    68  	return err
    69  }
    70  
    71  func (c *SwiftClient) Get() (*Payload, error) {
    72  	result := objects.Download(c.client, c.path, TFSTATE_NAME, nil)
    73  	bytes, err := result.ExtractContent()
    74  
    75  	if err != nil {
    76  		if strings.Contains(err.Error(), "but got 404 instead") {
    77  			return nil, nil
    78  		}
    79  		return nil, err
    80  	}
    81  
    82  	hash := md5.Sum(bytes)
    83  	payload := &Payload{
    84  		Data: bytes,
    85  		MD5:  hash[:md5.Size],
    86  	}
    87  
    88  	return payload, nil
    89  }
    90  
    91  func (c *SwiftClient) Put(data []byte) error {
    92  	if err := c.ensureContainerExists(); err != nil {
    93  		return err
    94  	}
    95  
    96  	reader := bytes.NewReader(data)
    97  	result := objects.Create(c.client, c.path, TFSTATE_NAME, reader, nil)
    98  
    99  	return result.Err
   100  }
   101  
   102  func (c *SwiftClient) Delete() error {
   103  	result := objects.Delete(c.client, c.path, TFSTATE_NAME, nil)
   104  	return result.Err
   105  }
   106  
   107  func (c *SwiftClient) ensureContainerExists() error {
   108  	result := containers.Create(c.client, c.path, nil)
   109  	if result.Err != nil {
   110  		return result.Err
   111  	}
   112  
   113  	return nil
   114  }