Use ObjectInfo.ToLifecycleOpts instead of literal values (#12772)
Promote getLifecycleTransitionTier to a method on lifecycle.Lifecycle.
This commit is contained in:
parent
dbd7f74bb9
commit
209e6d00c6
|
@ -80,7 +80,7 @@ func (api objectAPIHandlers) PutBucketLifecycleHandler(w http.ResponseWriter, r
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the transition storage ARNs
|
// Validate the transition storage ARNs
|
||||||
if err = validateTransitionTier(ctx, bucketLifecycle); err != nil {
|
if err = validateTransitionTier(bucketLifecycle); err != nil {
|
||||||
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -180,8 +180,8 @@ func initBackgroundTransition(ctx context.Context, objectAPI ObjectLayer) {
|
||||||
|
|
||||||
var errInvalidStorageClass = errors.New("invalid storage class")
|
var errInvalidStorageClass = errors.New("invalid storage class")
|
||||||
|
|
||||||
func validateTransitionTier(ctx context.Context, lfc *lifecycle.Lifecycle) error {
|
func validateTransitionTier(lc *lifecycle.Lifecycle) error {
|
||||||
for _, rule := range lfc.Rules {
|
for _, rule := range lc.Rules {
|
||||||
if rule.Transition.StorageClass == "" {
|
if rule.Transition.StorageClass == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -288,15 +288,10 @@ func transitionObject(ctx context.Context, objectAPI ObjectLayer, oi ObjectInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
lcOpts := lifecycle.ObjectOpts{
|
|
||||||
Name: oi.Name,
|
|
||||||
UserTags: oi.UserTags,
|
|
||||||
}
|
|
||||||
tierName := getLifeCycleTransitionTier(ctx, lc, oi.Bucket, lcOpts)
|
|
||||||
opts := ObjectOptions{
|
opts := ObjectOptions{
|
||||||
Transition: TransitionOptions{
|
Transition: TransitionOptions{
|
||||||
Status: lifecycle.TransitionPending,
|
Status: lifecycle.TransitionPending,
|
||||||
Tier: tierName,
|
Tier: lc.TransitionTier(oi.ToLifecycleOpts()),
|
||||||
ETag: oi.ETag,
|
ETag: oi.ETag,
|
||||||
},
|
},
|
||||||
VersionID: oi.VersionID,
|
VersionID: oi.VersionID,
|
||||||
|
@ -306,19 +301,6 @@ func transitionObject(ctx context.Context, objectAPI ObjectLayer, oi ObjectInfo)
|
||||||
return objectAPI.TransitionObject(ctx, oi.Bucket, oi.Name, opts)
|
return objectAPI.TransitionObject(ctx, oi.Bucket, oi.Name, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLifeCycleTransitionTier returns storage class for transition target
|
|
||||||
func getLifeCycleTransitionTier(ctx context.Context, lc *lifecycle.Lifecycle, bucket string, obj lifecycle.ObjectOpts) string {
|
|
||||||
for _, rule := range lc.FilterActionableRules(obj) {
|
|
||||||
if obj.IsLatest && rule.Transition.StorageClass != "" {
|
|
||||||
return rule.Transition.StorageClass
|
|
||||||
}
|
|
||||||
if !obj.IsLatest && rule.NoncurrentVersionTransition.StorageClass != "" {
|
|
||||||
return rule.NoncurrentVersionTransition.StorageClass
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// getTransitionedObjectReader returns a reader from the transitioned tier.
|
// getTransitionedObjectReader returns a reader from the transitioned tier.
|
||||||
func getTransitionedObjectReader(ctx context.Context, bucket, object string, rs *HTTPRangeSpec, h http.Header, oi ObjectInfo, opts ObjectOptions) (gr *GetObjectReader, err error) {
|
func getTransitionedObjectReader(ctx context.Context, bucket, object string, rs *HTTPRangeSpec, h http.Header, oi ObjectInfo, opts ObjectOptions) (gr *GetObjectReader, err error) {
|
||||||
tgtClient, err := globalTierConfigMgr.getDriver(oi.TransitionTier)
|
tgtClient, err := globalTierConfigMgr.getDriver(oi.TransitionTier)
|
||||||
|
|
|
@ -19,7 +19,6 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -240,46 +239,9 @@ func TestValidateTransitionTier(t *testing.T) {
|
||||||
t.Fatalf("Test %d: Failed to parse lifecycle config %v", i+1, err)
|
t.Fatalf("Test %d: Failed to parse lifecycle config %v", i+1, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = validateTransitionTier(context.Background(), lc)
|
err = validateTransitionTier(lc)
|
||||||
if err != tc.expectedErr {
|
if err != tc.expectedErr {
|
||||||
t.Fatalf("Test %d: Expected %v but got %v", i+1, tc.expectedErr, err)
|
t.Fatalf("Test %d: Expected %v but got %v", i+1, tc.expectedErr, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetLifecycleTransitionTier(t *testing.T) {
|
|
||||||
lc := lifecycle.Lifecycle{
|
|
||||||
Rules: []lifecycle.Rule{
|
|
||||||
{
|
|
||||||
ID: "rule-1",
|
|
||||||
Status: "Enabled",
|
|
||||||
Transition: lifecycle.Transition{
|
|
||||||
Days: lifecycle.TransitionDays(3),
|
|
||||||
StorageClass: "TIER-1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: "rule-2",
|
|
||||||
Status: "Enabled",
|
|
||||||
NoncurrentVersionTransition: lifecycle.NoncurrentVersionTransition{
|
|
||||||
NoncurrentDays: lifecycle.ExpirationDays(3),
|
|
||||||
StorageClass: "TIER-2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
obj1 := lifecycle.ObjectOpts{
|
|
||||||
Name: "obj1",
|
|
||||||
IsLatest: true,
|
|
||||||
}
|
|
||||||
obj2 := lifecycle.ObjectOpts{
|
|
||||||
Name: "obj2",
|
|
||||||
}
|
|
||||||
if got := getLifeCycleTransitionTier(context.TODO(), &lc, "bucket", obj1); got != "TIER-1" {
|
|
||||||
t.Fatalf("Expected TIER-1 but got %s", got)
|
|
||||||
}
|
|
||||||
if got := getLifeCycleTransitionTier(context.TODO(), &lc, "bucket", obj2); got != "TIER-2" {
|
|
||||||
t.Fatalf("Expected TIER-2 but got %s", got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1020,22 +1020,7 @@ func (i *scannerItem) applyActions(ctx context.Context, o ObjectLayer, meta acti
|
||||||
}
|
}
|
||||||
|
|
||||||
func evalActionFromLifecycle(ctx context.Context, lc lifecycle.Lifecycle, obj ObjectInfo, debug bool) (action lifecycle.Action) {
|
func evalActionFromLifecycle(ctx context.Context, lc lifecycle.Lifecycle, obj ObjectInfo, debug bool) (action lifecycle.Action) {
|
||||||
lcOpts := lifecycle.ObjectOpts{
|
action = lc.ComputeAction(obj.ToLifecycleOpts())
|
||||||
Name: obj.Name,
|
|
||||||
UserTags: obj.UserTags,
|
|
||||||
ModTime: obj.ModTime,
|
|
||||||
VersionID: obj.VersionID,
|
|
||||||
DeleteMarker: obj.DeleteMarker,
|
|
||||||
IsLatest: obj.IsLatest,
|
|
||||||
NumVersions: obj.NumVersions,
|
|
||||||
SuccessorModTime: obj.SuccessorModTime,
|
|
||||||
RestoreOngoing: obj.RestoreOngoing,
|
|
||||||
RestoreExpires: obj.RestoreExpires,
|
|
||||||
TransitionStatus: obj.TransitionStatus,
|
|
||||||
RemoteTiersImmediately: globalDebugRemoteTiersImmediately,
|
|
||||||
}
|
|
||||||
|
|
||||||
action = lc.ComputeAction(lcOpts)
|
|
||||||
if debug {
|
if debug {
|
||||||
console.Debugf(applyActionsLogPrefix+" lifecycle: Secondary scan: %v\n", action)
|
console.Debugf(applyActionsLogPrefix+" lifecycle: Secondary scan: %v\n", action)
|
||||||
}
|
}
|
||||||
|
@ -1086,25 +1071,11 @@ func applyTransitionAction(ctx context.Context, action lifecycle.Action, objLaye
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyExpiryOnTransitionedObject(ctx context.Context, objLayer ObjectLayer, obj ObjectInfo, restoredObject bool) bool {
|
func applyExpiryOnTransitionedObject(ctx context.Context, objLayer ObjectLayer, obj ObjectInfo, restoredObject bool) bool {
|
||||||
lcOpts := lifecycle.ObjectOpts{
|
|
||||||
Name: obj.Name,
|
|
||||||
UserTags: obj.UserTags,
|
|
||||||
ModTime: obj.ModTime,
|
|
||||||
VersionID: obj.VersionID,
|
|
||||||
DeleteMarker: obj.DeleteMarker,
|
|
||||||
IsLatest: obj.IsLatest,
|
|
||||||
NumVersions: obj.NumVersions,
|
|
||||||
SuccessorModTime: obj.SuccessorModTime,
|
|
||||||
RestoreOngoing: obj.RestoreOngoing,
|
|
||||||
RestoreExpires: obj.RestoreExpires,
|
|
||||||
TransitionStatus: obj.TransitionStatus,
|
|
||||||
}
|
|
||||||
|
|
||||||
action := expireObj
|
action := expireObj
|
||||||
if restoredObject {
|
if restoredObject {
|
||||||
action = expireRestoredObj
|
action = expireRestoredObj
|
||||||
}
|
}
|
||||||
if err := expireTransitionedObject(ctx, objLayer, &obj, lcOpts, action); err != nil {
|
if err := expireTransitionedObject(ctx, objLayer, &obj, obj.ToLifecycleOpts(), action); err != nil {
|
||||||
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
if isErrObjectNotFound(err) || isErrVersionNotFound(err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -476,3 +476,16 @@ func (lc Lifecycle) SetPredictionHeaders(w http.ResponseWriter, obj ObjectOpts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TransitionTier returns remote tier that applies to obj per ILM rules.
|
||||||
|
func (lc Lifecycle) TransitionTier(obj ObjectOpts) string {
|
||||||
|
for _, rule := range lc.FilterActionableRules(obj) {
|
||||||
|
if obj.IsLatest && rule.Transition.StorageClass != "" {
|
||||||
|
return rule.Transition.StorageClass
|
||||||
|
}
|
||||||
|
if !obj.IsLatest && rule.NoncurrentVersionTransition.StorageClass != "" {
|
||||||
|
return rule.NoncurrentVersionTransition.StorageClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
|
@ -516,3 +516,40 @@ func TestSetPredictionHeaders(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTransitionTier(t *testing.T) {
|
||||||
|
lc := Lifecycle{
|
||||||
|
Rules: []Rule{
|
||||||
|
{
|
||||||
|
ID: "rule-1",
|
||||||
|
Status: "Enabled",
|
||||||
|
Transition: Transition{
|
||||||
|
Days: TransitionDays(3),
|
||||||
|
StorageClass: "TIER-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "rule-2",
|
||||||
|
Status: "Enabled",
|
||||||
|
NoncurrentVersionTransition: NoncurrentVersionTransition{
|
||||||
|
NoncurrentDays: ExpirationDays(3),
|
||||||
|
StorageClass: "TIER-2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
obj1 := ObjectOpts{
|
||||||
|
Name: "obj1",
|
||||||
|
IsLatest: true,
|
||||||
|
}
|
||||||
|
obj2 := ObjectOpts{
|
||||||
|
Name: "obj2",
|
||||||
|
}
|
||||||
|
if got := lc.TransitionTier(obj1); got != "TIER-1" {
|
||||||
|
t.Fatalf("Expected TIER-1 but got %s", got)
|
||||||
|
}
|
||||||
|
if got := lc.TransitionTier(obj2); got != "TIER-2" {
|
||||||
|
t.Fatalf("Expected TIER-2 but got %s", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue