Change printing of backup stats to single line (#4526)
Previously we were printing a table for a single item which, for one
was unnecessary, but this also make the output of a backup more
compact.
Before:
```
Logging to file: /home/meain/.cache/corso/logs/2023-10-20T10-21-23Z.log
Connecting to M365 done
Connecting to repository 1s done
Backing Up ∙ Teams Testing (meain)
Discovering items to backup 27s done
Libraries (TeamsTestingmeain) done (found 0 items)
Libraries (TeamsTestingmeain-Shared0) done (found 0 items)
Libraries (TeamsTestingmeain-Private2) done (found 0 items)
Messages 7s done (found 6 channels)
Backing up data 7s done
Backup complete ∙ 7b40dd40-f808-4d57-8e39-b4553e48dc5d
ID Bytes Uploaded Items Uploaded Items Skipped Errors
7b40dd40-f808-4d57-8e39-b4553e48dc5d 0 B 0 0 0
Completed Backups:
ID Started At Duration Status Resource Owner
7b40dd40-f808-4d57-8e39-b4553e48dc5d 2023-10-20T10:21:32Z 36.632747912s Completed Teams Testing (meain)
```
After:
```
Connecting to M365 done
Connecting to repository 1s done
Backing Up ∙ Teams Testing (meain)
Discovering items to backup 31s done
Libraries (TeamsTestingmeain) done (found 0 items)
Libraries (TeamsTestingmeain-Shared0) done (found 0 items)
Libraries (TeamsTestingmeain-Private2) done (found 0 items)
Messages 9s done (found 6 channels)
Backing up data 7s done
Backup complete ∙ ffb2f619-1cb7-4a11-b3e2-7300aa513c6a
Bytes Uploaded: 0 B | Items Uploaded: 0 | Items Skipped: 0 | Errors: 0
Completed Backups:
ID ID Started At Duration Status Resource Owner
ffb2f619-1cb7-4a11-b3e2-7300aa513c6a 2023-10-20T10:23:35Z 40.096203016s Completed Teams Testing (meain)
```
---
#### Does this PR need a docs update or release note?
- [x] ✅ Yes, it's included
- [ ] 🕐 Yes, but in a later PR
- [ ] ⛔ No
#### Type of change
<!--- Please check the type of change your PR introduces: --->
- [x] 🌻 Feature
- [ ] 🐛 Bugfix
- [ ] 🗺️ Documentation
- [ ] 🤖 Supportability/Tests
- [ ] 💻 CI/Deployment
- [ ] 🧹 Tech Debt/Cleanup
#### Issue(s)
<!-- Can reference multiple issues. Use one of the following "magic words" - "closes, fixes" to auto-close the Github issue. -->
* #<issue>
#### Test Plan
<!-- How will this be tested prior to merging.-->
- [ ] 💪 Manual
- [x] ⚡ Unit test
- [ ] 💚 E2E
This commit is contained in:
parent
b46f242bc4
commit
68256cf59f
@ -9,13 +9,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Added export support for emails in exchange backups as `.eml` files
|
- Added export support for emails in exchange backups as `.eml` files
|
||||||
|
- More colorful and informational cli output
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Change file extension of messages export to json to match the content
|
- Change file extension of messages export to json to match the content
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Handle OneDrive folders being deleted and recreated midway through a backup
|
- Handle OneDrive folders being deleted and recreated midway through a backup
|
||||||
- Automatically re-run a full delta query on incrmental if the prior backup is found to have malformed prior-state information.
|
- Automatically re-run a full delta query on incremental if the prior backup is found to have malformed prior-state information.
|
||||||
- Retry drive item permission downloads during long-running backups after the jwt token expires and refreshes.
|
- Retry drive item permission downloads during long-running backups after the jwt token expires and refreshes.
|
||||||
|
|
||||||
## [v0.15.0] (beta) - 2023-10-31
|
## [v0.15.0] (beta) - 2023-10-31
|
||||||
|
|||||||
@ -247,7 +247,7 @@ func genericCreateCommand(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(bups) > 0 {
|
if len(bups) > 0 {
|
||||||
Info(ctx, "Completed Backups:")
|
Info(ctx, "\nCompleted Backups:")
|
||||||
backup.PrintAll(ctx, bups)
|
backup.PrintAll(ctx, bups)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,6 +420,5 @@ func printBackupStats(ctx context.Context, r repository.Repositoryer, bid string
|
|||||||
logger.CtxErr(ctx, err).Error("finding backup immediately after backup operation completion")
|
logger.CtxErr(ctx, err).Error("finding backup immediately after backup operation completion")
|
||||||
}
|
}
|
||||||
|
|
||||||
b.ToPrintable().Stats.Print(ctx)
|
b.ToPrintable().Stats.PrintProperties(ctx)
|
||||||
Info(ctx, " ")
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,11 +46,12 @@ func (ev envVar) MinimumPrintable() any {
|
|||||||
return ev
|
return ev
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ev envVar) Headers() []string {
|
func (ev envVar) Headers(bool) []string {
|
||||||
|
// NOTE: skipID does not make sense in this context
|
||||||
return []string{ev.category, " "}
|
return []string{ev.category, " "}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ev envVar) Values() []string {
|
func (ev envVar) Values(bool) []string {
|
||||||
return []string{ev.name, ev.description}
|
return []string{ev.name, ev.description}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/tidwall/pretty"
|
"github.com/tidwall/pretty"
|
||||||
@ -178,11 +179,11 @@ func outf(ctx context.Context, w io.Writer, t string, s ...any) {
|
|||||||
type Printable interface {
|
type Printable interface {
|
||||||
minimumPrintabler
|
minimumPrintabler
|
||||||
// should list the property names of the values surfaced in Values()
|
// should list the property names of the values surfaced in Values()
|
||||||
Headers() []string
|
Headers(skipID bool) []string
|
||||||
// list of values for tabular or csv formatting
|
// list of values for tabular or csv formatting
|
||||||
// if the backing data is nil or otherwise missing,
|
// if the backing data is nil or otherwise missing,
|
||||||
// values should provide an empty string as opposed to skipping entries
|
// values should provide an empty string as opposed to skipping entries
|
||||||
Values() []string
|
Values(skipID bool) []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type minimumPrintabler interface {
|
type minimumPrintabler interface {
|
||||||
@ -206,6 +207,23 @@ func printItem(w io.Writer, p Printable) {
|
|||||||
outputTable(w, []Printable{p})
|
outputTable(w, []Printable{p})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ItemProperties prints the printable either as in a single line or a json
|
||||||
|
// The difference between this and Item is that this one does not print the ID
|
||||||
|
func ItemProperties(ctx context.Context, p Printable) {
|
||||||
|
printItemProperties(getRootCmd(ctx).OutOrStdout(), p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// print prints the printable items,
|
||||||
|
// according to the caller's requested format.
|
||||||
|
func printItemProperties(w io.Writer, p Printable) {
|
||||||
|
if outputAsJSON || outputAsJSONDebug {
|
||||||
|
outputJSON(w, p, outputAsJSONDebug)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outputOneLine(w, []Printable{p})
|
||||||
|
}
|
||||||
|
|
||||||
// All prints the slice of printable items,
|
// All prints the slice of printable items,
|
||||||
// according to the caller's requested format.
|
// according to the caller's requested format.
|
||||||
func All(ctx context.Context, ps ...Printable) {
|
func All(ctx context.Context, ps ...Printable) {
|
||||||
@ -240,12 +258,12 @@ func Table(ctx context.Context, ps []Printable) {
|
|||||||
// output to stdout the list of printable structs in a table
|
// output to stdout the list of printable structs in a table
|
||||||
func outputTable(w io.Writer, ps []Printable) {
|
func outputTable(w io.Writer, ps []Printable) {
|
||||||
t := table.Table{
|
t := table.Table{
|
||||||
Headers: ps[0].Headers(),
|
Headers: ps[0].Headers(false),
|
||||||
Rows: [][]string{},
|
Rows: [][]string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, p := range ps {
|
for _, p := range ps {
|
||||||
t.Rows = append(t.Rows, p.Values())
|
t.Rows = append(t.Rows, p.Values(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = t.WriteTable(
|
_ = t.WriteTable(
|
||||||
@ -309,3 +327,28 @@ func printPrettyJSON(w io.Writer, a any) {
|
|||||||
|
|
||||||
fmt.Fprintln(w, string(pretty.Pretty(bs)))
|
fmt.Fprintln(w, string(pretty.Pretty(bs)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
// One line
|
||||||
|
// -------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Output in the following format:
|
||||||
|
// Bytes Uploaded: 401 kB | Items Uploaded: 59 | Items Skipped: 0 | Errors: 0
|
||||||
|
func outputOneLine(w io.Writer, ps []Printable) {
|
||||||
|
headers := ps[0].Headers(true)
|
||||||
|
rows := [][]string{}
|
||||||
|
|
||||||
|
for _, p := range ps {
|
||||||
|
rows = append(rows, p.Values(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
printables := []string{}
|
||||||
|
|
||||||
|
for _, row := range rows {
|
||||||
|
for i, col := range row {
|
||||||
|
printables = append(printables, fmt.Sprintf("%s: %s", headers[i], col))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintln(w, strings.Join(printables, " | "))
|
||||||
|
}
|
||||||
|
|||||||
@ -173,6 +173,12 @@ func (b Backup) Print(ctx context.Context) {
|
|||||||
print.Item(ctx, b)
|
print.Item(ctx, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrintProperties writes the Backup to StdOut, in the format requested by the caller.
|
||||||
|
// Unlike Print, it skips the ID of the Backup
|
||||||
|
func (b Backup) PrintProperties(ctx context.Context) {
|
||||||
|
print.ItemProperties(ctx, b)
|
||||||
|
}
|
||||||
|
|
||||||
// PrintAll writes the slice of Backups to StdOut, in the format requested by the caller.
|
// PrintAll writes the slice of Backups to StdOut, in the format requested by the caller.
|
||||||
func PrintAll(ctx context.Context, bs []*Backup) {
|
func PrintAll(ctx context.Context, bs []*Backup) {
|
||||||
if len(bs) == 0 {
|
if len(bs) == 0 {
|
||||||
@ -218,19 +224,24 @@ func (b Backup) MinimumPrintable() any {
|
|||||||
|
|
||||||
// Headers returns the human-readable names of properties in a Backup
|
// Headers returns the human-readable names of properties in a Backup
|
||||||
// for printing out to a terminal in a columnar display.
|
// for printing out to a terminal in a columnar display.
|
||||||
func (b Backup) Headers() []string {
|
func (b Backup) Headers(skipID bool) []string {
|
||||||
return []string{
|
headers := []string{
|
||||||
"ID",
|
|
||||||
"Started At",
|
"Started At",
|
||||||
"Duration",
|
"Duration",
|
||||||
"Status",
|
"Status",
|
||||||
"Resource Owner",
|
"Resource Owner",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skipID {
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
return append([]string{"ID"}, headers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values returns the values matching the Headers list for printing
|
// Values returns the values matching the Headers list for printing
|
||||||
// out to a terminal in a columnar display.
|
// out to a terminal in a columnar display.
|
||||||
func (b Backup) Values() []string {
|
func (b Backup) Values(skipID bool) []string {
|
||||||
var (
|
var (
|
||||||
status = b.Status
|
status = b.Status
|
||||||
errCount = b.ErrorCount
|
errCount = b.ErrorCount
|
||||||
@ -281,13 +292,18 @@ func (b Backup) Values() []string {
|
|||||||
|
|
||||||
bs := b.toStats()
|
bs := b.toStats()
|
||||||
|
|
||||||
return []string{
|
values := []string{
|
||||||
string(b.ID),
|
|
||||||
dttm.FormatToTabularDisplay(b.StartedAt),
|
dttm.FormatToTabularDisplay(b.StartedAt),
|
||||||
bs.EndedAt.Sub(bs.StartedAt).String(),
|
bs.EndedAt.Sub(bs.StartedAt).String(),
|
||||||
status,
|
status,
|
||||||
name,
|
name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skipID {
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
return append([]string{string(b.ID)}, values...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----- print backup stats
|
// ----- print backup stats
|
||||||
@ -326,6 +342,12 @@ func (bs backupStats) Print(ctx context.Context) {
|
|||||||
print.Item(ctx, bs)
|
print.Item(ctx, bs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrintProperties writes the Backup to StdOut, in the format requested by the caller.
|
||||||
|
// Unlike Print, it skips the ID of backupStats
|
||||||
|
func (bs backupStats) PrintProperties(ctx context.Context) {
|
||||||
|
print.ItemProperties(ctx, bs)
|
||||||
|
}
|
||||||
|
|
||||||
// MinimumPrintable reduces the Backup to its minimally printable details.
|
// MinimumPrintable reduces the Backup to its minimally printable details.
|
||||||
func (bs backupStats) MinimumPrintable() any {
|
func (bs backupStats) MinimumPrintable() any {
|
||||||
return bs
|
return bs
|
||||||
@ -333,24 +355,34 @@ func (bs backupStats) MinimumPrintable() any {
|
|||||||
|
|
||||||
// Headers returns the human-readable names of properties in a Backup
|
// Headers returns the human-readable names of properties in a Backup
|
||||||
// for printing out to a terminal in a columnar display.
|
// for printing out to a terminal in a columnar display.
|
||||||
func (bs backupStats) Headers() []string {
|
func (bs backupStats) Headers(skipID bool) []string {
|
||||||
return []string{
|
headers := []string{
|
||||||
"ID",
|
|
||||||
"Bytes Uploaded",
|
"Bytes Uploaded",
|
||||||
"Items Uploaded",
|
"Items Uploaded",
|
||||||
"Items Skipped",
|
"Items Skipped",
|
||||||
"Errors",
|
"Errors",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skipID {
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
|
return append([]string{"ID"}, headers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values returns the values matching the Headers list for printing
|
// Values returns the values matching the Headers list for printing
|
||||||
// out to a terminal in a columnar display.
|
// out to a terminal in a columnar display.
|
||||||
func (bs backupStats) Values() []string {
|
func (bs backupStats) Values(skipID bool) []string {
|
||||||
return []string{
|
values := []string{
|
||||||
bs.ID,
|
|
||||||
humanize.Bytes(uint64(bs.BytesUploaded)),
|
humanize.Bytes(uint64(bs.BytesUploaded)),
|
||||||
strconv.Itoa(bs.ItemsWritten),
|
strconv.Itoa(bs.ItemsWritten),
|
||||||
strconv.Itoa(bs.ItemsSkipped),
|
strconv.Itoa(bs.ItemsSkipped),
|
||||||
strconv.Itoa(bs.ErrorCount),
|
strconv.Itoa(bs.ErrorCount),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skipID {
|
||||||
|
return values
|
||||||
|
}
|
||||||
|
|
||||||
|
return append([]string{bs.ID}, values...)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -173,11 +173,17 @@ func (suite *BackupUnitSuite) TestBackup_HeadersValues() {
|
|||||||
b.StartAndEndTime.CompletedAt = later
|
b.StartAndEndTime.CompletedAt = later
|
||||||
|
|
||||||
// single skipped malware
|
// single skipped malware
|
||||||
hs := b.Headers()
|
hs := b.Headers(false)
|
||||||
assert.Equal(t, expectHs, hs)
|
assert.Equal(t, expectHs, hs)
|
||||||
|
|
||||||
vs := b.Values()
|
vs := b.Values(false)
|
||||||
assert.Equal(t, expectVs, vs)
|
assert.Equal(t, expectVs, vs)
|
||||||
|
|
||||||
|
hs = b.Headers(true)
|
||||||
|
assert.Equal(t, expectHs[1:], hs)
|
||||||
|
|
||||||
|
vs = b.Values(true)
|
||||||
|
assert.Equal(t, expectVs[1:], vs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *BackupUnitSuite) TestBackup_HeadersValues_onlyResourceOwners() {
|
func (suite *BackupUnitSuite) TestBackup_HeadersValues_onlyResourceOwners() {
|
||||||
@ -209,11 +215,17 @@ func (suite *BackupUnitSuite) TestBackup_HeadersValues_onlyResourceOwners() {
|
|||||||
b.StartAndEndTime.CompletedAt = later
|
b.StartAndEndTime.CompletedAt = later
|
||||||
|
|
||||||
// single skipped malware
|
// single skipped malware
|
||||||
hs := b.Headers()
|
hs := b.Headers(false)
|
||||||
assert.Equal(t, expectHs, hs)
|
assert.Equal(t, expectHs, hs)
|
||||||
|
|
||||||
vs := b.Values()
|
vs := b.Values(false)
|
||||||
assert.Equal(t, expectVs, vs)
|
assert.Equal(t, expectVs, vs)
|
||||||
|
|
||||||
|
hs = b.Headers(true)
|
||||||
|
assert.Equal(t, expectHs[1:], hs)
|
||||||
|
|
||||||
|
vs = b.Values(true)
|
||||||
|
assert.Equal(t, expectVs[1:], vs)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *BackupUnitSuite) TestBackup_Values_statusVariations() {
|
func (suite *BackupUnitSuite) TestBackup_Values_statusVariations() {
|
||||||
@ -297,8 +309,11 @@ func (suite *BackupUnitSuite) TestBackup_Values_statusVariations() {
|
|||||||
}
|
}
|
||||||
for _, test := range table {
|
for _, test := range table {
|
||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
result := test.bup.Values()
|
result := test.bup.Values(false)
|
||||||
assert.Equal(suite.T(), test.expect, result[3], "status value")
|
assert.Equal(suite.T(), test.expect, result[3], "status value")
|
||||||
|
|
||||||
|
result = test.bup.Values(true)
|
||||||
|
assert.Equal(suite.T(), test.expect, result[2], "status value")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,7 +370,8 @@ func (suite *BackupUnitSuite) TestStats_headersValues() {
|
|||||||
"Errors",
|
"Errors",
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, expectHeaders, s.Headers())
|
assert.Equal(t, expectHeaders, s.Headers(false))
|
||||||
|
assert.Equal(t, expectHeaders[1:], s.Headers(true))
|
||||||
|
|
||||||
expectValues := []string{
|
expectValues := []string{
|
||||||
"id",
|
"id",
|
||||||
@ -365,5 +381,6 @@ func (suite *BackupUnitSuite) TestStats_headersValues() {
|
|||||||
strconv.Itoa(b.ErrorCount),
|
strconv.Itoa(b.ErrorCount),
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, expectValues, s.Values())
|
assert.Equal(t, expectValues, s.Values(false))
|
||||||
|
assert.Equal(t, expectValues[1:], s.Values(true))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -174,10 +174,15 @@ func (suite *DetailsUnitSuite) TestDetailsEntry_HeadersValues() {
|
|||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
hs := test.entry.Headers()
|
hs := test.entry.Headers(false)
|
||||||
assert.Equal(t, test.expectHs, hs)
|
assert.Equal(t, test.expectHs, hs)
|
||||||
vs := test.entry.Values()
|
vs := test.entry.Values(false)
|
||||||
assert.Equal(t, test.expectVs, vs)
|
assert.Equal(t, test.expectVs, vs)
|
||||||
|
|
||||||
|
hs = test.entry.Headers(true)
|
||||||
|
assert.Equal(t, test.expectHs[1:], hs)
|
||||||
|
vs = test.entry.Values(true)
|
||||||
|
assert.Equal(t, test.expectVs[1:], vs)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,55 +140,63 @@ func (de Entry) MinimumPrintable() any {
|
|||||||
|
|
||||||
// Headers returns the human-readable names of properties in a DetailsEntry
|
// Headers returns the human-readable names of properties in a DetailsEntry
|
||||||
// for printing out to a terminal in a columnar display.
|
// for printing out to a terminal in a columnar display.
|
||||||
func (de Entry) Headers() []string {
|
func (de Entry) Headers(skipID bool) []string {
|
||||||
hs := []string{"ID"}
|
hs := []string{}
|
||||||
|
|
||||||
if de.ItemInfo.Folder != nil {
|
if de.ItemInfo.Folder != nil {
|
||||||
hs = append(hs, de.ItemInfo.Folder.Headers()...)
|
hs = de.ItemInfo.Folder.Headers()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.Exchange != nil {
|
if de.ItemInfo.Exchange != nil {
|
||||||
hs = append(hs, de.ItemInfo.Exchange.Headers()...)
|
hs = de.ItemInfo.Exchange.Headers()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.SharePoint != nil {
|
if de.ItemInfo.SharePoint != nil {
|
||||||
hs = append(hs, de.ItemInfo.SharePoint.Headers()...)
|
hs = de.ItemInfo.SharePoint.Headers()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.OneDrive != nil {
|
if de.ItemInfo.OneDrive != nil {
|
||||||
hs = append(hs, de.ItemInfo.OneDrive.Headers()...)
|
hs = de.ItemInfo.OneDrive.Headers()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.Groups != nil {
|
if de.ItemInfo.Groups != nil {
|
||||||
hs = append(hs, de.ItemInfo.Groups.Headers()...)
|
hs = de.ItemInfo.Groups.Headers()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skipID {
|
||||||
return hs
|
return hs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return append([]string{"ID"}, hs...)
|
||||||
|
}
|
||||||
|
|
||||||
// Values returns the values matching the Headers list.
|
// Values returns the values matching the Headers list.
|
||||||
func (de Entry) Values() []string {
|
func (de Entry) Values(skipID bool) []string {
|
||||||
vs := []string{de.ShortRef}
|
vs := []string{}
|
||||||
|
|
||||||
if de.ItemInfo.Folder != nil {
|
if de.ItemInfo.Folder != nil {
|
||||||
vs = append(vs, de.ItemInfo.Folder.Values()...)
|
vs = de.ItemInfo.Folder.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.Exchange != nil {
|
if de.ItemInfo.Exchange != nil {
|
||||||
vs = append(vs, de.ItemInfo.Exchange.Values()...)
|
vs = de.ItemInfo.Exchange.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.SharePoint != nil {
|
if de.ItemInfo.SharePoint != nil {
|
||||||
vs = append(vs, de.ItemInfo.SharePoint.Values()...)
|
vs = de.ItemInfo.SharePoint.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.OneDrive != nil {
|
if de.ItemInfo.OneDrive != nil {
|
||||||
vs = append(vs, de.ItemInfo.OneDrive.Values()...)
|
vs = de.ItemInfo.OneDrive.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
if de.ItemInfo.Groups != nil {
|
if de.ItemInfo.Groups != nil {
|
||||||
vs = append(vs, de.ItemInfo.Groups.Values()...)
|
vs = de.ItemInfo.Groups.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if skipID {
|
||||||
return vs
|
return vs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return append([]string{de.ShortRef}, vs...)
|
||||||
|
}
|
||||||
|
|||||||
@ -42,12 +42,13 @@ func (a Alert) MinimumPrintable() any {
|
|||||||
|
|
||||||
// Headers returns the human-readable names of properties of a skipped Item
|
// Headers returns the human-readable names of properties of a skipped Item
|
||||||
// for printing out to a terminal.
|
// for printing out to a terminal.
|
||||||
func (a Alert) Headers() []string {
|
func (a Alert) Headers(bool) []string {
|
||||||
|
// NOTE: skipID does not make sense in this context and is skipped
|
||||||
return []string{"Action", "Message", "Container", "Name", "ID"}
|
return []string{"Action", "Message", "Container", "Name", "ID"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values populates the printable values matching the Headers list.
|
// Values populates the printable values matching the Headers list.
|
||||||
func (a Alert) Values() []string {
|
func (a Alert) Values(bool) []string {
|
||||||
var cn string
|
var cn string
|
||||||
|
|
||||||
acn, ok := a.Item.Additional[AddtlContainerName]
|
acn, ok := a.Item.Additional[AddtlContainerName]
|
||||||
|
|||||||
@ -81,8 +81,11 @@ func (suite *AlertUnitSuite) TestAlert_HeadersValues() {
|
|||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
assert.Equal(t, []string{"Action", "Message", "Container", "Name", "ID"}, test.alert.Headers())
|
assert.Equal(t, []string{"Action", "Message", "Container", "Name", "ID"}, test.alert.Headers(false))
|
||||||
assert.Equal(t, test.expect, test.alert.Values())
|
assert.Equal(t, test.expect, test.alert.Values(false))
|
||||||
|
|
||||||
|
assert.Equal(t, []string{"Action", "Message", "Container", "Name", "ID"}, test.alert.Headers(true))
|
||||||
|
assert.Equal(t, test.expect, test.alert.Values(true))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -491,11 +491,12 @@ func (pec printableErrCore) MinimumPrintable() any {
|
|||||||
return pec
|
return pec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pec printableErrCore) Headers() []string {
|
func (pec printableErrCore) Headers(bool) []string {
|
||||||
|
// NOTE: skipID does not make sense in this context
|
||||||
return []string{"Error"}
|
return []string{"Error"}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pec printableErrCore) Values() []string {
|
func (pec printableErrCore) Values(bool) []string {
|
||||||
if pec.ErrCore == nil {
|
if pec.ErrCore == nil {
|
||||||
return []string{"<nil>"}
|
return []string{"<nil>"}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -103,12 +103,13 @@ func (i Item) MinimumPrintable() any {
|
|||||||
|
|
||||||
// Headers returns the human-readable names of properties of an Item
|
// Headers returns the human-readable names of properties of an Item
|
||||||
// for printing out to a terminal.
|
// for printing out to a terminal.
|
||||||
func (i Item) Headers() []string {
|
func (i Item) Headers(bool) []string {
|
||||||
|
// NOTE: skipID does not make sense in this context
|
||||||
return []string{"Action", "Type", "Name", "Container", "Cause"}
|
return []string{"Action", "Type", "Name", "Container", "Cause"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values populates the printable values matching the Headers list.
|
// Values populates the printable values matching the Headers list.
|
||||||
func (i Item) Values() []string {
|
func (i Item) Values(bool) []string {
|
||||||
var cn string
|
var cn string
|
||||||
|
|
||||||
acn, ok := i.Additional[AddtlContainerName]
|
acn, ok := i.Additional[AddtlContainerName]
|
||||||
|
|||||||
@ -149,8 +149,11 @@ func (suite *ItemUnitSuite) TestItem_HeadersValues() {
|
|||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
assert.Equal(t, []string{"Action", "Type", "Name", "Container", "Cause"}, test.item.Headers())
|
assert.Equal(t, []string{"Action", "Type", "Name", "Container", "Cause"}, test.item.Headers(false))
|
||||||
assert.Equal(t, test.expect, test.item.Values())
|
assert.Equal(t, test.expect, test.item.Values(false))
|
||||||
|
|
||||||
|
assert.Equal(t, []string{"Action", "Type", "Name", "Container", "Cause"}, test.item.Headers(true))
|
||||||
|
assert.Equal(t, test.expect, test.item.Values(true))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -76,12 +76,13 @@ func (s Skipped) MinimumPrintable() any {
|
|||||||
|
|
||||||
// Headers returns the human-readable names of properties of a skipped Item
|
// Headers returns the human-readable names of properties of a skipped Item
|
||||||
// for printing out to a terminal.
|
// for printing out to a terminal.
|
||||||
func (s Skipped) Headers() []string {
|
func (s Skipped) Headers(bool) []string {
|
||||||
|
// NOTE: skipID does not make sense in this context
|
||||||
return []string{"Action", "Type", "Name", "Container", "Cause"}
|
return []string{"Action", "Type", "Name", "Container", "Cause"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values populates the printable values matching the Headers list.
|
// Values populates the printable values matching the Headers list.
|
||||||
func (s Skipped) Values() []string {
|
func (s Skipped) Values(bool) []string {
|
||||||
var cn string
|
var cn string
|
||||||
|
|
||||||
acn, ok := s.Item.Additional[AddtlContainerName]
|
acn, ok := s.Item.Additional[AddtlContainerName]
|
||||||
|
|||||||
@ -120,8 +120,11 @@ func (suite *SkippedUnitSuite) TestSkipped_HeadersValues() {
|
|||||||
suite.Run(test.name, func() {
|
suite.Run(test.name, func() {
|
||||||
t := suite.T()
|
t := suite.T()
|
||||||
|
|
||||||
assert.Equal(t, []string{"Action", "Type", "Name", "Container", "Cause"}, test.skip.Headers())
|
assert.Equal(t, []string{"Action", "Type", "Name", "Container", "Cause"}, test.skip.Headers(false))
|
||||||
assert.Equal(t, test.expect, test.skip.Values())
|
assert.Equal(t, test.expect, test.skip.Values(false))
|
||||||
|
|
||||||
|
assert.Equal(t, []string{"Action", "Type", "Name", "Container", "Cause"}, test.skip.Headers(true))
|
||||||
|
assert.Equal(t, test.expect, test.skip.Values(true))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user