mirror of
https://github.com/kopia/kopia.git
synced 2026-04-14 02:59:13 -04:00
feat(cli): improved formatting of 'policy show' outputs (#1767)
This commit is contained in:
5
Makefile
5
Makefile
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user