Add node provider interfaace (#526)

This starts the work of having a `NodeProvider` which is responsible for
providing node details.
It splits the responsibilities of node management off to a new
controller.

The primary change here is to add the framework pieces for node
management and move the VK CLI to use this new controller.

It also adds support for node leases where available. This can be
enabled via the command line (disabled by default), but may fall back if
we find that leaess aren't supported on the cluster.
This commit is contained in:
Brian Goff
2019-03-25 15:02:40 -07:00
committed by Ria Bhatia
parent 9e245f3737
commit 10430f0b7f
34 changed files with 4939 additions and 101 deletions

View File

@@ -0,0 +1,161 @@
package format
import (
"bytes"
"fmt"
"strings"
"unicode"
"gotest.tools/internal/difflib"
)
const (
contextLines = 2
)
// DiffConfig for a unified diff
type DiffConfig struct {
A string
B string
From string
To string
}
// UnifiedDiff is a modified version of difflib.WriteUnifiedDiff with better
// support for showing the whitespace differences.
func UnifiedDiff(conf DiffConfig) string {
a := strings.SplitAfter(conf.A, "\n")
b := strings.SplitAfter(conf.B, "\n")
groups := difflib.NewMatcher(a, b).GetGroupedOpCodes(contextLines)
if len(groups) == 0 {
return ""
}
buf := new(bytes.Buffer)
writeFormat := func(format string, args ...interface{}) {
buf.WriteString(fmt.Sprintf(format, args...))
}
writeLine := func(prefix string, s string) {
buf.WriteString(prefix + s)
}
if hasWhitespaceDiffLines(groups, a, b) {
writeLine = visibleWhitespaceLine(writeLine)
}
formatHeader(writeFormat, conf)
for _, group := range groups {
formatRangeLine(writeFormat, group)
for _, opCode := range group {
in, out := a[opCode.I1:opCode.I2], b[opCode.J1:opCode.J2]
switch opCode.Tag {
case 'e':
formatLines(writeLine, " ", in)
case 'r':
formatLines(writeLine, "-", in)
formatLines(writeLine, "+", out)
case 'd':
formatLines(writeLine, "-", in)
case 'i':
formatLines(writeLine, "+", out)
}
}
}
return buf.String()
}
// hasWhitespaceDiffLines returns true if any diff groups is only different
// because of whitespace characters.
func hasWhitespaceDiffLines(groups [][]difflib.OpCode, a, b []string) bool {
for _, group := range groups {
in, out := new(bytes.Buffer), new(bytes.Buffer)
for _, opCode := range group {
if opCode.Tag == 'e' {
continue
}
for _, line := range a[opCode.I1:opCode.I2] {
in.WriteString(line)
}
for _, line := range b[opCode.J1:opCode.J2] {
out.WriteString(line)
}
}
if removeWhitespace(in.String()) == removeWhitespace(out.String()) {
return true
}
}
return false
}
func removeWhitespace(s string) string {
var result []rune
for _, r := range s {
if !unicode.IsSpace(r) {
result = append(result, r)
}
}
return string(result)
}
func visibleWhitespaceLine(ws func(string, string)) func(string, string) {
mapToVisibleSpace := func(r rune) rune {
switch r {
case '\n':
case ' ':
return '·'
case '\t':
return '▷'
case '\v':
return '▽'
case '\r':
return '↵'
case '\f':
return '↓'
default:
if unicode.IsSpace(r) {
return '<27>'
}
}
return r
}
return func(prefix, s string) {
ws(prefix, strings.Map(mapToVisibleSpace, s))
}
}
func formatHeader(wf func(string, ...interface{}), conf DiffConfig) {
if conf.From != "" || conf.To != "" {
wf("--- %s\n", conf.From)
wf("+++ %s\n", conf.To)
}
}
func formatRangeLine(wf func(string, ...interface{}), group []difflib.OpCode) {
first, last := group[0], group[len(group)-1]
range1 := formatRangeUnified(first.I1, last.I2)
range2 := formatRangeUnified(first.J1, last.J2)
wf("@@ -%s +%s @@\n", range1, range2)
}
// Convert range to the "ed" format
func formatRangeUnified(start, stop int) string {
// Per the diff spec at http://www.unix.org/single_unix_specification/
beginning := start + 1 // lines start numbering with one
length := stop - start
if length == 1 {
return fmt.Sprintf("%d", beginning)
}
if length == 0 {
beginning-- // empty ranges begin at line just before the range
}
return fmt.Sprintf("%d,%d", beginning, length)
}
func formatLines(writeLine func(string, string), prefix string, lines []string) {
for _, line := range lines {
writeLine(prefix, line)
}
// Add a newline if the last line is missing one so that the diff displays
// properly.
if !strings.HasSuffix(lines[len(lines)-1], "\n") {
writeLine("", "\n")
}
}

View File

@@ -0,0 +1,27 @@
package format // import "gotest.tools/internal/format"
import "fmt"
// Message accepts a msgAndArgs varargs and formats it using fmt.Sprintf
func Message(msgAndArgs ...interface{}) string {
switch len(msgAndArgs) {
case 0:
return ""
case 1:
return fmt.Sprintf("%v", msgAndArgs[0])
default:
return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
}
}
// WithCustomMessage accepts one or two messages and formats them appropriately
func WithCustomMessage(source string, msgAndArgs ...interface{}) string {
custom := Message(msgAndArgs...)
switch {
case custom == "":
return source
case source == "":
return custom
}
return fmt.Sprintf("%s: %s", source, custom)
}