diff --git a/cmd/backup/policy/policy.go b/cmd/backup/policy/policy.go index 8775ca9c..49be801e 100644 --- a/cmd/backup/policy/policy.go +++ b/cmd/backup/policy/policy.go @@ -158,7 +158,7 @@ var disablePolicyCmd = &cobra.Command{ } if len(resp.GetData()) < 1 { - logrus.Fatalln("No backup policies found for the given cluster") + logrus.Fatalln("No ACTIVE backup policies found to disable for the given cluster") } scheduleSpec := resp.GetData()[0].GetSpec() if scheduleSpec.GetState() == ybmclient.SCHEDULESTATEENUM_PAUSED { diff --git a/cmd/backup/policyv2/policy.go b/cmd/backup/policyv2/policy.go index cf2d2916..e4a9cd5f 100644 --- a/cmd/backup/policyv2/policy.go +++ b/cmd/backup/policyv2/policy.go @@ -144,7 +144,7 @@ var disablePolicyCmd = &cobra.Command{ } if len(resp.GetData()) < 1 { - logrus.Fatalln("No backup policies found for the given cluster") + logrus.Fatalln("No ACTIVE backup policies found to disable for the given cluster") } backupScheduleSpec := resp.GetData()[0].GetSpec() if backupScheduleSpec.GetState() == ybmclient.SCHEDULESTATEENUM_PAUSED { diff --git a/cmd/backup_test.go b/cmd/backup_test.go index 7c82a0d2..c1882f9b 100644 --- a/cmd/backup_test.go +++ b/cmd/backup_test.go @@ -68,9 +68,9 @@ var _ = Describe("Backup", func() { session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter) Expect(err).NotTo(HaveOccurred()) session.Wait(2) - Expect(session.Out).Should(gbytes.Say(fmt.Sprintf( - `ID Created On Expire On Clusters Description State Type Retains\(day\) -7d08a5c3-8097-48f0-8019-da236e876ab9 %s %s proficient-parrotfish scdasfdadf... SUCCEEDED MANUAL 25`, formatter.FormatDate("2023-01-17T08:31:35.818Z"), formatter.FormatDate("2023-02-11T08:31:35.818Z")))) + Expect(session.Out).Should(gbytes.Say(fmt.Sprintf(`ID Created On Inc Expire On Clusters State Type +c7742a97-cee0-449d-9c7c-4b934d9cf940 %s 🍕 %s mirthful-mole ✅ 🧑 +faaca956-b542-49ee-92a8-9f1e138d1311 %s 🟡 %s mirthful-mole ✅ 🧑`, formatter.FormatDate("2024-03-05T03:33:23.532Z"), formatter.FormatDateAndAddDays("2024-03-05T03:33:23.532Z", 8), formatter.FormatDate("2024-03-04T20:28:32.982Z"), formatter.FormatDateAndAddDays("2024-03-04T20:28:32.982Z", 1)))) session.Kill() }) diff --git a/cmd/test/fixtures/backups.json b/cmd/test/fixtures/backups.json index 7e61a4e2..4cff40bc 100644 --- a/cmd/test/fixtures/backups.json +++ b/cmd/test/fixtures/backups.json @@ -1,40 +1,83 @@ { "data": [ - { - "spec": { - "cluster_id": "6c7389b5-dbfa-4b79-a129-7afcbdd87f42", - "retention_period_in_days": 25, - "description": "scdasfdadfasdsad" - }, - "info": { - "id": "7d08a5c3-8097-48f0-8019-da236e876ab9", - "cluster_name": "proficient-parrotfish", - "state": "SUCCEEDED", - "action_type": "MANUAL", - "keyspace_info": [ - { - "table_type": "YSQL", - "keyspaces": [ - "yugabyte" - ] - } - ], - "size_in_bytes": 50397, - "deleted_on": "2023-02-11T08:33:18.699Z", - "completed_on": "2023-01-17T08:33:18.699Z", - "tablespaces": [], - "metadata": { - "created_on": "2023-01-17T08:31:35.818Z", - "updated_on": "2023-01-17T08:31:35.818Z" - } + { + "spec": { + "cluster_id": "d6954ca7-fc4f-4454-9ce2-8c2e10ed9deb", + "retention_period_in_days": 8, + "backup_type": "INCREMENTAL", + "description": "Backup of the cluster XYZ" + }, + "info": { + "id": "c7742a97-cee0-449d-9c7c-4b934d9cf940", + "cluster_name": "mirthful-mole", + "state": "SUCCEEDED", + "action_type": "MANUAL", + "keyspace_info": [ + { + "table_type": "YSQL", + "keyspaces": [ + "yugabyte" + ] } + ], + "size_in_bytes": 204684, + "deleted_on": "2024-03-13T03:34:36.330558Z", + "completed_on": "2024-03-05T03:34:36.330930Z", + "num_incremental_backups": null, + "last_incremental_backup_completed_on": null, + "last_full_backup_completed_on": null, + "backup_chain_size_in_bytes": 872830, + "backup_current_chain_size_in_bytes": 872830, + "tablespaces": [], + "base_backup_id": "faaca956-b542-49ee-92a8-9f1e138d1311", + "metadata": { + "created_on": "2024-03-05T03:33:23.532Z", + "updated_on": "2024-03-05T03:34:37.447Z" + } } + }, + { + "spec": { + "cluster_id": "d6954ca7-fc4f-4454-9ce2-8c2e10ed9deb", + "retention_period_in_days": 1, + "backup_type": "FULL", + "description": null + }, + "info": { + "id": "faaca956-b542-49ee-92a8-9f1e138d1311", + "cluster_name": "mirthful-mole", + "state": "SUCCEEDED", + "action_type": "MANUAL", + "keyspace_info": [ + { + "table_type": "YSQL", + "keyspaces": [ + "yugabyte" + ] + } + ], + "size_in_bytes": 668146, + "deleted_on": "2024-03-13T03:34:36.330558Z", + "completed_on": "2024-03-04T20:29:29.567924Z", + "num_incremental_backups": 1, + "last_incremental_backup_completed_on": "2024-03-05T03:34:36.330930Z", + "last_full_backup_completed_on": null, + "backup_chain_size_in_bytes": 872830, + "backup_current_chain_size_in_bytes": 668146, + "tablespaces": [], + "base_backup_id": null, + "metadata": { + "created_on": "2024-03-04T20:28:32.982Z", + "updated_on": "2024-03-05T03:34:39.070Z" + } + } + } ], "_metadata": { - "continuation_token": null, - "links": { - "self": "/api/public/v1/accounts/340af43a-8a7c-4659-9258-4876fd6a207b/projects/78d4459c-0f45-47a5-899a-45ddf43eba6e/backups", - "next": null - } + "continuation_token": null, + "links": { + "self": "/api/public/v1/accounts/f16a45ef-5081-4af1-ba45-50c98feaf027/projects/f2a38352-2deb-4bb1-8948-0a2eed0dc70b/backups?cluster_id=d6954ca7-fc4f-4454-9ce2-8c2e10ed9deb", + "next": null + } } -} \ No newline at end of file + } \ No newline at end of file diff --git a/internal/formatter/backup.go b/internal/formatter/backup.go index 6e50e070..026095ba 100644 --- a/internal/formatter/backup.go +++ b/internal/formatter/backup.go @@ -21,17 +21,20 @@ import ( "strconv" "time" + "github.com/enescakir/emoji" "github.com/sirupsen/logrus" ybmclient "github.com/yugabyte/yugabytedb-managed-go-client-internal" ) const ( - defaultBackupListing = "table {{.Id}}\t{{.CreatedOn}}\t{{.ExpireOn}}\t{{.ClusterName}}\t{{.Description}}\t{{.BackupState}}\t{{.BackupType}}\t{{.RetainInDays}}" + defaultBackupListing = "table {{.Id}}\t{{.CreatedOn}}\t{{.Incremental}}\t{{.ExpireOn}}\t{{.ClusterName}}\t{{.BackupState}}\t{{.BackupType}}" + incrementalHeader = "Inc" backupIdCreateOnHeader = "Created On" backupIdExpireOnHeader = "Expire On" backupIdHeader = "ID" backupTypeHeader = "Type" retainInDaysHeader = "Retains(day)" + sizeHeader = "Size" ) type BackupContext struct { @@ -77,10 +80,24 @@ func NewBackupContext() *BackupContext { "Description": descriptionHeader, "ExpireOn": backupIdExpireOnHeader, "RetainInDays": retainInDaysHeader, + "Incremental": incrementalHeader, + "Size": sizeHeader, } return &BackupCtx } +func (c *BackupContext) Incremental() string { + if *c.c.GetSpec().BackupType.Ptr() == ybmclient.BACKUPTYPEENUM_INCREMENTAL { + return emoji.Pizza.String() + } + return emoji.YellowCircle.String() +} + +func (c *BackupContext) Size() string { + // Convert the size to string + return strconv.FormatInt(*c.c.GetInfo().SizeInBytes.Get(), 10) +} + func (c *BackupContext) ExpireOn() string { CreatedOn := c.CreatedOn() if len(CreatedOn) > 0 { @@ -106,6 +123,9 @@ func (c *BackupContext) ClusterName() string { func (c *BackupContext) Description() string { if v, ok := c.c.Spec.GetDescriptionOk(); ok { + if v == nil { + return "" + } return Truncate(*v, 10) } return "" @@ -116,11 +136,27 @@ func (c *BackupContext) Id() string { } func (c *BackupContext) BackupState() string { - return string(*c.c.GetInfo().State) + switch *c.c.GetInfo().State { + case ybmclient.BACKUPSTATEENUM_SUCCEEDED: + return emoji.CheckMarkButton.String() + case ybmclient.BACKUPSTATEENUM_FAILED: + return emoji.CrossMark.String() + case ybmclient.BACKUPSTATEENUM_IN_PROGRESS: + return emoji.HourglassNotDone.String() + default: + return emoji.QuestionMark.String() + } } func (c *BackupContext) BackupType() string { - return string(*c.c.GetInfo().ActionType) + switch *c.c.GetInfo().ActionType { + case ybmclient.BACKUPACTIONTYPEENUM_MANUAL: + return emoji.Person.String() + case ybmclient.BACKUPACTIONTYPEENUM_SCHEDULED: + return emoji.Calendar.String() + default: + return emoji.QuestionMark.String() + } } func (c *BackupContext) RetainInDays() string { @@ -136,3 +172,8 @@ func FormatDate(dateToBeFormatted string) string { t, _ := time.Parse(time.RFC3339Nano, dateToBeFormatted) return t.Local().Format("2006-01-02,15:04") } + +func FormatDateAndAddDays(dateToBeFormatted string, days int) string { + t, _ := time.Parse(time.RFC3339Nano, dateToBeFormatted) + return t.Local().AddDate(0, 0, days).Format("2006-01-02,15:04") +}