Skip to content

Commit

Permalink
chore: show the recoverable time when describing the cluster (#329)
Browse files Browse the repository at this point in the history
  • Loading branch information
wangyelei authored May 7, 2024
1 parent bb707c8 commit d7100c8
Show file tree
Hide file tree
Showing 16 changed files with 134 additions and 75 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require (
github.com/99designs/keyring v1.2.2
github.com/Masterminds/semver/v3 v3.2.1
github.com/apecloud/kubebench v0.0.0-20240327101848-6a031d3f4ebe
github.com/apecloud/kubeblocks v0.9.0-beta.15
github.com/apecloud/kubeblocks v0.9.0-beta.18
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
github.com/benbjohnson/clock v1.3.5
github.com/briandowns/spinner v1.23.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,8 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df h
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df/go.mod h1:pSwJ0fSY5KhvocuWSx4fz3BA8OrA1bQn+K1Eli3BRwM=
github.com/apecloud/kubebench v0.0.0-20240327101848-6a031d3f4ebe h1:OFkCAToRcNt0VqgCndw0mw1Ke3P2XgRJLrXsNOyc3sQ=
github.com/apecloud/kubebench v0.0.0-20240327101848-6a031d3f4ebe/go.mod h1:5IZiDkFdgiZRGLsL+FOlvPsiF9LbyU55DVj4/5vT7+4=
github.com/apecloud/kubeblocks v0.9.0-beta.15 h1:EoIIw8ycvo7TH/Bb6ImPKgJUO1T1/nw6v1Ba2j8MzyQ=
github.com/apecloud/kubeblocks v0.9.0-beta.15/go.mod h1:RsLwGOD0SmBCoGjm+nyaWZQvyAJ2uELBL5pqg0fI1I4=
github.com/apecloud/kubeblocks v0.9.0-beta.18 h1:9d7cLCyhfZAZbrgpPUuEjryDL0jw1D3rY6Nr0F4n7Zo=
github.com/apecloud/kubeblocks v0.9.0-beta.18/go.mod h1:RsLwGOD0SmBCoGjm+nyaWZQvyAJ2uELBL5pqg0fI1I4=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/cluster/config_observer.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ func (r *configObserverOptions) printConfigureHistory(component string) error {
tplNames := getTemplateNameFromOps(ops.Spec)
keyNames := getKeyNameFromOps(ops.Spec)
tbl.AddRow(ops.Name,
ops.Spec.ClusterRef,
ops.Spec.GetClusterName(),
components,
tplNames,
keyNames,
Expand Down
22 changes: 11 additions & 11 deletions pkg/cmd/cluster/dataprotection.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,11 @@ var (
const TrueValue = "true"

type CreateBackupOptions struct {
BackupSpec appsv1alpha1.BackupSpec `json:"backupSpec"`
ClusterName string `json:"clusterName"`
OpsType string `json:"opsType"`
OpsRequestName string `json:"opsRequestName"`
Force bool `json:"force"`
BackupSpec appsv1alpha1.Backup `json:"backupSpec"`
ClusterName string `json:"clusterName"`
OpsType string `json:"opsType"`
OpsRequestName string `json:"opsRequestName"`
Force bool `json:"force"`

action.CreateOptions `json:"-"`
}
Expand Down Expand Up @@ -504,11 +504,11 @@ func completeForDeleteBackup(o *action.DeleteOptions, args []string) error {
}

type CreateRestoreOptions struct {
RestoreSpec appsv1alpha1.RestoreSpec `json:"restoreSpec"`
ClusterName string `json:"clusterName"`
OpsType string `json:"opsType"`
OpsRequestName string `json:"opsRequestName"`
Force bool `json:"force"`
RestoreSpec appsv1alpha1.Restore `json:"restoreSpec"`
ClusterName string `json:"clusterName"`
OpsType string `json:"opsType"`
OpsRequestName string `json:"opsRequestName"`
Force bool `json:"force"`

action.CreateOptions `json:"-"`
}
Expand Down Expand Up @@ -567,7 +567,7 @@ func NewCreateRestoreCmd(f cmdutil.Factory, streams genericiooptions.IOStreams)
}

cmd.Flags().StringVar(&o.RestoreSpec.BackupName, "backup", "", "Backup name")
cmd.Flags().StringVar(&o.RestoreSpec.RestoreTimeStr, "restore-to-time", "", "point in time recovery(PITR)")
cmd.Flags().StringVar(&o.RestoreSpec.RestorePointInTime, "restore-to-time", "", "point in time recovery(PITR)")
cmd.Flags().StringVar(&o.RestoreSpec.VolumeRestorePolicy, "volume-restore-policy", "Parallel", "the volume claim restore policy, supported values: [Serial, Parallel]")
return cmd
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/cluster/dataprotection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ var _ = Describe("DataProtection", func() {
CueTemplateName: "backup_template.cue",
Name: testing.ClusterName,
},
BackupSpec: appsv1alpha1.BackupSpec{
BackupSpec: appsv1alpha1.Backup{
BackupPolicyName: otherBackupPolicy.Name,
BackupMethod: testing.BackupMethodName,
},
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/cluster/delete_ops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ var _ = Describe("Expose", func() {
Namespace: namespace,
},
Spec: appsv1alpha1.OpsRequestSpec{
ClusterRef: "test-cluster",
Type: "Restart",
ClusterName: "test-cluster",
Type: "Restart",
},
Status: appsv1alpha1.OpsRequestStatus{
Phase: phase,
Expand Down
113 changes: 85 additions & 28 deletions pkg/cmd/cluster/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,11 @@ import (
"context"
"fmt"
"io"
"sort"
"strings"
"time"

"github.com/apecloud/kubeblocks/pkg/constant"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -38,6 +41,7 @@ import (

appsv1alpha1 "github.com/apecloud/kubeblocks/apis/apps/v1alpha1"
dpv1alpha1 "github.com/apecloud/kubeblocks/apis/dataprotection/v1alpha1"
dptypes "github.com/apecloud/kubeblocks/pkg/dataprotection/types"
"github.com/apecloud/kubeblocks/pkg/dataprotection/utils/boolptr"

"github.com/apecloud/kbcli/pkg/cluster"
Expand Down Expand Up @@ -169,7 +173,11 @@ func (o *describeOptions) describeCluster(name string) error {
if err != nil {
return err
}
showDataProtection(o.BackupPolicies, o.BackupSchedules, defaultBackupRepo, o.Out)
recoverableTime, continuousMethod, err := o.getBackupRecoverableTime()
if err != nil {
return err
}
showDataProtection(o.BackupPolicies, o.BackupSchedules, defaultBackupRepo, continuousMethod, recoverableTime, o.Out)

// events
showEvents(o.Cluster.Name, o.Cluster.Namespace, o.Out)
Expand Down Expand Up @@ -251,11 +259,17 @@ func showEndpoints(c *appsv1alpha1.Cluster, svcList *corev1.ServiceList, out io.
tbl.Print()
}

func showDataProtection(backupPolicies []dpv1alpha1.BackupPolicy, backupSchedules []dpv1alpha1.BackupSchedule, defaultBackupRepo string, out io.Writer) {
func showDataProtection(backupPolicies []dpv1alpha1.BackupPolicy, backupSchedules []dpv1alpha1.BackupSchedule, defaultBackupRepo, continuousMethod, recoverableTimeRange string, out io.Writer) {
if len(backupPolicies) == 0 || len(backupSchedules) == 0 {
return
}
tbl := newTbl(out, "\nData Protection:", "BACKUP-REPO", "AUTO-BACKUP", "BACKUP-SCHEDULE", "BACKUP-METHOD", "BACKUP-RETENTION")
tbl := newTbl(out, "\nData Protection:", "BACKUP-REPO", "AUTO-BACKUP", "BACKUP-SCHEDULE", "BACKUP-METHOD", "BACKUP-RETENTION", "RECOVERABLE-TIME")
getEnableString := func(enable bool) string {
if enable {
return "Enabled"
}
return "Disabled"
}
for _, schedule := range backupSchedules {
backupRepo := defaultBackupRepo
for _, policy := range backupPolicies {
Expand All @@ -267,34 +281,77 @@ func showDataProtection(backupPolicies []dpv1alpha1.BackupPolicy, backupSchedule
}
}
for _, schedulePolicy := range schedule.Spec.Schedules {
if !boolptr.IsSetToTrue(schedulePolicy.Enabled) {
continue
if recoverableTimeRange != "" && continuousMethod == schedulePolicy.BackupMethod {
// continuous backup with recoverable time
tbl.AddRow(backupRepo, getEnableString(boolptr.IsSetToTrue(schedulePolicy.Enabled)), schedulePolicy.CronExpression, schedulePolicy.BackupMethod, schedulePolicy.RetentionPeriod.String(), recoverableTimeRange)
} else if boolptr.IsSetToTrue(schedulePolicy.Enabled) {
tbl.AddRow(backupRepo, "Enabled", schedulePolicy.CronExpression, schedulePolicy.BackupMethod, schedulePolicy.RetentionPeriod.String(), "")
}

tbl.AddRow(backupRepo, "Enabled", schedulePolicy.CronExpression, schedulePolicy.BackupMethod, schedulePolicy.RetentionPeriod.String())
}
}
tbl.Print()
}

// getBackupRecoverableTime returns the recoverable time range string
// func getBackupRecoverableTime(backups []dpv1alpha1.Backup) string {
// recoverabelTime := dpv1alpha1.GetRecoverableTimeRange(backups)
// var result string
// for _, i := range recoverabelTime {
// result = addTimeRange(result, i.StartTime, i.StopTime)
// }
// if result == "" {
// return printer.NoneString
// }
// return result
// }

// func addTimeRange(result string, start, end *metav1.Time) string {
// if result != "" {
// result += ", "
// }
// result += fmt.Sprintf("%s ~ %s", util.TimeFormatWithDuration(start, time.Second),
// util.TimeFormatWithDuration(end, time.Second))
// return result
// }
// getBackupRecoverableTime returns the recoverable time range string
func (o *describeOptions) getBackupRecoverableTime() (string, string, error) {
continuousBackups, err := o.getBackupList(dpv1alpha1.BackupTypeContinuous)
if err != nil {
return "", "", err
}
if len(continuousBackups) == 0 {
return "", "", nil
}
continuousBackup := continuousBackups[0]
if continuousBackup.GetStartTime() == nil || continuousBackup.GetEndTime() == nil {
return "", "", nil
}
fullBackups, err := o.getBackupList(dpv1alpha1.BackupTypeFull)
if err != nil {
return "", "", err
}
sortBackup(fullBackups, false)
for _, backup := range fullBackups {
completeTime := backup.GetEndTime()
if completeTime != nil && !completeTime.Before(continuousBackup.GetStartTime()) {
return fmt.Sprintf("%s ~ %s", util.TimeFormatWithDuration(completeTime, time.Second),
util.TimeFormatWithDuration(continuousBackup.GetEndTime(), time.Second)), continuousBackup.Spec.BackupMethod, nil
}
}
return "", "", nil
}

func (o *describeOptions) getBackupList(backupType dpv1alpha1.BackupType) ([]*dpv1alpha1.Backup, error) {
backupList, err := o.dynamic.Resource(types.BackupGVR()).Namespace(o.namespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: fmt.Sprintf("%s=%s,%s=%s",
constant.AppInstanceLabelKey, o.Cluster.Name,
dptypes.BackupTypeLabelKey, backupType),
})
if err != nil {
return nil, err
}
var backups []*dpv1alpha1.Backup
for i := range backupList.Items {
fullBackup := &dpv1alpha1.Backup{}
if err = runtime.DefaultUnstructuredConverter.FromUnstructured(backupList.Items[i].Object, fullBackup); err != nil {
return nil, err
}
backups = append(backups, fullBackup)
}
return backups, nil
}

func sortBackup(backups []*dpv1alpha1.Backup, reverse bool) []*dpv1alpha1.Backup {
sort.Slice(backups, func(i, j int) bool {
if reverse {
i, j = j, i
}
if backups[i].GetEndTime() == nil {
return false
}
if backups[j].GetEndTime() == nil {
return true
}
return backups[i].GetEndTime().Before(backups[j].GetEndTime())
})
return backups
}
20 changes: 10 additions & 10 deletions pkg/cmd/cluster/describe_ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func (o *describeOpsOptions) printOpsRequest(ops *appsv1alpha1.OpsRequest) error
// first pair string
printer.NewPair(" Name", ops.Name),
printer.NewPair("NameSpace", ops.Namespace),
printer.NewPair("Cluster", ops.Spec.ClusterRef),
printer.NewPair("Cluster", ops.Spec.GetClusterName()),
printer.NewPair("Type", string(ops.Spec.Type)),
)

Expand Down Expand Up @@ -234,15 +234,15 @@ func (o *describeOpsOptions) getRestartCommand(spec appsv1alpha1.OpsRequestSpec)
componentNames[i] = v.ComponentName
}
return []string{
fmt.Sprintf("kbcli cluster restart %s --components=%s", spec.ClusterRef,
fmt.Sprintf("kbcli cluster restart %s --components=%s", spec.GetClusterName(),
strings.Join(componentNames, ",")),
}
}

// getUpgradeCommand gets the command of the Upgrade OpsRequest.
func (o *describeOpsOptions) getUpgradeCommand(spec appsv1alpha1.OpsRequestSpec) []string {
return []string{
fmt.Sprintf("kbcli cluster upgrade %s --cluster-version=%s", spec.ClusterRef,
fmt.Sprintf("kbcli cluster upgrade %s --cluster-version=%s", spec.GetClusterName(),
spec.Upgrade.ClusterVersionRef),
}
}
Expand Down Expand Up @@ -271,7 +271,7 @@ func (o *describeOpsOptions) getVerticalScalingCommand(spec appsv1alpha1.OpsRequ
commands := make([]string, len(componentNameSlice))
for i := range componentNameSlice {
commands[i] = fmt.Sprintf("kbcli cluster vscale %s --components=%s",
spec.ClusterRef, strings.Join(componentNameSlice[i], ","))
spec.GetClusterName(), strings.Join(componentNameSlice[i], ","))
resource := resourceSlice[i].(corev1.ResourceRequirements)
commands[i] += o.addResourceFlag("cpu", resource.Limits.Cpu())
commands[i] += o.addResourceFlag("memory", resource.Limits.Memory())
Expand All @@ -295,7 +295,7 @@ func (o *describeOpsOptions) getHorizontalScalingCommand(spec appsv1alpha1.OpsRe
commands := make([]string, len(componentNameSlice))
for i := range componentNameSlice {
commands[i] = fmt.Sprintf("kbcli cluster hscale %s --components=%s --replicas=%d",
spec.ClusterRef, strings.Join(componentNameSlice[i], ","), replicasSlice[i].(int32))
spec.GetClusterName(), strings.Join(componentNameSlice[i], ","), replicasSlice[i].(int32))
}
return commands
}
Expand All @@ -315,7 +315,7 @@ func (o *describeOpsOptions) getVolumeExpansionCommand(spec appsv1alpha1.OpsRequ
for i := range vctNameSlice {
storage := storageSlice[i].(resource.Quantity)
commands = append(commands, fmt.Sprintf("kbcli cluster volume-expand %s --components=%s --volume-claim-template-names=%s --storage=%s",
spec.ClusterRef, v.ComponentName, strings.Join(vctNameSlice[i], ","), storage.String()))
spec.GetClusterName(), v.ComponentName, strings.Join(vctNameSlice[i], ","), storage.String()))
}
}
return commands
Expand All @@ -324,7 +324,7 @@ func (o *describeOpsOptions) getVolumeExpansionCommand(spec appsv1alpha1.OpsRequ
// getReconfiguringCommand gets the command of the VolumeExpansion command.
func (o *describeOpsOptions) getReconfiguringCommand(spec appsv1alpha1.OpsRequestSpec) []string {
if spec.Reconfigure != nil {
return generateReconfiguringCommand(spec.ClusterRef, spec.Reconfigure, []string{spec.Reconfigure.ComponentName})
return generateReconfiguringCommand(spec.GetClusterName(), spec.Reconfigure, []string{spec.Reconfigure.ComponentName})
}

if len(spec.Reconfigures) == 0 {
Expand All @@ -334,10 +334,10 @@ func (o *describeOpsOptions) getReconfiguringCommand(spec appsv1alpha1.OpsReques
for i, reconfigure := range spec.Reconfigures {
components[i] = reconfigure.ComponentName
}
return generateReconfiguringCommand(spec.ClusterRef, &spec.Reconfigures[0], components)
return generateReconfiguringCommand(spec.GetClusterName(), &spec.Reconfigures[0], components)
}

func generateReconfiguringCommand(clusterRef string, updatedParams *appsv1alpha1.Reconfigure, components []string) []string {
func generateReconfiguringCommand(clusterName string, updatedParams *appsv1alpha1.Reconfigure, components []string) []string {
if len(updatedParams.Configurations) == 0 {
return nil
}
Expand All @@ -351,7 +351,7 @@ func generateReconfiguringCommand(clusterRef string, updatedParams *appsv1alpha1
commandArgs = append(commandArgs, "kbcli")
commandArgs = append(commandArgs, "cluster")
commandArgs = append(commandArgs, "configure")
commandArgs = append(commandArgs, clusterRef)
commandArgs = append(commandArgs, clusterName)
commandArgs = append(commandArgs, fmt.Sprintf("--components=%s", strings.Join(components, ",")))
commandArgs = append(commandArgs, fmt.Sprintf("--config-spec=%s", configuration.Name))

Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/cluster/describe_ops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ var _ = Describe("Expose", func() {
Namespace: namespace,
},
Spec: appsv1alpha1.OpsRequestSpec{
ClusterRef: "test-cluster",
Type: opsType,
ClusterName: "test-cluster",
Type: opsType,
},
}
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/cluster/describe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ var _ = Describe("Expose", func() {
*testing.FakeBackupSchedule("backup-schedule-test", "backup-policy-test"),
}

showDataProtection(fakeBackupPolicies, fakeBackupSchedules, "test-repository", out)
showDataProtection(fakeBackupPolicies, fakeBackupSchedules, "test-repository", "", "", out)
strs := strings.Split(out.String(), "\n")
Expect(strs).ShouldNot(BeEmpty())
})
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/cluster/list_ops.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (o *opsListOptions) printOpsList() error {
opsType := string(ops.Spec.Type)
if len(o.opsRequestName) != 0 {
if ops.Name == o.opsRequestName {
tblPrinter.AddRow(ops.Name, ops.GetNamespace(), opsType, ops.Spec.ClusterRef, getComponentNameFromOps(ops), phase, ops.Status.Progress, util.TimeFormat(&ops.CreationTimestamp))
tblPrinter.AddRow(ops.Name, ops.GetNamespace(), opsType, ops.Spec.GetClusterName(), getComponentNameFromOps(ops), phase, ops.Status.Progress, util.TimeFormat(&ops.CreationTimestamp))
}
continue
}
Expand All @@ -145,7 +145,7 @@ func (o *opsListOptions) printOpsList() error {
if len(o.opsType) != 0 && !o.containsIgnoreCase(o.opsType, opsType) {
continue
}
tblPrinter.AddRow(ops.Name, ops.GetNamespace(), opsType, ops.Spec.ClusterRef, getComponentNameFromOps(ops), phase, ops.Status.Progress, util.TimeFormat(&ops.CreationTimestamp))
tblPrinter.AddRow(ops.Name, ops.GetNamespace(), opsType, ops.Spec.GetClusterName, getComponentNameFromOps(ops), phase, ops.Status.Progress, util.TimeFormat(&ops.CreationTimestamp))
}
if tblPrinter.Tbl.Length() != 0 {
tblPrinter.Print()
Expand Down
4 changes: 2 additions & 2 deletions pkg/cmd/cluster/list_ops_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ var _ = Describe("Expose", func() {
Namespace: namespace,
},
Spec: appsv1alpha1.OpsRequestSpec{
ClusterRef: "test-cluster",
Type: opsType,
ClusterName: "test-cluster",
Type: opsType,
},
Status: appsv1alpha1.OpsRequestStatus{
Phase: phase,
Expand Down
Loading

0 comments on commit d7100c8

Please sign in to comment.