refactor(cli): DRY up Namespace and Resource array formatting in desc… (#10112)

* refactor(cli): DRY up Namespace and Resource array formatting in describers

Signed-off-by: shellyco-code <shellychahar57@gmail.com>

* Add unit test for JoinStringWithFallback

Signed-off-by: shellyco-code <shellyco-code@users.noreply.github.com>

---------

Signed-off-by: shellyco-code <shellychahar57@gmail.com>
Signed-off-by: shellyco-code <shellyco-code@users.noreply.github.com>
Co-authored-by: shellyco-code <shellyco-code@users.noreply.github.com>
This commit is contained in:
Shelly Chahar
2026-09-17 15:41:52 +08:00
committed by GitHub
co-authored by shellyco-code
parent fa01151214
commit 3721f043f0
5 changed files with 74 additions and 148 deletions
+13 -76
View File
@@ -154,68 +154,26 @@ func DescribeUploaderConfigForBackup(d *Describer, spec velerov1api.BackupSpec)
// DescribeBackupSpec describes a backup spec in human-readable format.
func DescribeBackupSpec(d *Describer, spec velerov1api.BackupSpec) {
// TODO make a helper for this and use it in all the describers.
d.Printf("Namespaces:\n")
var s string
if len(spec.IncludedNamespaces) == 0 {
s = "*"
} else {
s = strings.Join(spec.IncludedNamespaces, ", ")
}
d.Printf("\tIncluded:\t%s\n", s)
if len(spec.ExcludedNamespaces) == 0 {
s = emptyDisplay
} else {
s = strings.Join(spec.ExcludedNamespaces, ", ")
}
d.Printf("\tExcluded:\t%s\n", s)
d.Printf("\tIncluded:\t%s\n", JoinStringWithFallback(spec.IncludedNamespaces, "*"))
d.Printf("\tExcluded:\t%s\n", JoinStringWithFallback(spec.ExcludedNamespaces, emptyDisplay))
d.Println()
d.Printf("Resources:\n")
if collections.UseOldResourceFilters(spec) {
if len(spec.IncludedResources) == 0 {
s = "*"
} else {
s = strings.Join(spec.IncludedResources, ", ")
}
d.Printf("\tIncluded:\t%s\n", s)
if len(spec.ExcludedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(spec.ExcludedResources, ", ")
}
d.Printf("\tExcluded:\t%s\n", s)
d.Printf("\tIncluded:\t%s\n", JoinStringWithFallback(spec.IncludedResources, "*"))
d.Printf("\tExcluded:\t%s\n", JoinStringWithFallback(spec.ExcludedResources, emptyDisplay))
d.Printf("\tCluster-scoped:\t%s\n", BoolPointerString(spec.IncludeClusterResources, "excluded", "included", "auto"))
} else {
if len(spec.IncludedClusterScopedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(spec.IncludedClusterScopedResources, ", ")
}
d.Printf("\tIncluded cluster-scoped:\t%s\n", s)
if len(spec.ExcludedClusterScopedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(spec.ExcludedClusterScopedResources, ", ")
}
d.Printf("\tExcluded cluster-scoped:\t%s\n", s)
d.Printf("\tIncluded cluster-scoped:\t%s\n", JoinStringWithFallback(spec.IncludedClusterScopedResources, emptyDisplay))
d.Printf("\tExcluded cluster-scoped:\t%s\n", JoinStringWithFallback(spec.ExcludedClusterScopedResources, emptyDisplay))
if len(spec.IncludedNamespaceScopedResources) == 0 {
s = "*"
} else {
s = strings.Join(spec.IncludedNamespaceScopedResources, ", ")
}
d.Printf("\tIncluded namespace-scoped:\t%s\n", s)
if len(spec.ExcludedNamespaceScopedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(spec.ExcludedNamespaceScopedResources, ", ")
}
d.Printf("\tExcluded namespace-scoped:\t%s\n", s)
d.Printf("\tIncluded namespace-scoped:\t%s\n", JoinStringWithFallback(spec.IncludedNamespaceScopedResources, "*"))
d.Printf("\tExcluded namespace-scoped:\t%s\n", JoinStringWithFallback(spec.ExcludedNamespaceScopedResources, emptyDisplay))
}
d.Println()
s = emptyDisplay
s := emptyDisplay
if spec.LabelSelector != nil {
s = metav1.FormatLabelSelector(spec.LabelSelector)
}
@@ -269,34 +227,13 @@ func DescribeBackupSpec(d *Describer, spec velerov1api.BackupSpec) {
for _, backupResourceHookSpec := range spec.Hooks.Resources {
d.Printf("\t\t%s:\n", backupResourceHookSpec.Name)
d.Printf("\t\t\tNamespaces:\n")
var s string
if len(backupResourceHookSpec.IncludedNamespaces) == 0 {
s = "*"
} else {
s = strings.Join(backupResourceHookSpec.IncludedNamespaces, ", ")
}
d.Printf("\t\t\t\tIncluded:\t%s\n", s)
if len(backupResourceHookSpec.ExcludedNamespaces) == 0 {
s = emptyDisplay
} else {
s = strings.Join(backupResourceHookSpec.ExcludedNamespaces, ", ")
}
d.Printf("\t\t\t\tExcluded:\t%s\n", s)
d.Printf("\t\t\t\tIncluded:\t%s\n", JoinStringWithFallback(backupResourceHookSpec.IncludedNamespaces, "*"))
d.Printf("\t\t\t\tExcluded:\t%s\n", JoinStringWithFallback(backupResourceHookSpec.ExcludedNamespaces, emptyDisplay))
d.Println()
d.Printf("\t\t\tResources:\n")
if len(backupResourceHookSpec.IncludedResources) == 0 {
s = "*"
} else {
s = strings.Join(backupResourceHookSpec.IncludedResources, ", ")
}
d.Printf("\t\t\t\tIncluded:\t%s\n", s)
if len(backupResourceHookSpec.ExcludedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(backupResourceHookSpec.ExcludedResources, ", ")
}
d.Printf("\t\t\t\tExcluded:\t%s\n", s)
d.Printf("\t\t\t\tIncluded:\t%s\n", JoinStringWithFallback(backupResourceHookSpec.IncludedResources, "*"))
d.Printf("\t\t\t\tExcluded:\t%s\n", JoinStringWithFallback(backupResourceHookSpec.ExcludedResources, emptyDisplay))
d.Println()
s = emptyDisplay
@@ -83,35 +83,14 @@ func DescribeBackupSpecInSF(d *StructuredDescriber, spec velerov1api.BackupSpec)
// describe namespaces
namespaceInfo := make(map[string]any)
if len(spec.IncludedNamespaces) == 0 {
s = "*"
} else {
s = strings.Join(spec.IncludedNamespaces, ", ")
}
namespaceInfo["included"] = s
if len(spec.ExcludedNamespaces) == 0 {
s = emptyDisplay
} else {
s = strings.Join(spec.ExcludedNamespaces, ", ")
}
namespaceInfo["excluded"] = s
namespaceInfo["included"] = JoinStringWithFallback(spec.IncludedNamespaces, "*")
namespaceInfo["excluded"] = JoinStringWithFallback(spec.ExcludedNamespaces, emptyDisplay)
backupSpecInfo["namespaces"] = namespaceInfo
// describe resources
resourcesInfo := make(map[string]string)
if len(spec.IncludedResources) == 0 {
s = "*"
} else {
s = strings.Join(spec.IncludedResources, ", ")
}
resourcesInfo["included"] = s
if len(spec.ExcludedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(spec.ExcludedResources, ", ")
}
resourcesInfo["excluded"] = s
resourcesInfo["included"] = JoinStringWithFallback(spec.IncludedResources, "*")
resourcesInfo["excluded"] = JoinStringWithFallback(spec.ExcludedResources, emptyDisplay)
resourcesInfo["clusterScoped"] = BoolPointerString(spec.IncludeClusterResources, "excluded", "included", "auto")
backupSpecInfo["resources"] = resourcesInfo
@@ -153,33 +132,13 @@ func DescribeBackupSpecInSF(d *StructuredDescriber, spec velerov1api.BackupSpec)
ResourceDetails := make(map[string]any)
var s string
namespaceInfo := make(map[string]string)
if len(backupResourceHookSpec.IncludedNamespaces) == 0 {
s = "*"
} else {
s = strings.Join(backupResourceHookSpec.IncludedNamespaces, ", ")
}
namespaceInfo["included"] = s
if len(backupResourceHookSpec.ExcludedNamespaces) == 0 {
s = emptyDisplay
} else {
s = strings.Join(backupResourceHookSpec.ExcludedNamespaces, ", ")
}
namespaceInfo["excluded"] = s
namespaceInfo["included"] = JoinStringWithFallback(backupResourceHookSpec.IncludedNamespaces, "*")
namespaceInfo["excluded"] = JoinStringWithFallback(backupResourceHookSpec.ExcludedNamespaces, emptyDisplay)
ResourceDetails["namespaces"] = namespaceInfo
resourcesInfo := make(map[string]string)
if len(backupResourceHookSpec.IncludedResources) == 0 {
s = "*"
} else {
s = strings.Join(backupResourceHookSpec.IncludedResources, ", ")
}
resourcesInfo["included"] = s
if len(backupResourceHookSpec.ExcludedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(backupResourceHookSpec.ExcludedResources, ", ")
}
resourcesInfo["excluded"] = s
resourcesInfo["included"] = JoinStringWithFallback(backupResourceHookSpec.IncludedResources, "*")
resourcesInfo["excluded"] = JoinStringWithFallback(backupResourceHookSpec.ExcludedResources, emptyDisplay)
ResourceDetails["resources"] = resourcesInfo
s = emptyDisplay
+8
View File
@@ -110,6 +110,14 @@ func (d *Describer) DescribeSlice(preindent int, name string, s []string) {
}
}
// JoinStringWithFallback returns a comma-separated string of the slice, or the fallback string if the slice is empty.
func JoinStringWithFallback(s []string, fallback string) string {
if len(s) == 0 {
return fallback
}
return strings.Join(s, ", ")
}
// BoolPointerString returns the appropriate string based on the bool pointer's value.
func BoolPointerString(b *bool, falseString, trueString, nilString string) string {
if b == nil {
+40
View File
@@ -166,3 +166,43 @@ func TestStructuredDescriber_DescribeMetadata(t *testing.T) {
assert.True(t, reflect.DeepEqual(expect, d.output))
}
func TestJoinStringWithFallback(t *testing.T) {
testcases := []struct {
name string
input []string
fallback string
expect string
}{
{
name: "empty slice",
input: []string{},
fallback: "fallback-str",
expect: "fallback-str",
},
{
name: "nil slice",
input: nil,
fallback: "fallback-str",
expect: "fallback-str",
},
{
name: "single element",
input: []string{"a"},
fallback: "fallback-str",
expect: "a",
},
{
name: "multiple elements",
input: []string{"a", "b", "c"},
fallback: "fallback-str",
expect: "a, b, c",
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
got := JoinStringWithFallback(tc.input, tc.fallback)
assert.Equal(t, tc.expect, got)
})
}
}
+5 -23
View File
@@ -118,35 +118,17 @@ func DescribeRestore(
d.Println()
d.Printf("Namespaces:\n")
var s string
if len(restore.Spec.IncludedNamespaces) == 0 {
s = JoinStringWithFallback(restore.Spec.IncludedNamespaces, "all namespaces found in the backup")
if s == "*" {
s = "all namespaces found in the backup"
} else if len(restore.Spec.IncludedNamespaces) == 1 && restore.Spec.IncludedNamespaces[0] == "*" {
s = "all namespaces found in the backup"
} else {
s = strings.Join(restore.Spec.IncludedNamespaces, ", ")
}
d.Printf("\tIncluded:\t%s\n", s)
if len(restore.Spec.ExcludedNamespaces) == 0 {
s = emptyDisplay
} else {
s = strings.Join(restore.Spec.ExcludedNamespaces, ", ")
}
d.Printf("\tExcluded:\t%s\n", s)
d.Printf("\tExcluded:\t%s\n", JoinStringWithFallback(restore.Spec.ExcludedNamespaces, emptyDisplay))
d.Println()
d.Printf("Resources:\n")
if len(restore.Spec.IncludedResources) == 0 {
s = "*"
} else {
s = strings.Join(restore.Spec.IncludedResources, ", ")
}
d.Printf("\tIncluded:\t%s\n", s)
if len(restore.Spec.ExcludedResources) == 0 {
s = emptyDisplay
} else {
s = strings.Join(restore.Spec.ExcludedResources, ", ")
}
d.Printf("\tExcluded:\t%s\n", s)
d.Printf("\tIncluded:\t%s\n", JoinStringWithFallback(restore.Spec.IncludedResources, "*"))
d.Printf("\tExcluded:\t%s\n", JoinStringWithFallback(restore.Spec.ExcludedResources, emptyDisplay))
d.Printf("\tCluster-scoped:\t%s\n", BoolPointerString(restore.Spec.IncludeClusterResources, "excluded", "included", "auto"))