github.com/bendemaree/terraform@v0.5.4-0.20150613200311-f50d97d6eee6/state/remote/s3.go (about) 1 package remote 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/aws/credentials" 12 "github.com/aws/aws-sdk-go/service/s3" 13 ) 14 15 func s3Factory(conf map[string]string) (Client, error) { 16 bucketName, ok := conf["bucket"] 17 if !ok { 18 return nil, fmt.Errorf("missing 'bucket' configuration") 19 } 20 21 keyName, ok := conf["key"] 22 if !ok { 23 return nil, fmt.Errorf("missing 'key' configuration") 24 } 25 26 regionName, ok := conf["region"] 27 if !ok { 28 regionName = os.Getenv("AWS_DEFAULT_REGION") 29 if regionName == "" { 30 return nil, fmt.Errorf( 31 "missing 'region' configuration or AWS_DEFAULT_REGION environment variable") 32 } 33 } 34 35 accessKeyId := conf["access_key"] 36 secretAccessKey := conf["secret_key"] 37 38 credentialsProvider := credentials.NewChainCredentials([]credentials.Provider{ 39 &credentials.StaticProvider{Value: credentials.Value{ 40 AccessKeyID: accessKeyId, 41 SecretAccessKey: secretAccessKey, 42 SessionToken: "", 43 }}, 44 &credentials.EnvProvider{}, 45 &credentials.SharedCredentialsProvider{Filename: "", Profile: ""}, 46 &credentials.EC2RoleProvider{}, 47 }) 48 49 // Make sure we got some sort of working credentials. 50 _, err := credentialsProvider.Get() 51 if err != nil { 52 return nil, fmt.Errorf("Unable to determine AWS credentials. Set the AWS_ACCESS_KEY_ID and "+ 53 "AWS_SECRET_ACCESS_KEY environment variables.\n(error was: %s)", err) 54 } 55 56 awsConfig := &aws.Config{ 57 Credentials: credentialsProvider, 58 Region: regionName, 59 } 60 nativeClient := s3.New(awsConfig) 61 62 return &S3Client{ 63 nativeClient: nativeClient, 64 bucketName: bucketName, 65 keyName: keyName, 66 }, nil 67 } 68 69 type S3Client struct { 70 nativeClient *s3.S3 71 bucketName string 72 keyName string 73 } 74 75 func (c *S3Client) Get() (*Payload, error) { 76 output, err := c.nativeClient.GetObject(&s3.GetObjectInput{ 77 Bucket: &c.bucketName, 78 Key: &c.keyName, 79 }) 80 81 if err != nil { 82 if awserr := err.(awserr.Error); awserr != nil { 83 if awserr.Code() == "NoSuchKey" { 84 return nil, nil 85 } else { 86 return nil, err 87 } 88 } else { 89 return nil, err 90 } 91 } 92 93 defer output.Body.Close() 94 95 buf := bytes.NewBuffer(nil) 96 if _, err := io.Copy(buf, output.Body); err != nil { 97 return nil, fmt.Errorf("Failed to read remote state: %s", err) 98 } 99 100 payload := &Payload{ 101 Data: buf.Bytes(), 102 } 103 104 // If there was no data, then return nil 105 if len(payload.Data) == 0 { 106 return nil, nil 107 } 108 109 return payload, nil 110 } 111 112 func (c *S3Client) Put(data []byte) error { 113 contentType := "application/octet-stream" 114 contentLength := int64(len(data)) 115 116 _, err := c.nativeClient.PutObject(&s3.PutObjectInput{ 117 ContentType: &contentType, 118 ContentLength: &contentLength, 119 Body: bytes.NewReader(data), 120 Bucket: &c.bucketName, 121 Key: &c.keyName, 122 }) 123 124 if err == nil { 125 return nil 126 } else { 127 return fmt.Errorf("Failed to upload state: %v", err) 128 } 129 } 130 131 func (c *S3Client) Delete() error { 132 _, err := c.nativeClient.DeleteObject(&s3.DeleteObjectInput{ 133 Bucket: &c.bucketName, 134 Key: &c.keyName, 135 }) 136 137 return err 138 }