Introduce plusWorkaround: generate copy of file with '+' -> ' ' to workaround S3/apt bug. #98

This commit is contained in:
Andrey Smirnov
2014-10-01 21:32:56 +04:00
parent 8049d69793
commit aeae6009c4
7 changed files with 56 additions and 14 deletions
+2 -1
View File
@@ -217,7 +217,8 @@ func (context *AptlyContext) GetPublishedStorage(name string) aptly.PublishedSto
var err error var err error
publishedStorage, err = s3.NewPublishedStorage(params.AccessKeyID, params.SecretAccessKey, publishedStorage, err = s3.NewPublishedStorage(params.AccessKeyID, params.SecretAccessKey,
params.Region, params.Bucket, params.ACL, params.Prefix, params.StorageClass, params.EncryptionMethod) params.Region, params.Bucket, params.ACL, params.Prefix, params.StorageClass,
params.EncryptionMethod, params.PlusWorkaround)
if err != nil { if err != nil {
Fatal(err) Fatal(err)
} }
+7 -2
View File
@@ -57,7 +57,8 @@ Configuration file is stored in JSON format (default values shown below):
"prefix": "", "prefix": "",
"acl": "public\-read", "acl": "public\-read",
"storageClass": "", "storageClass": "",
"encryptionMethod": "" "encryptionMethod": "",
"plusWorkaround": false
} }
} }
. .
@@ -117,7 +118,7 @@ if enabled, all mirrors created would have flag set to download source packages;
specifies paramaters for short PPA url expansion, if left blank they default to output of \fBlsb_release\fR command specifies paramaters for short PPA url expansion, if left blank they default to output of \fBlsb_release\fR command
. .
.TP .TP
\fBS3PublisEndpoints\fR \fBS3PublishEndpoints\fR
configuration of Amazon S3 publishing endpoints (see below) configuration of Amazon S3 publishing endpoints (see below)
. .
.SH "S3 PUBLISHING ENDPOINTS" .SH "S3 PUBLISHING ENDPOINTS"
@@ -151,6 +152,10 @@ bucket name
\fBencryptionMethod\fR \fBencryptionMethod\fR
(optional) server\-side encryption method, defaults to none\. Currently the only available encryption method is \fBAES256\fR (optional) server\-side encryption method, defaults to none\. Currently the only available encryption method is \fBAES256\fR
. .
.TP
\fBplusWorkaround\fR
(optional) workaround misbehavior in apt and Amazon S3 for files with \fB+\fR in filename by creating two copies of package files with \fB+\fR in filename: one original and another one with spaces instead of plus signs With \fBplusWorkaround\fR enabled, package files with plus sign would be stored twice\. aptly might not cleanup files with spaces when published repository is dropped or updated (switched) to new version of repository (snapshot)\.
.
.P .P
In order to publish to S3, specify endpoint as \fBs3:endpoint\-name:\fR before publishing prefix on the command line, e\.g\.: In order to publish to S3, specify endpoint as \fBs3:endpoint\-name:\fR before publishing prefix on the command line, e\.g\.:
. .
+11 -3
View File
@@ -49,7 +49,8 @@ Configuration file is stored in JSON format (default values shown below):
"prefix": "", "prefix": "",
"acl": "public-read", "acl": "public-read",
"storageClass": "", "storageClass": "",
"encryptionMethod": "" "encryptionMethod": "",
"plusWorkaround": false
} }
} }
@@ -97,7 +98,7 @@ Options:
specifies paramaters for short PPA url expansion, if left blank they default specifies paramaters for short PPA url expansion, if left blank they default
to output of `lsb_release` command to output of `lsb_release` command
* `S3PublisEndpoints`: * `S3PublishEndpoints`:
configuration of Amazon S3 publishing endpoints (see below) configuration of Amazon S3 publishing endpoints (see below)
## S3 PUBLISHING ENDPOINTS ## S3 PUBLISHING ENDPOINTS
@@ -129,7 +130,14 @@ and associated settings:
* `encryptionMethod`: * `encryptionMethod`:
(optional) server-side encryption method, defaults to none. Currently (optional) server-side encryption method, defaults to none. Currently
the only available encryption method is `AES256` the only available encryption method is `AES256`
* `plusWorkaround`:
(optional) workaround misbehavior in apt and Amazon S3
for files with `+` in filename by
creating two copies of package files with `+` in filename: one original
and another one with spaces instead of plus signs
With `plusWorkaround` enabled, package files with plus sign
would be stored twice. aptly might not cleanup files with spaces when published
repository is dropped or updated (switched) to new version of repository (snapshot).
In order to publish to S3, specify endpoint as `s3:endpoint-name:` before In order to publish to S3, specify endpoint as `s3:endpoint-name:` before
publishing prefix on the command line, e.g.: publishing prefix on the command line, e.g.:
+10 -4
View File
@@ -19,6 +19,7 @@ type PublishedStorage struct {
prefix string prefix string
storageClass string storageClass string
encryptionMethod string encryptionMethod string
plusWorkaround bool
} }
// Check interface // Check interface
@@ -28,7 +29,7 @@ var (
// NewPublishedStorageRaw creates published storage from raw aws credentials // NewPublishedStorageRaw creates published storage from raw aws credentials
func NewPublishedStorageRaw(auth aws.Auth, region aws.Region, bucket, defaultACL, prefix, func NewPublishedStorageRaw(auth aws.Auth, region aws.Region, bucket, defaultACL, prefix,
storageClass, encryptionMethod string) (*PublishedStorage, error) { storageClass, encryptionMethod string, plusWorkaround bool) (*PublishedStorage, error) {
if defaultACL == "" { if defaultACL == "" {
defaultACL = "private" defaultACL = "private"
} }
@@ -42,7 +43,8 @@ func NewPublishedStorageRaw(auth aws.Auth, region aws.Region, bucket, defaultACL
acl: s3.ACL(defaultACL), acl: s3.ACL(defaultACL),
prefix: prefix, prefix: prefix,
storageClass: storageClass, storageClass: storageClass,
encryptionMethod: encryptionMethod} encryptionMethod: encryptionMethod,
plusWorkaround: plusWorkaround}
result.bucket = result.s3.Bucket(bucket) result.bucket = result.s3.Bucket(bucket)
return result, nil return result, nil
@@ -51,7 +53,7 @@ func NewPublishedStorageRaw(auth aws.Auth, region aws.Region, bucket, defaultACL
// NewPublishedStorage creates new instance of PublishedStorage with specified S3 access // NewPublishedStorage creates new instance of PublishedStorage with specified S3 access
// keys, region and bucket name // keys, region and bucket name
func NewPublishedStorage(accessKey, secretKey, region, bucket, defaultACL, prefix, func NewPublishedStorage(accessKey, secretKey, region, bucket, defaultACL, prefix,
storageClass, encryptionMethod string) (*PublishedStorage, error) { storageClass, encryptionMethod string, plusWorkaround bool) (*PublishedStorage, error) {
auth, err := aws.GetAuth(accessKey, secretKey) auth, err := aws.GetAuth(accessKey, secretKey)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -62,7 +64,7 @@ func NewPublishedStorage(accessKey, secretKey, region, bucket, defaultACL, prefi
return nil, fmt.Errorf("unknown region: %#v", region) return nil, fmt.Errorf("unknown region: %#v", region)
} }
return NewPublishedStorageRaw(auth, awsRegion, bucket, defaultACL, prefix, storageClass, encryptionMethod) return NewPublishedStorageRaw(auth, awsRegion, bucket, defaultACL, prefix, storageClass, encryptionMethod, plusWorkaround)
} }
// String // String
@@ -108,6 +110,10 @@ func (storage *PublishedStorage) PutFile(path string, sourceFilename string) err
if err != nil { if err != nil {
return fmt.Errorf("error uploading %s to %s: %s", sourceFilename, storage, err) return fmt.Errorf("error uploading %s to %s: %s", sourceFilename, storage, err)
} }
if storage.plusWorkaround && strings.Index(path, "+") != -1 {
return storage.PutFile(strings.Replace(path, "+", " ", -1), sourceFilename)
}
return nil return nil
} }
+22 -3
View File
@@ -24,10 +24,10 @@ func (s *PublishedStorageSuite) SetUpTest(c *C) {
c.Assert(s.srv, NotNil) c.Assert(s.srv, NotNil)
auth, _ := aws.GetAuth("aa", "bb") 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", "", "", "", "", false)
c.Assert(err, IsNil) 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", "", "", false)
c.Assert(err, IsNil) c.Assert(err, IsNil)
err = s.storage.s3.Bucket("test").PutBucket("private") err = s.storage.s3.Bucket("test").PutBucket("private")
@@ -39,7 +39,7 @@ func (s *PublishedStorageSuite) TearDownTest(c *C) {
} }
func (s *PublishedStorageSuite) TestNewPublishedStorage(c *C) { func (s *PublishedStorageSuite) TestNewPublishedStorage(c *C) {
stor, err := NewPublishedStorage("aa", "bbb", "", "", "", "", "", "") stor, err := NewPublishedStorage("aa", "bbb", "", "", "", "", "", "", false)
c.Check(stor, IsNil) c.Check(stor, IsNil)
c.Check(err, ErrorMatches, "unknown region: .*") c.Check(err, ErrorMatches, "unknown region: .*")
} }
@@ -64,6 +64,25 @@ func (s *PublishedStorageSuite) TestPutFile(c *C) {
c.Check(data, DeepEquals, []byte("welcome to s3!")) c.Check(data, DeepEquals, []byte("welcome to s3!"))
} }
func (s *PublishedStorageSuite) TestPutFilePlusWorkaround(c *C) {
s.storage.plusWorkaround = true
dir := c.MkDir()
err := ioutil.WriteFile(filepath.Join(dir, "a"), []byte("welcome to s3!"), 0644)
c.Assert(err, IsNil)
err = s.storage.PutFile("a/b+c.txt", filepath.Join(dir, "a"))
c.Check(err, IsNil)
data, err := s.storage.bucket.Get("a/b+c.txt")
c.Check(err, IsNil)
c.Check(data, DeepEquals, []byte("welcome to s3!"))
data, err = s.storage.bucket.Get("a/b c.txt")
c.Check(err, IsNil)
c.Check(data, DeepEquals, []byte("welcome to s3!"))
}
func (s *PublishedStorageSuite) TestFilelist(c *C) { func (s *PublishedStorageSuite) TestFilelist(c *C) {
paths := []string{"a", "b", "c", "testa", "test/a", "test/b", "lala/a", "lala/b", "lala/c"} paths := []string{"a", "b", "c", "testa", "test/a", "test/b", "lala/a", "lala/b", "lala/c"}
for _, path := range paths { for _, path := range paths {
+1
View File
@@ -34,6 +34,7 @@ type S3PublishRoot struct {
ACL string `json:"acl"` ACL string `json:"acl"`
StorageClass string `json:"storageClass"` StorageClass string `json:"storageClass"`
EncryptionMethod string `json:"encryptionMethod"` EncryptionMethod string `json:"encryptionMethod"`
PlusWorkaround bool `json:"plusWorkaround"`
} }
// Config is configuration for aptly, shared by all modules // Config is configuration for aptly, shared by all modules
+3 -1
View File
@@ -67,7 +67,9 @@ func (s *ConfigSuite) TestSaveConfig(c *C) {
" \"prefix\": \"\",\n"+ " \"prefix\": \"\",\n"+
" \"acl\": \"\",\n"+ " \"acl\": \"\",\n"+
" \"storageClass\": \"\",\n"+ " \"storageClass\": \"\",\n"+
" \"encryptionMethod\": \"\"\n"+" }\n"+ " \"encryptionMethod\": \"\",\n"+
" \"plusWorkaround\": false\n"+
" }\n"+
" }\n"+ " }\n"+
"}") "}")
} }