From f86cac5713774555d4d2fc14851d12a79d4cb068 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 5 Apr 2019 17:02:23 +0200 Subject: [PATCH 1/9] bump gotest.tools v2.3.0 Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- vendor/gotest.tools/LICENSE | 209 +----------------- vendor/gotest.tools/README.md | 6 +- vendor/gotest.tools/assert/cmp/compare.go | 48 +++- vendor/gotest.tools/assert/cmp/result.go | 20 +- vendor/gotest.tools/assert/result.go | 1 - vendor/gotest.tools/env/env.go | 3 + vendor/gotest.tools/fs/file.go | 24 +- vendor/gotest.tools/fs/manifest.go | 18 +- vendor/gotest.tools/fs/ops.go | 37 +++- vendor/gotest.tools/fs/path.go | 52 ++++- vendor/gotest.tools/fs/report.go | 80 ++++++- vendor/gotest.tools/icmd/command.go | 9 +- vendor/gotest.tools/icmd/ops.go | 34 +++ .../gotest.tools/internal/difflib/difflib.go | 25 ++- vendor/gotest.tools/internal/source/defers.go | 53 +++++ vendor/gotest.tools/internal/source/source.go | 203 ++++++++--------- vendor/gotest.tools/poll/check.go | 39 ++++ vendor/gotest.tools/poll/poll.go | 2 +- vendor/gotest.tools/skip/skip.go | 28 ++- 20 files changed, 529 insertions(+), 364 deletions(-) create mode 100644 vendor/gotest.tools/internal/source/defers.go create mode 100644 vendor/gotest.tools/poll/check.go diff --git a/vendor.conf b/vendor.conf index b41e743c93..7742ee509d 100644 --- a/vendor.conf +++ b/vendor.conf @@ -19,7 +19,7 @@ golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba github.com/docker/go-units 47565b4f722fb6ceae66b95f853feed578a4a51c # v0.3.3 github.com/docker/go-connections 7395e3f8aa162843a74ed6d48e79627d9792ac55 # v0.4.0 golang.org/x/text f21a4dfb5e38f5895301dc265a8def02365cc3d0 # v0.3.0 -gotest.tools v2.1.0 +gotest.tools 1083505acf35a0bd8a696b26837e1fb3187a7a83 # v2.3.0 github.com/google/go-cmp v0.2.0 github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 diff --git a/vendor/gotest.tools/LICENSE b/vendor/gotest.tools/LICENSE index d645695673..aeaa2fac3d 100644 --- a/vendor/gotest.tools/LICENSE +++ b/vendor/gotest.tools/LICENSE @@ -1,202 +1,13 @@ +Copyright 2018 gotest.tools authors - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +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 - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + http://www.apache.org/licenses/LICENSE-2.0 - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. +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. diff --git a/vendor/gotest.tools/README.md b/vendor/gotest.tools/README.md index f5df204315..3155723dd7 100644 --- a/vendor/gotest.tools/README.md +++ b/vendor/gotest.tools/README.md @@ -3,7 +3,7 @@ A collection of packages to augment `testing` and support common patterns. [![GoDoc](https://godoc.org/gotest.tools?status.svg)](https://godoc.org/gotest.tools) -[![CircleCI](https://circleci.com/gh/gotestyourself/gotestyourself/tree/master.svg?style=shield)](https://circleci.com/gh/gotestyourself/gotestyourself/tree/master) +[![CircleCI](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master.svg?style=shield)](https://circleci.com/gh/gotestyourself/gotest.tools/tree/master) [![Go Reportcard](https://goreportcard.com/badge/gotest.tools)](https://goreportcard.com/report/gotest.tools) @@ -29,3 +29,7 @@ A collection of packages to augment `testing` and support common patterns. * [gotest.tools/gotestsum](https://github.com/gotestyourself/gotestsum) - go test runner with custom output * [maxbrunsfeld/counterfeiter](https://github.com/maxbrunsfeld/counterfeiter) - generate fakes for interfaces * [jonboulle/clockwork](https://github.com/jonboulle/clockwork) - a fake clock for testing code that uses `time` + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md). diff --git a/vendor/gotest.tools/assert/cmp/compare.go b/vendor/gotest.tools/assert/cmp/compare.go index ae03749e20..cf48d887ac 100644 --- a/vendor/gotest.tools/assert/cmp/compare.go +++ b/vendor/gotest.tools/assert/cmp/compare.go @@ -4,6 +4,7 @@ package cmp // import "gotest.tools/assert/cmp" import ( "fmt" "reflect" + "regexp" "strings" "github.com/google/go-cmp/cmp" @@ -58,6 +59,39 @@ func toResult(success bool, msg string) Result { return ResultFailure(msg) } +// RegexOrPattern may be either a *regexp.Regexp or a string that is a valid +// regexp pattern. +type RegexOrPattern interface{} + +// Regexp succeeds if value v matches regular expression re. +// +// Example: +// assert.Assert(t, cmp.Regexp("^[0-9a-f]{32}$", str)) +// r := regexp.MustCompile("^[0-9a-f]{32}$") +// assert.Assert(t, cmp.Regexp(r, str)) +func Regexp(re RegexOrPattern, v string) Comparison { + match := func(re *regexp.Regexp) Result { + return toResult( + re.MatchString(v), + fmt.Sprintf("value %q does not match regexp %q", v, re.String())) + } + + return func() Result { + switch regex := re.(type) { + case *regexp.Regexp: + return match(regex) + case string: + re, err := regexp.Compile(regex) + if err != nil { + return ResultFailure(err.Error()) + } + return match(re) + default: + return ResultFailure(fmt.Sprintf("invalid type %T for regex pattern", regex)) + } + } +} + // Equal succeeds if x == y. See assert.Equal for full documentation. func Equal(x, y interface{}) Comparison { return func() Result { @@ -186,7 +220,7 @@ func Error(err error, message string) Comparison { return ResultFailure("expected an error, got nil") case err.Error() != message: return ResultFailure(fmt.Sprintf( - "expected error %q, got %+v", message, err)) + "expected error %q, got %s", message, formatErrorMessage(err))) } return ResultSuccess } @@ -201,12 +235,22 @@ func ErrorContains(err error, substring string) Comparison { return ResultFailure("expected an error, got nil") case !strings.Contains(err.Error(), substring): return ResultFailure(fmt.Sprintf( - "expected error to contain %q, got %+v", substring, err)) + "expected error to contain %q, got %s", substring, formatErrorMessage(err))) } return ResultSuccess } } +func formatErrorMessage(err error) string { + if _, ok := err.(interface { + Cause() error + }); ok { + return fmt.Sprintf("%q\n%+v", err, err) + } + // This error was not wrapped with github.com/pkg/errors + return fmt.Sprintf("%q", err) +} + // Nil succeeds if obj is a nil interface, pointer, or function. // // Use NilError() for comparing errors. Use Len(obj, 0) for comparing slices, diff --git a/vendor/gotest.tools/assert/cmp/result.go b/vendor/gotest.tools/assert/cmp/result.go index 7c3c37dd72..204edda4bc 100644 --- a/vendor/gotest.tools/assert/cmp/result.go +++ b/vendor/gotest.tools/assert/cmp/result.go @@ -9,31 +9,37 @@ import ( "gotest.tools/internal/source" ) -// Result of a Comparison. +// A Result of a Comparison. type Result interface { Success() bool } -type result struct { +// StringResult is an implementation of Result that reports the error message +// string verbatim and does not provide any templating or formatting of the +// message. +type StringResult struct { success bool message string } -func (r result) Success() bool { +// Success returns true if the comparison was successful. +func (r StringResult) Success() bool { return r.success } -func (r result) FailureMessage() string { +// FailureMessage returns the message used to provide additional information +// about the failure. +func (r StringResult) FailureMessage() string { return r.message } // ResultSuccess is a constant which is returned by a ComparisonWithResult to // indicate success. -var ResultSuccess = result{success: true} +var ResultSuccess = StringResult{success: true} // ResultFailure returns a failed Result with a failure message. -func ResultFailure(message string) Result { - return result{message: message} +func ResultFailure(message string) StringResult { + return StringResult{message: message} } // ResultFromError returns ResultSuccess if err is nil. Otherwise ResultFailure diff --git a/vendor/gotest.tools/assert/result.go b/vendor/gotest.tools/assert/result.go index 3900264d0b..949d939619 100644 --- a/vendor/gotest.tools/assert/result.go +++ b/vendor/gotest.tools/assert/result.go @@ -70,7 +70,6 @@ func filterPrintableExpr(args []ast.Expr) []ast.Expr { result[i] = starExpr.X continue } - result[i] = nil } return result } diff --git a/vendor/gotest.tools/env/env.go b/vendor/gotest.tools/env/env.go index ed0f189916..609d90e996 100644 --- a/vendor/gotest.tools/env/env.go +++ b/vendor/gotest.tools/env/env.go @@ -79,6 +79,9 @@ func ToMap(env []string) map[string]string { } func getParts(raw string) (string, string) { + if raw == "" { + return "", "" + } // Environment variables on windows can begin with = // http://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx parts := strings.SplitN(raw[1:], "=", 2) diff --git a/vendor/gotest.tools/fs/file.go b/vendor/gotest.tools/fs/file.go index 8bf0188d2f..7d0cab363b 100644 --- a/vendor/gotest.tools/fs/file.go +++ b/vendor/gotest.tools/fs/file.go @@ -7,6 +7,8 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" + "strings" "gotest.tools/assert" "gotest.tools/x/subtest" @@ -40,20 +42,25 @@ func NewFile(t assert.TestingT, prefix string, ops ...PathOp) *File { if ht, ok := t.(helperT); ok { ht.Helper() } - tempfile, err := ioutil.TempFile("", prefix+"-") + tempfile, err := ioutil.TempFile("", cleanPrefix(prefix)+"-") assert.NilError(t, err) file := &File{path: tempfile.Name()} assert.NilError(t, tempfile.Close()) - - for _, op := range ops { - assert.NilError(t, op(file)) - } + assert.NilError(t, applyPathOps(file, ops)) if tc, ok := t.(subtest.TestContext); ok { tc.AddCleanup(file.Remove) } return file } +func cleanPrefix(prefix string) string { + // windows requires both / and \ are replaced + if runtime.GOOS == "windows" { + prefix = strings.Replace(prefix, string(os.PathSeparator), "-", -1) + } + return strings.Replace(prefix, "/", "-", -1) +} + // Path returns the full path to the file func (f *File) Path() string { return f.path @@ -76,13 +83,10 @@ func NewDir(t assert.TestingT, prefix string, ops ...PathOp) *Dir { if ht, ok := t.(helperT); ok { ht.Helper() } - path, err := ioutil.TempDir("", prefix+"-") + path, err := ioutil.TempDir("", cleanPrefix(prefix)+"-") assert.NilError(t, err) dir := &Dir{path: path} - - for _, op := range ops { - assert.NilError(t, op(dir)) - } + assert.NilError(t, applyPathOps(dir, ops)) if tc, ok := t.(subtest.TestContext); ok { tc.AddCleanup(dir.Remove) } diff --git a/vendor/gotest.tools/fs/manifest.go b/vendor/gotest.tools/fs/manifest.go index 00976ef19c..e5e693e6c5 100644 --- a/vendor/gotest.tools/fs/manifest.go +++ b/vendor/gotest.tools/fs/manifest.go @@ -24,7 +24,9 @@ type resource struct { type file struct { resource - content io.ReadCloser + content io.ReadCloser + ignoreCariageReturn bool + compareContentFunc func(b []byte) CompareResult } func (f *file) Type() string { @@ -42,7 +44,8 @@ func (f *symlink) Type() string { type directory struct { resource - items map[string]dirEntry + items map[string]dirEntry + filepathGlobs map[string]*filePath } func (f *directory) Type() string { @@ -94,8 +97,9 @@ func newDirectory(path string, info os.FileInfo) (*directory, error) { } return &directory{ - resource: newResourceFromInfo(info), - items: items, + resource: newResourceFromInfo(info), + items: items, + filepathGlobs: make(map[string]*filePath), }, nil } @@ -113,6 +117,9 @@ func getTypedResource(path string, info os.FileInfo) (dirEntry, error) { func newSymlink(path string, info os.FileInfo) (*symlink, error) { target, err := os.Readlink(path) + if err != nil { + return nil, err + } return &symlink{ resource: newResourceFromInfo(info), target: target, @@ -122,6 +129,9 @@ func newSymlink(path string, info os.FileInfo) (*symlink, error) { func newFile(path string, info os.FileInfo) (*file, error) { // TODO: defer file opening to reduce number of open FDs? readCloser, err := os.Open(path) + if err != nil { + return nil, err + } return &file{ resource: newResourceFromInfo(info), content: readCloser, diff --git a/vendor/gotest.tools/fs/ops.go b/vendor/gotest.tools/fs/ops.go index ec9d11c110..c3c33587b6 100644 --- a/vendor/gotest.tools/fs/ops.go +++ b/vendor/gotest.tools/fs/ops.go @@ -10,6 +10,7 @@ import ( "time" "github.com/pkg/errors" + "gotest.tools/assert" ) const defaultFileMode = 0644 @@ -144,6 +145,14 @@ func WithDir(name string, ops ...PathOp) PathOp { } } +// Apply the PathOps to the File +func Apply(t assert.TestingT, path Path, ops ...PathOp) { + if ht, ok := t.(helperT); ok { + ht.Helper() + } + assert.NilError(t, applyPathOps(path, ops)) +} + func applyPathOps(path Path, ops []PathOp) error { for _, op := range ops { if err := op(path); err != nil { @@ -172,23 +181,35 @@ func copyDirectory(source, dest string) error { for _, entry := range entries { sourcePath := filepath.Join(source, entry.Name()) destPath := filepath.Join(dest, entry.Name()) - if entry.IsDir() { + switch { + case entry.IsDir(): if err := os.Mkdir(destPath, 0755); err != nil { return err } if err := copyDirectory(sourcePath, destPath); err != nil { return err } - continue - } - // TODO: handle symlinks - if err := copyFile(sourcePath, destPath); err != nil { - return err + case entry.Mode()&os.ModeSymlink != 0: + if err := copySymLink(sourcePath, destPath); err != nil { + return err + } + default: + if err := copyFile(sourcePath, destPath); err != nil { + return err + } } } return nil } +func copySymLink(source, dest string) error { + link, err := os.Readlink(source) + if err != nil { + return err + } + return os.Symlink(link, dest) +} + func copyFile(source, dest string) error { content, err := ioutil.ReadFile(source) if err != nil { @@ -219,7 +240,7 @@ func WithSymlink(path, target string) PathOp { func WithHardlink(path, target string) PathOp { return func(root Path) error { if _, ok := root.(manifestDirectory); ok { - return errors.New("WithHardlink yet implemented for manifests") + return errors.New("WithHardlink not implemented for manifests") } return os.Link(filepath.Join(root.Path(), target), filepath.Join(root.Path(), path)) } @@ -230,7 +251,7 @@ func WithHardlink(path, target string) PathOp { func WithTimestamps(atime, mtime time.Time) PathOp { return func(root Path) error { if _, ok := root.(manifestDirectory); ok { - return errors.New("WithTimestamp yet implemented for manifests") + return errors.New("WithTimestamp not implemented for manifests") } return os.Chtimes(root.Path(), atime, mtime) } diff --git a/vendor/gotest.tools/fs/path.go b/vendor/gotest.tools/fs/path.go index baf777f0df..4bb38774bc 100644 --- a/vendor/gotest.tools/fs/path.go +++ b/vendor/gotest.tools/fs/path.go @@ -64,6 +64,13 @@ func (p *directoryPath) AddFile(path string, ops ...PathOp) error { return applyPathOps(exp, ops) } +func (p *directoryPath) AddGlobFiles(glob string, ops ...PathOp) error { + newFile := &file{resource: newResource(0)} + newFilePath := &filePath{file: newFile} + p.directory.filepathGlobs[glob] = newFilePath + return applyPathOps(newFilePath, ops) +} + func (p *directoryPath) AddDirectory(path string, ops ...PathOp) error { newDir := newDirectoryWithDefaults() p.directory.items[path] = newDir @@ -87,8 +94,9 @@ func Expected(t assert.TestingT, ops ...PathOp) Manifest { func newDirectoryWithDefaults() *directory { return &directory{ - resource: newResource(defaultRootDirMode), - items: make(map[string]dirEntry), + resource: newResource(defaultRootDirMode), + items: make(map[string]dirEntry), + filepathGlobs: make(map[string]*filePath), } } @@ -127,6 +135,15 @@ func MatchAnyFileContent(path Path) error { return nil } +// MatchContentIgnoreCarriageReturn is a PathOp that ignores cariage return +// discrepancies. +func MatchContentIgnoreCarriageReturn(path Path) error { + if m, ok := path.(*filePath); ok { + m.file.ignoreCariageReturn = true + } + return nil +} + const anyFile = "*" // MatchExtraFiles is a PathOp that updates a Manifest to allow a directory @@ -138,6 +155,37 @@ func MatchExtraFiles(path Path) error { return nil } +// CompareResult is the result of comparison. +// +// See gotest.tools/assert/cmp.StringResult for a convenient implementation of +// this interface. +type CompareResult interface { + Success() bool + FailureMessage() string +} + +// MatchFileContent is a PathOp that updates a Manifest to use the provided +// function to determine if a file's content matches the expectation. +func MatchFileContent(f func([]byte) CompareResult) PathOp { + return func(path Path) error { + if m, ok := path.(*filePath); ok { + m.file.compareContentFunc = f + } + return nil + } +} + +// MatchFilesWithGlob is a PathOp that updates a Manifest to match files using +// glob pattern, and check them using the ops. +func MatchFilesWithGlob(glob string, ops ...PathOp) PathOp { + return func(path Path) error { + if m, ok := path.(*directoryPath); ok { + m.AddGlobFiles(glob, ops...) + } + return nil + } +} + // anyFileMode is represented by uint32_max const anyFileMode os.FileMode = 4294967295 diff --git a/vendor/gotest.tools/fs/report.go b/vendor/gotest.tools/fs/report.go index 4de85a6ef7..adc5a5f1bc 100644 --- a/vendor/gotest.tools/fs/report.go +++ b/vendor/gotest.tools/fs/report.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "sort" "strings" @@ -67,6 +68,11 @@ func eqResource(x, y resource) []problem { return p } +func removeCarriageReturn(in []byte) []byte { + return bytes.Replace(in, []byte("\r\n"), []byte("\n"), -1) +} + +// nolint: gocyclo func eqFile(x, y *file) []problem { p := eqResource(x.resource, y.resource) @@ -96,6 +102,19 @@ func eqFile(x, y *file) []problem { return p } + if x.compareContentFunc != nil { + r := x.compareContentFunc(yContent) + if !r.Success() { + p = append(p, existenceProblem("content", r.FailureMessage())) + } + return p + } + + if x.ignoreCariageReturn || y.ignoreCariageReturn { + xContent = removeCarriageReturn(xContent) + yContent = removeCarriageReturn(yContent) + } + if !bytes.Equal(xContent, yContent) { p = append(p, diffContent(xContent, yContent)) } @@ -126,7 +145,13 @@ func indent(s, prefix string) string { func eqSymlink(x, y *symlink) []problem { p := eqResource(x.resource, y.resource) - if x.target != y.target { + xTarget := x.target + yTarget := y.target + if runtime.GOOS == "windows" { + xTarget = strings.ToLower(xTarget) + yTarget = strings.ToLower(yTarget) + } + if xTarget != yTarget { p = append(p, notEqual("target", x.target, y.target)) } return p @@ -135,11 +160,13 @@ func eqSymlink(x, y *symlink) []problem { func eqDirectory(path string, x, y *directory) []failure { p := eqResource(x.resource, y.resource) var f []failure + matchedFiles := make(map[string]bool) for _, name := range sortedKeys(x.items) { if name == anyFile { continue } + matchedFiles[name] = true xEntry := x.items[name] yEntry, ok := y.items[name] if !ok { @@ -155,19 +182,30 @@ func eqDirectory(path string, x, y *directory) []failure { f = append(f, eqEntry(filepath.Join(path, name), xEntry, yEntry)...) } - if _, ok := x.items[anyFile]; !ok { + if len(x.filepathGlobs) != 0 { for _, name := range sortedKeys(y.items) { - if _, ok := x.items[name]; !ok { - yEntry := y.items[name] - p = append(p, existenceProblem(name, "unexpected %s", yEntry.Type())) - } + m := matchGlob(name, y.items[name], x.filepathGlobs) + matchedFiles[name] = m.match + f = append(f, m.failures...) } } - if len(p) > 0 { - f = append(f, failure{path: path, problems: p}) + if _, ok := x.items[anyFile]; ok { + return maybeAppendFailure(f, path, p) } - return f + for _, name := range sortedKeys(y.items) { + if !matchedFiles[name] { + p = append(p, existenceProblem(name, "unexpected %s", y.items[name].Type())) + } + } + return maybeAppendFailure(f, path, p) +} + +func maybeAppendFailure(failures []failure, path string, problems []problem) []failure { + if len(problems) > 0 { + return append(failures, failure{path: path, problems: problems}) + } + return failures } func sortedKeys(items map[string]dirEntry) []string { @@ -199,6 +237,30 @@ func eqEntry(path string, x, y dirEntry) []failure { return nil } +type globMatch struct { + match bool + failures []failure +} + +func matchGlob(name string, yEntry dirEntry, globs map[string]*filePath) globMatch { + m := globMatch{} + + for glob, expectedFile := range globs { + ok, err := filepath.Match(glob, name) + if err != nil { + p := errProblem("failed to match glob pattern", err) + f := failure{path: name, problems: []problem{p}} + m.failures = append(m.failures, f) + } + if ok { + m.match = true + m.failures = eqEntry(name, expectedFile.file, yEntry) + return m + } + } + return m +} + func formatFailures(failures []failure) string { sort.Slice(failures, func(i, j int) bool { return failures[i].path < failures[j].path diff --git a/vendor/gotest.tools/icmd/command.go b/vendor/gotest.tools/icmd/command.go index 901895991a..e931ccb928 100644 --- a/vendor/gotest.tools/icmd/command.go +++ b/vendor/gotest.tools/icmd/command.go @@ -132,18 +132,21 @@ func (r *Result) String() string { if r.Timeout { timeout = " (timeout)" } + var errString string + if r.Error != nil { + errString = "\nError: " + r.Error.Error() + } return fmt.Sprintf(` Command: %s -ExitCode: %d%s -Error: %v +ExitCode: %d%s%s Stdout: %v Stderr: %v `, strings.Join(r.Cmd.Args, " "), r.ExitCode, timeout, - r.Error, + errString, r.Stdout(), r.Stderr()) } diff --git a/vendor/gotest.tools/icmd/ops.go b/vendor/gotest.tools/icmd/ops.go index 02b1d84023..18176eead3 100644 --- a/vendor/gotest.tools/icmd/ops.go +++ b/vendor/gotest.tools/icmd/ops.go @@ -1,4 +1,38 @@ package icmd +import ( + "io" + "time" +) + // CmdOp is an operation which modified a Cmd structure used to execute commands type CmdOp func(*Cmd) + +// WithTimeout sets the timeout duration of the command +func WithTimeout(timeout time.Duration) CmdOp { + return func(c *Cmd) { + c.Timeout = timeout + } +} + +// WithEnv sets the environment variable of the command. +// Each arguments are in the form of KEY=VALUE +func WithEnv(env ...string) CmdOp { + return func(c *Cmd) { + c.Env = env + } +} + +// Dir sets the working directory of the command +func Dir(path string) CmdOp { + return func(c *Cmd) { + c.Dir = path + } +} + +// WithStdin sets the standard input of the command to the specified reader +func WithStdin(r io.Reader) CmdOp { + return func(c *Cmd) { + c.Stdin = r + } +} diff --git a/vendor/gotest.tools/internal/difflib/difflib.go b/vendor/gotest.tools/internal/difflib/difflib.go index 5efa99c1d4..b6f486b9c9 100644 --- a/vendor/gotest.tools/internal/difflib/difflib.go +++ b/vendor/gotest.tools/internal/difflib/difflib.go @@ -1,4 +1,4 @@ -/* Package difflib is a partial port of Python difflib module. +/*Package difflib is a partial port of Python difflib module. Original source: https://github.com/pmezard/go-difflib @@ -20,12 +20,14 @@ func max(a, b int) int { return b } +// Match stores line numbers of size of match type Match struct { A int B int Size int } +// OpCode identifies the type of diff type OpCode struct { Tag byte I1 int @@ -73,19 +75,20 @@ type SequenceMatcher struct { opCodes []OpCode } +// NewMatcher returns a new SequenceMatcher func NewMatcher(a, b []string) *SequenceMatcher { m := SequenceMatcher{autoJunk: true} m.SetSeqs(a, b) return &m } -// Set two sequences to be compared. +// SetSeqs sets two sequences to be compared. func (m *SequenceMatcher) SetSeqs(a, b []string) { m.SetSeq1(a) m.SetSeq2(b) } -// Set the first sequence to be compared. The second sequence to be compared is +// SetSeq1 sets the first sequence to be compared. The second sequence to be compared is // not changed. // // SequenceMatcher computes and caches detailed information about the second @@ -103,7 +106,7 @@ func (m *SequenceMatcher) SetSeq1(a []string) { m.opCodes = nil } -// Set the second sequence to be compared. The first sequence to be compared is +// SetSeq2 sets the second sequence to be compared. The first sequence to be compared is // not changed. func (m *SequenceMatcher) SetSeq2(b []string) { if &b == &m.b { @@ -129,12 +132,12 @@ func (m *SequenceMatcher) chainB() { m.bJunk = map[string]struct{}{} if m.IsJunk != nil { junk := m.bJunk - for s, _ := range b2j { + for s := range b2j { if m.IsJunk(s) { junk[s] = struct{}{} } } - for s, _ := range junk { + for s := range junk { delete(b2j, s) } } @@ -149,7 +152,7 @@ func (m *SequenceMatcher) chainB() { popular[s] = struct{}{} } } - for s, _ := range popular { + for s := range popular { delete(b2j, s) } } @@ -259,7 +262,7 @@ func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { return Match{A: besti, B: bestj, Size: bestsize} } -// Return list of triples describing matching subsequences. +// GetMatchingBlocks returns a list of triples describing matching subsequences. // // Each triple is of the form (i, j, n), and means that // a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in @@ -323,7 +326,7 @@ func (m *SequenceMatcher) GetMatchingBlocks() []Match { return m.matchingBlocks } -// Return list of 5-tuples describing how to turn a into b. +// GetOpCodes returns a list of 5-tuples describing how to turn a into b. // // Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple // has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the @@ -374,7 +377,7 @@ func (m *SequenceMatcher) GetOpCodes() []OpCode { return m.opCodes } -// Isolate change clusters by eliminating ranges with no changes. +// GetGroupedOpCodes isolates change clusters by eliminating ranges with no changes. // // Return a generator of groups with up to n lines of context. // Each group is in the same format as returned by GetOpCodes(). @@ -384,7 +387,7 @@ func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { } codes := m.GetOpCodes() if len(codes) == 0 { - codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} + codes = []OpCode{{'e', 0, 1, 0, 1}} } // Fixup leading and trailing groups if they show no changes. if codes[0].Tag == 'e' { diff --git a/vendor/gotest.tools/internal/source/defers.go b/vendor/gotest.tools/internal/source/defers.go new file mode 100644 index 0000000000..66cfafbb64 --- /dev/null +++ b/vendor/gotest.tools/internal/source/defers.go @@ -0,0 +1,53 @@ +package source + +import ( + "go/ast" + "go/token" + + "github.com/pkg/errors" +) + +func scanToDeferLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { + var matchedNode ast.Node + ast.Inspect(node, func(node ast.Node) bool { + switch { + case node == nil || matchedNode != nil: + return false + case fileset.Position(node.End()).Line == lineNum: + if funcLit, ok := node.(*ast.FuncLit); ok { + matchedNode = funcLit + return false + } + } + return true + }) + debug("defer line node: %s", debugFormatNode{matchedNode}) + return matchedNode +} + +func guessDefer(node ast.Node) (ast.Node, error) { + defers := collectDefers(node) + switch len(defers) { + case 0: + return nil, errors.New("failed to expression in defer") + case 1: + return defers[0].Call, nil + default: + return nil, errors.Errorf( + "ambiguous call expression: multiple (%d) defers in call block", + len(defers)) + } +} + +func collectDefers(node ast.Node) []*ast.DeferStmt { + var defers []*ast.DeferStmt + ast.Inspect(node, func(node ast.Node) bool { + if d, ok := node.(*ast.DeferStmt); ok { + defers = append(defers, d) + debug("defer: %s", debugFormatNode{d}) + return false + } + return true + }) + return defers +} diff --git a/vendor/gotest.tools/internal/source/source.go b/vendor/gotest.tools/internal/source/source.go index a05933cc33..8a5d0e8d35 100644 --- a/vendor/gotest.tools/internal/source/source.go +++ b/vendor/gotest.tools/internal/source/source.go @@ -24,106 +24,12 @@ func FormattedCallExprArg(stackIndex int, argPos int) (string, error) { if err != nil { return "", err } + if argPos >= len(args) { + return "", errors.New("failed to find expression") + } return FormatNode(args[argPos]) } -func getNodeAtLine(filename string, lineNum int) (ast.Node, error) { - fileset := token.NewFileSet() - astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors) - if err != nil { - return nil, errors.Wrapf(err, "failed to parse source file: %s", filename) - } - - node := scanToLine(fileset, astFile, lineNum) - if node == nil { - return nil, errors.Errorf( - "failed to find an expression on line %d in %s", lineNum, filename) - } - return node, nil -} - -func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { - v := &scanToLineVisitor{lineNum: lineNum, fileset: fileset} - ast.Walk(v, node) - return v.matchedNode -} - -type scanToLineVisitor struct { - lineNum int - matchedNode ast.Node - fileset *token.FileSet -} - -func (v *scanToLineVisitor) Visit(node ast.Node) ast.Visitor { - if node == nil || v.matchedNode != nil { - return nil - } - if v.nodePosition(node).Line == v.lineNum { - v.matchedNode = node - return nil - } - return v -} - -// In golang 1.9 the line number changed from being the line where the statement -// ended to the line where the statement began. -func (v *scanToLineVisitor) nodePosition(node ast.Node) token.Position { - if goVersionBefore19 { - return v.fileset.Position(node.End()) - } - return v.fileset.Position(node.Pos()) -} - -var goVersionBefore19 = isGOVersionBefore19() - -func isGOVersionBefore19() bool { - version := runtime.Version() - // not a release version - if !strings.HasPrefix(version, "go") { - return false - } - version = strings.TrimPrefix(version, "go") - parts := strings.Split(version, ".") - if len(parts) < 2 { - return false - } - minor, err := strconv.ParseInt(parts[1], 10, 32) - return err == nil && parts[0] == "1" && minor < 9 -} - -func getCallExprArgs(node ast.Node) ([]ast.Expr, error) { - visitor := &callExprVisitor{} - ast.Walk(visitor, node) - if visitor.expr == nil { - return nil, errors.New("failed to find call expression") - } - return visitor.expr.Args, nil -} - -type callExprVisitor struct { - expr *ast.CallExpr -} - -func (v *callExprVisitor) Visit(node ast.Node) ast.Visitor { - if v.expr != nil || node == nil { - return nil - } - debug("visit (%T): %s", node, debugFormatNode{node}) - - if callExpr, ok := node.(*ast.CallExpr); ok { - v.expr = callExpr - return nil - } - return v -} - -// FormatNode using go/format.Node and return the result as a string -func FormatNode(node ast.Node) (string, error) { - buf := new(bytes.Buffer) - err := format.Node(buf, token.NewFileSet(), node) - return buf.String(), err -} - // CallExprArgs returns the ast.Expr slice for the args of an ast.CallExpr at // the index in the call stack. func CallExprArgs(stackIndex int) ([]ast.Expr, error) { @@ -137,12 +43,109 @@ func CallExprArgs(stackIndex int) ([]ast.Expr, error) { if err != nil { return nil, err } - debug("found node (%T): %s", node, debugFormatNode{node}) + debug("found node: %s", debugFormatNode{node}) return getCallExprArgs(node) } -var debugEnabled = os.Getenv("GOTESTYOURSELF_DEBUG") != "" +func getNodeAtLine(filename string, lineNum int) (ast.Node, error) { + fileset := token.NewFileSet() + astFile, err := parser.ParseFile(fileset, filename, nil, parser.AllErrors) + if err != nil { + return nil, errors.Wrapf(err, "failed to parse source file: %s", filename) + } + + if node := scanToLine(fileset, astFile, lineNum); node != nil { + return node, nil + } + if node := scanToDeferLine(fileset, astFile, lineNum); node != nil { + node, err := guessDefer(node) + if err != nil || node != nil { + return node, err + } + } + return nil, errors.Errorf( + "failed to find an expression on line %d in %s", lineNum, filename) +} + +func scanToLine(fileset *token.FileSet, node ast.Node, lineNum int) ast.Node { + var matchedNode ast.Node + ast.Inspect(node, func(node ast.Node) bool { + switch { + case node == nil || matchedNode != nil: + return false + case nodePosition(fileset, node).Line == lineNum: + matchedNode = node + return false + } + return true + }) + return matchedNode +} + +// In golang 1.9 the line number changed from being the line where the statement +// ended to the line where the statement began. +func nodePosition(fileset *token.FileSet, node ast.Node) token.Position { + if goVersionBefore19 { + return fileset.Position(node.End()) + } + return fileset.Position(node.Pos()) +} + +var goVersionBefore19 = func() bool { + version := runtime.Version() + // not a release version + if !strings.HasPrefix(version, "go") { + return false + } + version = strings.TrimPrefix(version, "go") + parts := strings.Split(version, ".") + if len(parts) < 2 { + return false + } + minor, err := strconv.ParseInt(parts[1], 10, 32) + return err == nil && parts[0] == "1" && minor < 9 +}() + +func getCallExprArgs(node ast.Node) ([]ast.Expr, error) { + visitor := &callExprVisitor{} + ast.Walk(visitor, node) + if visitor.expr == nil { + return nil, errors.New("failed to find call expression") + } + debug("callExpr: %s", debugFormatNode{visitor.expr}) + return visitor.expr.Args, nil +} + +type callExprVisitor struct { + expr *ast.CallExpr +} + +func (v *callExprVisitor) Visit(node ast.Node) ast.Visitor { + if v.expr != nil || node == nil { + return nil + } + debug("visit: %s", debugFormatNode{node}) + + switch typed := node.(type) { + case *ast.CallExpr: + v.expr = typed + return nil + case *ast.DeferStmt: + ast.Walk(v, typed.Call.Fun) + return nil + } + return v +} + +// FormatNode using go/format.Node and return the result as a string +func FormatNode(node ast.Node) (string, error) { + buf := new(bytes.Buffer) + err := format.Node(buf, token.NewFileSet(), node) + return buf.String(), err +} + +var debugEnabled = os.Getenv("GOTESTTOOLS_DEBUG") != "" func debug(format string, args ...interface{}) { if debugEnabled { @@ -159,5 +162,5 @@ func (n debugFormatNode) String() string { if err != nil { return fmt.Sprintf("failed to format %s: %s", n.Node, err) } - return out + return fmt.Sprintf("(%T) %s", n.Node, out) } diff --git a/vendor/gotest.tools/poll/check.go b/vendor/gotest.tools/poll/check.go new file mode 100644 index 0000000000..060b099890 --- /dev/null +++ b/vendor/gotest.tools/poll/check.go @@ -0,0 +1,39 @@ +package poll + +import ( + "net" + "os" +) + +// Check is a function which will be used as check for the WaitOn method. +type Check func(t LogT) Result + +// FileExists looks on filesystem and check that path exists. +func FileExists(path string) Check { + return func(t LogT) Result { + _, err := os.Stat(path) + if os.IsNotExist(err) { + t.Logf("waiting on file %s to exist", path) + return Continue("file %s does not exist", path) + } + if err != nil { + return Error(err) + } + + return Success() + } +} + +// Connection try to open a connection to the address on the +// named network. See net.Dial for a description of the network and +// address parameters. +func Connection(network, address string) Check { + return func(t LogT) Result { + _, err := net.Dial(network, address) + if err != nil { + t.Logf("waiting on socket %s://%s to be available...", network, address) + return Continue("socket %s://%s not available", network, address) + } + return Success() + } +} diff --git a/vendor/gotest.tools/poll/poll.go b/vendor/gotest.tools/poll/poll.go index 3e3dd7f58a..5e238dca42 100644 --- a/vendor/gotest.tools/poll/poll.go +++ b/vendor/gotest.tools/poll/poll.go @@ -104,7 +104,7 @@ func Error(err error) Result { // WaitOn a condition or until a timeout. Poll by calling check and exit when // check returns a done Result. To fail a test and exit polling with an error // return a error result. -func WaitOn(t TestingT, check func(t LogT) Result, pollOps ...SettingOp) { +func WaitOn(t TestingT, check Check, pollOps ...SettingOp) { if ht, ok := t.(helperT); ok { ht.Helper() } diff --git a/vendor/gotest.tools/skip/skip.go b/vendor/gotest.tools/skip/skip.go index 4bfc9a11c2..d27ca53c3d 100644 --- a/vendor/gotest.tools/skip/skip.go +++ b/vendor/gotest.tools/skip/skip.go @@ -19,17 +19,29 @@ type skipT interface { Log(args ...interface{}) } +// Result of skip function +type Result interface { + Skip() bool + Message() string +} + type helperT interface { Helper() } -// BoolOrCheckFunc can be a bool or func() bool, other types will panic +// BoolOrCheckFunc can be a bool, func() bool, or func() Result. Other types will panic type BoolOrCheckFunc interface{} -// If the condition expression evaluates to true, or the condition function returns -// true, skip the test. +// If the condition expression evaluates to true, skip the test. +// +// The condition argument may be one of three types: bool, func() bool, or +// func() SkipResult. +// When called with a bool, the test will be skip if the condition evaluates to true. +// When called with a func() bool, the test will be skip if the function returns true. +// When called with a func() Result, the test will be skip if the Skip method +// of the result returns true. // The skip message will contain the source code of the expression. -// Extra message text can be passed as a format string with args +// Extra message text can be passed as a format string with args. func If(t skipT, condition BoolOrCheckFunc, msgAndArgs ...interface{}) { if ht, ok := t.(helperT); ok { ht.Helper() @@ -41,12 +53,18 @@ func If(t skipT, condition BoolOrCheckFunc, msgAndArgs ...interface{}) { if check() { t.Skip(format.WithCustomMessage(getFunctionName(check), msgAndArgs...)) } + case func() Result: + result := check() + if result.Skip() { + msg := getFunctionName(check) + ": " + result.Message() + t.Skip(format.WithCustomMessage(msg, msgAndArgs...)) + } default: panic(fmt.Sprintf("invalid type for condition arg: %T", check)) } } -func getFunctionName(function func() bool) string { +func getFunctionName(function interface{}) string { funcPath := runtime.FuncForPC(reflect.ValueOf(function).Pointer()).Name() return strings.SplitN(path.Base(funcPath), ".", 2)[1] } From f5b80463355c53d858b90cdf505823e2378378b4 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Fri, 5 Apr 2019 17:28:47 +0200 Subject: [PATCH 2/9] bump github.com/kr/pty v1.1.4 Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- vendor/github.com/kr/pty/README.md | 64 +++++++++++++++ vendor/github.com/kr/pty/ioctl.go | 2 + vendor/github.com/kr/pty/pty_darwin.go | 15 ++-- vendor/github.com/kr/pty/pty_dragonfly.go | 80 +++++++++++++++++++ vendor/github.com/kr/pty/pty_freebsd.go | 19 +++-- vendor/github.com/kr/pty/pty_linux.go | 11 ++- vendor/github.com/kr/pty/pty_openbsd.go | 33 ++++++++ vendor/github.com/kr/pty/pty_unsupported.go | 2 +- vendor/github.com/kr/pty/run.go | 36 ++++++++- vendor/github.com/kr/pty/util.go | 49 +++++++++--- .../kr/pty/ztypes_dragonfly_amd64.go | 14 ++++ vendor/github.com/kr/pty/ztypes_mipsx.go | 12 +++ .../github.com/kr/pty/ztypes_openbsd_386.go | 13 +++ .../github.com/kr/pty/ztypes_openbsd_amd64.go | 13 +++ 15 files changed, 334 insertions(+), 31 deletions(-) create mode 100644 vendor/github.com/kr/pty/pty_dragonfly.go create mode 100644 vendor/github.com/kr/pty/pty_openbsd.go create mode 100644 vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go create mode 100644 vendor/github.com/kr/pty/ztypes_mipsx.go create mode 100644 vendor/github.com/kr/pty/ztypes_openbsd_386.go create mode 100644 vendor/github.com/kr/pty/ztypes_openbsd_amd64.go diff --git a/vendor.conf b/vendor.conf index 7742ee509d..1cf0b56c57 100644 --- a/vendor.conf +++ b/vendor.conf @@ -9,7 +9,7 @@ github.com/google/uuid v1.1.1 github.com/gorilla/mux v1.7.0 github.com/Microsoft/opengcs a10967154e143a36014584a6f664344e3bb0aa64 github.com/konsorten/go-windows-terminal-sequences v1.0.1 -github.com/kr/pty 5cf931ef8f +github.com/kr/pty 521317be5ebc228a0f0ede099fa2a0b5ece22e49 # v1.1.4 github.com/mattn/go-shellwords v1.0.3 github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1 github.com/tchap/go-patricia v2.2.6 diff --git a/vendor/github.com/kr/pty/README.md b/vendor/github.com/kr/pty/README.md index 7b7900c3ae..f9bb002e03 100644 --- a/vendor/github.com/kr/pty/README.md +++ b/vendor/github.com/kr/pty/README.md @@ -8,6 +8,8 @@ Pty is a Go package for using unix pseudo-terminals. ## Example +### Command + ```go package main @@ -34,3 +36,65 @@ func main() { io.Copy(os.Stdout, f) } ``` + +### Shell + +```go +package main + +import ( + "io" + "log" + "os" + "os/exec" + "os/signal" + "syscall" + + "github.com/kr/pty" + "golang.org/x/crypto/ssh/terminal" +) + +func test() error { + // Create arbitrary command. + c := exec.Command("bash") + + // Start the command with a pty. + ptmx, err := pty.Start(c) + if err != nil { + return err + } + // Make sure to close the pty at the end. + defer func() { _ = ptmx.Close() }() // Best effort. + + // Handle pty size. + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGWINCH) + go func() { + for range ch { + if err := pty.InheritSize(os.Stdin, ptmx); err != nil { + log.Printf("error resizing pty: %s", err) + } + } + }() + ch <- syscall.SIGWINCH // Initial resize. + + // Set stdin in raw mode. + oldState, err := terminal.MakeRaw(int(os.Stdin.Fd())) + if err != nil { + panic(err) + } + defer func() { _ = terminal.Restore(int(os.Stdin.Fd()), oldState) }() // Best effort. + + // Copy stdin to the pty and the pty to stdout. + go func() { _, _ = io.Copy(ptmx, os.Stdin) }() + _, _ = io.Copy(os.Stdout, ptmx) + + return nil +} + +func main() { + if err := test(); err != nil { + log.Fatal(err) + } +} +``` diff --git a/vendor/github.com/kr/pty/ioctl.go b/vendor/github.com/kr/pty/ioctl.go index 5b856e8711..c57c19e7e2 100644 --- a/vendor/github.com/kr/pty/ioctl.go +++ b/vendor/github.com/kr/pty/ioctl.go @@ -1,3 +1,5 @@ +// +build !windows + package pty import "syscall" diff --git a/vendor/github.com/kr/pty/pty_darwin.go b/vendor/github.com/kr/pty/pty_darwin.go index 4f4d5ca26e..6344b6b0ef 100644 --- a/vendor/github.com/kr/pty/pty_darwin.go +++ b/vendor/github.com/kr/pty/pty_darwin.go @@ -8,23 +8,28 @@ import ( ) func open() (pty, tty *os.File, err error) { - p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + pFD, err := syscall.Open("/dev/ptmx", syscall.O_RDWR|syscall.O_CLOEXEC, 0) if err != nil { return nil, nil, err } + p := os.NewFile(uintptr(pFD), "/dev/ptmx") + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() sname, err := ptsname(p) if err != nil { return nil, nil, err } - err = grantpt(p) - if err != nil { + if err := grantpt(p); err != nil { return nil, nil, err } - err = unlockpt(p) - if err != nil { + if err := unlockpt(p); err != nil { return nil, nil, err } diff --git a/vendor/github.com/kr/pty/pty_dragonfly.go b/vendor/github.com/kr/pty/pty_dragonfly.go new file mode 100644 index 0000000000..b7d1f20f29 --- /dev/null +++ b/vendor/github.com/kr/pty/pty_dragonfly.go @@ -0,0 +1,80 @@ +package pty + +import ( + "errors" + "os" + "strings" + "syscall" + "unsafe" +) + +// same code as pty_darwin.go +func open() (pty, tty *os.File, err error) { + p, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + + sname, err := ptsname(p) + if err != nil { + return nil, nil, err + } + + if err := grantpt(p); err != nil { + return nil, nil, err + } + + if err := unlockpt(p); err != nil { + return nil, nil, err + } + + t, err := os.OpenFile(sname, os.O_RDWR, 0) + if err != nil { + return nil, nil, err + } + return p, t, nil +} + +func grantpt(f *os.File) error { + _, err := isptmaster(f.Fd()) + return err +} + +func unlockpt(f *os.File) error { + _, err := isptmaster(f.Fd()) + return err +} + +func isptmaster(fd uintptr) (bool, error) { + err := ioctl(fd, syscall.TIOCISPTMASTER, 0) + return err == nil, err +} + +var ( + emptyFiodgnameArg fiodgnameArg + ioctl_FIODNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) +) + +func ptsname(f *os.File) (string, error) { + name := make([]byte, _C_SPECNAMELEN) + fa := fiodgnameArg{Name: (*byte)(unsafe.Pointer(&name[0])), Len: _C_SPECNAMELEN, Pad_cgo_0: [4]byte{0, 0, 0, 0}} + + err := ioctl(f.Fd(), ioctl_FIODNAME, uintptr(unsafe.Pointer(&fa))) + if err != nil { + return "", err + } + + for i, c := range name { + if c == 0 { + s := "/dev/" + string(name[:i]) + return strings.Replace(s, "ptm", "pts", -1), nil + } + } + return "", errors.New("TIOCPTYGNAME string not NUL-terminated") +} diff --git a/vendor/github.com/kr/pty/pty_freebsd.go b/vendor/github.com/kr/pty/pty_freebsd.go index b341babd05..63b6d91337 100644 --- a/vendor/github.com/kr/pty/pty_freebsd.go +++ b/vendor/github.com/kr/pty/pty_freebsd.go @@ -7,22 +7,28 @@ import ( "unsafe" ) -func posix_openpt(oflag int) (fd int, err error) { +func posixOpenpt(oflag int) (fd int, err error) { r0, _, e1 := syscall.Syscall(syscall.SYS_POSIX_OPENPT, uintptr(oflag), 0, 0) fd = int(r0) if e1 != 0 { err = e1 } - return + return fd, err } func open() (pty, tty *os.File, err error) { - fd, err := posix_openpt(syscall.O_RDWR | syscall.O_CLOEXEC) + fd, err := posixOpenpt(syscall.O_RDWR | syscall.O_CLOEXEC) if err != nil { return nil, nil, err } - p := os.NewFile(uintptr(fd), "/dev/pts") + // In case of error after this point, make sure we close the pts fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() + sname, err := ptsname(p) if err != nil { return nil, nil, err @@ -42,7 +48,7 @@ func isptmaster(fd uintptr) (bool, error) { var ( emptyFiodgnameArg fiodgnameArg - ioctl_FIODGNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) + ioctlFIODGNAME = _IOW('f', 120, unsafe.Sizeof(emptyFiodgnameArg)) ) func ptsname(f *os.File) (string, error) { @@ -59,8 +65,7 @@ func ptsname(f *os.File) (string, error) { buf = make([]byte, n) arg = fiodgnameArg{Len: n, Buf: (*byte)(unsafe.Pointer(&buf[0]))} ) - err = ioctl(f.Fd(), ioctl_FIODGNAME, uintptr(unsafe.Pointer(&arg))) - if err != nil { + if err := ioctl(f.Fd(), ioctlFIODGNAME, uintptr(unsafe.Pointer(&arg))); err != nil { return "", err } diff --git a/vendor/github.com/kr/pty/pty_linux.go b/vendor/github.com/kr/pty/pty_linux.go index cb901a21e0..4a833de184 100644 --- a/vendor/github.com/kr/pty/pty_linux.go +++ b/vendor/github.com/kr/pty/pty_linux.go @@ -12,14 +12,19 @@ func open() (pty, tty *os.File, err error) { if err != nil { return nil, nil, err } + // In case of error after this point, make sure we close the ptmx fd. + defer func() { + if err != nil { + _ = p.Close() // Best effort. + } + }() sname, err := ptsname(p) if err != nil { return nil, nil, err } - err = unlockpt(p) - if err != nil { + if err := unlockpt(p); err != nil { return nil, nil, err } @@ -41,6 +46,6 @@ func ptsname(f *os.File) (string, error) { func unlockpt(f *os.File) error { var u _C_int - // use TIOCSPTLCK with a zero valued arg to clear the slave pty lock + // use TIOCSPTLCK with a pointer to zero to clear the lock return ioctl(f.Fd(), syscall.TIOCSPTLCK, uintptr(unsafe.Pointer(&u))) } diff --git a/vendor/github.com/kr/pty/pty_openbsd.go b/vendor/github.com/kr/pty/pty_openbsd.go new file mode 100644 index 0000000000..a6a35d1e67 --- /dev/null +++ b/vendor/github.com/kr/pty/pty_openbsd.go @@ -0,0 +1,33 @@ +package pty + +import ( + "os" + "syscall" + "unsafe" +) + +func open() (pty, tty *os.File, err error) { + /* + * from ptm(4): + * The PTMGET command allocates a free pseudo terminal, changes its + * ownership to the caller, revokes the access privileges for all previous + * users, opens the file descriptors for the pty and tty devices and + * returns them to the caller in struct ptmget. + */ + + p, err := os.OpenFile("/dev/ptm", os.O_RDWR|syscall.O_CLOEXEC, 0) + if err != nil { + return nil, nil, err + } + defer p.Close() + + var ptm ptmget + if err := ioctl(p.Fd(), uintptr(ioctl_PTMGET), uintptr(unsafe.Pointer(&ptm))); err != nil { + return nil, nil, err + } + + pty = os.NewFile(uintptr(ptm.Cfd), "/dev/ptm") + tty = os.NewFile(uintptr(ptm.Sfd), "/dev/ptm") + + return pty, tty, nil +} diff --git a/vendor/github.com/kr/pty/pty_unsupported.go b/vendor/github.com/kr/pty/pty_unsupported.go index 898c7303c4..9a3e721bc4 100644 --- a/vendor/github.com/kr/pty/pty_unsupported.go +++ b/vendor/github.com/kr/pty/pty_unsupported.go @@ -1,4 +1,4 @@ -// +build !linux,!darwin,!freebsd +// +build !linux,!darwin,!freebsd,!dragonfly,!openbsd package pty diff --git a/vendor/github.com/kr/pty/run.go b/vendor/github.com/kr/pty/run.go index f0678d2a27..56a26adae1 100644 --- a/vendor/github.com/kr/pty/run.go +++ b/vendor/github.com/kr/pty/run.go @@ -1,3 +1,5 @@ +// +build !windows + package pty import ( @@ -10,15 +12,41 @@ import ( // and c.Stderr, calls c.Start, and returns the File of the tty's // corresponding pty. func Start(c *exec.Cmd) (pty *os.File, err error) { + return StartWithSize(c, nil) +} + +// StartWithSize assigns a pseudo-terminal tty os.File to c.Stdin, c.Stdout, +// and c.Stderr, calls c.Start, and returns the File of the tty's +// corresponding pty. +// +// This will resize the pty to the specified size before starting the command +func StartWithSize(c *exec.Cmd, sz *Winsize) (pty *os.File, err error) { pty, tty, err := Open() if err != nil { return nil, err } defer tty.Close() - c.Stdout = tty - c.Stdin = tty - c.Stderr = tty - c.SysProcAttr = &syscall.SysProcAttr{Setctty: true, Setsid: true} + if sz != nil { + err = Setsize(pty, sz) + if err != nil { + pty.Close() + return nil, err + } + } + if c.Stdout == nil { + c.Stdout = tty + } + if c.Stderr == nil { + c.Stderr = tty + } + if c.Stdin == nil { + c.Stdin = tty + } + if c.SysProcAttr == nil { + c.SysProcAttr = &syscall.SysProcAttr{} + } + c.SysProcAttr.Setctty = true + c.SysProcAttr.Setsid = true err = c.Start() if err != nil { pty.Close() diff --git a/vendor/github.com/kr/pty/util.go b/vendor/github.com/kr/pty/util.go index 67c52d06cd..2fa741cca3 100644 --- a/vendor/github.com/kr/pty/util.go +++ b/vendor/github.com/kr/pty/util.go @@ -1,3 +1,5 @@ +// +build !windows + package pty import ( @@ -6,26 +8,53 @@ import ( "unsafe" ) +// InheritSize applies the terminal size of pty to tty. This should be run +// in a signal handler for syscall.SIGWINCH to automatically resize the tty when +// the pty receives a window size change notification. +func InheritSize(pty, tty *os.File) error { + size, err := GetsizeFull(pty) + if err != nil { + return err + } + err = Setsize(tty, size) + if err != nil { + return err + } + return nil +} + +// Setsize resizes t to s. +func Setsize(t *os.File, ws *Winsize) error { + return windowRectCall(ws, t.Fd(), syscall.TIOCSWINSZ) +} + +// GetsizeFull returns the full terminal size description. +func GetsizeFull(t *os.File) (size *Winsize, err error) { + var ws Winsize + err = windowRectCall(&ws, t.Fd(), syscall.TIOCGWINSZ) + return &ws, err +} + // Getsize returns the number of rows (lines) and cols (positions // in each line) in terminal t. func Getsize(t *os.File) (rows, cols int, err error) { - var ws winsize - err = windowrect(&ws, t.Fd()) - return int(ws.ws_row), int(ws.ws_col), err + ws, err := GetsizeFull(t) + return int(ws.Rows), int(ws.Cols), err } -type winsize struct { - ws_row uint16 - ws_col uint16 - ws_xpixel uint16 - ws_ypixel uint16 +// Winsize describes the terminal size. +type Winsize struct { + Rows uint16 // ws_row: Number of rows (in cells) + Cols uint16 // ws_col: Number of columns (in cells) + X uint16 // ws_xpixel: Width in pixels + Y uint16 // ws_ypixel: Height in pixels } -func windowrect(ws *winsize, fd uintptr) error { +func windowRectCall(ws *Winsize, fd, a2 uintptr) error { _, _, errno := syscall.Syscall( syscall.SYS_IOCTL, fd, - syscall.TIOCGWINSZ, + a2, uintptr(unsafe.Pointer(ws)), ) if errno != 0 { diff --git a/vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go b/vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go new file mode 100644 index 0000000000..6b0ba037f8 --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_dragonfly_amd64.go @@ -0,0 +1,14 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_dragonfly.go + +package pty + +const ( + _C_SPECNAMELEN = 0x3f +) + +type fiodgnameArg struct { + Name *byte + Len uint32 + Pad_cgo_0 [4]byte +} diff --git a/vendor/github.com/kr/pty/ztypes_mipsx.go b/vendor/github.com/kr/pty/ztypes_mipsx.go new file mode 100644 index 0000000000..f0ce74086a --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_mipsx.go @@ -0,0 +1,12 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types.go + +// +build linux +// +build mips mipsle mips64 mips64le + +package pty + +type ( + _C_int int32 + _C_uint uint32 +) diff --git a/vendor/github.com/kr/pty/ztypes_openbsd_386.go b/vendor/github.com/kr/pty/ztypes_openbsd_386.go new file mode 100644 index 0000000000..ccb3aab9ae --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_openbsd_386.go @@ -0,0 +1,13 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_openbsd.go + +package pty + +type ptmget struct { + Cfd int32 + Sfd int32 + Cn [16]int8 + Sn [16]int8 +} + +var ioctl_PTMGET = 0x40287401 diff --git a/vendor/github.com/kr/pty/ztypes_openbsd_amd64.go b/vendor/github.com/kr/pty/ztypes_openbsd_amd64.go new file mode 100644 index 0000000000..e67051688f --- /dev/null +++ b/vendor/github.com/kr/pty/ztypes_openbsd_amd64.go @@ -0,0 +1,13 @@ +// Created by cgo -godefs - DO NOT EDIT +// cgo -godefs types_openbsd.go + +package pty + +type ptmget struct { + Cfd int32 + Sfd int32 + Cn [16]int8 + Sn [16]int8 +} + +var ioctl_PTMGET = 0x40287401 From 059e2ca13525b9669b51dbfb595e6cb706de527d Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 6 Apr 2019 01:05:20 +0200 Subject: [PATCH 3/9] bump imdario/mergo v0.3.7 Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- vendor/github.com/imdario/mergo/README.md | 18 +++++++++++++++++- vendor/github.com/imdario/mergo/map.go | 1 + vendor/github.com/imdario/mergo/merge.go | 19 +++++++++++-------- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/vendor.conf b/vendor.conf index 1cf0b56c57..fd15042df9 100644 --- a/vendor.conf +++ b/vendor.conf @@ -23,7 +23,7 @@ gotest.tools 1083505acf35a0bd8a696b26837e1fb3187a7a83 # v2.3.0 github.com/google/go-cmp v0.2.0 github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 -github.com/imdario/mergo v0.3.6 +github.com/imdario/mergo 7c29201646fa3de8506f701213473dd407f19646 # v0.3.7 golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca # buildkit diff --git a/vendor/github.com/imdario/mergo/README.md b/vendor/github.com/imdario/mergo/README.md index 8b76f1fbf3..02fc81e062 100644 --- a/vendor/github.com/imdario/mergo/README.md +++ b/vendor/github.com/imdario/mergo/README.md @@ -13,6 +13,7 @@ It is ready for production use. [It is used in several projects by Docker, Googl [![Build Status][1]][2] [![Coverage Status][7]][8] [![Sourcegraph][9]][10] +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_shield) [1]: https://travis-ci.org/imdario/mergo.png [2]: https://travis-ci.org/imdario/mergo @@ -27,7 +28,7 @@ It is ready for production use. [It is used in several projects by Docker, Googl ### Latest release -[Release v0.3.6](https://github.com/imdario/mergo/releases/tag/v0.3.6). +[Release v0.3.7](https://github.com/imdario/mergo/releases/tag/v0.3.7). ### Important note @@ -217,6 +218,21 @@ If I can help you, you have an idea or you are using Mergo in your projects, don Written by [Dario Castañé](http://dario.im). +## Top Contributors + +[![0](https://sourcerer.io/fame/imdario/imdario/mergo/images/0)](https://sourcerer.io/fame/imdario/imdario/mergo/links/0) +[![1](https://sourcerer.io/fame/imdario/imdario/mergo/images/1)](https://sourcerer.io/fame/imdario/imdario/mergo/links/1) +[![2](https://sourcerer.io/fame/imdario/imdario/mergo/images/2)](https://sourcerer.io/fame/imdario/imdario/mergo/links/2) +[![3](https://sourcerer.io/fame/imdario/imdario/mergo/images/3)](https://sourcerer.io/fame/imdario/imdario/mergo/links/3) +[![4](https://sourcerer.io/fame/imdario/imdario/mergo/images/4)](https://sourcerer.io/fame/imdario/imdario/mergo/links/4) +[![5](https://sourcerer.io/fame/imdario/imdario/mergo/images/5)](https://sourcerer.io/fame/imdario/imdario/mergo/links/5) +[![6](https://sourcerer.io/fame/imdario/imdario/mergo/images/6)](https://sourcerer.io/fame/imdario/imdario/mergo/links/6) +[![7](https://sourcerer.io/fame/imdario/imdario/mergo/images/7)](https://sourcerer.io/fame/imdario/imdario/mergo/links/7) + + ## License [BSD 3-Clause](http://opensource.org/licenses/BSD-3-Clause) license, as [Go language](http://golang.org/LICENSE). + + +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fimdario%2Fmergo.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fimdario%2Fmergo?ref=badge_large) diff --git a/vendor/github.com/imdario/mergo/map.go b/vendor/github.com/imdario/mergo/map.go index 6ea38e636b..3f5afa83a1 100644 --- a/vendor/github.com/imdario/mergo/map.go +++ b/vendor/github.com/imdario/mergo/map.go @@ -72,6 +72,7 @@ func deepMap(dst, src reflect.Value, visited map[uintptr]*visit, depth int, conf case reflect.Struct: srcMap := src.Interface().(map[string]interface{}) for key := range srcMap { + config.overwriteWithEmptyValue = true srcValue := srcMap[key] fieldName := changeInitialCase(key, unicode.ToUpper) dstElement := dst.FieldByName(fieldName) diff --git a/vendor/github.com/imdario/mergo/merge.go b/vendor/github.com/imdario/mergo/merge.go index 44f70a89d9..f8de6c5430 100644 --- a/vendor/github.com/imdario/mergo/merge.go +++ b/vendor/github.com/imdario/mergo/merge.go @@ -26,9 +26,10 @@ func hasExportedField(dst reflect.Value) (exported bool) { } type Config struct { - Overwrite bool - AppendSlice bool - Transformers Transformers + Overwrite bool + AppendSlice bool + Transformers Transformers + overwriteWithEmptyValue bool } type Transformers interface { @@ -40,6 +41,8 @@ type Transformers interface { // short circuiting on recursive types. func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, config *Config) (err error) { overwrite := config.Overwrite + overwriteWithEmptySrc := config.overwriteWithEmptyValue + config.overwriteWithEmptyValue = false if !src.IsValid() { return @@ -74,7 +77,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co } } } else { - if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { + if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) { dst.Set(src) } } @@ -125,7 +128,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co dstSlice = reflect.ValueOf(dstElement.Interface()) } - if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { + if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { dstSlice = srcSlice } else if config.AppendSlice { if srcSlice.Type() != dstSlice.Type() { @@ -136,7 +139,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co dst.SetMapIndex(key, dstSlice) } } - if dstElement.IsValid() && reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map { + if dstElement.IsValid() && !isEmptyValue(dstElement) && (reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Map || reflect.TypeOf(srcElement.Interface()).Kind() == reflect.Slice) { continue } @@ -151,7 +154,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co if !dst.CanSet() { break } - if !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { + if (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) && !config.AppendSlice { dst.Set(src) } else if config.AppendSlice { if src.Type() != dst.Type() { @@ -191,7 +194,7 @@ func deepMerge(dst, src reflect.Value, visited map[uintptr]*visit, depth int, co return } default: - if dst.CanSet() && !isEmptyValue(src) && (overwrite || isEmptyValue(dst)) { + if dst.CanSet() && (!isEmptyValue(src) || overwriteWithEmptySrc) && (overwrite || isEmptyValue(dst)) { dst.Set(src) } } From 8b3759eae1c9503d985f7daa73749c204dcfecec Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 6 Apr 2019 01:10:59 +0200 Subject: [PATCH 4/9] bump mattn/go-shellwords v1.0.5 Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- .../mattn/go-shellwords/shellwords.go | 74 ++++++++++++++++--- .../mattn/go-shellwords/util_go15.go | 24 ++++++ .../mattn/go-shellwords/util_posix.go | 5 +- .../mattn/go-shellwords/util_windows.go | 5 ++ 5 files changed, 96 insertions(+), 14 deletions(-) create mode 100644 vendor/github.com/mattn/go-shellwords/util_go15.go diff --git a/vendor.conf b/vendor.conf index fd15042df9..4fc2167e6e 100644 --- a/vendor.conf +++ b/vendor.conf @@ -10,7 +10,7 @@ github.com/gorilla/mux v1.7.0 github.com/Microsoft/opengcs a10967154e143a36014584a6f664344e3bb0aa64 github.com/konsorten/go-windows-terminal-sequences v1.0.1 github.com/kr/pty 521317be5ebc228a0f0ede099fa2a0b5ece22e49 # v1.1.4 -github.com/mattn/go-shellwords v1.0.3 +github.com/mattn/go-shellwords a72fbe27a1b0ed0df2f02754945044ce1456608b # v1.0.5 github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1 github.com/tchap/go-patricia v2.2.6 github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 # v0.1.0 diff --git a/vendor/github.com/mattn/go-shellwords/shellwords.go b/vendor/github.com/mattn/go-shellwords/shellwords.go index 107803927a..41429d8f26 100644 --- a/vendor/github.com/mattn/go-shellwords/shellwords.go +++ b/vendor/github.com/mattn/go-shellwords/shellwords.go @@ -4,6 +4,7 @@ import ( "errors" "os" "regexp" + "strings" ) var ( @@ -21,13 +22,17 @@ func isSpace(r rune) bool { return false } -func replaceEnv(s string) string { +func replaceEnv(getenv func(string) string, s string) string { + if getenv == nil { + getenv = os.Getenv + } + return envRe.ReplaceAllStringFunc(s, func(s string) string { s = s[1:] if s[0] == '{' { s = s[1 : len(s)-1] } - return os.Getenv(s) + return getenv(s) }) } @@ -35,16 +40,24 @@ type Parser struct { ParseEnv bool ParseBacktick bool Position int + + // If ParseEnv is true, use this for getenv. + // If nil, use os.Getenv. + Getenv func(string) string } func NewParser() *Parser { - return &Parser{ParseEnv, ParseBacktick, 0} + return &Parser{ + ParseEnv: ParseEnv, + ParseBacktick: ParseBacktick, + Position: 0, + } } func (p *Parser) Parse(line string) ([]string, error) { args := []string{} buf := "" - var escaped, doubleQuoted, singleQuoted, backQuote bool + var escaped, doubleQuoted, singleQuoted, backQuote, dollarQuote bool backtick := "" pos := -1 @@ -68,12 +81,12 @@ loop: } if isSpace(r) { - if singleQuoted || doubleQuoted || backQuote { + if singleQuoted || doubleQuoted || backQuote || dollarQuote { buf += string(r) backtick += string(r) } else if got { if p.ParseEnv { - buf = replaceEnv(buf) + buf = replaceEnv(p.Getenv, buf) } args = append(args, buf) buf = "" @@ -84,7 +97,7 @@ loop: switch r { case '`': - if !singleQuoted && !doubleQuoted { + if !singleQuoted && !doubleQuoted && !dollarQuote { if p.ParseBacktick { if backQuote { out, err := shellRun(backtick) @@ -100,18 +113,55 @@ loop: backtick = "" backQuote = !backQuote } + case ')': + if !singleQuoted && !doubleQuoted && !backQuote { + if p.ParseBacktick { + if dollarQuote { + out, err := shellRun(backtick) + if err != nil { + return nil, err + } + if r == ')' { + buf = buf[:len(buf)-len(backtick)-2] + out + } else { + buf = buf[:len(buf)-len(backtick)-1] + out + } + } + backtick = "" + dollarQuote = !dollarQuote + continue + } + backtick = "" + dollarQuote = !dollarQuote + } + case '(': + if !singleQuoted && !doubleQuoted && !backQuote { + if !dollarQuote && strings.HasSuffix(buf, "$") { + dollarQuote = true + buf += "(" + continue + } else { + return nil, errors.New("invalid command line string") + } + } case '"': - if !singleQuoted { + if !singleQuoted && !dollarQuote { doubleQuoted = !doubleQuoted continue } case '\'': - if !doubleQuoted { + if !doubleQuoted && !dollarQuote { singleQuoted = !singleQuoted continue } case ';', '&', '|', '<', '>': if !(escaped || singleQuoted || doubleQuoted || backQuote) { + if r == '>' && len(buf) > 0 { + if c := buf[0]; '0' <= c && c <= '9' { + i -= 1 + got = false + } + } pos = i break loop } @@ -119,19 +169,19 @@ loop: got = true buf += string(r) - if backQuote { + if backQuote || dollarQuote { backtick += string(r) } } if got { if p.ParseEnv { - buf = replaceEnv(buf) + buf = replaceEnv(p.Getenv, buf) } args = append(args, buf) } - if escaped || singleQuoted || doubleQuoted || backQuote { + if escaped || singleQuoted || doubleQuoted || backQuote || dollarQuote { return nil, errors.New("invalid command line string") } diff --git a/vendor/github.com/mattn/go-shellwords/util_go15.go b/vendor/github.com/mattn/go-shellwords/util_go15.go new file mode 100644 index 0000000000..180f00f0bd --- /dev/null +++ b/vendor/github.com/mattn/go-shellwords/util_go15.go @@ -0,0 +1,24 @@ +// +build !go1.6 + +package shellwords + +import ( + "os" + "os/exec" + "runtime" + "strings" +) + +func shellRun(line string) (string, error) { + var b []byte + var err error + if runtime.GOOS == "windows" { + b, err = exec.Command(os.Getenv("COMSPEC"), "/c", line).Output() + } else { + b, err = exec.Command(os.Getenv("SHELL"), "-c", line).Output() + } + if err != nil { + return "", err + } + return strings.TrimSpace(string(b)), nil +} diff --git a/vendor/github.com/mattn/go-shellwords/util_posix.go b/vendor/github.com/mattn/go-shellwords/util_posix.go index 4f8ac55e47..eaf1011d60 100644 --- a/vendor/github.com/mattn/go-shellwords/util_posix.go +++ b/vendor/github.com/mattn/go-shellwords/util_posix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !windows,go1.6 package shellwords @@ -13,6 +13,9 @@ func shellRun(line string) (string, error) { shell := os.Getenv("SHELL") b, err := exec.Command(shell, "-c", line).Output() if err != nil { + if eerr, ok := err.(*exec.ExitError); ok { + b = eerr.Stderr + } return "", errors.New(err.Error() + ":" + string(b)) } return strings.TrimSpace(string(b)), nil diff --git a/vendor/github.com/mattn/go-shellwords/util_windows.go b/vendor/github.com/mattn/go-shellwords/util_windows.go index 7cad4cf06f..e46f89a1fe 100644 --- a/vendor/github.com/mattn/go-shellwords/util_windows.go +++ b/vendor/github.com/mattn/go-shellwords/util_windows.go @@ -1,3 +1,5 @@ +// +build windows,go1.6 + package shellwords import ( @@ -11,6 +13,9 @@ func shellRun(line string) (string, error) { shell := os.Getenv("COMSPEC") b, err := exec.Command(shell, "/c", line).Output() if err != nil { + if eerr, ok := err.(*exec.ExitError); ok { + b = eerr.Stderr + } return "", errors.New(err.Error() + ":" + string(b)) } return strings.TrimSpace(string(b)), nil From 1e2eea5ce87fdcf36518a3d5beec1b68f473d39e Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 6 Apr 2019 01:13:02 +0200 Subject: [PATCH 5/9] bump konsorten/go-windows-terminal-sequences v1.0.2 Add Linux build support; Increase compatibility as the module will appear empty and cause an error on Linux. Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- .../konsorten/go-windows-terminal-sequences/README.md | 1 + .../go-windows-terminal-sequences/sequences_dummy.go | 11 +++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go diff --git a/vendor.conf b/vendor.conf index 4fc2167e6e..8021f0200c 100644 --- a/vendor.conf +++ b/vendor.conf @@ -8,7 +8,7 @@ github.com/golang/gddo 9b12a26f3fbd7397dee4e20939ddca719d840d2a github.com/google/uuid v1.1.1 github.com/gorilla/mux v1.7.0 github.com/Microsoft/opengcs a10967154e143a36014584a6f664344e3bb0aa64 -github.com/konsorten/go-windows-terminal-sequences v1.0.1 +github.com/konsorten/go-windows-terminal-sequences f55edac94c9bbba5d6182a4be46d86a2c9b5b50e # v1.0.2 github.com/kr/pty 521317be5ebc228a0f0ede099fa2a0b5ece22e49 # v1.1.4 github.com/mattn/go-shellwords a72fbe27a1b0ed0df2f02754945044ce1456608b # v1.0.5 github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1 diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md index 949b77e304..195333e51d 100644 --- a/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/README.md @@ -26,6 +26,7 @@ The tool is sponsored by the [marvin + konsorten GmbH](http://www.konsorten.de). We thank all the authors who provided code to this library: * Felix Kollmann +* Nicolas Perraut ## License diff --git a/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go new file mode 100644 index 0000000000..df61a6f2f6 --- /dev/null +++ b/vendor/github.com/konsorten/go-windows-terminal-sequences/sequences_dummy.go @@ -0,0 +1,11 @@ +// +build linux darwin + +package sequences + +import ( + "fmt" +) + +func EnableVirtualTerminalProcessing(stream uintptr, enable bool) error { + return fmt.Errorf("windows only package") +} From dfa863db456a184a6ed8a64ba1128076057bf175 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 6 Apr 2019 01:23:00 +0200 Subject: [PATCH 6/9] bump golang.org/x/sync e225da77a7e68af35c70ccbf71af2b83e6acac3c removes use of golang.org/x/net/context Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- vendor/golang.org/x/sync/errgroup/errgroup.go | 3 +-- vendor/golang.org/x/sync/semaphore/semaphore.go | 12 ++++-------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/vendor.conf b/vendor.conf index 8021f0200c..9860467d84 100644 --- a/vendor.conf +++ b/vendor.conf @@ -24,7 +24,7 @@ github.com/google/go-cmp v0.2.0 github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 github.com/imdario/mergo 7c29201646fa3de8506f701213473dd407f19646 # v0.3.7 -golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca +golang.org/x/sync e225da77a7e68af35c70ccbf71af2b83e6acac3c # buildkit github.com/moby/buildkit b3028967ae6259c9a31c1a1deeccd30fe3469cce diff --git a/vendor/golang.org/x/sync/errgroup/errgroup.go b/vendor/golang.org/x/sync/errgroup/errgroup.go index 533438d91c..9857fe53d3 100644 --- a/vendor/golang.org/x/sync/errgroup/errgroup.go +++ b/vendor/golang.org/x/sync/errgroup/errgroup.go @@ -7,9 +7,8 @@ package errgroup import ( + "context" "sync" - - "golang.org/x/net/context" ) // A Group is a collection of goroutines working on subtasks that are part of diff --git a/vendor/golang.org/x/sync/semaphore/semaphore.go b/vendor/golang.org/x/sync/semaphore/semaphore.go index e9d2d79a97..ac53e733e7 100644 --- a/vendor/golang.org/x/sync/semaphore/semaphore.go +++ b/vendor/golang.org/x/sync/semaphore/semaphore.go @@ -7,12 +7,8 @@ package semaphore // import "golang.org/x/sync/semaphore" import ( "container/list" + "context" "sync" - - // Use the old context because packages that depend on this one - // (e.g. cloud.google.com/go/...) must run on Go 1.6. - // TODO(jba): update to "context" when possible. - "golang.org/x/net/context" ) type waiter struct { @@ -36,9 +32,9 @@ type Weighted struct { waiters list.List } -// Acquire acquires the semaphore with a weight of n, blocking only until ctx -// is done. On success, returns nil. On failure, returns ctx.Err() and leaves -// the semaphore unchanged. +// Acquire acquires the semaphore with a weight of n, blocking until resources +// are available or ctx is done. On success, returns nil. On failure, returns +// ctx.Err() and leaves the semaphore unchanged. // // If ctx is already done, Acquire may still succeed without blocking. func (s *Weighted) Acquire(ctx context.Context, n int64) error { From d72d3adf1c77b3d460d9101615058b677ec52f34 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 6 Apr 2019 01:34:05 +0200 Subject: [PATCH 7/9] bump RackSec/srslog a4725f04ec91af1a91b380da679d6e0c2f061e59 Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- vendor/github.com/RackSec/srslog/README.md | 16 ++++++++ vendor/github.com/RackSec/srslog/dialer.go | 17 ++++++++ vendor/github.com/RackSec/srslog/formatter.go | 14 ++++++- vendor/github.com/RackSec/srslog/srslog.go | 40 ++++++++++++++++--- vendor/github.com/RackSec/srslog/writer.go | 28 ++++++++++--- 6 files changed, 102 insertions(+), 15 deletions(-) diff --git a/vendor.conf b/vendor.conf index 9860467d84..2f86f5daa9 100644 --- a/vendor.conf +++ b/vendor.conf @@ -22,7 +22,7 @@ golang.org/x/text f21a4dfb5e38f5895301dc265a8def02365cc3d0 # v0.3.0 gotest.tools 1083505acf35a0bd8a696b26837e1fb3187a7a83 # v2.3.0 github.com/google/go-cmp v0.2.0 -github.com/RackSec/srslog 456df3a81436d29ba874f3590eeeee25d666f8a5 +github.com/RackSec/srslog a4725f04ec91af1a91b380da679d6e0c2f061e59 github.com/imdario/mergo 7c29201646fa3de8506f701213473dd407f19646 # v0.3.7 golang.org/x/sync e225da77a7e68af35c70ccbf71af2b83e6acac3c diff --git a/vendor/github.com/RackSec/srslog/README.md b/vendor/github.com/RackSec/srslog/README.md index 1ae1fd4ef8..dcacc34881 100644 --- a/vendor/github.com/RackSec/srslog/README.md +++ b/vendor/github.com/RackSec/srslog/README.md @@ -90,6 +90,22 @@ w.Debug("this is debug") w.Write([]byte("these are some bytes")) ``` +If you need further control over connection attempts, you can use the DialWithCustomDialer +function. To continue with the DialWithTLSConfig example: + +``` +netDialer := &net.Dialer{Timeout: time.Second*5} // easy timeouts +realNetwork := "tcp" // real network, other vars your dail func can close over +dial := func(network, addr string) (net.Conn, error) { + // cannot use "network" here as it'll simply be "custom" which will fail + return tls.DialWithDialer(netDialer, realNetwork, addr, &config) +} + +w, err := DialWithCustomDialer("custom", "192.168.0.52:514", syslog.LOG_ERR, "testtag", dial) +``` + +Your custom dial func can set timeouts, proxy connections, and do whatever else it needs before returning a net.Conn. + # Generating TLS Certificates We've provided a script that you can use to generate a self-signed keypair: diff --git a/vendor/github.com/RackSec/srslog/dialer.go b/vendor/github.com/RackSec/srslog/dialer.go index 47a7b2beaf..fc7e53860f 100644 --- a/vendor/github.com/RackSec/srslog/dialer.go +++ b/vendor/github.com/RackSec/srslog/dialer.go @@ -37,6 +37,7 @@ func (w *Writer) getDialer() dialerFunctionWrapper { dialers := map[string]dialerFunctionWrapper{ "": dialerFunctionWrapper{"unixDialer", w.unixDialer}, "tcp+tls": dialerFunctionWrapper{"tlsDialer", w.tlsDialer}, + "custom": dialerFunctionWrapper{"customDialer", w.customDialer}, } dialer, ok := dialers[w.network] if !ok { @@ -85,3 +86,19 @@ func (w *Writer) basicDialer() (serverConn, string, error) { } return sc, hostname, err } + +// customDialer uses the custom dialer when the Writer was created +// giving developers total control over how connections are made and returned. +// Note it does not check if cdialer is nil, as it should only be referenced from getDialer. +func (w *Writer) customDialer() (serverConn, string, error) { + c, err := w.customDial(w.network, w.raddr) + var sc serverConn + hostname := w.hostname + if err == nil { + sc = &netConn{conn: c} + if hostname == "" { + hostname = c.LocalAddr().String() + } + } + return sc, hostname, err +} diff --git a/vendor/github.com/RackSec/srslog/formatter.go b/vendor/github.com/RackSec/srslog/formatter.go index 7852ad37e4..e306fd6713 100644 --- a/vendor/github.com/RackSec/srslog/formatter.go +++ b/vendor/github.com/RackSec/srslog/formatter.go @@ -6,6 +6,8 @@ import ( "time" ) +const appNameMaxLength = 48 // limit to 48 chars as per RFC5424 + // Formatter is a type of function that takes the consituent parts of a // syslog message and returns a formatted string. A different Formatter is // defined for each different syslog protocol we support. @@ -37,12 +39,20 @@ func RFC3164Formatter(p Priority, hostname, tag, content string) string { return msg } +// if string's length is greater than max, then use the last part +func truncateStartStr(s string, max int) string { + if (len(s) > max) { + return s[len(s) - max:] + } + return s +} + // RFC5424Formatter provides an RFC 5424 compliant message. func RFC5424Formatter(p Priority, hostname, tag, content string) string { timestamp := time.Now().Format(time.RFC3339) pid := os.Getpid() - appName := os.Args[0] - msg := fmt.Sprintf("<%d>%d %s %s %s %d %s %s", + appName := truncateStartStr(os.Args[0], appNameMaxLength) + msg := fmt.Sprintf("<%d>%d %s %s %s %d %s - %s", p, 1, timestamp, hostname, appName, pid, tag, content) return msg } diff --git a/vendor/github.com/RackSec/srslog/srslog.go b/vendor/github.com/RackSec/srslog/srslog.go index b404dff7c5..b47ad72df4 100644 --- a/vendor/github.com/RackSec/srslog/srslog.go +++ b/vendor/github.com/RackSec/srslog/srslog.go @@ -3,8 +3,10 @@ package srslog import ( "crypto/tls" "crypto/x509" + "errors" "io/ioutil" "log" + "net" "os" ) @@ -15,6 +17,10 @@ type serverConn interface { close() error } +// DialFunc is the function signature to be used for a custom dialer callback +// with DialWithCustomDialer +type DialFunc func(string, string) (net.Conn, error) + // New establishes a new connection to the system log daemon. Each // write to the returned Writer sends a log message with the given // priority and prefix. @@ -31,6 +37,22 @@ func Dial(network, raddr string, priority Priority, tag string) (*Writer, error) return DialWithTLSConfig(network, raddr, priority, tag, nil) } +// ErrNilDialFunc is returned from DialWithCustomDialer when a nil DialFunc is passed, +// avoiding a nil pointer deference panic. +var ErrNilDialFunc = errors.New("srslog: nil DialFunc passed to DialWithCustomDialer") + +// DialWithCustomDialer establishes a connection by calling customDial. +// Each write to the returned Writer sends a log message with the given facility, severity and tag. +// Network must be "custom" in order for this package to use customDial. +// While network and raddr will be passed to customDial, it is allowed for customDial to ignore them. +// If customDial is nil, this function returns ErrNilDialFunc. +func DialWithCustomDialer(network, raddr string, priority Priority, tag string, customDial DialFunc) (*Writer, error) { + if customDial == nil { + return nil, ErrNilDialFunc + } + return dialAllParameters(network, raddr, priority, tag, nil, customDial) +} + // DialWithTLSCertPath establishes a secure connection to a log daemon by connecting to // address raddr on the specified network. It uses certPath to load TLS certificates and configure // the secure connection. @@ -59,6 +81,11 @@ func DialWithTLSCert(network, raddr string, priority Priority, tag string, serve // DialWithTLSConfig establishes a secure connection to a log daemon by connecting to // address raddr on the specified network. It uses tlsConfig to configure the secure connection. func DialWithTLSConfig(network, raddr string, priority Priority, tag string, tlsConfig *tls.Config) (*Writer, error) { + return dialAllParameters(network, raddr, priority, tag, tlsConfig, nil) +} + +// implementation of the various functions above +func dialAllParameters(network, raddr string, priority Priority, tag string, tlsConfig *tls.Config, customDial DialFunc) (*Writer, error) { if err := validatePriority(priority); err != nil { return nil, err } @@ -69,12 +96,13 @@ func DialWithTLSConfig(network, raddr string, priority Priority, tag string, tls hostname, _ := os.Hostname() w := &Writer{ - priority: priority, - tag: tag, - hostname: hostname, - network: network, - raddr: raddr, - tlsConfig: tlsConfig, + priority: priority, + tag: tag, + hostname: hostname, + network: network, + raddr: raddr, + tlsConfig: tlsConfig, + customDial: customDial, } _, err := w.connect() diff --git a/vendor/github.com/RackSec/srslog/writer.go b/vendor/github.com/RackSec/srslog/writer.go index ce3d867635..86bccba157 100644 --- a/vendor/github.com/RackSec/srslog/writer.go +++ b/vendor/github.com/RackSec/srslog/writer.go @@ -17,6 +17,9 @@ type Writer struct { framer Framer formatter Formatter + //non-nil if custom dialer set, used in getDialer + customDial DialFunc + mu sync.RWMutex // guards conn conn serverConn } @@ -71,15 +74,20 @@ func (w *Writer) SetFramer(f Framer) { w.framer = f } +// SetHostname changes the hostname for syslog messages if needed. +func (w *Writer) SetHostname(hostname string) { + w.hostname = hostname +} + // Write sends a log message to the syslog daemon using the default priority // passed into `srslog.New` or the `srslog.Dial*` functions. func (w *Writer) Write(b []byte) (int, error) { return w.writeAndRetry(w.priority, string(b)) } -// WriteWithPriority sends a log message with a custom priority +// WriteWithPriority sends a log message with a custom priority. func (w *Writer) WriteWithPriority(p Priority, b []byte) (int, error) { - return w.writeAndRetry(p, string(b)) + return w.writeAndRetryWithPriority(p, string(b)) } // Close closes a connection to the syslog daemon. @@ -149,12 +157,20 @@ func (w *Writer) Debug(m string) (err error) { return err } -func (w *Writer) writeAndRetry(p Priority, s string) (int, error) { - pr := (w.priority & facilityMask) | (p & severityMask) +// writeAndRetry takes a severity and the string to write. Any facility passed to +// it as part of the severity Priority will be ignored. +func (w *Writer) writeAndRetry(severity Priority, s string) (int, error) { + pr := (w.priority & facilityMask) | (severity & severityMask) + return w.writeAndRetryWithPriority(pr, s) +} + +// writeAndRetryWithPriority differs from writeAndRetry in that it allows setting +// of both the facility and the severity. +func (w *Writer) writeAndRetryWithPriority(p Priority, s string) (int, error) { conn := w.getConn() if conn != nil { - if n, err := w.write(conn, pr, s); err == nil { + if n, err := w.write(conn, p, s); err == nil { return n, err } } @@ -163,7 +179,7 @@ func (w *Writer) writeAndRetry(p Priority, s string) (int, error) { if conn, err = w.connect(); err != nil { return 0, err } - return w.write(conn, pr, s) + return w.write(conn, p, s) } // write generates and writes a syslog formatted string. It formats the From b00897d51a6620260ef320a2ffad1d77848a7172 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 6 Apr 2019 01:36:47 +0200 Subject: [PATCH 8/9] bump philhofer/fwd v1.0.0 Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- vendor/github.com/philhofer/fwd/reader.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/vendor.conf b/vendor.conf index 2f86f5daa9..3d8e05e021 100644 --- a/vendor.conf +++ b/vendor.conf @@ -97,7 +97,7 @@ github.com/Graylog2/go-gelf 4143646226541087117ff2f83334ea48b3201841 github.com/fluent/fluent-logger-golang v1.3.0 # fluent-logger-golang deps -github.com/philhofer/fwd 98c11a7a6ec829d672b03833c3d69a7fae1ca972 +github.com/philhofer/fwd bb6d471dc95d4fe11e432687f8b70ff496cf3136 # v1.0.0 github.com/tinylib/msgp 3b556c64540842d4f82967be066a7f7fffc3adad # fsnotify diff --git a/vendor/github.com/philhofer/fwd/reader.go b/vendor/github.com/philhofer/fwd/reader.go index e591910306..75be62ab09 100644 --- a/vendor/github.com/philhofer/fwd/reader.go +++ b/vendor/github.com/philhofer/fwd/reader.go @@ -109,6 +109,10 @@ func (r *Reader) more() { if a == 0 && r.state == nil { r.state = io.ErrNoProgress return + } else if a > 0 && r.state == io.EOF { + // discard the io.EOF if we read more than 0 bytes. + // the next call to Read should return io.EOF again. + r.state = nil } r.data = r.data[:len(r.data)+a] } From 6251d81510956f55ff52c01e375b9a5adeb625b7 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Sat, 6 Apr 2019 01:46:41 +0200 Subject: [PATCH 9/9] bump tchap/go-patricia v2.3.0 Signed-off-by: Sebastiaan van Stijn --- vendor.conf | 2 +- vendor/github.com/tchap/go-patricia/README.md | 6 --- .../tchap/go-patricia/patricia/children.go | 38 +++++++++++++++++++ .../tchap/go-patricia/patricia/patricia.go | 12 ++++++ 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/vendor.conf b/vendor.conf index 3d8e05e021..8486fdcdcb 100644 --- a/vendor.conf +++ b/vendor.conf @@ -12,7 +12,7 @@ github.com/konsorten/go-windows-terminal-sequences f55edac94c9bbba5d6182a4be46d8 github.com/kr/pty 521317be5ebc228a0f0ede099fa2a0b5ece22e49 # v1.1.4 github.com/mattn/go-shellwords a72fbe27a1b0ed0df2f02754945044ce1456608b # v1.0.5 github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1 -github.com/tchap/go-patricia v2.2.6 +github.com/tchap/go-patricia a7f0089c6f496e8e70402f61733606daa326cac5 # v2.3.0 github.com/vdemeester/shakers 24d7f1d6a71aa5d9cbe7390e4afb66b7eef9e1b3 # v0.1.0 golang.org/x/net a680a1efc54dd51c040b3b5ce4939ea3cf2ea0d1 golang.org/x/sys d455e41777fca6e8a5a79e34a14b8368bc11d9ba diff --git a/vendor/github.com/tchap/go-patricia/README.md b/vendor/github.com/tchap/go-patricia/README.md index d9cbf624f3..e936d18390 100644 --- a/vendor/github.com/tchap/go-patricia/README.md +++ b/vendor/github.com/tchap/go-patricia/README.md @@ -1,8 +1,6 @@ # go-patricia # **Documentation**: [GoDoc](http://godoc.org/github.com/tchap/go-patricia/patricia)
-**Build Status**: [![Build -Status](https://drone.io/github.com/tchap/go-patricia/status.png)](https://drone.io/github.com/tchap/go-patricia/latest)
**Test Coverage**: [![Coverage Status](https://coveralls.io/repos/tchap/go-patricia/badge.png)](https://coveralls.io/r/tchap/go-patricia) @@ -117,7 +115,3 @@ MIT, check the `LICENSE` file. [![Gittip Badge](http://img.shields.io/gittip/alanhamlett.png)](https://www.gittip.com/tchap/ "Gittip Badge") - -[![Bitdeli -Badge](https://d2weczhvl823v0.cloudfront.net/tchap/go-patricia/trend.png)](https://bitdeli.com/free -"Bitdeli Badge") diff --git a/vendor/github.com/tchap/go-patricia/patricia/children.go b/vendor/github.com/tchap/go-patricia/patricia/children.go index a5677c3352..bcfd0a5dd0 100644 --- a/vendor/github.com/tchap/go-patricia/patricia/children.go +++ b/vendor/github.com/tchap/go-patricia/patricia/children.go @@ -20,6 +20,7 @@ type childList interface { next(b byte) *Trie walk(prefix *Prefix, visitor VisitorFunc) error print(w io.Writer, indent int) + clone() childList total() int } @@ -143,6 +144,17 @@ func (list *sparseChildList) total() int { return tot } +func (list *sparseChildList) clone() childList { + clones := make(tries, len(list.children), cap(list.children)) + for i, child := range list.children { + clones[i] = child.Clone() + } + + return &sparseChildList{ + children: clones, + } +} + func (list *sparseChildList) print(w io.Writer, indent int) { for _, child := range list.children { if child != nil { @@ -314,6 +326,32 @@ func (list *denseChildList) print(w io.Writer, indent int) { } } +func (list *denseChildList) clone() childList { + clones := make(tries, cap(list.children)) + + if list.numChildren != 0 { + clonedCount := 0 + for i := list.headIndex; i < len(list.children); i++ { + child := list.children[i] + if child != nil { + clones[i] = child.Clone() + clonedCount++ + if clonedCount == list.numChildren { + break + } + } + } + } + + return &denseChildList{ + min: list.min, + max: list.max, + numChildren: list.numChildren, + headIndex: list.headIndex, + children: clones, + } +} + func (list *denseChildList) total() int { tot := 0 for _, child := range list.children { diff --git a/vendor/github.com/tchap/go-patricia/patricia/patricia.go b/vendor/github.com/tchap/go-patricia/patricia/patricia.go index a1fc53d5db..7b9975e383 100644 --- a/vendor/github.com/tchap/go-patricia/patricia/patricia.go +++ b/vendor/github.com/tchap/go-patricia/patricia/patricia.go @@ -77,6 +77,18 @@ func MaxChildrenPerSparseNode(value int) Option { } } +// Clone makes a copy of an existing trie. +// Items stored in both tries become shared, obviously. +func (trie *Trie) Clone() *Trie { + return &Trie{ + prefix: append(Prefix(nil), trie.prefix...), + item: trie.item, + maxPrefixPerNode: trie.maxPrefixPerNode, + maxChildrenPerSparseNode: trie.maxChildrenPerSparseNode, + children: trie.children.clone(), + } +} + // Item returns the item stored in the root of this trie. func (trie *Trie) Item() Item { return trie.item