77e69b9cf3
Signed-off-by: Olivier Gambier <olivier@docker.com>
203 lines
5.4 KiB
Go
203 lines
5.4 KiB
Go
package s3
|
|
|
|
import (
|
|
"crypto/md5"
|
|
"encoding/base64"
|
|
"encoding/xml"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// Implements an interface for s3 bucket lifecycle configuration
|
|
// See goo.gl/d0bbDf for details.
|
|
|
|
const (
|
|
LifecycleRuleStatusEnabled = "Enabled"
|
|
LifecycleRuleStatusDisabled = "Disabled"
|
|
LifecycleRuleDateFormat = "2006-01-02"
|
|
StorageClassGlacier = "GLACIER"
|
|
)
|
|
|
|
type Expiration struct {
|
|
Days *uint `xml:"Days,omitempty"`
|
|
Date string `xml:"Date,omitempty"`
|
|
}
|
|
|
|
// Returns Date as a time.Time.
|
|
func (r *Expiration) ParseDate() (time.Time, error) {
|
|
return time.Parse(LifecycleRuleDateFormat, r.Date)
|
|
}
|
|
|
|
type Transition struct {
|
|
Days *uint `xml:"Days,omitempty"`
|
|
Date string `xml:"Date,omitempty"`
|
|
StorageClass string `xml:"StorageClass"`
|
|
}
|
|
|
|
// Returns Date as a time.Time.
|
|
func (r *Transition) ParseDate() (time.Time, error) {
|
|
return time.Parse(LifecycleRuleDateFormat, r.Date)
|
|
}
|
|
|
|
type NoncurrentVersionExpiration struct {
|
|
Days *uint `xml:"NoncurrentDays,omitempty"`
|
|
}
|
|
|
|
type NoncurrentVersionTransition struct {
|
|
Days *uint `xml:"NoncurrentDays,omitempty"`
|
|
StorageClass string `xml:"StorageClass"`
|
|
}
|
|
|
|
type LifecycleRule struct {
|
|
ID string `xml:"ID"`
|
|
Prefix string `xml:"Prefix"`
|
|
Status string `xml:"Status"`
|
|
NoncurrentVersionTransition *NoncurrentVersionTransition `xml:"NoncurrentVersionTransition,omitempty"`
|
|
NoncurrentVersionExpiration *NoncurrentVersionExpiration `xml:"NoncurrentVersionExpiration,omitempty"`
|
|
Transition *Transition `xml:"Transition,omitempty"`
|
|
Expiration *Expiration `xml:"Expiration,omitempty"`
|
|
}
|
|
|
|
// Create a lifecycle rule with arbitrary identifier id and object name prefix
|
|
// for which the rules should apply.
|
|
func NewLifecycleRule(id, prefix string) *LifecycleRule {
|
|
rule := &LifecycleRule{
|
|
ID: id,
|
|
Prefix: prefix,
|
|
Status: LifecycleRuleStatusEnabled,
|
|
}
|
|
return rule
|
|
}
|
|
|
|
// Adds a transition rule in days. Overwrites any previous transition rule.
|
|
func (r *LifecycleRule) SetTransitionDays(days uint) {
|
|
r.Transition = &Transition{
|
|
Days: &days,
|
|
StorageClass: StorageClassGlacier,
|
|
}
|
|
}
|
|
|
|
// Adds a transition rule as a date. Overwrites any previous transition rule.
|
|
func (r *LifecycleRule) SetTransitionDate(date time.Time) {
|
|
r.Transition = &Transition{
|
|
Date: date.Format(LifecycleRuleDateFormat),
|
|
StorageClass: StorageClassGlacier,
|
|
}
|
|
}
|
|
|
|
// Adds an expiration rule in days. Overwrites any previous expiration rule.
|
|
// Days must be > 0.
|
|
func (r *LifecycleRule) SetExpirationDays(days uint) {
|
|
r.Expiration = &Expiration{
|
|
Days: &days,
|
|
}
|
|
}
|
|
|
|
// Adds an expiration rule as a date. Overwrites any previous expiration rule.
|
|
func (r *LifecycleRule) SetExpirationDate(date time.Time) {
|
|
r.Expiration = &Expiration{
|
|
Date: date.Format(LifecycleRuleDateFormat),
|
|
}
|
|
}
|
|
|
|
// Adds a noncurrent version transition rule. Overwrites any previous
|
|
// noncurrent version transition rule.
|
|
func (r *LifecycleRule) SetNoncurrentVersionTransitionDays(days uint) {
|
|
r.NoncurrentVersionTransition = &NoncurrentVersionTransition{
|
|
Days: &days,
|
|
StorageClass: StorageClassGlacier,
|
|
}
|
|
}
|
|
|
|
// Adds a noncurrent version expiration rule. Days must be > 0. Overwrites
|
|
// any previous noncurrent version expiration rule.
|
|
func (r *LifecycleRule) SetNoncurrentVersionExpirationDays(days uint) {
|
|
r.NoncurrentVersionExpiration = &NoncurrentVersionExpiration{
|
|
Days: &days,
|
|
}
|
|
}
|
|
|
|
// Marks the rule as disabled.
|
|
func (r *LifecycleRule) Disable() {
|
|
r.Status = LifecycleRuleStatusDisabled
|
|
}
|
|
|
|
// Marks the rule as enabled (default).
|
|
func (r *LifecycleRule) Enable() {
|
|
r.Status = LifecycleRuleStatusEnabled
|
|
}
|
|
|
|
type LifecycleConfiguration struct {
|
|
XMLName xml.Name `xml:"LifecycleConfiguration"`
|
|
Rules *[]*LifecycleRule `xml:"Rule,omitempty"`
|
|
}
|
|
|
|
// Adds a LifecycleRule to the configuration.
|
|
func (c *LifecycleConfiguration) AddRule(r *LifecycleRule) {
|
|
var rules []*LifecycleRule
|
|
if c.Rules != nil {
|
|
rules = *c.Rules
|
|
}
|
|
rules = append(rules, r)
|
|
c.Rules = &rules
|
|
}
|
|
|
|
// Sets the bucket's lifecycle configuration.
|
|
func (b *Bucket) PutLifecycleConfiguration(c *LifecycleConfiguration) error {
|
|
doc, err := xml.Marshal(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
buf := makeXmlBuffer(doc)
|
|
digest := md5.New()
|
|
size, err := digest.Write(buf.Bytes())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
headers := map[string][]string{
|
|
"Content-Length": {strconv.FormatInt(int64(size), 10)},
|
|
"Content-MD5": {base64.StdEncoding.EncodeToString(digest.Sum(nil))},
|
|
}
|
|
|
|
req := &request{
|
|
path: "/",
|
|
method: "PUT",
|
|
bucket: b.Name,
|
|
headers: headers,
|
|
payload: buf,
|
|
params: url.Values{"lifecycle": {""}},
|
|
}
|
|
|
|
return b.S3.queryV4Sign(req, nil)
|
|
}
|
|
|
|
// Retrieves the lifecycle configuration for the bucket. AWS returns an error
|
|
// if no lifecycle found.
|
|
func (b *Bucket) GetLifecycleConfiguration() (*LifecycleConfiguration, error) {
|
|
req := &request{
|
|
method: "GET",
|
|
bucket: b.Name,
|
|
path: "/",
|
|
params: url.Values{"lifecycle": {""}},
|
|
}
|
|
|
|
conf := &LifecycleConfiguration{}
|
|
err := b.S3.queryV4Sign(req, conf)
|
|
return conf, err
|
|
}
|
|
|
|
// Delete the bucket's lifecycle configuration.
|
|
func (b *Bucket) DeleteLifecycleConfiguration() error {
|
|
req := &request{
|
|
method: "DELETE",
|
|
bucket: b.Name,
|
|
path: "/",
|
|
params: url.Values{"lifecycle": {""}},
|
|
}
|
|
|
|
return b.S3.queryV4Sign(req, nil)
|
|
}
|