github.com/aznashwan/terraform@v0.4.3-0.20151118032030-21f93ca4558d/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 }