Skip to content

Commit

Permalink
Support for custom storage class and encryption method. #105
Browse files Browse the repository at this point in the history
  • Loading branch information
smira committed Oct 1, 2014
1 parent a02a90a commit 8aa1954
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 24 deletions.
2 changes: 1 addition & 1 deletion cmd/context.go
Expand Up @@ -217,7 +217,7 @@ func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedSto

var err error
publishedStorage, err = s3.NewPublishedStorage(params.AccessKeyID, params.SecretAccessKey,
params.Region, params.Bucket, params.ACL, params.Prefix)
params.Region, params.Bucket, params.ACL, params.Prefix, params.StorageClass, params.EncryptionMethod)
if err != nil {
Fatal(err)
}
Expand Down
14 changes: 12 additions & 2 deletions man/aptly.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "APTLY" "1" "September 2014" "" ""
.TH "APTLY" "1" "October 2014" "" ""
.
.SH "NAME"
\fBaptly\fR \- Debian repository management tool
Expand Down Expand Up @@ -55,7 +55,9 @@ Configuration file is stored in JSON format (default values shown below):
"awsAccessKeyID": ""
"awsSecretAccessKey": "",
"prefix": "",
"acl": "public\-read"
"acl": "public\-read",
"storageClass": "",
"encryptionMethod": ""
}
}
.
Expand Down Expand Up @@ -141,6 +143,14 @@ bucket name
\fBawsAccessKeyID\fR, \fBawsSecretAccessKey\fR
(optional) Amazon credentials to access S3 bucket\. If not supplied, environment variables \fBAWS_ACCESS_KEY_ID\fR and \fBAWS_SECRET_ACCESS_KEY\fR are used\.
.
.TP
\fBstorageClass\fR
(optional) Amazon S3 storage class, defaults to \fBSTANDARD\fR\. Other values available: \fBREDUCED_REDUNDANCY\fR (lower price, lower redundancy)
.
.TP
\fBencryptionMethod\fR
(optional) server\-side encryption method, defaults to none\. Currently the only available encryption method is \fBAES256\fR
.
.P
In order to publish to S3, specify endpoint as \fBs3:endpoint\-name:\fR before publishing prefix on the command line, e\.g\.:
.
Expand Down
11 changes: 10 additions & 1 deletion man/aptly.1.ronn.tmpl
Expand Up @@ -47,7 +47,9 @@ Configuration file is stored in JSON format (default values shown below):
"awsAccessKeyID": ""
"awsSecretAccessKey": "",
"prefix": "",
"acl": "public-read"
"acl": "public-read",
"storageClass": "",
"encryptionMethod": ""
}
}

Expand Down Expand Up @@ -121,6 +123,13 @@ and associated settings:
(optional) Amazon credentials to access S3 bucket. If not supplied,
environment variables `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`
are used.
* `storageClass`:
(optional) Amazon S3 storage class, defaults to `STANDARD`. Other values
available: `REDUCED_REDUNDANCY` (lower price, lower redundancy)
* `encryptionMethod`:
(optional) server-side encryption method, defaults to none. Currently
the only available encryption method is `AES256`


In order to publish to S3, specify endpoint as `s3:endpoint-name:` before
publishing prefix on the command line, e.g.:
Expand Down
41 changes: 32 additions & 9 deletions s3/public.go
Expand Up @@ -13,10 +13,12 @@ import (

// PublishedStorage abstract file system with published files (actually hosted on S3)
type PublishedStorage struct {
s3 *s3.S3
bucket *s3.Bucket
acl s3.ACL
prefix string
s3 *s3.S3
bucket *s3.Bucket
acl s3.ACL
prefix string
storageClass string
encryptionMethod string
}

// Check interface
Expand All @@ -25,20 +27,31 @@ var (
)

// NewPublishedStorageRaw creates published storage from raw aws credentials
func NewPublishedStorageRaw(auth aws.Auth, region aws.Region, bucket, defaultACL, prefix string) (*PublishedStorage, error) {
func NewPublishedStorageRaw(auth aws.Auth, region aws.Region, bucket, defaultACL, prefix,
storageClass, encryptionMethod string) (*PublishedStorage, error) {
if defaultACL == "" {
defaultACL = "private"
}

result := &PublishedStorage{s3: s3.New(auth, region), acl: s3.ACL(defaultACL), prefix: prefix}
if storageClass == "STANDARD" {
storageClass = ""
}

result := &PublishedStorage{
s3: s3.New(auth, region),
acl: s3.ACL(defaultACL),
prefix: prefix,
storageClass: storageClass,
encryptionMethod: encryptionMethod}
result.bucket = result.s3.Bucket(bucket)

return result, nil
}

// NewPublishedStorage creates new instance of PublishedStorage with specified S3 access
// keys, region and bucket name
func NewPublishedStorage(accessKey, secretKey, region, bucket, defaultACL, prefix string) (*PublishedStorage, error) {
func NewPublishedStorage(accessKey, secretKey, region, bucket, defaultACL, prefix,
storageClass, encryptionMethod string) (*PublishedStorage, error) {
auth, err := aws.GetAuth(accessKey, secretKey)
if err != nil {
return nil, err
Expand All @@ -49,7 +62,7 @@ func NewPublishedStorage(accessKey, secretKey, region, bucket, defaultACL, prefi
return nil, fmt.Errorf("unknown region: %#v", region)
}

return NewPublishedStorageRaw(auth, awsRegion, bucket, defaultACL, prefix)
return NewPublishedStorageRaw(auth, awsRegion, bucket, defaultACL, prefix, storageClass, encryptionMethod)
}

// String
Expand Down Expand Up @@ -81,7 +94,17 @@ func (storage *PublishedStorage) PutFile(path string, sourceFilename string) err
return err
}

err = storage.bucket.PutReader(filepath.Join(storage.prefix, path), source, fi.Size(), "binary/octet-stream", storage.acl)
headers := map[string][]string{
"Content-Type": {"binary/octet-stream"},
}
if storage.storageClass != "" {
headers["x-amz-storage-class"] = []string{storage.storageClass}
}
if storage.encryptionMethod != "" {
headers["x-amz-server-side-encryption"] = []string{storage.encryptionMethod}
}

err = storage.bucket.PutReaderHeader(filepath.Join(storage.prefix, path), source, fi.Size(), headers, storage.acl)
if err != nil {
return fmt.Errorf("error uploading %s to %s: %s", sourceFilename, storage, err)
}
Expand Down
6 changes: 3 additions & 3 deletions s3/public_test.go
Expand Up @@ -24,10 +24,10 @@ func (s *PublishedStorageSuite) SetUpTest(c *C) {
c.Assert(s.srv, NotNil)

auth, _ := aws.GetAuth("aa", "bb")
s.storage, err = NewPublishedStorageRaw(auth, aws.Region{Name: "test-1", S3Endpoint: s.srv.URL(), S3LocationConstraint: true}, "test", "", "")
s.storage, err = NewPublishedStorageRaw(auth, aws.Region{Name: "test-1", S3Endpoint: s.srv.URL(), S3LocationConstraint: true}, "test", "", "", "", "")
c.Assert(err, IsNil)

s.prefixedStorage, err = NewPublishedStorageRaw(auth, aws.Region{Name: "test-1", S3Endpoint: s.srv.URL(), S3LocationConstraint: true}, "test", "", "lala")
s.prefixedStorage, err = NewPublishedStorageRaw(auth, aws.Region{Name: "test-1", S3Endpoint: s.srv.URL(), S3LocationConstraint: true}, "test", "", "lala", "", "")
c.Assert(err, IsNil)

err = s.storage.s3.Bucket("test").PutBucket("private")
Expand All @@ -39,7 +39,7 @@ func (s *PublishedStorageSuite) TearDownTest(c *C) {
}

func (s *PublishedStorageSuite) TestNewPublishedStorage(c *C) {
stor, err := NewPublishedStorage("aa", "bbb", "", "", "", "")
stor, err := NewPublishedStorage("aa", "bbb", "", "", "", "", "", "")
c.Check(stor, IsNil)
c.Check(err, ErrorMatches, "unknown region: .*")
}
Expand Down
14 changes: 8 additions & 6 deletions utils/config.go
Expand Up @@ -26,12 +26,14 @@ type ConfigStructure struct {

// S3PublishRoot describes single S3 publishing entry point
type S3PublishRoot struct {
Region string `json:"region"`
Bucket string `json:"bucket"`
AccessKeyID string `json:"awsAccessKeyID"`
SecretAccessKey string `json:"awsSecretAccessKey"`
Prefix string `json:"prefix"`
ACL string `json:"acl"`
Region string `json:"region"`
Bucket string `json:"bucket"`
AccessKeyID string `json:"awsAccessKeyID"`
SecretAccessKey string `json:"awsSecretAccessKey"`
Prefix string `json:"prefix"`
ACL string `json:"acl"`
StorageClass string `json:"storageClass"`
EncryptionMethod string `json:"encryptionMethod"`
}

// Config is configuration for aptly, shared by all modules
Expand Down
5 changes: 3 additions & 2 deletions utils/config_test.go
Expand Up @@ -65,8 +65,9 @@ func (s *ConfigSuite) TestSaveConfig(c *C) {
" \"awsAccessKeyID\": \"\",\n"+
" \"awsSecretAccessKey\": \"\",\n"+
" \"prefix\": \"\",\n"+
" \"acl\": \"\"\n"+
" }\n"+
" \"acl\": \"\",\n"+
" \"storageClass\": \"\",\n"+
" \"encryptionMethod\": \"\"\n"+" }\n"+
" }\n"+
"}")
}
Expand Down

0 comments on commit 8aa1954

Please sign in to comment.