feat(pkger): extend DiffBucket with name for existing and new bucket values

provides mapping between pkgName and resource the diff represents. Now that
stacks are in place, the existing bucket may change names.
pull/17459/head^2
Johnny Steenbergen 2020-03-31 12:45:18 -07:00 committed by Johnny Steenbergen
parent 6fa144192f
commit 098fd27ab4
9 changed files with 223 additions and 43 deletions

View File

@ -720,21 +720,32 @@ func (b *cmdPkgBuilder) printPkgDiff(diff pkger.Diff) error {
}
if bkts := diff.Buckets; len(bkts) > 0 {
headers := []string{"New", "ID", "Name", "Retention Period", "Description"}
tablePrintFn("BUCKETS", headers, len(bkts), func(i int) []string {
b := bkts[i]
var old pkger.DiffBucketValues
bktPrinter := newDiffPrinter(b.w, !b.disableColor, !b.disableTableBorders)
bktPrinter.
Title("Buckets").
SetHeaders("ID", "Name", "Retention Period", "Description")
appendValues := func(id pkger.SafeID, v pkger.DiffBucketValues) []string {
return []string{id.String(), v.Name, v.RetentionRules.RP().String(), v.Description}
}
for _, b := range bkts {
var oldRow []string
if b.Old != nil {
old = *b.Old
oldRow = appendValues(b.ID, *b.Old)
}
return []string{
boolDiff(b.IsNew()),
b.ID.String(),
b.Name,
diffLn(b.IsNew(), old.RetentionRules.RP().String(), b.New.RetentionRules.RP().String()),
diffLn(b.IsNew(), old.Description, b.New.Description),
newRow := appendValues(b.ID, b.New)
switch {
case b.IsNew():
bktPrinter.AppendDiff(nil, newRow)
case b.Remove:
bktPrinter.AppendDiff(oldRow, nil)
default:
bktPrinter.AppendDiff(oldRow, newRow)
}
})
}
bktPrinter.Render()
}
if checks := diff.Checks; len(checks) > 0 {
@ -1030,6 +1041,159 @@ func (b *cmdPkgBuilder) tablePrinterGen() func(table string, headers []string, c
}
}
type diffPrinter struct {
w io.Writer
writer *tablewriter.Table
colorAdd tablewriter.Colors
colorRemove tablewriter.Colors
title string
appendCalls int
headerLen int
hasColor bool
}
func newDiffPrinter(w io.Writer, hasColor, hasBorder bool) *diffPrinter {
wr := tablewriter.NewWriter(w)
wr.SetBorder(hasBorder)
wr.SetRowLine(hasBorder)
return &diffPrinter{
w: w,
writer: wr,
colorRemove: tablewriter.Colors{tablewriter.FgRedColor, tablewriter.Bold},
colorAdd: tablewriter.Colors{tablewriter.FgHiGreenColor, tablewriter.Bold},
hasColor: hasColor,
}
}
func (d *diffPrinter) Render() {
if d.appendCalls == 0 {
return
}
// set the title and the add/remove legend
title := color.New(color.FgYellow, color.Bold).Sprint(strings.ToUpper(d.title))
add := color.New(color.FgHiGreen, color.Bold).Sprint("+add")
remove := color.New(color.FgRed, color.Bold).Sprint("-remove")
fmt.Fprintf(d.w, "%s %s | %s | unchanged\n", title, add, remove)
d.setFooter()
d.writer.Render()
}
func (d *diffPrinter) Title(title string) *diffPrinter {
d.title = title
return d
}
func (d *diffPrinter) SetHeaders(headers ...string) *diffPrinter {
headers = d.prepend(headers, "+/-")
d.headerLen = len(headers)
d.writer.SetHeader(headers)
headerColors := make([]tablewriter.Colors, d.headerLen)
for i := range headerColors {
headerColors[i] = tablewriter.Colors{tablewriter.Bold, tablewriter.FgCyanColor}
}
d.writer.SetHeaderColor(headerColors...)
return d
}
func (d *diffPrinter) setFooter() *diffPrinter {
footers := make([]string, d.headerLen)
if d.headerLen > 1 {
footers[len(footers)-2] = "TOTAL"
footers[len(footers)-1] = strconv.Itoa(d.appendCalls)
} else {
footers[0] = "TOTAL: " + strconv.Itoa(d.appendCalls)
}
d.writer.SetFooter(footers)
if d.hasColor {
colors := make([]tablewriter.Colors, d.headerLen)
if d.headerLen > 1 {
colors[len(colors)-2] = tablewriter.Color(tablewriter.FgHiBlueColor)
colors[len(colors)-1] = tablewriter.Color(tablewriter.FgHiBlueColor)
} else {
colors[0] = tablewriter.Color(tablewriter.FgHiBlueColor)
}
d.writer.SetFooterColor(colors...)
}
return d
}
func (d *diffPrinter) Append(slc []string) {
d.writer.Append(d.prepend(slc, ""))
}
func (d *diffPrinter) AppendDiff(remove, add []string) {
defer func() { d.appendCalls++ }()
if d.appendCalls > 0 {
d.appendBufferLine()
}
lenAdd, lenRemove := len(add), len(remove)
preppedAdd, preppedRemove := d.prepend(add, "+"), d.prepend(remove, "-")
if lenRemove > 0 && lenAdd == 0 {
d.writer.Rich(preppedRemove, d.redRow(len(preppedRemove)))
return
}
if lenAdd > 0 && lenRemove == 0 {
d.writer.Rich(preppedAdd, d.greenRow(len(preppedAdd)))
return
}
var (
addColors = make([]tablewriter.Colors, len(preppedAdd))
removeColors = make([]tablewriter.Colors, len(preppedRemove))
hasDiff bool
)
for i := 0; i < lenRemove; i++ {
if add[i] != remove[i] {
hasDiff = true
// offset to skip prepended +/- column
addColors[i+1], removeColors[i+1] = d.colorAdd, d.colorRemove
}
}
if !hasDiff {
d.writer.Append(d.prepend(add, ""))
return
}
addColors[0], removeColors[0] = d.colorAdd, d.colorRemove
d.writer.Rich(d.prepend(remove, "-"), removeColors)
d.writer.Rich(d.prepend(add, "+"), addColors)
}
func (d *diffPrinter) appendBufferLine() {
d.writer.Append([]string{})
}
func (d *diffPrinter) redRow(i int) []tablewriter.Colors {
return colorRow(d.colorRemove, i)
}
func (d *diffPrinter) greenRow(i int) []tablewriter.Colors {
return colorRow(d.colorAdd, i)
}
func (d *diffPrinter) prepend(slc []string, val string) []string {
return append([]string{val}, slc...)
}
func colorRow(color tablewriter.Colors, i int) []tablewriter.Colors {
colors := make([]tablewriter.Colors, i)
for i := range colors {
colors[i] = color
}
return colors
}
func tablePrinter(wr io.Writer, table string, headers []string, count int, hasColor, hasTableBorders bool, rowFn func(i int) []string) {
color.New(color.FgYellow, color.Bold).Fprintln(wr, strings.ToUpper(table))

2
go.mod
View File

@ -64,7 +64,7 @@ require (
github.com/nats-io/nats-streaming-server v0.11.2
github.com/nats-io/nkeys v0.0.2 // indirect
github.com/nats-io/nuid v1.0.0 // indirect
github.com/olekukonko/tablewriter v0.0.1
github.com/olekukonko/tablewriter v0.0.4
github.com/onsi/ginkgo v1.7.0 // indirect
github.com/onsi/gomega v1.4.3 // indirect
github.com/opentracing/opentracing-go v1.1.0

6
go.sum
View File

@ -307,6 +307,8 @@ github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.3 h1:a+kO+98RDGEfo6asOGMmpodZq4FNtnGP54yps8BzLR4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104 h1:d8RFOZ2IiFtFWBcKEHAFYJcPTf0wY5q0exFNJZVWa1U=
@ -351,8 +353,8 @@ github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7
github.com/nats-io/nuid v1.0.0 h1:44QGdhbiANq8ZCbUkdn6W5bqtg+mHuDE4wOUuxxndFs=
github.com/nats-io/nuid v1.0.0/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=

View File

@ -7504,11 +7504,13 @@ components:
properties:
id:
type: string
name:
pkgName:
type: string
new:
type: object
properties:
name:
type: string
description:
type: string
retentionRules:
@ -7516,6 +7518,8 @@ components:
old:
type: object
properties:
name:
type: string
description:
type: string
retentionRules:

View File

@ -157,7 +157,7 @@ func TestPkgerHTTPServer(t *testing.T) {
var diff pkger.Diff
for _, b := range sum.Buckets {
diff.Buckets = append(diff.Buckets, pkger.DiffBucket{
Name: b.Name,
PkgName: b.Name,
})
}
return sum, diff, nil
@ -211,7 +211,7 @@ func TestPkgerHTTPServer(t *testing.T) {
var diff pkger.Diff
for _, b := range sum.Buckets {
diff.Buckets = append(diff.Buckets, pkger.DiffBucket{
Name: b.Name,
PkgName: b.Name,
})
}
return sum, diff, nil
@ -313,7 +313,7 @@ func TestPkgerHTTPServer(t *testing.T) {
var diff pkger.Diff
for _, b := range sum.Buckets {
diff.Buckets = append(diff.Buckets, pkger.DiffBucket{
Name: b.Name,
PkgName: b.Name,
})
}
return sum, diff, nil
@ -353,7 +353,7 @@ func TestPkgerHTTPServer(t *testing.T) {
var diff pkger.Diff
for _, b := range sum.Buckets {
diff.Buckets = append(diff.Buckets, pkger.DiffBucket{
Name: b.Name,
PkgName: b.Name,
})
}
return sum, diff, nil

View File

@ -176,22 +176,26 @@ func (d Diff) HasConflicts() bool {
// DiffBucketValues are the varying values for a bucket.
type DiffBucketValues struct {
Name string `json:"name"`
Description string `json:"description"`
RetentionRules retentionRules `json:"retentionRules"`
}
// DiffBucket is a diff of an individual bucket.
type DiffBucket struct {
ID SafeID `json:"id"`
Name string `json:"name"`
New DiffBucketValues `json:"new"`
Old *DiffBucketValues `json:"old,omitempty"` // using omitempty here to signal there was no prev state with a nil
Remove bool `json:"remove"`
ID SafeID `json:"id"`
PkgName string `json:"pkgName"`
New DiffBucketValues `json:"new"`
Old *DiffBucketValues `json:"old,omitempty"` // using omitempty here to signal there was no prev state with a nil
}
func newDiffBucket(b *bucket, i *influxdb.Bucket) DiffBucket {
diff := DiffBucket{
Name: b.Name(),
Remove: b.shouldRemove,
PkgName: b.PkgName(),
New: DiffBucketValues{
Name: b.Name(),
Description: b.Description,
RetentionRules: b.RetentionRules,
},
@ -199,6 +203,7 @@ func newDiffBucket(b *bucket, i *influxdb.Bucket) DiffBucket {
if i != nil {
diff.ID = SafeID(i.ID)
diff.Old = &DiffBucketValues{
Name: i.Name,
Description: i.Description,
}
if i.RetentionPeriod > 0 {
@ -750,8 +755,9 @@ type SummaryVariable struct {
}
type identity struct {
name *references
displayName *references
name *references
displayName *references
shouldRemove bool
}
func (i *identity) Name() string {
@ -856,7 +862,8 @@ func (b *bucket) valid() []validationErr {
}
func (b *bucket) shouldApply() bool {
return b.existing == nil ||
return b.shouldRemove ||
b.existing == nil ||
b.Description != b.existing.Description ||
b.Name() != b.existing.Name ||
b.RetentionRules.RP() != b.existing.RetentionPeriod

View File

@ -136,7 +136,7 @@ func TestPkg(t *testing.T) {
{
name: "new bucket",
resource: DiffBucket{
Name: "new bucket",
PkgName: "new bucket",
New: DiffBucketValues{
Description: "new desc",
},
@ -146,8 +146,8 @@ func TestPkg(t *testing.T) {
{
name: "existing bucket with no changes",
resource: DiffBucket{
ID: 3,
Name: "new bucket",
ID: 3,
PkgName: "new bucket",
New: DiffBucketValues{
Description: "new desc",
RetentionRules: retentionRules{{
@ -168,8 +168,8 @@ func TestPkg(t *testing.T) {
{
name: "existing bucket with desc changes",
resource: DiffBucket{
ID: 3,
Name: "existing bucket",
ID: 3,
PkgName: "existing bucket",
New: DiffBucketValues{
Description: "new desc",
RetentionRules: retentionRules{{
@ -190,8 +190,8 @@ func TestPkg(t *testing.T) {
{
name: "existing bucket with retention changes",
resource: DiffBucket{
ID: 3,
Name: "existing bucket",
ID: 3,
PkgName: "existing bucket",
New: DiffBucketValues{
Description: "new desc",
RetentionRules: retentionRules{{
@ -208,8 +208,8 @@ func TestPkg(t *testing.T) {
{
name: "existing bucket with retention changes",
resource: DiffBucket{
ID: 3,
Name: "existing bucket",
ID: 3,
PkgName: "existing bucket",
New: DiffBucketValues{
Description: "new desc",
RetentionRules: retentionRules{{
@ -230,8 +230,8 @@ func TestPkg(t *testing.T) {
{
name: "existing bucket with retention changes",
resource: DiffBucket{
ID: 3,
Name: "existing bucket",
ID: 3,
PkgName: "existing bucket",
New: DiffBucketValues{
Description: "new desc",
RetentionRules: retentionRules{{

View File

@ -725,7 +725,7 @@ func (s *Service) dryRunBuckets(ctx context.Context, orgID influxdb.ID, pkg *Pkg
diffs = append(diffs, diff)
}
sort.Slice(diffs, func(i, j int) bool {
return diffs[i].Name < diffs[j].Name
return diffs[i].PkgName < diffs[j].PkgName
})
return diffs

View File

@ -83,13 +83,15 @@ func TestService(t *testing.T) {
require.Len(t, diff.Buckets, 2)
expected := DiffBucket{
ID: SafeID(1),
Name: "rucket_11",
ID: SafeID(1),
PkgName: "rucket_11",
Old: &DiffBucketValues{
Name: "rucket_11",
Description: "old desc",
RetentionRules: retentionRules{newRetentionRule(30 * time.Hour)},
},
New: DiffBucketValues{
Name: "rucket_11",
Description: "bucket 1 description",
RetentionRules: retentionRules{newRetentionRule(time.Hour)},
},
@ -112,8 +114,9 @@ func TestService(t *testing.T) {
require.Len(t, diff.Buckets, 2)
expected := DiffBucket{
Name: "rucket_11",
PkgName: "rucket_11",
New: DiffBucketValues{
Name: "rucket_11",
Description: "bucket 1 description",
RetentionRules: retentionRules{newRetentionRule(time.Hour)},
},