github.com/i0n/terraform@v0.4.3-0.20150506151324-010a39a58ec1/state/remote/s3.go (about)

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