Browse Source

vendor: coreos/pkg: -> v2

Adrian Clepcea 8 năm trước cách đây
mục cha
commit
b8c0e57f79

+ 3 - 3
glide.lock

@@ -1,5 +1,5 @@
-hash: d21f17e2078ce20f063091179f7688d67568e1508519fcfb7d9a39a65865eb0b
-updated: 2016-06-15T14:05:51.080462474-07:00
+hash: ae9f09c90f4bb4230fb7dc06798b809078b98816df63c91f4ad636b89ff31e38
+updated: 2016-06-23T13:29:22.013543886Z
 imports:
 - name: github.com/aws/aws-sdk-go
   version: 5c0313fff8cd85670ae4fc996254dd7d66cb4cf7
@@ -40,7 +40,7 @@ imports:
   - activation
   - daemon
 - name: github.com/coreos/pkg
-  version: b0d3d81732aea341039d191d8618a3466fe54395
+  version: 7f080b6c11ac2d2347c3cd7521e810207ea1a041
   subpackages:
   - flagutil
 - name: github.com/golang/glog

+ 1 - 1
glide.yaml

@@ -30,7 +30,7 @@ import:
   - activation
   - daemon
 - package: github.com/coreos/pkg
-  version: b0d3d81732aea341039d191d8618a3466fe54395
+  version: v2 
   subpackages:
   - flagutil
 - package: github.com/golang/glog

+ 8 - 0
vendor/github.com/coreos/pkg/.travis.yml

@@ -0,0 +1,8 @@
+language: go
+
+go:
+ - 1.5.4
+ - 1.6.2
+
+script:
+ - ./test

+ 2 - 1
vendor/github.com/coreos/pkg/README.md

@@ -1,3 +1,4 @@
 a collection of go utility packages
 
-[![Build Status](https://semaphoreci.com/api/v1/projects/14b3f261-22c2-4f56-b1ff-f23f4aa03f5c/411991/badge.svg)](https://semaphoreci.com/coreos/pkg)
+[![Build Status](https://travis-ci.org/coreos/pkg.png?branch=master)](https://travis-ci.org/coreos/pkg)
+[![Godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/coreos/pkg)

+ 10 - 9
vendor/github.com/coreos/pkg/capnslog/README.md

@@ -1,32 +1,33 @@
-# CoreOS Log
+# capnslog, the CoreOS logging package
 
-There are far too many logging packages out there, with varying degrees of licenses, far too many features (colorization, all sorts of log frameworks) or are just a pain to use (lack of `Fatalln()`?)
+There are far too many logging packages out there, with varying degrees of licenses, far too many features (colorization, all sorts of log frameworks) or are just a pain to use (lack of `Fatalln()`?).
+capnslog provides a simple but consistent logging interface suitable for all kinds of projects.
 
-## Design Principles
+### Design Principles
 
-* `package main` is the place where logging gets turned on and routed
+##### `package main` is the place where logging gets turned on and routed
 
 A library should not touch log options, only generate log entries. Libraries are silent until main lets them speak.
 
-* All log options are runtime-configurable. 
+##### All log options are runtime-configurable. 
 
 Still the job of `main` to expose these configurations. `main` may delegate this to, say, a configuration webhook, but does so explicitly. 
 
-* There is one log object per package. It is registered under its repository and package name.
+##### There is one log object per package. It is registered under its repository and package name.
 
 `main` activates logging for its repository and any dependency repositories it would also like to have output in its logstream. `main` also dictates at which level each subpackage logs.
 
-* There is *one* output stream, and it is an `io.Writer` composed with a formatter.
+##### There is *one* output stream, and it is an `io.Writer` composed with a formatter.
 
 Splitting streams is probably not the job of your program, but rather, your log aggregation framework. If you must split output streams, again, `main` configures this and you can write a very simple two-output struct that satisfies io.Writer.
 
 Fancy colorful formatting and JSON output are beyond the scope of a basic logging framework -- they're application/log-collector dependant. These are, at best, provided as options, but more likely, provided by your application.
 
-* Log objects are an interface
+##### Log objects are an interface
 
 An object knows best how to print itself. Log objects can collect more interesting metadata if they wish, however, because text isn't going away anytime soon, they must all be marshalable to text. The simplest log object is a string, which returns itself. If you wish to do more fancy tricks for printing your log objects, see also JSON output -- introspect and write a formatter which can handle your advanced log interface. Making strings is the only thing guaranteed.
 
-* Log levels have specific meanings:
+##### Log levels have specific meanings:
 
   * Critical: Unrecoverable. Must fail.
   * Error: Data has been lost, a request has failed for a bad reason, or a required resource has been lost

+ 52 - 1
vendor/github.com/coreos/pkg/capnslog/formatters.go

@@ -18,6 +18,7 @@ import (
 	"bufio"
 	"fmt"
 	"io"
+	"log"
 	"runtime"
 	"strings"
 	"time"
@@ -28,7 +29,7 @@ type Formatter interface {
 	Flush()
 }
 
-func NewStringFormatter(w io.Writer) *StringFormatter {
+func NewStringFormatter(w io.Writer) Formatter {
 	return &StringFormatter{
 		w: bufio.NewWriter(w),
 	}
@@ -104,3 +105,53 @@ func (c *PrettyFormatter) Format(pkg string, l LogLevel, depth int, entries ...i
 func (c *PrettyFormatter) Flush() {
 	c.w.Flush()
 }
+
+// LogFormatter emulates the form of the traditional built-in logger.
+type LogFormatter struct {
+	logger *log.Logger
+	prefix string
+}
+
+// NewLogFormatter is a helper to produce a new LogFormatter struct. It uses the
+// golang log package to actually do the logging work so that logs look similar.
+func NewLogFormatter(w io.Writer, prefix string, flag int) Formatter {
+	return &LogFormatter{
+		logger: log.New(w, "", flag), // don't use prefix here
+		prefix: prefix,               // save it instead
+	}
+}
+
+// Format builds a log message for the LogFormatter. The LogLevel is ignored.
+func (lf *LogFormatter) Format(pkg string, _ LogLevel, _ int, entries ...interface{}) {
+	str := fmt.Sprint(entries...)
+	prefix := lf.prefix
+	if pkg != "" {
+		prefix = fmt.Sprintf("%s%s: ", prefix, pkg)
+	}
+	lf.logger.Output(5, fmt.Sprintf("%s%v", prefix, str)) // call depth is 5
+}
+
+// Flush is included so that the interface is complete, but is a no-op.
+func (lf *LogFormatter) Flush() {
+	// noop
+}
+
+// NilFormatter is a no-op log formatter that does nothing.
+type NilFormatter struct {
+}
+
+// NewNilFormatter is a helper to produce a new LogFormatter struct. It logs no
+// messages so that you can cause part of your logging to be silent.
+func NewNilFormatter() Formatter {
+	return &NilFormatter{}
+}
+
+// Format does nothing.
+func (_ *NilFormatter) Format(_ string, _ LogLevel, _ int, _ ...interface{}) {
+	// noop
+}
+
+// Flush is included so that the interface is complete, but is a no-op.
+func (_ *NilFormatter) Flush() {
+	// noop
+}

+ 2 - 0
vendor/github.com/coreos/pkg/capnslog/init.go

@@ -11,6 +11,8 @@
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 // See the License for the specific language governing permissions and
 // limitations under the License.
+//
+// +build !windows
 
 package capnslog
 

+ 25 - 0
vendor/github.com/coreos/pkg/capnslog/init_windows.go

@@ -0,0 +1,25 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package capnslog
+
+import "os"
+
+func init() {
+	initHijack()
+
+	// Go `log` package uses os.Stderr.
+	SetFormatter(NewPrettyFormatter(os.Stderr, false))
+	SetGlobalLogLevel(INFO)
+}

+ 3 - 1
vendor/github.com/coreos/pkg/capnslog/journald_formatter.go

@@ -20,6 +20,7 @@ import (
 	"errors"
 	"fmt"
 	"os"
+	"path/filepath"
 
 	"github.com/coreos/go-systemd/journal"
 )
@@ -55,7 +56,8 @@ func (j *journaldFormatter) Format(pkg string, l LogLevel, _ int, entries ...int
 	}
 	msg := fmt.Sprint(entries...)
 	tags := map[string]string{
-		"PACKAGE": pkg,
+		"PACKAGE":           pkg,
+		"SYSLOG_IDENTIFIER": filepath.Base(os.Args[0]),
 	}
 	err := journal.Send(msg, pri, tags)
 	if err != nil {

+ 24 - 11
vendor/github.com/coreos/pkg/capnslog/pkg_logger.go

@@ -27,17 +27,19 @@ type PackageLogger struct {
 const calldepth = 2
 
 func (p *PackageLogger) internalLog(depth int, inLevel LogLevel, entries ...interface{}) {
+	logger.Lock()
+	defer logger.Unlock()
 	if inLevel != CRITICAL && p.level < inLevel {
 		return
 	}
-	logger.Lock()
-	defer logger.Unlock()
 	if logger.formatter != nil {
 		logger.formatter.Format(p.pkg, inLevel, depth+1, entries...)
 	}
 }
 
 func (p *PackageLogger) LevelAt(l LogLevel) bool {
+	logger.Lock()
+	defer logger.Unlock()
 	return p.level >= l
 }
 
@@ -58,7 +60,7 @@ func (p *PackageLogger) Println(args ...interface{}) {
 }
 
 func (p *PackageLogger) Printf(format string, args ...interface{}) {
-	p.internalLog(calldepth, INFO, fmt.Sprintf(format, args...))
+	p.Logf(INFO, format, args...)
 }
 
 func (p *PackageLogger) Print(args ...interface{}) {
@@ -80,8 +82,7 @@ func (p *PackageLogger) Panic(args ...interface{}) {
 }
 
 func (p *PackageLogger) Fatalf(format string, args ...interface{}) {
-	s := fmt.Sprintf(format, args...)
-	p.internalLog(calldepth, CRITICAL, s)
+	p.Logf(CRITICAL, format, args...)
 	os.Exit(1)
 }
 
@@ -94,7 +95,7 @@ func (p *PackageLogger) Fatal(args ...interface{}) {
 // Error Functions
 
 func (p *PackageLogger) Errorf(format string, args ...interface{}) {
-	p.internalLog(calldepth, ERROR, fmt.Sprintf(format, args...))
+	p.Logf(ERROR, format, args...)
 }
 
 func (p *PackageLogger) Error(entries ...interface{}) {
@@ -104,7 +105,7 @@ func (p *PackageLogger) Error(entries ...interface{}) {
 // Warning Functions
 
 func (p *PackageLogger) Warningf(format string, args ...interface{}) {
-	p.internalLog(calldepth, WARNING, fmt.Sprintf(format, args...))
+	p.Logf(WARNING, format, args...)
 }
 
 func (p *PackageLogger) Warning(entries ...interface{}) {
@@ -114,7 +115,7 @@ func (p *PackageLogger) Warning(entries ...interface{}) {
 // Notice Functions
 
 func (p *PackageLogger) Noticef(format string, args ...interface{}) {
-	p.internalLog(calldepth, NOTICE, fmt.Sprintf(format, args...))
+	p.Logf(NOTICE, format, args...)
 }
 
 func (p *PackageLogger) Notice(entries ...interface{}) {
@@ -124,7 +125,7 @@ func (p *PackageLogger) Notice(entries ...interface{}) {
 // Info Functions
 
 func (p *PackageLogger) Infof(format string, args ...interface{}) {
-	p.internalLog(calldepth, INFO, fmt.Sprintf(format, args...))
+	p.Logf(INFO, format, args...)
 }
 
 func (p *PackageLogger) Info(entries ...interface{}) {
@@ -134,20 +135,32 @@ func (p *PackageLogger) Info(entries ...interface{}) {
 // Debug Functions
 
 func (p *PackageLogger) Debugf(format string, args ...interface{}) {
-	p.internalLog(calldepth, DEBUG, fmt.Sprintf(format, args...))
+	if p.level < DEBUG {
+		return
+	}
+	p.Logf(DEBUG, format, args...)
 }
 
 func (p *PackageLogger) Debug(entries ...interface{}) {
+	if p.level < DEBUG {
+		return
+	}
 	p.internalLog(calldepth, DEBUG, entries...)
 }
 
 // Trace Functions
 
 func (p *PackageLogger) Tracef(format string, args ...interface{}) {
-	p.internalLog(calldepth, TRACE, fmt.Sprintf(format, args...))
+	if p.level < TRACE {
+		return
+	}
+	p.Logf(TRACE, format, args...)
 }
 
 func (p *PackageLogger) Trace(entries ...interface{}) {
+	if p.level < TRACE {
+		return
+	}
 	p.internalLog(calldepth, TRACE, entries...)
 }
 

+ 82 - 0
vendor/github.com/coreos/pkg/dlopen/dlopen.go

@@ -0,0 +1,82 @@
+// Copyright 2016 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// Package dlopen provides some convenience functions to dlopen a library and
+// get its symbols.
+package dlopen
+
+// #cgo LDFLAGS: -ldl
+// #include <stdlib.h>
+// #include <dlfcn.h>
+import "C"
+import (
+	"errors"
+	"fmt"
+	"unsafe"
+)
+
+var ErrSoNotFound = errors.New("unable to open a handle to the library")
+
+// LibHandle represents an open handle to a library (.so)
+type LibHandle struct {
+	Handle  unsafe.Pointer
+	Libname string
+}
+
+// GetHandle tries to get a handle to a library (.so), attempting to access it
+// by the names specified in libs and returning the first that is successfully
+// opened. Callers are responsible for closing the handler. If no library can
+// be successfully opened, an error is returned.
+func GetHandle(libs []string) (*LibHandle, error) {
+	for _, name := range libs {
+		libname := C.CString(name)
+		defer C.free(unsafe.Pointer(libname))
+		handle := C.dlopen(libname, C.RTLD_LAZY)
+		if handle != nil {
+			h := &LibHandle{
+				Handle:  handle,
+				Libname: name,
+			}
+			return h, nil
+		}
+	}
+	return nil, ErrSoNotFound
+}
+
+// GetSymbolPointer takes a symbol name and returns a pointer to the symbol.
+func (l *LibHandle) GetSymbolPointer(symbol string) (unsafe.Pointer, error) {
+	sym := C.CString(symbol)
+	defer C.free(unsafe.Pointer(sym))
+
+	C.dlerror()
+	p := C.dlsym(l.Handle, sym)
+	e := C.dlerror()
+	if e != nil {
+		return nil, fmt.Errorf("error resolving symbol %q: %v", symbol, errors.New(C.GoString(e)))
+	}
+
+	return p, nil
+}
+
+// Close closes a LibHandle.
+func (l *LibHandle) Close() error {
+	C.dlerror()
+	C.dlclose(l.Handle)
+	e := C.dlerror()
+	if e != nil {
+		return fmt.Errorf("error closing %v: %v", l.Libname, errors.New(C.GoString(e)))
+	}
+
+	return nil
+}

+ 56 - 0
vendor/github.com/coreos/pkg/dlopen/dlopen_example.go

@@ -0,0 +1,56 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// +build linux
+
+package dlopen
+
+// #include <string.h>
+// #include <stdlib.h>
+//
+// int
+// my_strlen(void *f, const char *s)
+// {
+//   size_t (*strlen)(const char *);
+//
+//   strlen = (size_t (*)(const char *))f;
+//   return strlen(s);
+// }
+import "C"
+
+import (
+	"fmt"
+	"unsafe"
+)
+
+func strlen(libs []string, s string) (int, error) {
+	h, err := GetHandle(libs)
+	if err != nil {
+		return -1, fmt.Errorf(`couldn't get a handle to the library: %v`, err)
+	}
+	defer h.Close()
+
+	f := "strlen"
+	cs := C.CString(s)
+	defer C.free(unsafe.Pointer(cs))
+
+	strlen, err := h.GetSymbolPointer(f)
+	if err != nil {
+		return -1, fmt.Errorf(`couldn't get symbol %q: %v`, f, err)
+	}
+
+	len := C.my_strlen(strlen, cs)
+
+	return int(len), nil
+}

+ 63 - 0
vendor/github.com/coreos/pkg/dlopen/dlopen_test.go

@@ -0,0 +1,63 @@
+// Copyright 2015 CoreOS, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package dlopen
+
+import (
+	"fmt"
+	"testing"
+)
+
+func checkFailure(shouldSucceed bool, err error) (rErr error) {
+	switch {
+	case err != nil && shouldSucceed:
+		rErr = fmt.Errorf("expected test to succeed, failed unexpectedly: %v", err)
+	case err == nil && !shouldSucceed:
+		rErr = fmt.Errorf("expected test to fail, succeeded unexpectedly")
+	}
+
+	return
+}
+
+func TestDlopen(t *testing.T) {
+	tests := []struct {
+		libs          []string
+		shouldSucceed bool
+	}{
+		{
+			libs: []string{
+				"libc.so.6",
+				"libc.so",
+			},
+			shouldSucceed: true,
+		},
+		{
+			libs: []string{
+				"libstrange.so",
+			},
+			shouldSucceed: false,
+		},
+	}
+
+	for i, tt := range tests {
+		expLen := 4
+		len, err := strlen(tt.libs, "test")
+		if checkFailure(tt.shouldSucceed, err) != nil {
+			t.Errorf("case %d: %v", i, err)
+		}
+
+		if tt.shouldSucceed && len != expLen {
+			t.Errorf("case %d: expected length %d, got %d", i, expLen, len)
+		}
+	}
+}

+ 77 - 0
vendor/github.com/coreos/pkg/flagutil/env_file.go

@@ -0,0 +1,77 @@
+package flagutil
+
+import (
+	"bufio"
+	"flag"
+	"fmt"
+	"os"
+	"strings"
+)
+
+// SetFlagsFromEnvFile iterates the given flagset and if any flags are not
+// already set it attempts to set their values from the given env file. Env
+// files may have KEY=VALUE lines where the environment variable names are
+// in UPPERCASE, prefixed by the given PREFIX, and dashes are replaced by
+// underscores. For example, if prefix=PREFIX, some-flag is named
+// PREFIX_SOME_FLAG.
+// Comment lines are skipped, but more complex env file parsing is not
+// performed.
+func SetFlagsFromEnvFile(fs *flag.FlagSet, prefix string, path string) (err error) {
+	alreadySet := make(map[string]bool)
+	fs.Visit(func(f *flag.Flag) {
+		alreadySet[f.Name] = true
+	})
+	envs, err := parseEnvFile(path)
+	if err != nil {
+		return err
+	}
+	fs.VisitAll(func(f *flag.Flag) {
+		if !alreadySet[f.Name] {
+			key := prefix + "_" + strings.ToUpper(strings.Replace(f.Name, "-", "_", -1))
+			val := envs[key]
+			if val != "" {
+				if serr := fs.Set(f.Name, val); serr != nil {
+					err = fmt.Errorf("invalid value %q for %s: %v", val, key, serr)
+				}
+			}
+		}
+	})
+	return err
+}
+
+func parseEnvFile(path string) (map[string]string, error) {
+	file, err := os.Open(path)
+	if err != nil {
+		return nil, err
+	}
+	defer file.Close()
+
+	envs := make(map[string]string)
+	scanner := bufio.NewScanner(file)
+	for scanner.Scan() {
+		token := scanner.Text()
+		if !skipLine(token) {
+			key, val, err := parseLine(token)
+			if err == nil {
+				envs[key] = val
+			}
+		}
+	}
+	return envs, nil
+}
+
+func skipLine(line string) bool {
+	return len(line) == 0 || strings.HasPrefix(line, "#")
+}
+
+func parseLine(line string) (key string, val string, err error) {
+	trimmed := strings.TrimSpace(line)
+	pair := strings.SplitN(trimmed, "=", 2)
+	if len(pair) != 2 {
+		err = fmt.Errorf("invalid KEY=value line: %q", line)
+		return
+	}
+	key = strings.TrimSpace(pair[0])
+	val = strings.TrimSpace(pair[1])
+	return
+}

+ 107 - 0
vendor/github.com/coreos/pkg/flagutil/file_env_test.go

@@ -0,0 +1,107 @@
+package flagutil
+
+import (
+	"flag"
+	"io/ioutil"
+	"os"
+	"testing"
+)
+
+var envFile = `
+# some secret env vars
+MYPROJ_A=foo		
+MYPROJ_C=woof
+`
+
+func TestSetFlagsFromEnvFile(t *testing.T) {
+	fs := flag.NewFlagSet("testing", flag.ExitOnError)
+	fs.String("a", "", "")
+	fs.String("b", "", "")
+	fs.String("c", "", "")
+	fs.Parse([]string{})
+
+	// add command-line flags
+	if err := fs.Set("b", "bar"); err != nil {
+		t.Fatal(err)
+	}
+	if err := fs.Set("c", "quack"); err != nil {
+		t.Fatal(err)
+	}
+
+	// first verify that flags are as expected before reading the env
+	for f, want := range map[string]string{
+		"a": "",
+		"b": "bar",
+		"c": "quack",
+	} {
+		if got := fs.Lookup(f).Value.String(); got != want {
+			t.Fatalf("flag %q=%q, want %q", f, got, want)
+		}
+	}
+
+	file, err := ioutil.TempFile("", "env-file")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Remove(file.Name())
+	file.Write([]byte(envFile))
+
+	// read env file and verify flags were updated as expected
+	err = SetFlagsFromEnvFile(fs, "MYPROJ", file.Name())
+	if err != nil {
+		t.Errorf("err=%v, want nil", err)
+	}
+	for f, want := range map[string]string{
+		"a": "foo",
+		"b": "bar",
+		"c": "quack",
+	} {
+		if got := fs.Lookup(f).Value.String(); got != want {
+			t.Errorf("flag %q=%q, want %q", f, got, want)
+		}
+	}
+}
+
+func TestSetFlagsFromEnvFile_FlagSetError(t *testing.T) {
+	// now verify that an error is propagated
+	fs := flag.NewFlagSet("testing", flag.ExitOnError)
+	fs.Int("x", 0, "")
+	file, err := ioutil.TempFile("", "env-file")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Remove(file.Name())
+	file.Write([]byte("MYPROJ_X=not_a_number"))
+	if err := SetFlagsFromEnvFile(fs, "MYPROJ", file.Name()); err == nil {
+		t.Errorf("err=nil, want != nil")
+	}
+}
+
+func TestParseLine(t *testing.T) {
+	cases := []struct {
+		line        string
+		expectedKey string
+		expectedVal string
+		nilErr      bool
+	}{
+		{"key=value", "key", "value", true},
+		{" key  =  value  	", "key", "value", true},
+		{"key='#gopher' #blah", "key", "'#gopher' #blah", true},
+		// invalid
+		{"key:value", "", "", false},
+		{"keyvalue", "", "", false},
+	}
+	for _, c := range cases {
+		key, val, err := parseLine(c.line)
+		if (err == nil) != c.nilErr {
+			if c.nilErr {
+				t.Errorf("got %s, want err=nil", err)
+			} else {
+				t.Errorf("got err=nil, want err!=nil")
+			}
+		}
+		if c.expectedKey != key || c.expectedVal != val {
+			t.Errorf("got %q=%q, want %q=%q", key, val, c.expectedKey, c.expectedVal)
+		}
+	}
+}

+ 189 - 0
vendor/github.com/coreos/pkg/progressutil/iocopy.go

@@ -0,0 +1,189 @@
+// Copyright 2016 CoreOS Inc
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package progressutil
+
+import (
+	"errors"
+	"fmt"
+	"io"
+	"sync"
+	"time"
+)
+
+var (
+	ErrAlreadyStarted = errors.New("cannot add copies after PrintAndWait has been called")
+)
+
+type copyReader struct {
+	reader  io.Reader
+	current int64
+	total   int64
+	pb      *ProgressBar
+}
+
+func (cr *copyReader) Read(p []byte) (int, error) {
+	n, err := cr.reader.Read(p)
+	cr.current += int64(n)
+	err1 := cr.updateProgressBar()
+	if err == nil {
+		err = err1
+	}
+	return n, err
+}
+
+func (cr *copyReader) updateProgressBar() error {
+	cr.pb.SetPrintAfter(cr.formattedProgress())
+
+	progress := float64(cr.current) / float64(cr.total)
+	if progress > 1 {
+		progress = 1
+	}
+	return cr.pb.SetCurrentProgress(progress)
+}
+
+// NewCopyProgressPrinter returns a new CopyProgressPrinter
+func NewCopyProgressPrinter() *CopyProgressPrinter {
+	return &CopyProgressPrinter{results: make(chan error), cancel: make(chan struct{})}
+}
+
+// CopyProgressPrinter will perform an arbitrary number of io.Copy calls, while
+// continually printing the progress of each copy.
+type CopyProgressPrinter struct {
+	results chan error
+	cancel  chan struct{}
+
+	// `lock` mutex protects all fields below it in CopyProgressPrinter struct
+	lock    sync.Mutex
+	readers []*copyReader
+	started bool
+	pbp     *ProgressBarPrinter
+}
+
+// AddCopy adds a copy for this CopyProgressPrinter to perform. An io.Copy call
+// will be made to copy bytes from reader to dest, and name and size will be
+// used to label the progress bar and display how much progress has been made.
+// If size is 0, the total size of the reader is assumed to be unknown.
+// AddCopy can only be called before PrintAndWait; otherwise, ErrAlreadyStarted
+// will be returned.
+func (cpp *CopyProgressPrinter) AddCopy(reader io.Reader, name string, size int64, dest io.Writer) error {
+	cpp.lock.Lock()
+	defer cpp.lock.Unlock()
+
+	if cpp.started {
+		return ErrAlreadyStarted
+	}
+	if cpp.pbp == nil {
+		cpp.pbp = &ProgressBarPrinter{}
+		cpp.pbp.PadToBeEven = true
+	}
+
+	cr := &copyReader{
+		reader:  reader,
+		current: 0,
+		total:   size,
+		pb:      cpp.pbp.AddProgressBar(),
+	}
+	cr.pb.SetPrintBefore(name)
+	cr.pb.SetPrintAfter(cr.formattedProgress())
+
+	cpp.readers = append(cpp.readers, cr)
+
+	go func() {
+		_, err := io.Copy(dest, cr)
+		select {
+		case <-cpp.cancel:
+			return
+		case cpp.results <- err:
+			return
+		}
+	}()
+	return nil
+}
+
+// PrintAndWait will print the progress for each copy operation added with
+// AddCopy to printTo every printInterval. This will continue until every added
+// copy is finished, or until cancel is written to.
+// PrintAndWait may only be called once; any subsequent calls will immediately
+// return ErrAlreadyStarted.  After PrintAndWait has been called, no more
+// copies may be added to the CopyProgressPrinter.
+func (cpp *CopyProgressPrinter) PrintAndWait(printTo io.Writer, printInterval time.Duration, cancel chan struct{}) error {
+	cpp.lock.Lock()
+	if cpp.started {
+		cpp.lock.Unlock()
+		return ErrAlreadyStarted
+	}
+	cpp.started = true
+	cpp.lock.Unlock()
+
+	n := len(cpp.readers)
+	if n == 0 {
+		// Nothing to do.
+		return nil
+	}
+
+	defer close(cpp.cancel)
+	t := time.NewTicker(printInterval)
+	allDone := false
+	for i := 0; i < n; {
+		select {
+		case <-cancel:
+			return nil
+		case <-t.C:
+			_, err := cpp.pbp.Print(printTo)
+			if err != nil {
+				return err
+			}
+		case err := <-cpp.results:
+			i++
+			// Once completion is signaled, further on this just drains
+			// (unlikely) errors from the channel.
+			if err == nil && !allDone {
+				allDone, err = cpp.pbp.Print(printTo)
+			}
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func (cr *copyReader) formattedProgress() string {
+	var totalStr string
+	if cr.total == 0 {
+		totalStr = "?"
+	} else {
+		totalStr = ByteUnitStr(cr.total)
+	}
+	return fmt.Sprintf("%s / %s", ByteUnitStr(cr.current), totalStr)
+}
+
+var byteUnits = []string{"B", "KB", "MB", "GB", "TB", "PB"}
+
+// ByteUnitStr pretty prints a number of bytes.
+func ByteUnitStr(n int64) string {
+	var unit string
+	size := float64(n)
+	for i := 1; i < len(byteUnits); i++ {
+		if size < 1000 {
+			unit = byteUnits[i-1]
+			break
+		}
+
+		size = size / 1000
+	}
+
+	return fmt.Sprintf("%.3g %s", size, unit)
+}

+ 256 - 0
vendor/github.com/coreos/pkg/progressutil/progressbar.go

@@ -0,0 +1,256 @@
+// Copyright 2016 CoreOS Inc
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package progressutil
+
+import (
+	"fmt"
+	"io"
+	"os"
+	"strings"
+	"sync"
+
+	"golang.org/x/crypto/ssh/terminal"
+)
+
+var (
+	// ErrorProgressOutOfBounds is returned if the progress is set to a value
+	// not between 0 and 1.
+	ErrorProgressOutOfBounds = fmt.Errorf("progress is out of bounds (0 to 1)")
+
+	// ErrorNoBarsAdded is returned when no progress bars have been added to a
+	// ProgressBarPrinter before PrintAndWait is called.
+	ErrorNoBarsAdded = fmt.Errorf("AddProgressBar hasn't been called yet")
+)
+
+// ProgressBar represents one progress bar in a ProgressBarPrinter. Should not
+// be created directly, use the AddProgressBar on a ProgressBarPrinter to
+// create these.
+type ProgressBar struct {
+	lock sync.Mutex
+
+	currentProgress float64
+	printBefore     string
+	printAfter      string
+	done            bool
+}
+
+func (pb *ProgressBar) clone() *ProgressBar {
+	pb.lock.Lock()
+	pbClone := &ProgressBar{
+		currentProgress: pb.currentProgress,
+		printBefore:     pb.printBefore,
+		printAfter:      pb.printAfter,
+		done:            pb.done,
+	}
+	pb.lock.Unlock()
+	return pbClone
+}
+
+func (pb *ProgressBar) GetCurrentProgress() float64 {
+	pb.lock.Lock()
+	val := pb.currentProgress
+	pb.lock.Unlock()
+	return val
+}
+
+// SetCurrentProgress sets the progress of this ProgressBar. The progress must
+// be between 0 and 1 inclusive.
+func (pb *ProgressBar) SetCurrentProgress(progress float64) error {
+	if progress < 0 || progress > 1 {
+		return ErrorProgressOutOfBounds
+	}
+	pb.lock.Lock()
+	pb.currentProgress = progress
+	pb.lock.Unlock()
+	return nil
+}
+
+// GetDone returns whether or not this progress bar is done
+func (pb *ProgressBar) GetDone() bool {
+	pb.lock.Lock()
+	val := pb.done
+	pb.lock.Unlock()
+	return val
+}
+
+// SetDone sets whether or not this progress bar is done
+func (pb *ProgressBar) SetDone(val bool) {
+	pb.lock.Lock()
+	pb.done = val
+	pb.lock.Unlock()
+}
+
+// GetPrintBefore gets the text printed on the line before the progress bar.
+func (pb *ProgressBar) GetPrintBefore() string {
+	pb.lock.Lock()
+	val := pb.printBefore
+	pb.lock.Unlock()
+	return val
+}
+
+// SetPrintBefore sets the text printed on the line before the progress bar.
+func (pb *ProgressBar) SetPrintBefore(before string) {
+	pb.lock.Lock()
+	pb.printBefore = before
+	pb.lock.Unlock()
+}
+
+// GetPrintAfter gets the text printed on the line after the progress bar.
+func (pb *ProgressBar) GetPrintAfter() string {
+	pb.lock.Lock()
+	val := pb.printAfter
+	pb.lock.Unlock()
+	return val
+}
+
+// SetPrintAfter sets the text printed on the line after the progress bar.
+func (pb *ProgressBar) SetPrintAfter(after string) {
+	pb.lock.Lock()
+	pb.printAfter = after
+	pb.lock.Unlock()
+}
+
+// ProgressBarPrinter will print out the progress of some number of
+// ProgressBars.
+type ProgressBarPrinter struct {
+	lock sync.Mutex
+
+	// DisplayWidth can be set to influence how large the progress bars are.
+	// The bars will be scaled to attempt to produce lines of this number of
+	// characters, but lines of different lengths may still be printed. When
+	// this value is 0 (aka unset), 80 character columns are assumed.
+	DisplayWidth int
+	// PadToBeEven, when set to true, will make Print pad the printBefore text
+	// with trailing spaces and the printAfter text with leading spaces to make
+	// the progress bars the same length.
+	PadToBeEven         bool
+	numLinesInLastPrint int
+	progressBars        []*ProgressBar
+	maxBefore           int
+	maxAfter            int
+}
+
+// AddProgressBar will create a new ProgressBar, register it with this
+// ProgressBarPrinter, and return it. This must be called at least once before
+// PrintAndWait is called.
+func (pbp *ProgressBarPrinter) AddProgressBar() *ProgressBar {
+	pb := &ProgressBar{}
+	pbp.lock.Lock()
+	pbp.progressBars = append(pbp.progressBars, pb)
+	pbp.lock.Unlock()
+	return pb
+}
+
+// Print will print out progress information for each ProgressBar that has been
+// added to this ProgressBarPrinter. The progress will be written to printTo,
+// and if printTo is a terminal it will draw progress bars.  AddProgressBar
+// must be called at least once before Print is called. If printing to a
+// terminal, all draws after the first one will move the cursor up to draw over
+// the previously printed bars.
+func (pbp *ProgressBarPrinter) Print(printTo io.Writer) (bool, error) {
+	pbp.lock.Lock()
+	var bars []*ProgressBar
+	for _, bar := range pbp.progressBars {
+		bars = append(bars, bar.clone())
+	}
+	numColumns := pbp.DisplayWidth
+	pbp.lock.Unlock()
+
+	if len(bars) == 0 {
+		return false, ErrorNoBarsAdded
+	}
+
+	if numColumns == 0 {
+		numColumns = 80
+	}
+
+	if isTerminal(printTo) {
+		moveCursorUp(printTo, pbp.numLinesInLastPrint)
+	}
+
+	for _, bar := range bars {
+		beforeSize := len(bar.GetPrintBefore())
+		afterSize := len(bar.GetPrintAfter())
+		if beforeSize > pbp.maxBefore {
+			pbp.maxBefore = beforeSize
+		}
+		if afterSize > pbp.maxAfter {
+			pbp.maxAfter = afterSize
+		}
+	}
+
+	allDone := true
+	for _, bar := range bars {
+		if isTerminal(printTo) {
+			bar.printToTerminal(printTo, numColumns, pbp.PadToBeEven, pbp.maxBefore, pbp.maxAfter)
+		} else {
+			bar.printToNonTerminal(printTo)
+		}
+		allDone = allDone && bar.GetCurrentProgress() == 1
+	}
+
+	pbp.numLinesInLastPrint = len(bars)
+
+	return allDone, nil
+}
+
+// moveCursorUp moves the cursor up numLines in the terminal
+func moveCursorUp(printTo io.Writer, numLines int) {
+	if numLines > 0 {
+		fmt.Fprintf(printTo, "\033[%dA", numLines)
+	}
+}
+
+func (pb *ProgressBar) printToTerminal(printTo io.Writer, numColumns int, padding bool, maxBefore, maxAfter int) {
+	before := pb.GetPrintBefore()
+	after := pb.GetPrintAfter()
+
+	if padding {
+		before = before + strings.Repeat(" ", maxBefore-len(before))
+		after = strings.Repeat(" ", maxAfter-len(after)) + after
+	}
+
+	progressBarSize := numColumns - (len(fmt.Sprintf("%s [] %s", before, after)))
+	progressBar := ""
+	if progressBarSize > 0 {
+		currentProgress := int(pb.GetCurrentProgress() * float64(progressBarSize))
+		progressBar = fmt.Sprintf("[%s%s] ",
+			strings.Repeat("=", currentProgress),
+			strings.Repeat(" ", progressBarSize-currentProgress))
+	} else {
+		// If we can't fit the progress bar, better to not pad the before/after.
+		before = pb.GetPrintBefore()
+		after = pb.GetPrintAfter()
+	}
+
+	fmt.Fprintf(printTo, "%s %s%s\n", before, progressBar, after)
+}
+
+func (pb *ProgressBar) printToNonTerminal(printTo io.Writer) {
+	if !pb.GetDone() {
+		fmt.Fprintf(printTo, "%s %s\n", pb.printBefore, pb.printAfter)
+		if pb.GetCurrentProgress() == 1 {
+			pb.SetDone(true)
+		}
+	}
+}
+
+// isTerminal returns True when w is going to a tty, and false otherwise.
+func isTerminal(w io.Writer) bool {
+	if f, ok := w.(*os.File); ok {
+		return terminal.IsTerminal(int(f.Fd()))
+	}
+	return false
+}

+ 1 - 1
vendor/github.com/coreos/pkg/test

@@ -14,7 +14,7 @@ COVER=${COVER:-"-cover"}
 
 source ./build
 
-TESTABLE="cryptoutil flagutil timeutil netutil yamlutil httputil health multierror"
+TESTABLE="cryptoutil flagutil timeutil netutil yamlutil httputil health multierror dlopen"
 FORMATTABLE="$TESTABLE capnslog"
 
 # user has not provided PKG override