Add UI to select number of non-current versions subject to ILM expiry rule (#3088)

This commit is contained in:
jinapurapu
2023-11-16 11:34:04 -08:00
committed by GitHub
parent 8c26eff2c1
commit da53daff37
9 changed files with 135 additions and 28 deletions

View File

@@ -46,6 +46,9 @@ type AddBucketLifecycle struct {
// Required in case of expiry_date or transition fields are not set. it defines an expiry days for ILM
ExpiryDays int32 `json:"expiry_days,omitempty"`
// Non required, can be set in case of expiration is enabled
NewerNoncurrentversionExpirationVersions int32 `json:"newer_noncurrentversion_expiration_versions,omitempty"`
// Non required, can be set in case of expiration is enabled
NoncurrentversionExpirationDays int32 `json:"noncurrentversion_expiration_days,omitempty"`

View File

@@ -43,6 +43,9 @@ type ExpirationResponse struct {
// delete marker
DeleteMarker bool `json:"delete_marker,omitempty"`
// newer noncurrent expiration versions
NewerNoncurrentExpirationVersions int64 `json:"newer_noncurrent_expiration_versions,omitempty"`
// noncurrent expiration days
NoncurrentExpirationDays int64 `json:"noncurrent_expiration_days,omitempty"`
}

View File

@@ -880,6 +880,8 @@ export interface ExpirationResponse {
delete_marker?: boolean;
/** @format int64 */
noncurrent_expiration_days?: number;
/** @format int64 */
newer_noncurrent_expiration_versions?: number;
}
export interface TransitionResponse {
@@ -943,6 +945,12 @@ export interface AddBucketLifecycle {
* @default 0
*/
noncurrentversion_transition_days?: number;
/**
* Non required, can be set in case of expiration is enabled
* @format int32
* @default 0
*/
newer_noncurrentversion_expiration_versions?: number;
/** Non required, can be set in case of transition is enabled */
noncurrentversion_transition_storage_class?: string;
}

View File

@@ -19,9 +19,11 @@ import React, { Fragment, useEffect, useState } from "react";
import get from "lodash/get";
import {
Accordion,
AlertIcon,
Button,
FormLayout,
Grid,
HelpTip,
InputBox,
LifecycleConfigIcon,
ProgressBar,
@@ -74,6 +76,7 @@ const AddLifecycleModal = ({
const [loadingVersioning, setLoadingVersioning] = useState<boolean>(true);
const [expandedAdv, setExpandedAdv] = useState<boolean>(false);
const [expanded, setExpanded] = useState<boolean>(false);
const [expiryUnit, setExpiryUnit] = useState<string>("days");
/*To be removed on component replacement*/
const formFieldRowFilter = {
@@ -116,6 +119,13 @@ const AddLifecycleModal = ({
valid = false;
}
}
if (!lifecycleDays || parseInt(lifecycleDays) === 0) {
valid = false;
}
if (parseInt(lifecycleDays) > 2147483647) {
//values over int32 cannot be parsed
valid = false;
}
setIsFormValid(valid);
}, [ilmType, lifecycleDays, storageClass]);
@@ -142,8 +152,11 @@ const AddLifecycleModal = ({
if (targetVersion === "current") {
expiry["expiry_days"] = parseInt(lifecycleDays);
} else {
} else if (expiryUnit === "days") {
expiry["noncurrentversion_expiration_days"] = parseInt(lifecycleDays);
} else {
expiry["newer_noncurrentversion_expiration_versions"] =
parseInt(lifecycleDays);
}
rules = {
@@ -154,7 +167,7 @@ const AddLifecycleModal = ({
if (targetVersion === "current") {
transition["transition_days"] = parseInt(lifecycleDays);
transition["storage_class"] = storageClass;
} else {
} else if (expiryUnit === "days") {
transition["noncurrentversion_transition_days"] =
parseInt(lifecycleDays);
transition["noncurrentversion_transition_storage_class"] = storageClass;
@@ -184,7 +197,6 @@ const AddLifecycleModal = ({
dispatch(setModalErrorSnackMessage(errorToHandler(err)));
});
};
return (
<ModalWrapper
modalOpen={open}
@@ -284,6 +296,15 @@ const AddLifecycleModal = ({
)}
<InputBox
error={
lifecycleDays && !isFormValid
? parseInt(lifecycleDays) <= 0
? `Number of ${expiryUnit} to retain must be greater than zero`
: parseInt(lifecycleDays) > 2147483647
? `Number of ${expiryUnit} must be less than or equal to 2147483647`
: ""
: ""
}
id="expiry_days"
name="expiry_days"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -295,12 +316,38 @@ const AddLifecycleModal = ({
label="After"
value={lifecycleDays}
overlayObject={
<InputUnitMenu
id={"expire-current-unit"}
unitSelected={"days"}
unitsList={[{ label: "Days", value: "days" }]}
disabled={true}
/>
<Fragment>
<Grid container sx={{ justifyContent: "center" }}>
<InputUnitMenu
id={"expire-current-unit"}
unitSelected={expiryUnit}
unitsList={[
{ label: "Days", value: "days" },
{ label: "Versions", value: "versions" },
]}
disabled={
targetVersion !== "noncurrent" || ilmType !== "expiry"
}
onUnitChange={(newValue) => {
setExpiryUnit(newValue);
}}
/>
{ilmType === "expiry" && targetVersion === "noncurrent" && (
<HelpTip
content={
<Fragment>
Select to set expiry by days or newer noncurrent
versions
</Fragment>
}
placement="right"
>
{" "}
<AlertIcon style={{ width: 15, height: 15 }} />
</HelpTip>
)}
</Grid>
</Fragment>
}
/>

View File

@@ -86,7 +86,6 @@ const BucketLifecyclePanel = () => {
.getBucketLifecycle(bucketName)
.then((res) => {
const records = get(res.data, "lifecycle", []);
setLifecycleRecords(records || []);
setLoadingLifecycle(false);
})
@@ -147,7 +146,10 @@ const BucketLifecyclePanel = () => {
}
if (
el.expiration &&
(el.expiration.days > 0 || el.expiration.noncurrent_expiration_days)
(el.expiration.days > 0 ||
el.expiration.noncurrent_expiration_days ||
(el.expiration.newer_noncurrent_expiration_versions &&
el.expiration.newer_noncurrent_expiration_versions > 0))
) {
return <span>Expiry</span>;
}
@@ -170,7 +172,10 @@ const BucketLifecyclePanel = () => {
if (el.expiration) {
if (el.expiration.days > 0) {
return <span>Current</span>;
} else if (el.expiration.noncurrent_expiration_days) {
} else if (
el.expiration.noncurrent_expiration_days ||
el.expiration.newer_noncurrent_expiration_versions
) {
return <span>Non-Current</span>;
}
}
@@ -200,13 +205,6 @@ const BucketLifecyclePanel = () => {
if (!el) {
return <Fragment />;
}
if (el.expiration) {
if (el.expiration.days > 0) {
return <span>{el.expiration.days} days</span>;
} else if (el.expiration.noncurrent_expiration_days) {
return <span>{el.expiration.noncurrent_expiration_days} days</span>;
}
}
if (el.transition) {
if (el.transition.days > 0) {
return <span>{el.transition.days} days</span>;
@@ -214,6 +212,19 @@ const BucketLifecyclePanel = () => {
return <span>{el.transition.noncurrent_transition_days} days</span>;
}
}
if (el.expiration) {
if (el.expiration.days > 0) {
return <span>{el.expiration.days} days</span>;
} else if (el.expiration.noncurrent_expiration_days) {
return <span>{el.expiration.noncurrent_expiration_days} days</span>;
} else {
return (
<span>
{el.expiration.newer_noncurrent_expiration_versions} versions
</span>
);
}
}
},
},
{

View File

@@ -42,6 +42,7 @@ interface IExpirationLifecycle {
date: string;
delete_marker?: boolean;
noncurrent_expiration_days?: number;
newer_noncurrent_expiration_versions?: number;
}
interface ITransitionLifecycle {

View File

@@ -5385,6 +5385,12 @@ func init() {
"format": "int32",
"default": 0
},
"newer_noncurrentversion_expiration_versions": {
"description": "Non required, can be set in case of expiration is enabled",
"type": "integer",
"format": "int32",
"default": 0
},
"noncurrentversion_expiration_days": {
"description": "Non required, can be set in case of expiration is enabled",
"type": "integer",
@@ -6190,6 +6196,10 @@ func init() {
"delete_marker": {
"type": "boolean"
},
"newer_noncurrent_expiration_versions": {
"type": "integer",
"format": "int64"
},
"noncurrent_expiration_days": {
"type": "integer",
"format": "int64"
@@ -14656,6 +14666,12 @@ func init() {
"format": "int32",
"default": 0
},
"newer_noncurrentversion_expiration_versions": {
"description": "Non required, can be set in case of expiration is enabled",
"type": "integer",
"format": "int32",
"default": 0
},
"noncurrentversion_expiration_days": {
"description": "Non required, can be set in case of expiration is enabled",
"type": "integer",
@@ -15456,6 +15472,10 @@ func init() {
"delete_marker": {
"type": "boolean"
},
"newer_noncurrent_expiration_versions": {
"type": "integer",
"format": "int64"
},
"noncurrent_expiration_days": {
"type": "integer",
"format": "int64"

View File

@@ -90,7 +90,6 @@ func getBucketLifecycle(ctx context.Context, client MinioClient, bucketName stri
if err != nil {
return nil, err
}
var rules []*models.ObjectBucketLifecycle
for _, rule := range lifecycleList.Rules {
@@ -115,10 +114,11 @@ func getBucketLifecycle(ctx context.Context, client MinioClient, bucketName stri
Status: rule.Status,
Prefix: rulePrefix,
Expiration: &models.ExpirationResponse{
Date: rule.Expiration.Date.Format(time.RFC3339),
Days: int64(rule.Expiration.Days),
DeleteMarker: rule.Expiration.DeleteMarker.IsEnabled(),
NoncurrentExpirationDays: int64(rule.NoncurrentVersionExpiration.NoncurrentDays),
Date: rule.Expiration.Date.Format(time.RFC3339),
Days: int64(rule.Expiration.Days),
DeleteMarker: rule.Expiration.DeleteMarker.IsEnabled(),
NoncurrentExpirationDays: int64(rule.NoncurrentVersionExpiration.NoncurrentDays),
NewerNoncurrentExpirationVersions: int64(rule.NoncurrentVersionExpiration.NewerNoncurrentVersions),
},
Transition: &models.TransitionResponse{
Date: rule.Transition.Date.Format(time.RFC3339),
@@ -178,7 +178,7 @@ func addBucketLifecycle(ctx context.Context, client MinioClient, params bucketAp
switch params.Body.Type {
case models.AddBucketLifecycleTypeTransition:
if params.Body.TransitionDays == 0 && params.Body.NoncurrentversionTransitionDays == 0 {
return errors.New("only one expiry configuration can be set (days or date)")
return errors.New("you must provide a value for transition days or date")
}
status := !params.Body.Disable
@@ -195,12 +195,13 @@ func addBucketLifecycle(ctx context.Context, client MinioClient, params bucketAp
noncurrentVersionTransitionStorageClass := strings.ToUpper(params.Body.NoncurrentversionTransitionStorageClass)
opts.NoncurrentVersionTransitionDays = &noncurrentVersionTransitionDays
opts.NoncurrentVersionTransitionStorageClass = &noncurrentVersionTransitionStorageClass
} else {
} else if params.Body.TransitionDays > 0 {
tdays := strconv.Itoa(int(params.Body.TransitionDays))
sclass := strings.ToUpper(params.Body.StorageClass)
opts.TransitionDays = &tdays
opts.StorageClass = &sclass
}
case models.AddBucketLifecycleTypeExpiry:
// Verify if expiry items are set
if params.Body.NoncurrentversionTransitionDays != 0 {
@@ -220,10 +221,15 @@ func addBucketLifecycle(ctx context.Context, client MinioClient, params bucketAp
ExpiredObjectDeleteMarker: &params.Body.ExpiredObjectDeleteMarker,
}
if params.Body.NoncurrentversionExpirationDays > 0 {
if params.Body.NewerNoncurrentversionExpirationVersions > 0 {
versions := int(params.Body.NewerNoncurrentversionExpirationVersions)
opts.NewerNoncurrentExpirationVersions = &versions
}
switch {
case params.Body.NoncurrentversionExpirationDays > 0:
days := int(params.Body.NoncurrentversionExpirationDays)
opts.NoncurrentVersionExpirationDays = &days
} else {
case params.Body.ExpiryDays > 0:
days := strconv.Itoa(int(params.Body.ExpiryDays))
opts.ExpiryDays = &days
}

View File

@@ -5067,6 +5067,9 @@ definitions:
noncurrent_expiration_days:
type: integer
format: int64
newer_noncurrent_expiration_versions:
type: integer
format: int64
transitionResponse:
type: object
@@ -5154,6 +5157,11 @@ definitions:
type: integer
format: int32
default: 0
newer_noncurrentversion_expiration_versions:
description: Non required, can be set in case of expiration is enabled
type: integer
format: int32
default: 0
noncurrentversion_transition_storage_class:
description: Non required, can be set in case of transition is enabled
type: string