feat(cli): improved formatting of 'policy show' outputs (#1767)

This commit is contained in:
Jarek Kowalski
2022-02-22 22:21:48 -08:00
committed by GitHub
parent c9d9bf2de2
commit 9d63e56bb9
5 changed files with 318 additions and 169 deletions

View File

@@ -13,7 +13,10 @@ rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst
go_source_dirs=cli fs internal repo snapshot
all_go_sources=$(foreach d,$(go_source_dirs),$(call rwildcard,$d/,*.go)) $(wildcard *.go)
all: test lint vet integration-tests
all:
$(MAKE) test
$(MAKE) lint
$(MAKE) integration-tests
include tools/tools.mk

View File

@@ -1,6 +1,7 @@
package cli_test
import (
"strings"
"testing"
"github.com/stretchr/testify/require"
@@ -16,23 +17,25 @@ func TestSetLoggingPolicy(t *testing.T) {
e.RunAndExpectSuccess(t, "repo", "create", "filesystem", "--path", e.RepoDir)
lines := e.RunAndExpectSuccess(t, "policy", "show", "--global")
require.Contains(t, lines, " Directory snapshotted: 5 (defined for this target)")
require.Contains(t, lines, " Directory ignored: 5 (defined for this target)")
require.Contains(t, lines, " Entry snapshotted: 0 (defined for this target)")
require.Contains(t, lines, " Entry ignored: 5 (defined for this target)")
require.Contains(t, lines, " Entry cache hit 0 (defined for this target)")
require.Contains(t, lines, " Entry cache miss 0 (defined for this target)")
lines = compressSpaces(lines)
require.Contains(t, lines, " Directory snapshotted: 5 (defined for this target)")
require.Contains(t, lines, " Directory ignored: 5 (defined for this target)")
require.Contains(t, lines, " Entry snapshotted: 0 (defined for this target)")
require.Contains(t, lines, " Entry ignored: 5 (defined for this target)")
require.Contains(t, lines, " Entry cache hit: 0 (defined for this target)")
require.Contains(t, lines, " Entry cache miss: 0 (defined for this target)")
// make some directory we'll be setting policy on
td := testutil.TempDirectory(t)
lines = e.RunAndExpectSuccess(t, "policy", "show", td)
require.Contains(t, lines, " Directory snapshotted: 5 inherited from (global)")
require.Contains(t, lines, " Directory ignored: 5 inherited from (global)")
require.Contains(t, lines, " Entry snapshotted: 0 inherited from (global)")
require.Contains(t, lines, " Entry ignored: 5 inherited from (global)")
require.Contains(t, lines, " Entry cache hit 0 inherited from (global)")
require.Contains(t, lines, " Entry cache miss 0 inherited from (global)")
lines = compressSpaces(lines)
require.Contains(t, lines, " Directory snapshotted: 5 inherited from (global)")
require.Contains(t, lines, " Directory ignored: 5 inherited from (global)")
require.Contains(t, lines, " Entry snapshotted: 0 inherited from (global)")
require.Contains(t, lines, " Entry ignored: 5 inherited from (global)")
require.Contains(t, lines, " Entry cache hit: 0 inherited from (global)")
require.Contains(t, lines, " Entry cache miss: 0 inherited from (global)")
e.RunAndExpectSuccess(t, "policy", "set", td,
"--log-dir-snapshotted=1",
@@ -43,17 +46,19 @@ func TestSetLoggingPolicy(t *testing.T) {
"--log-entry-cache-miss=6")
lines = e.RunAndExpectSuccess(t, "policy", "show", td)
require.Contains(t, lines, " Directory snapshotted: 1 (defined for this target)")
require.Contains(t, lines, " Directory ignored: 2 (defined for this target)")
require.Contains(t, lines, " Entry snapshotted: 3 (defined for this target)")
require.Contains(t, lines, " Entry ignored: 4 (defined for this target)")
require.Contains(t, lines, " Entry cache hit 5 (defined for this target)")
require.Contains(t, lines, " Entry cache miss 6 (defined for this target)")
lines = compressSpaces(lines)
require.Contains(t, lines, " Directory snapshotted: 1 (defined for this target)")
require.Contains(t, lines, " Directory ignored: 2 (defined for this target)")
require.Contains(t, lines, " Entry snapshotted: 3 (defined for this target)")
require.Contains(t, lines, " Entry ignored: 4 (defined for this target)")
require.Contains(t, lines, " Entry cache hit: 5 (defined for this target)")
require.Contains(t, lines, " Entry cache miss: 6 (defined for this target)")
e.RunAndExpectSuccess(t, "policy", "set", td, "--log-entry-ignored=inherit")
lines = e.RunAndExpectSuccess(t, "policy", "show", td)
require.Contains(t, lines, " Entry ignored: 5 inherited from (global)")
lines = compressSpaces(lines)
require.Contains(t, lines, " Entry ignored: 5 inherited from (global)")
e.RunAndExpectFailure(t, "policy", "set", td, "--log-dir-snapshotted=-1")
e.RunAndExpectFailure(t, "policy", "set", td, "--log-dir-ignored=11")
@@ -62,3 +67,17 @@ func TestSetLoggingPolicy(t *testing.T) {
e.RunAndExpectFailure(t, "policy", "set", td, "--log-entry-cache-hit=-1")
e.RunAndExpectFailure(t, "policy", "set", td, "--log-entry-cache-miss=-1")
}
func compressSpaces(lines []string) []string {
var result []string
for _, l := range lines {
for l2 := strings.ReplaceAll(l, " ", " "); l != l2; l2 = strings.ReplaceAll(l, " ", " ") {
l = l2
}
result = append(result, l)
}
return result
}

View File

@@ -4,6 +4,7 @@
"context"
"fmt"
"strings"
"time"
"github.com/pkg/errors"
@@ -51,6 +52,59 @@ func (c *commandPolicyShow) run(ctx context.Context, rep repo.Repository) error
return nil
}
type policyTableRow struct {
name string
value string
def string
}
func alignedPolicyTableRows(v []policyTableRow) string {
var nameValueLen int
const (
nameValueSpace = " "
defSpace = " "
)
for _, it := range v {
if it.value == "" {
continue
}
t := it.name
if it.value != "" {
t += nameValueSpace + it.value
}
if len(t) > nameValueLen {
nameValueLen = len(t)
}
}
var lines []string
for _, it := range v {
l := it.name
if it.value != "" || it.def != "" {
if spaces := nameValueLen - len(l) - len(it.value); spaces > 0 {
l += strings.Repeat(" ", spaces)
}
l += it.value
}
if it.def != "" {
l += defSpace
l += it.def
}
lines = append(lines, l)
}
return strings.Join(lines, "\n")
}
func definitionPointToString(target, src snapshot.SourceInfo) string {
if src == target {
return "(defined for this target)"
@@ -60,253 +114,309 @@ func definitionPointToString(target, src snapshot.SourceInfo) string {
}
func printPolicy(out *textOutput, p *policy.Policy, def *policy.Definition) {
out.printStdout("Policy for %v:\n\n", p.Target())
var rows []policyTableRow
printRetentionPolicy(out, p, def)
out.printStdout("\n")
printFilesPolicy(out, p, def)
out.printStdout("\n")
printErrorHandlingPolicy(out, p, def)
out.printStdout("\n")
printSchedulingPolicy(out, p, def)
out.printStdout("\n")
printCompressionPolicy(out, p, def)
out.printStdout("\n")
printActions(out, p, def)
out.printStdout("\n")
printLoggingPolicy(out, p, def)
rows = appendRetentionPolicyRows(rows, p, def)
rows = append(rows, policyTableRow{})
rows = appendFilesPolicyValue(rows, p, def)
rows = append(rows, policyTableRow{})
rows = appendErrorHandlingPolicyRows(rows, p, def)
rows = append(rows, policyTableRow{})
rows = appendSchedulingPolicyRows(rows, p, def)
rows = append(rows, policyTableRow{})
rows = appendCompressionPolicyRows(rows, p, def)
rows = append(rows, policyTableRow{})
rows = appendActionsPolicyRows(rows, p, def)
rows = append(rows, policyTableRow{})
rows = appendLoggingPolicyRows(rows, p, def)
out.printStdout("Policy for %v:\n\n%v\n", p.Target(), alignedPolicyTableRows(rows))
}
func printRetentionPolicy(out *textOutput, p *policy.Policy, def *policy.Definition) {
out.printStdout("Retention:\n")
out.printStdout(" Annual snapshots: %3v %v\n",
valueOrNotSet(p.RetentionPolicy.KeepAnnual),
definitionPointToString(p.Target(), def.RetentionPolicy.KeepAnnual))
out.printStdout(" Monthly snapshots: %3v %v\n",
valueOrNotSet(p.RetentionPolicy.KeepMonthly),
definitionPointToString(p.Target(), def.RetentionPolicy.KeepMonthly))
out.printStdout(" Weekly snapshots: %3v %v\n",
valueOrNotSet(p.RetentionPolicy.KeepWeekly),
definitionPointToString(p.Target(), def.RetentionPolicy.KeepWeekly))
out.printStdout(" Daily snapshots: %3v %v\n",
valueOrNotSet(p.RetentionPolicy.KeepDaily),
definitionPointToString(p.Target(), def.RetentionPolicy.KeepDaily))
out.printStdout(" Hourly snapshots: %3v %v\n",
valueOrNotSet(p.RetentionPolicy.KeepHourly),
definitionPointToString(p.Target(), def.RetentionPolicy.KeepHourly))
out.printStdout(" Latest snapshots: %3v %v\n",
valueOrNotSet(p.RetentionPolicy.KeepLatest),
definitionPointToString(p.Target(), def.RetentionPolicy.KeepLatest))
func appendRetentionPolicyRows(rows []policyTableRow, p *policy.Policy, def *policy.Definition) []policyTableRow {
return append(rows,
policyTableRow{"Retention:", "", ""},
policyTableRow{" Annual snapshots:", valueOrNotSet(p.RetentionPolicy.KeepAnnual), definitionPointToString(p.Target(), def.RetentionPolicy.KeepAnnual)},
policyTableRow{" Monthly snapshots:", valueOrNotSet(p.RetentionPolicy.KeepMonthly), definitionPointToString(p.Target(), def.RetentionPolicy.KeepMonthly)},
policyTableRow{" Weekly snapshots:", valueOrNotSet(p.RetentionPolicy.KeepWeekly), definitionPointToString(p.Target(), def.RetentionPolicy.KeepWeekly)},
policyTableRow{" Daily snapshots:", valueOrNotSet(p.RetentionPolicy.KeepDaily), definitionPointToString(p.Target(), def.RetentionPolicy.KeepDaily)},
policyTableRow{" Hourly snapshots:", valueOrNotSet(p.RetentionPolicy.KeepHourly), definitionPointToString(p.Target(), def.RetentionPolicy.KeepHourly)},
policyTableRow{" Latest snapshots:", valueOrNotSet(p.RetentionPolicy.KeepLatest), definitionPointToString(p.Target(), def.RetentionPolicy.KeepLatest)},
)
}
func printFilesPolicy(out *textOutput, p *policy.Policy, def *policy.Definition) {
out.printStdout("Files policy:\n")
out.printStdout(" Ignore cache directories: %5v %v\n",
p.FilesPolicy.IgnoreCacheDirectories.OrDefault(true),
definitionPointToString(p.Target(), def.FilesPolicy.IgnoreCacheDirectories))
if len(p.FilesPolicy.IgnoreRules) > 0 {
out.printStdout(" Ignore rules: %v\n",
definitionPointToString(p.Target(), def.FilesPolicy.IgnoreRules))
} else {
out.printStdout(" No ignore rules.\n")
func boolToString(v bool) string {
if v {
return "true"
}
for _, rule := range p.FilesPolicy.IgnoreRules {
out.printStdout(" %-30v\n", rule)
return "false"
}
func logDetailToString(v policy.LogDetail) string {
return fmt.Sprintf("%v", v)
}
func appendFilesPolicyValue(items []policyTableRow, p *policy.Policy, def *policy.Definition) []policyTableRow {
items = append(items,
policyTableRow{"Files policy:", "", ""},
policyTableRow{
" Ignore cache directories:",
boolToString(p.FilesPolicy.IgnoreCacheDirectories.OrDefault(true)),
definitionPointToString(p.Target(), def.FilesPolicy.IgnoreCacheDirectories),
})
if len(p.FilesPolicy.IgnoreRules) > 0 {
items = append(items, policyTableRow{
" Ignore rules:", "", definitionPointToString(p.Target(), def.FilesPolicy.IgnoreRules),
})
for _, rule := range p.FilesPolicy.IgnoreRules {
items = append(items, policyTableRow{" " + rule, "", ""})
}
} else {
items = append(items, policyTableRow{" No ignore rules:", "", ""})
}
if len(p.FilesPolicy.DotIgnoreFiles) > 0 {
out.printStdout(" Read ignore rules from files: %v\n",
definitionPointToString(p.Target(), def.FilesPolicy.DotIgnoreFiles))
}
items = append(items, policyTableRow{
" Read ignore rules from files:", "",
definitionPointToString(p.Target(), def.FilesPolicy.DotIgnoreFiles),
})
for _, dotFile := range p.FilesPolicy.DotIgnoreFiles {
out.printStdout(" %-30v\n", dotFile)
for _, dotFile := range p.FilesPolicy.DotIgnoreFiles {
items = append(items, policyTableRow{" " + dotFile, "", ""})
}
}
if maxSize := p.FilesPolicy.MaxFileSize; maxSize > 0 {
out.printStdout(" Ignore files above: %10v %v\n",
items = append(items, policyTableRow{
" Ignore files above:",
units.BytesStringBase2(maxSize),
definitionPointToString(p.Target(), def.FilesPolicy.MaxFileSize))
definitionPointToString(p.Target(), def.FilesPolicy.MaxFileSize),
})
}
out.printStdout(" Scan one filesystem only: %5v %v\n",
p.FilesPolicy.OneFileSystem.OrDefault(false),
definitionPointToString(p.Target(), def.FilesPolicy.OneFileSystem))
items = append(items, policyTableRow{
" Scan one filesystem only:",
boolToString(p.FilesPolicy.OneFileSystem.OrDefault(false)),
definitionPointToString(p.Target(), def.FilesPolicy.OneFileSystem),
})
return items
}
func printErrorHandlingPolicy(out *textOutput, p *policy.Policy, def *policy.Definition) {
out.printStdout("Error handling policy:\n")
out.printStdout(" Ignore file read errors: %5v %v\n",
p.ErrorHandlingPolicy.IgnoreFileErrors.OrDefault(false),
definitionPointToString(p.Target(), def.ErrorHandlingPolicy.IgnoreFileErrors))
out.printStdout(" Ignore directory read errors: %5v %v\n",
p.ErrorHandlingPolicy.IgnoreDirectoryErrors.OrDefault(false),
definitionPointToString(p.Target(), def.ErrorHandlingPolicy.IgnoreDirectoryErrors))
out.printStdout(" Ignore unknown types: %5v %v\n",
p.ErrorHandlingPolicy.IgnoreUnknownTypes.OrDefault(true),
definitionPointToString(p.Target(), def.ErrorHandlingPolicy.IgnoreUnknownTypes))
func appendErrorHandlingPolicyRows(rows []policyTableRow, p *policy.Policy, def *policy.Definition) []policyTableRow {
return append(rows,
policyTableRow{"Error handling policy:", "", ""},
policyTableRow{
" Ignore file read errors:",
boolToString(p.ErrorHandlingPolicy.IgnoreFileErrors.OrDefault(false)),
definitionPointToString(p.Target(), def.ErrorHandlingPolicy.IgnoreFileErrors),
},
policyTableRow{
" Ignore directory read errors:",
boolToString(p.ErrorHandlingPolicy.IgnoreDirectoryErrors.OrDefault(false)),
definitionPointToString(p.Target(), def.ErrorHandlingPolicy.IgnoreDirectoryErrors),
},
policyTableRow{
" Ignore unknown types:",
boolToString(p.ErrorHandlingPolicy.IgnoreUnknownTypes.OrDefault(true)),
definitionPointToString(p.Target(), def.ErrorHandlingPolicy.IgnoreUnknownTypes),
},
)
}
func printLoggingPolicy(out *textOutput, p *policy.Policy, def *policy.Definition) {
out.printStdout("Logging details (%v-none, %v-maximum):\n", policy.LogDetailNone, policy.LogDetailMax)
out.printStdout(" Directory snapshotted: %5v %v\n",
p.LoggingPolicy.Directories.Snapshotted.OrDefault(policy.LogDetailNone),
definitionPointToString(p.Target(), def.LoggingPolicy.Directories.Snapshotted))
out.printStdout(" Directory ignored: %5v %v\n",
p.LoggingPolicy.Directories.Ignored.OrDefault(policy.LogDetailNone),
definitionPointToString(p.Target(), def.LoggingPolicy.Directories.Ignored))
out.printStdout(" Entry snapshotted: %5v %v\n",
p.LoggingPolicy.Entries.Snapshotted.OrDefault(policy.LogDetailNone),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.Snapshotted))
out.printStdout(" Entry ignored: %5v %v\n",
p.LoggingPolicy.Entries.Ignored.OrDefault(policy.LogDetailNone),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.Ignored))
out.printStdout(" Entry cache hit %5v %v\n",
p.LoggingPolicy.Entries.CacheHit.OrDefault(policy.LogDetailNone),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.CacheHit))
out.printStdout(" Entry cache miss %5v %v\n",
p.LoggingPolicy.Entries.CacheMiss.OrDefault(policy.LogDetailNone),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.CacheMiss))
func appendLoggingPolicyRows(rows []policyTableRow, p *policy.Policy, def *policy.Definition) []policyTableRow {
return append(rows,
policyTableRow{
fmt.Sprintf("Logging details (%v-none, %v-maximum):", policy.LogDetailNone, policy.LogDetailMax), "", "",
},
policyTableRow{
" Directory snapshotted:",
logDetailToString(p.LoggingPolicy.Directories.Snapshotted.OrDefault(policy.LogDetailNone)),
definitionPointToString(p.Target(), def.LoggingPolicy.Directories.Snapshotted),
},
policyTableRow{
" Directory ignored:",
logDetailToString(p.LoggingPolicy.Directories.Ignored.OrDefault(policy.LogDetailNone)),
definitionPointToString(p.Target(), def.LoggingPolicy.Directories.Ignored),
},
policyTableRow{
" Entry snapshotted:",
logDetailToString(p.LoggingPolicy.Entries.Snapshotted.OrDefault(policy.LogDetailNone)),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.Snapshotted),
},
policyTableRow{
" Entry ignored:",
logDetailToString(p.LoggingPolicy.Entries.Ignored.OrDefault(policy.LogDetailNone)),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.Ignored),
},
policyTableRow{
" Entry cache hit:",
logDetailToString(p.LoggingPolicy.Entries.CacheHit.OrDefault(policy.LogDetailNone)),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.CacheHit),
},
policyTableRow{
" Entry cache miss:",
logDetailToString(p.LoggingPolicy.Entries.CacheMiss.OrDefault(policy.LogDetailNone)),
definitionPointToString(p.Target(), def.LoggingPolicy.Entries.CacheMiss),
},
)
}
func printSchedulingPolicy(out *textOutput, p *policy.Policy, def *policy.Definition) {
out.printStdout("Scheduling policy:\n")
func appendSchedulingPolicyRows(rows []policyTableRow, p *policy.Policy, def *policy.Definition) []policyTableRow {
rows = append(rows, policyTableRow{"Scheduling policy:", "", ""})
any := false
out.printStdout(" Scheduled snapshots:\n")
rows = append(rows, policyTableRow{" Scheduled snapshots:", "", ""})
if p.SchedulingPolicy.Interval() != 0 {
out.printStdout(" Snapshot interval: %10v %v\n", p.SchedulingPolicy.Interval(),
definitionPointToString(p.Target(), def.SchedulingPolicy.IntervalSeconds))
rows = append(rows, policyTableRow{
" Snapshot interval:",
p.SchedulingPolicy.Interval().String(),
definitionPointToString(p.Target(), def.SchedulingPolicy.IntervalSeconds),
})
any = true
}
if len(p.SchedulingPolicy.TimesOfDay) > 0 {
out.printStdout(" Snapshot times: %v\n", definitionPointToString(p.Target(), def.SchedulingPolicy.TimesOfDay))
rows = append(rows, policyTableRow{" Snapshot times:", "", definitionPointToString(p.Target(), def.SchedulingPolicy.TimesOfDay)})
for _, tod := range p.SchedulingPolicy.TimesOfDay {
out.printStdout(" %9v\n", tod)
rows = append(rows, policyTableRow{" " + tod.String(), "", ""})
}
any = true
}
if !any {
out.printStdout(" None\n")
rows = append(rows, policyTableRow{" None.", "", ""})
}
out.printStdout(" Manual snapshot: %5v %v\n",
p.SchedulingPolicy.Manual,
definitionPointToString(p.Target(), def.SchedulingPolicy.Manual))
rows = append(rows, policyTableRow{" Manual snapshot:", boolToString(p.SchedulingPolicy.Manual), definitionPointToString(p.Target(), def.SchedulingPolicy.Manual)})
return rows
}
func printCompressionPolicy(out *textOutput, p *policy.Policy, def *policy.Definition) {
if p.CompressionPolicy.CompressorName != "" && p.CompressionPolicy.CompressorName != "none" {
out.printStdout("Compression:\n")
out.printStdout(" Compressor: %q %v\n", p.CompressionPolicy.CompressorName,
definitionPointToString(p.Target(), def.CompressionPolicy.CompressorName))
} else {
out.printStdout("Compression disabled.\n")
return
func appendCompressionPolicyRows(rows []policyTableRow, p *policy.Policy, def *policy.Definition) []policyTableRow {
if p.CompressionPolicy.CompressorName == "" || p.CompressionPolicy.CompressorName == "none" {
rows = append(rows, policyTableRow{"Compression disabled.", "", ""})
return rows
}
rows = append(rows,
policyTableRow{"Compression:", "", ""},
policyTableRow{" Compressor:", string(p.CompressionPolicy.CompressorName), definitionPointToString(p.Target(), def.CompressionPolicy.CompressorName)})
switch {
case len(p.CompressionPolicy.OnlyCompress) > 0:
out.printStdout(" Only compress files with the following extensions: %v\n",
definitionPointToString(p.Target(), def.CompressionPolicy.OnlyCompress))
rows = append(rows, policyTableRow{
" Only compress files with the following extensions:", "",
definitionPointToString(p.Target(), def.CompressionPolicy.OnlyCompress),
})
for _, rule := range p.CompressionPolicy.OnlyCompress {
out.printStdout(" %-30v\n", rule)
rows = append(rows, policyTableRow{" - " + rule, "", ""})
}
case len(p.CompressionPolicy.NeverCompress) > 0:
out.printStdout(" Compress all files except the following extensions: %v\n",
definitionPointToString(p.Target(), def.CompressionPolicy.NeverCompress))
rows = append(rows, policyTableRow{
" Compress all files except the following extensions:", "",
definitionPointToString(p.Target(), def.CompressionPolicy.NeverCompress),
})
for _, rule := range p.CompressionPolicy.NeverCompress {
out.printStdout(" %-30v\n", rule)
rows = append(rows, policyTableRow{" " + rule, "", ""})
}
default:
out.printStdout(" Compress files regardless of extensions.\n")
rows = append(rows, policyTableRow{" Compress files regardless of extensions.", "", ""})
}
switch {
case p.CompressionPolicy.MaxSize > 0:
out.printStdout(" Only compress files between %v and %v.\n", units.BytesStringBase10(p.CompressionPolicy.MinSize), units.BytesStringBase10(p.CompressionPolicy.MaxSize))
rows = append(rows, policyTableRow{fmt.Sprintf(
" Only compress files between %v and %v.",
units.BytesStringBase10(p.CompressionPolicy.MinSize),
units.BytesStringBase10(p.CompressionPolicy.MaxSize)), "", ""})
case p.CompressionPolicy.MinSize > 0:
out.printStdout(" Only compress files bigger than %v.\n", units.BytesStringBase10(p.CompressionPolicy.MinSize))
rows = append(rows, policyTableRow{fmt.Sprintf(
" Only compress files bigger than %v.",
units.BytesStringBase10(p.CompressionPolicy.MinSize)), "", ""})
default:
out.printStdout(" Compress files of all sizes.\n")
rows = append(rows, policyTableRow{" Compress files of all sizes.", "", ""})
}
return rows
}
func printActions(out *textOutput, p *policy.Policy, def *policy.Definition) {
func appendActionsPolicyRows(rows []policyTableRow, p *policy.Policy, def *policy.Definition) []policyTableRow {
var anyActions bool
if h := p.Actions.BeforeSnapshotRoot; h != nil {
out.printStdout("Run command before snapshot root: %v\n",
definitionPointToString(p.Target(), def.Actions.BeforeSnapshotRoot))
printActionCommand(out, h)
rows = append(rows,
policyTableRow{"Run command before snapshot root:", "", definitionPointToString(p.Target(), def.Actions.BeforeSnapshotRoot)})
rows = appendActionCommandRows(rows, h)
anyActions = true
}
if h := p.Actions.AfterSnapshotRoot; h != nil {
out.printStdout("Run command after snapshot root: %v\n",
definitionPointToString(p.Target(), def.Actions.AfterSnapshotRoot))
printActionCommand(out, h)
rows = append(rows, policyTableRow{"Run command after snapshot root:", "", definitionPointToString(p.Target(), def.Actions.AfterSnapshotRoot)})
rows = appendActionCommandRows(rows, h)
anyActions = true
}
if h := p.Actions.BeforeFolder; h != nil {
out.printStdout("Run command before this folder: (non-inheritable)\n")
printActionCommand(out, h)
rows = append(rows, policyTableRow{"Run command before this folder:", "", "(non-inheritable)"})
rows = appendActionCommandRows(rows, h)
anyActions = true
}
if h := p.Actions.AfterFolder; h != nil {
out.printStdout("Run command after this folder: (non-inheritable)\n")
printActionCommand(out, h)
rows = append(rows, policyTableRow{"Run command after this folder:", "", "(non-inheritable)"})
rows = appendActionCommandRows(rows, h)
anyActions = true
}
if !anyActions {
out.printStdout("No actions defined.\n")
rows = append(rows, policyTableRow{"No actions defined.", "", ""})
}
return rows
}
func printActionCommand(out *textOutput, h *policy.ActionCommand) {
func appendActionCommandRows(rows []policyTableRow, h *policy.ActionCommand) []policyTableRow {
if h.Script != "" {
out.printStdout(" Embedded Script: %q\n", h.Script)
rows = append(rows,
policyTableRow{" Embedded script (stored in repository):", "", ""},
policyTableRow{indentMultilineString(h.Script, " "), "", ""},
)
} else {
out.printStdout(" Command: %v %v\n", h.Command, strings.Join(h.Arguments, " "))
rows = append(rows,
policyTableRow{" Command:", "", ""},
policyTableRow{" " + h.Command + " " + strings.Join(h.Arguments, " "), "", ""})
}
out.printStdout(" Mode: %v\n", h.Mode)
out.printStdout(" Timeout: %v\n", h.TimeoutSeconds)
out.printStdout("\n")
actualMode := h.Mode
if actualMode == "" {
actualMode = "sync"
}
rows = append(rows,
policyTableRow{" Mode:", actualMode, ""},
policyTableRow{" Timeout:", (time.Second * time.Duration(h.TimeoutSeconds)).String(), ""},
policyTableRow{"", "", ""},
)
return rows
}
func valueOrNotSet(p *policy.OptionalInt) string {

View File

@@ -165,8 +165,12 @@ func (c *commandRepositoryCreate) populateRepository(ctx context.Context, passwo
return errors.Wrap(err, "unable to set global policy")
}
printRetentionPolicy(&c.out, policy.DefaultPolicy, &policy.Definition{})
printCompressionPolicy(&c.out, policy.DefaultPolicy, &policy.Definition{})
var rows []policyTableRow
rows = appendRetentionPolicyRows(rows, policy.DefaultPolicy, &policy.Definition{})
rows = appendCompressionPolicyRows(rows, policy.DefaultPolicy, &policy.Definition{})
c.out.printStdout("%v\n", alignedPolicyTableRows(rows))
c.out.printStderr("\nTo find more information about default policy run 'kopia policy get'.\nTo change the policy use 'kopia policy set' command.\n")

View File

@@ -1,11 +1,13 @@
package cli
import (
"bufio"
"bytes"
"compress/gzip"
"encoding/json"
"fmt"
"io"
"strings"
"time"
"github.com/pkg/errors"
@@ -103,3 +105,14 @@ func formatCompressionPercentage(original, compressed int64) string {
return fmt.Sprintf("%.1f%%", oneHundredPercent*(1-float64(compressed)/float64(original)))
}
func indentMultilineString(l, prefix string) string {
var lines []string
s := bufio.NewScanner(strings.NewReader(l))
for s.Scan() {
lines = append(lines, prefix+s.Text())
}
return strings.Join(lines, "\n")
}