diff --git a/cmd/gateway/manta/gateway-manta.go b/cmd/gateway/manta/gateway-manta.go index 0f291dd99..2cb831845 100644 --- a/cmd/gateway/manta/gateway-manta.go +++ b/cmd/gateway/manta/gateway-manta.go @@ -27,10 +27,9 @@ import ( "path" "strings" - "github.com/hashicorp/errwrap" triton "github.com/joyent/triton-go" "github.com/joyent/triton-go/authentication" - tclient "github.com/joyent/triton-go/client" + terrors "github.com/joyent/triton-go/errors" "github.com/joyent/triton-go/storage" "github.com/minio/cli" minio "github.com/minio/minio/cmd" @@ -340,7 +339,7 @@ func (t *tritonObjects) ListObjects(bucket, prefix, marker, delimiter string, ma } objs, err = t.client.Dir().List(ctx, input) if err != nil { - if tclient.IsResourceNotFoundError(err) { + if terrors.IsResourceNotFoundError(err) { return result, nil } return result, errors.Trace(err) @@ -417,7 +416,7 @@ func (t *tritonObjects) ListObjectsV2(bucket, prefix, continuationToken, delimit } objs, err = t.client.Dir().List(ctx, input) if err != nil { - if tclient.IsResourceNotFoundError(err) { + if terrors.IsResourceNotFoundError(err) { return result, nil } return result, errors.Trace(err) @@ -506,14 +505,10 @@ func (t *tritonObjects) GetObjectInfo(bucket, object string) (objInfo minio.Obje ObjectPath: path.Join(mantaRoot, bucket, object), }) if err != nil { - errType := &tclient.MantaError{} - if errwrap.ContainsType(err, errType) { - mantaErr := errwrap.GetType(err, errType).(*tclient.MantaError) - if mantaErr.StatusCode == http.StatusNotFound { - return objInfo, minio.ObjectNotFound{ - Bucket: bucket, - Object: object, - } + if terrors.IsStatusNotFoundCode(err) { + return objInfo, minio.ObjectNotFound{ + Bucket: bucket, + Object: object, } } diff --git a/vendor/github.com/hashicorp/errwrap/LICENSE b/vendor/github.com/hashicorp/errwrap/LICENSE deleted file mode 100644 index c33dcc7c9..000000000 --- a/vendor/github.com/hashicorp/errwrap/LICENSE +++ /dev/null @@ -1,354 +0,0 @@ -Mozilla Public License, version 2.0 - -1. Definitions - -1.1. “Contributor” - - means each individual or legal entity that creates, contributes to the - creation of, or owns Covered Software. - -1.2. “Contributor Version” - - means the combination of the Contributions of others (if any) used by a - Contributor and that particular Contributor’s Contribution. - -1.3. “Contribution” - - means Covered Software of a particular Contributor. - -1.4. “Covered Software” - - means Source Code Form to which the initial Contributor has attached the - notice in Exhibit A, the Executable Form of such Source Code Form, and - Modifications of such Source Code Form, in each case including portions - thereof. - -1.5. “Incompatible With Secondary Licenses” - means - - a. that the initial Contributor has attached the notice described in - Exhibit B to the Covered Software; or - - b. that the Covered Software was made available under the terms of version - 1.1 or earlier of the License, but not also under the terms of a - Secondary License. - -1.6. “Executable Form” - - means any form of the work other than Source Code Form. - -1.7. “Larger Work” - - means a work that combines Covered Software with other material, in a separate - file or files, that is not Covered Software. - -1.8. “License” - - means this document. - -1.9. “Licensable” - - means having the right to grant, to the maximum extent possible, whether at the - time of the initial grant or subsequently, any and all of the rights conveyed by - this License. - -1.10. “Modifications” - - means any of the following: - - a. any file in Source Code Form that results from an addition to, deletion - from, or modification of the contents of Covered Software; or - - b. any new file in Source Code Form that contains any Covered Software. - -1.11. “Patent Claims” of a Contributor - - means any patent claim(s), including without limitation, method, process, - and apparatus claims, in any patent Licensable by such Contributor that - would be infringed, but for the grant of the License, by the making, - using, selling, offering for sale, having made, import, or transfer of - either its Contributions or its Contributor Version. - -1.12. “Secondary License” - - means either the GNU General Public License, Version 2.0, the GNU Lesser - General Public License, Version 2.1, the GNU Affero General Public - License, Version 3.0, or any later versions of those licenses. - -1.13. “Source Code Form” - - means the form of the work preferred for making modifications. - -1.14. “You” (or “Your”) - - means an individual or a legal entity exercising rights under this - License. For legal entities, “You” includes any entity that controls, is - controlled by, or is under common control with You. For purposes of this - definition, “control” means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by contract or - otherwise, or (b) ownership of more than fifty percent (50%) of the - outstanding shares or beneficial ownership of such entity. - - -2. License Grants and Conditions - -2.1. Grants - - Each Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - a. under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or as - part of a Larger Work; and - - b. under Patent Claims of such Contributor to make, use, sell, offer for - sale, have made, import, and otherwise transfer either its Contributions - or its Contributor Version. - -2.2. Effective Date - - The licenses granted in Section 2.1 with respect to any Contribution become - effective for each Contribution on the date the Contributor first distributes - such Contribution. - -2.3. Limitations on Grant Scope - - The licenses granted in this Section 2 are the only rights granted under this - License. No additional rights or licenses will be implied from the distribution - or licensing of Covered Software under this License. Notwithstanding Section - 2.1(b) above, no patent license is granted by a Contributor: - - a. for any code that a Contributor has removed from Covered Software; or - - b. for infringements caused by: (i) Your and any other third party’s - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - - c. under Patent Claims infringed by Covered Software in the absence of its - Contributions. - - This License does not grant any rights in the trademarks, service marks, or - logos of any Contributor (except as may be necessary to comply with the - notice requirements in Section 3.4). - -2.4. Subsequent Licenses - - No Contributor makes additional grants as a result of Your choice to - distribute the Covered Software under a subsequent version of this License - (see Section 10.2) or under the terms of a Secondary License (if permitted - under the terms of Section 3.3). - -2.5. Representation - - Each Contributor represents that the Contributor believes its Contributions - are its original creation(s) or it has sufficient rights to grant the - rights to its Contributions conveyed by this License. - -2.6. Fair Use - - This License is not intended to limit any rights You have under applicable - copyright doctrines of fair use, fair dealing, or other equivalents. - -2.7. Conditions - - Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in - Section 2.1. - - -3. Responsibilities - -3.1. Distribution of Source Form - - All distribution of Covered Software in Source Code Form, including any - Modifications that You create or to which You contribute, must be under the - terms of this License. You must inform recipients that the Source Code Form - of the Covered Software is governed by the terms of this License, and how - they can obtain a copy of this License. You may not attempt to alter or - restrict the recipients’ rights in the Source Code Form. - -3.2. Distribution of Executable Form - - If You distribute Covered Software in Executable Form then: - - a. such Covered Software must also be made available in Source Code Form, - as described in Section 3.1, and You must inform recipients of the - Executable Form how they can obtain a copy of such Source Code Form by - reasonable means in a timely manner, at a charge no more than the cost - of distribution to the recipient; and - - b. You may distribute such Executable Form under the terms of this License, - or sublicense it under different terms, provided that the license for - the Executable Form does not attempt to limit or alter the recipients’ - rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - - You may create and distribute a Larger Work under terms of Your choice, - provided that You also comply with the requirements of this License for the - Covered Software. If the Larger Work is a combination of Covered Software - with a work governed by one or more Secondary Licenses, and the Covered - Software is not Incompatible With Secondary Licenses, this License permits - You to additionally distribute such Covered Software under the terms of - such Secondary License(s), so that the recipient of the Larger Work may, at - their option, further distribute the Covered Software under the terms of - either this License or such Secondary License(s). - -3.4. Notices - - You may not remove or alter the substance of any license notices (including - copyright notices, patent notices, disclaimers of warranty, or limitations - of liability) contained within the Source Code Form of the Covered - Software, except that You may alter any license notices to the extent - required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - - You may choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of Covered - Software. However, You may do so only on Your own behalf, and not on behalf - of any Contributor. You must make it absolutely clear that any such - warranty, support, indemnity, or liability obligation is offered by You - alone, and You hereby agree to indemnify every Contributor for any - liability incurred by such Contributor as a result of warranty, support, - indemnity or liability terms You offer. You may include additional - disclaimers of warranty and limitations of liability specific to any - jurisdiction. - -4. Inability to Comply Due to Statute or Regulation - - If it is impossible for You to comply with any of the terms of this License - with respect to some or all of the Covered Software due to statute, judicial - order, or regulation then You must: (a) comply with the terms of this License - to the maximum extent possible; and (b) describe the limitations and the code - they affect. Such description must be placed in a text file included with all - distributions of the Covered Software under this License. Except to the - extent prohibited by statute or regulation, such description must be - sufficiently detailed for a recipient of ordinary skill to be able to - understand it. - -5. Termination - -5.1. The rights granted under this License will terminate automatically if You - fail to comply with any of its terms. However, if You become compliant, - then the rights granted under this License from a particular Contributor - are reinstated (a) provisionally, unless and until such Contributor - explicitly and finally terminates Your grants, and (b) on an ongoing basis, - if such Contributor fails to notify You of the non-compliance by some - reasonable means prior to 60 days after You have come back into compliance. - Moreover, Your grants from a particular Contributor are reinstated on an - ongoing basis if such Contributor notifies You of the non-compliance by - some reasonable means, this is the first time You have received notice of - non-compliance with this License from such Contributor, and You become - compliant prior to 30 days after Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent - infringement claim (excluding declaratory judgment actions, counter-claims, - and cross-claims) alleging that a Contributor Version directly or - indirectly infringes any patent, then the rights granted to You by any and - all Contributors for the Covered Software under Section 2.1 of this License - shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user - license agreements (excluding distributors and resellers) which have been - validly granted by You or Your distributors under this License prior to - termination shall survive termination. - -6. Disclaimer of Warranty - - Covered Software is provided under this License on an “as is” basis, without - warranty of any kind, either expressed, implied, or statutory, including, - without limitation, warranties that the Covered Software is free of defects, - merchantable, fit for a particular purpose or non-infringing. The entire - risk as to the quality and performance of the Covered Software is with You. - Should any Covered Software prove defective in any respect, You (not any - Contributor) assume the cost of any necessary servicing, repair, or - correction. This disclaimer of warranty constitutes an essential part of this - License. No use of any Covered Software is authorized under this License - except under this disclaimer. - -7. Limitation of Liability - - Under no circumstances and under no legal theory, whether tort (including - negligence), contract, or otherwise, shall any Contributor, or anyone who - distributes Covered Software as permitted above, be liable to You for any - direct, indirect, special, incidental, or consequential damages of any - character including, without limitation, damages for lost profits, loss of - goodwill, work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses, even if such party shall have been - informed of the possibility of such damages. This limitation of liability - shall not apply to liability for death or personal injury resulting from such - party’s negligence to the extent applicable law prohibits such limitation. - Some jurisdictions do not allow the exclusion or limitation of incidental or - consequential damages, so this exclusion and limitation may not apply to You. - -8. Litigation - - Any litigation relating to this License may be brought only in the courts of - a jurisdiction where the defendant maintains its principal place of business - and such litigation shall be governed by laws of that jurisdiction, without - reference to its conflict-of-law provisions. Nothing in this Section shall - prevent a party’s ability to bring cross-claims or counter-claims. - -9. Miscellaneous - - This License represents the complete agreement concerning the subject matter - hereof. If any provision of this License is held to be unenforceable, such - provision shall be reformed only to the extent necessary to make it - enforceable. Any law or regulation which provides that the language of a - contract shall be construed against the drafter shall not be used to construe - this License against a Contributor. - - -10. Versions of the License - -10.1. New Versions - - Mozilla Foundation is the license steward. Except as provided in Section - 10.3, no one other than the license steward has the right to modify or - publish new versions of this License. Each version will be given a - distinguishing version number. - -10.2. Effect of New Versions - - You may distribute the Covered Software under the terms of the version of - the License under which You originally received the Covered Software, or - under the terms of any subsequent version published by the license - steward. - -10.3. Modified Versions - - If you create software not governed by this License, and you want to - create a new license for such software, you may create and use a modified - version of this License if you rename the license and remove any - references to the name of the license steward (except to note that such - modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses - If You choose to distribute Source Code Form that is Incompatible With - Secondary Licenses under the terms of this version of the License, the - notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice - - This Source Code Form is subject to the - terms of the Mozilla Public License, v. - 2.0. If a copy of the MPL was not - distributed with this file, You can - obtain one at - http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular file, then -You may include the notice in a location (such as a LICENSE file in a relevant -directory) where a recipient would be likely to look for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - “Incompatible With Secondary Licenses” Notice - - This Source Code Form is “Incompatible - With Secondary Licenses”, as defined by - the Mozilla Public License, v. 2.0. - diff --git a/vendor/github.com/hashicorp/errwrap/README.md b/vendor/github.com/hashicorp/errwrap/README.md deleted file mode 100644 index 1c95f5978..000000000 --- a/vendor/github.com/hashicorp/errwrap/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# errwrap - -`errwrap` is a package for Go that formalizes the pattern of wrapping errors -and checking if an error contains another error. - -There is a common pattern in Go of taking a returned `error` value and -then wrapping it (such as with `fmt.Errorf`) before returning it. The problem -with this pattern is that you completely lose the original `error` structure. - -Arguably the _correct_ approach is that you should make a custom structure -implementing the `error` interface, and have the original error as a field -on that structure, such [as this example](http://golang.org/pkg/os/#PathError). -This is a good approach, but you have to know the entire chain of possible -rewrapping that happens, when you might just care about one. - -`errwrap` formalizes this pattern (it doesn't matter what approach you use -above) by giving a single interface for wrapping errors, checking if a specific -error is wrapped, and extracting that error. - -## Installation and Docs - -Install using `go get github.com/hashicorp/errwrap`. - -Full documentation is available at -http://godoc.org/github.com/hashicorp/errwrap - -## Usage - -#### Basic Usage - -Below is a very basic example of its usage: - -```go -// A function that always returns an error, but wraps it, like a real -// function might. -func tryOpen() error { - _, err := os.Open("/i/dont/exist") - if err != nil { - return errwrap.Wrapf("Doesn't exist: {{err}}", err) - } - - return nil -} - -func main() { - err := tryOpen() - - // We can use the Contains helpers to check if an error contains - // another error. It is safe to do this with a nil error, or with - // an error that doesn't even use the errwrap package. - if errwrap.Contains(err, ErrNotExist) { - // Do something - } - if errwrap.ContainsType(err, new(os.PathError)) { - // Do something - } - - // Or we can use the associated `Get` functions to just extract - // a specific error. This would return nil if that specific error doesn't - // exist. - perr := errwrap.GetType(err, new(os.PathError)) -} -``` - -#### Custom Types - -If you're already making custom types that properly wrap errors, then -you can get all the functionality of `errwraps.Contains` and such by -implementing the `Wrapper` interface with just one function. Example: - -```go -type AppError { - Code ErrorCode - Err error -} - -func (e *AppError) WrappedErrors() []error { - return []error{e.Err} -} -``` - -Now this works: - -```go -err := &AppError{Err: fmt.Errorf("an error")} -if errwrap.ContainsType(err, fmt.Errorf("")) { - // This will work! -} -``` diff --git a/vendor/github.com/hashicorp/errwrap/errwrap.go b/vendor/github.com/hashicorp/errwrap/errwrap.go deleted file mode 100644 index a733bef18..000000000 --- a/vendor/github.com/hashicorp/errwrap/errwrap.go +++ /dev/null @@ -1,169 +0,0 @@ -// Package errwrap implements methods to formalize error wrapping in Go. -// -// All of the top-level functions that take an `error` are built to be able -// to take any error, not just wrapped errors. This allows you to use errwrap -// without having to type-check and type-cast everywhere. -package errwrap - -import ( - "errors" - "reflect" - "strings" -) - -// WalkFunc is the callback called for Walk. -type WalkFunc func(error) - -// Wrapper is an interface that can be implemented by custom types to -// have all the Contains, Get, etc. functions in errwrap work. -// -// When Walk reaches a Wrapper, it will call the callback for every -// wrapped error in addition to the wrapper itself. Since all the top-level -// functions in errwrap use Walk, this means that all those functions work -// with your custom type. -type Wrapper interface { - WrappedErrors() []error -} - -// Wrap defines that outer wraps inner, returning an error type that -// can be cleanly used with the other methods in this package, such as -// Contains, GetAll, etc. -// -// This function won't modify the error message at all (the outer message -// will be used). -func Wrap(outer, inner error) error { - return &wrappedError{ - Outer: outer, - Inner: inner, - } -} - -// Wrapf wraps an error with a formatting message. This is similar to using -// `fmt.Errorf` to wrap an error. If you're using `fmt.Errorf` to wrap -// errors, you should replace it with this. -// -// format is the format of the error message. The string '{{err}}' will -// be replaced with the original error message. -func Wrapf(format string, err error) error { - outerMsg := "" - if err != nil { - outerMsg = err.Error() - } - - outer := errors.New(strings.Replace( - format, "{{err}}", outerMsg, -1)) - - return Wrap(outer, err) -} - -// Contains checks if the given error contains an error with the -// message msg. If err is not a wrapped error, this will always return -// false unless the error itself happens to match this msg. -func Contains(err error, msg string) bool { - return len(GetAll(err, msg)) > 0 -} - -// ContainsType checks if the given error contains an error with -// the same concrete type as v. If err is not a wrapped error, this will -// check the err itself. -func ContainsType(err error, v interface{}) bool { - return len(GetAllType(err, v)) > 0 -} - -// Get is the same as GetAll but returns the deepest matching error. -func Get(err error, msg string) error { - es := GetAll(err, msg) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetType is the same as GetAllType but returns the deepest matching error. -func GetType(err error, v interface{}) error { - es := GetAllType(err, v) - if len(es) > 0 { - return es[len(es)-1] - } - - return nil -} - -// GetAll gets all the errors that might be wrapped in err with the -// given message. The order of the errors is such that the outermost -// matching error (the most recent wrap) is index zero, and so on. -func GetAll(err error, msg string) []error { - var result []error - - Walk(err, func(err error) { - if err.Error() == msg { - result = append(result, err) - } - }) - - return result -} - -// GetAllType gets all the errors that are the same type as v. -// -// The order of the return value is the same as described in GetAll. -func GetAllType(err error, v interface{}) []error { - var result []error - - var search string - if v != nil { - search = reflect.TypeOf(v).String() - } - Walk(err, func(err error) { - var needle string - if err != nil { - needle = reflect.TypeOf(err).String() - } - - if needle == search { - result = append(result, err) - } - }) - - return result -} - -// Walk walks all the wrapped errors in err and calls the callback. If -// err isn't a wrapped error, this will be called once for err. If err -// is a wrapped error, the callback will be called for both the wrapper -// that implements error as well as the wrapped error itself. -func Walk(err error, cb WalkFunc) { - if err == nil { - return - } - - switch e := err.(type) { - case *wrappedError: - cb(e.Outer) - Walk(e.Inner, cb) - case Wrapper: - cb(err) - - for _, err := range e.WrappedErrors() { - Walk(err, cb) - } - default: - cb(err) - } -} - -// wrappedError is an implementation of error that has both the -// outer and inner errors. -type wrappedError struct { - Outer error - Inner error -} - -func (w *wrappedError) Error() string { - return w.Outer.Error() -} - -func (w *wrappedError) WrappedErrors() []error { - return []error{w.Outer, w.Inner} -} diff --git a/vendor/github.com/joyent/triton-go/CHANGELOG.md b/vendor/github.com/joyent/triton-go/CHANGELOG.md index c0d740998..7b2df2e8a 100644 --- a/vendor/github.com/joyent/triton-go/CHANGELOG.md +++ b/vendor/github.com/joyent/triton-go/CHANGELOG.md @@ -1,5 +1,11 @@ ## Unreleased +- Add support for managing columes in Triton [#100] +- identity/policies: Add support for managing policies in Triton [#86] +- addition of triton-go errors package to expose unwraping of internal errors +- Migration from hashicorp/errwrap to pkg/errors +- Using path.Join() for URL structures rather than fmt.Sprintf() + ## 0.5.2 (December 28) - Standardise the API SSH Signers input casing and naming diff --git a/vendor/github.com/joyent/triton-go/GNUmakefile b/vendor/github.com/joyent/triton-go/GNUmakefile index cca7f6759..f996b9951 100644 --- a/vendor/github.com/joyent/triton-go/GNUmakefile +++ b/vendor/github.com/joyent/triton-go/GNUmakefile @@ -12,9 +12,8 @@ tools:: ## Download and install all dev/code tools go test -i $(TEST) || exit 1 test:: ## Run unit tests - @echo "==> Running unit tests" - @echo $(TEST) | \ - xargs -t go test -v $(TESTARGS) -timeout=30s -parallel=1 | grep -Ev 'TRITON_TEST|TestAcc' + @echo "==> Running unit test with coverage" + @./scripts/go-test-with-coverage.sh testacc:: ## Run acceptance tests @echo "==> Running acceptance tests" diff --git a/vendor/github.com/joyent/triton-go/Gopkg.lock b/vendor/github.com/joyent/triton-go/Gopkg.lock index b61936ad3..858574604 100644 --- a/vendor/github.com/joyent/triton-go/Gopkg.lock +++ b/vendor/github.com/joyent/triton-go/Gopkg.lock @@ -7,17 +7,11 @@ packages = ["."] revision = "d5467c17e7afe8d8f08f556c6c811a50c3feb28d" -[[projects]] - name = "github.com/davecgh/go-spew" - packages = ["spew"] - revision = "346938d642f2ec3594ed81d874461961cd0faa76" - version = "v1.1.0" - [[projects]] branch = "master" - name = "github.com/hashicorp/errwrap" + name = "github.com/pkg/errors" packages = ["."] - revision = "7554cd9344cec97297fa6649b055a8c98c2a1e55" + revision = "e881fd58d78e04cf6d0de1217f8707c8cc2249bc" [[projects]] branch = "master" @@ -29,11 +23,11 @@ branch = "master" name = "golang.org/x/crypto" packages = ["curve25519","ed25519","ed25519/internal/edwards25519","ssh","ssh/agent"] - revision = "bd6f299fb381e4c3393d1c4b1f0b94f5e77650c8" + revision = "0fcca4842a8d74bfddc2c96a073bd2a4d2a7a2e8" [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "28853a8970ee33112a9e7998b18e658bed04d177537ec69db678189f0b8a9a7d" + inputs-digest = "f7efd974ae38e2ee077c4d2698df74128a04797460b5f9c833853ddfaa86a0a0" solver-name = "gps-cdcl" solver-version = 1 diff --git a/vendor/github.com/joyent/triton-go/Gopkg.toml b/vendor/github.com/joyent/triton-go/Gopkg.toml index 3b85ddf9b..3d3f322e6 100644 --- a/vendor/github.com/joyent/triton-go/Gopkg.toml +++ b/vendor/github.com/joyent/triton-go/Gopkg.toml @@ -25,14 +25,6 @@ branch = "master" name = "github.com/abdullin/seq" -[[constraint]] - name = "github.com/davecgh/go-spew" - version = "1.1.0" - -[[constraint]] - branch = "master" - name = "github.com/hashicorp/errwrap" - [[constraint]] branch = "master" name = "github.com/sean-/seed" @@ -40,3 +32,7 @@ [[constraint]] branch = "master" name = "golang.org/x/crypto" + +[[constraint]] + branch = "master" + name = "github.com/pkg/errors" diff --git a/vendor/github.com/joyent/triton-go/authentication/dummy.go b/vendor/github.com/joyent/triton-go/authentication/dummy.go index cd16273b6..797e0047b 100644 --- a/vendor/github.com/joyent/triton-go/authentication/dummy.go +++ b/vendor/github.com/joyent/triton-go/authentication/dummy.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication // DON'T USE THIS OUTSIDE TESTING ~ This key was only created to use for diff --git a/vendor/github.com/joyent/triton-go/authentication/ecdsa_signature.go b/vendor/github.com/joyent/triton-go/authentication/ecdsa_signature.go index 8aaba97a5..7fb5a5ab8 100644 --- a/vendor/github.com/joyent/triton-go/authentication/ecdsa_signature.go +++ b/vendor/github.com/joyent/triton-go/authentication/ecdsa_signature.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication import ( @@ -6,7 +14,7 @@ import ( "fmt" "math/big" - "github.com/hashicorp/errwrap" + "github.com/pkg/errors" "golang.org/x/crypto/ssh" ) @@ -44,7 +52,7 @@ func newECDSASignature(signatureBlob []byte) (*ecdsaSignature, error) { } if err := ssh.Unmarshal(signatureBlob, &ecSig); err != nil { - return nil, errwrap.Wrapf("Error unmarshaling signature: {{err}}", err) + return nil, errors.Wrap(err, "unable to unmarshall signature") } rValue := ecSig.R.Bytes() diff --git a/vendor/github.com/joyent/triton-go/authentication/private_key_signer.go b/vendor/github.com/joyent/triton-go/authentication/private_key_signer.go index 35abff0f6..6e5a67331 100644 --- a/vendor/github.com/joyent/triton-go/authentication/private_key_signer.go +++ b/vendor/github.com/joyent/triton-go/authentication/private_key_signer.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication import ( @@ -7,12 +15,11 @@ import ( "crypto/x509" "encoding/base64" "encoding/pem" - "errors" "fmt" "path" "strings" - "github.com/hashicorp/errwrap" + "github.com/pkg/errors" "golang.org/x/crypto/ssh" ) @@ -44,12 +51,12 @@ func NewPrivateKeySigner(input PrivateKeySignerInput) (*PrivateKeySigner, error) rsakey, err := x509.ParsePKCS1PrivateKey(block.Bytes) if err != nil { - return nil, errwrap.Wrapf("Error parsing private key: {{err}}", err) + return nil, errors.Wrap(err, "unable to parse private key") } sshPublicKey, err := ssh.NewPublicKey(rsakey.Public()) if err != nil { - return nil, errwrap.Wrapf("Error parsing SSH key from private key: {{err}}", err) + return nil, errors.Wrap(err, "unable to parse SSH key from private key") } matchKeyFingerprint := formatPublicKeyFingerprint(sshPublicKey, false) @@ -89,7 +96,7 @@ func (s *PrivateKeySigner) Sign(dateHeader string) (string, error) { signed, err := rsa.SignPKCS1v15(rand.Reader, s.privateKey, s.hashFunc, digest) if err != nil { - return "", errwrap.Wrapf("Error signing date header: {{err}}", err) + return "", errors.Wrap(err, "unable to sign date header") } signedBase64 := base64.StdEncoding.EncodeToString(signed) @@ -110,7 +117,7 @@ func (s *PrivateKeySigner) SignRaw(toSign string) (string, string, error) { signed, err := rsa.SignPKCS1v15(rand.Reader, s.privateKey, s.hashFunc, digest) if err != nil { - return "", "", errwrap.Wrapf("Error signing date header: {{err}}", err) + return "", "", errors.Wrap(err, "unable to sign date header") } signedBase64 := base64.StdEncoding.EncodeToString(signed) return signedBase64, "rsa-sha1", nil diff --git a/vendor/github.com/joyent/triton-go/authentication/rsa_signature.go b/vendor/github.com/joyent/triton-go/authentication/rsa_signature.go index 8d513f6c4..81b735eb1 100644 --- a/vendor/github.com/joyent/triton-go/authentication/rsa_signature.go +++ b/vendor/github.com/joyent/triton-go/authentication/rsa_signature.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication import ( diff --git a/vendor/github.com/joyent/triton-go/authentication/signature.go b/vendor/github.com/joyent/triton-go/authentication/signature.go index e6a52df30..8cc18d964 100644 --- a/vendor/github.com/joyent/triton-go/authentication/signature.go +++ b/vendor/github.com/joyent/triton-go/authentication/signature.go @@ -1,8 +1,16 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication import ( - "regexp" "fmt" + "regexp" ) type httpAuthSignature interface { diff --git a/vendor/github.com/joyent/triton-go/authentication/signer.go b/vendor/github.com/joyent/triton-go/authentication/signer.go index 6e3d31dd7..f1e114194 100644 --- a/vendor/github.com/joyent/triton-go/authentication/signer.go +++ b/vendor/github.com/joyent/triton-go/authentication/signer.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication const authorizationHeaderFormat = `Signature keyId="%s",algorithm="%s",headers="%s",signature="%s"` diff --git a/vendor/github.com/joyent/triton-go/authentication/ssh_agent_signer.go b/vendor/github.com/joyent/triton-go/authentication/ssh_agent_signer.go index c068dae27..304e7fb3b 100644 --- a/vendor/github.com/joyent/triton-go/authentication/ssh_agent_signer.go +++ b/vendor/github.com/joyent/triton-go/authentication/ssh_agent_signer.go @@ -1,23 +1,30 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication import ( "crypto/md5" "crypto/sha256" "encoding/base64" - "errors" "fmt" "net" "os" "path" "strings" - "github.com/hashicorp/errwrap" + pkgerrors "github.com/pkg/errors" "golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh/agent" ) var ( - ErrUnsetEnvVar = errors.New("SSH_AUTH_SOCK is not set") + ErrUnsetEnvVar = pkgerrors.New("environment variable SSH_AUTH_SOCK not set") ) type SSHAgentSigner struct { @@ -46,7 +53,7 @@ func NewSSHAgentSigner(input SSHAgentSignerInput) (*SSHAgentSigner, error) { conn, err := net.Dial("unix", sshAgentAddress) if err != nil { - return nil, errwrap.Wrapf("Error dialing SSH agent: {{err}}", err) + return nil, pkgerrors.Wrap(err, "unable to dial SSH agent") } ag := agent.NewClient(conn) @@ -82,7 +89,7 @@ func NewSSHAgentSigner(input SSHAgentSignerInput) (*SSHAgentSigner, error) { func (s *SSHAgentSigner) MatchKey() (ssh.PublicKey, error) { keys, err := s.agent.List() if err != nil { - return nil, errwrap.Wrapf("Error listing keys in SSH Agent: %s", err) + return nil, pkgerrors.Wrap(err, "unable to list keys in SSH Agent") } keyFingerprintStripped := strings.TrimPrefix(s.keyFingerprint, "MD5:") @@ -116,12 +123,12 @@ func (s *SSHAgentSigner) Sign(dateHeader string) (string, error) { signature, err := s.agent.Sign(s.key, []byte(fmt.Sprintf("%s: %s", headerName, dateHeader))) if err != nil { - return "", errwrap.Wrapf("Error signing date header: {{err}}", err) + return "", pkgerrors.Wrap(err, "unable to sign date header") } keyFormat, err := keyFormatToKeyType(signature.Format) if err != nil { - return "", errwrap.Wrapf("Error reading signature: {{err}}", err) + return "", pkgerrors.Wrap(err, "unable to format signature") } var authSignature httpAuthSignature @@ -129,12 +136,12 @@ func (s *SSHAgentSigner) Sign(dateHeader string) (string, error) { case "rsa": authSignature, err = newRSASignature(signature.Blob) if err != nil { - return "", errwrap.Wrapf("Error reading signature: {{err}}", err) + return "", pkgerrors.Wrap(err, "unable to read RSA signature") } case "ecdsa": authSignature, err = newECDSASignature(signature.Blob) if err != nil { - return "", errwrap.Wrapf("Error reading signature: {{err}}", err) + return "", pkgerrors.Wrap(err, "unable to read ECDSA signature") } default: return "", fmt.Errorf("Unsupported algorithm from SSH agent: %s", signature.Format) @@ -147,12 +154,12 @@ func (s *SSHAgentSigner) Sign(dateHeader string) (string, error) { func (s *SSHAgentSigner) SignRaw(toSign string) (string, string, error) { signature, err := s.agent.Sign(s.key, []byte(toSign)) if err != nil { - return "", "", errwrap.Wrapf("Error signing string: {{err}}", err) + return "", "", pkgerrors.Wrap(err, "unable to sign string") } keyFormat, err := keyFormatToKeyType(signature.Format) if err != nil { - return "", "", errwrap.Wrapf("Error reading signature: {{err}}", err) + return "", "", pkgerrors.Wrap(err, "unable to format key") } var authSignature httpAuthSignature @@ -160,12 +167,12 @@ func (s *SSHAgentSigner) SignRaw(toSign string) (string, string, error) { case "rsa": authSignature, err = newRSASignature(signature.Blob) if err != nil { - return "", "", errwrap.Wrapf("Error reading signature: {{err}}", err) + return "", "", pkgerrors.Wrap(err, "unable to read RSA signature") } case "ecdsa": authSignature, err = newECDSASignature(signature.Blob) if err != nil { - return "", "", errwrap.Wrapf("Error reading signature: {{err}}", err) + return "", "", pkgerrors.Wrap(err, "unable to read ECDSA signature") } default: return "", "", fmt.Errorf("Unsupported algorithm from SSH agent: %s", signature.Format) diff --git a/vendor/github.com/joyent/triton-go/authentication/test_signer.go b/vendor/github.com/joyent/triton-go/authentication/test_signer.go index a9c2c82d5..4ccfd3847 100644 --- a/vendor/github.com/joyent/triton-go/authentication/test_signer.go +++ b/vendor/github.com/joyent/triton-go/authentication/test_signer.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication // TestSigner represents an authentication key signer which we can use for diff --git a/vendor/github.com/joyent/triton-go/authentication/util.go b/vendor/github.com/joyent/triton-go/authentication/util.go index 7c298b68c..95918439f 100644 --- a/vendor/github.com/joyent/triton-go/authentication/util.go +++ b/vendor/github.com/joyent/triton-go/authentication/util.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package authentication import ( diff --git a/vendor/github.com/joyent/triton-go/client/client.go b/vendor/github.com/joyent/triton-go/client/client.go index cccf3a25d..0d8bc8931 100644 --- a/vendor/github.com/joyent/triton-go/client/client.go +++ b/vendor/github.com/joyent/triton-go/client/client.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package client import ( @@ -5,7 +13,6 @@ import ( "context" "crypto/tls" "encoding/json" - "errors" "fmt" "io" "net" @@ -14,19 +21,21 @@ import ( "os" "time" - "github.com/hashicorp/errwrap" + "github.com/joyent/triton-go" "github.com/joyent/triton-go/authentication" + "github.com/joyent/triton-go/errors" + pkgerrors "github.com/pkg/errors" ) const nilContext = "nil context" var ( - ErrDefaultAuth = errors.New("default SSH agent authentication requires SDC_KEY_ID / TRITON_KEY_ID and SSH_AUTH_SOCK") - ErrAccountName = errors.New("missing account name for Triton/Manta") - ErrMissingURL = errors.New("missing Triton and/or Manta URL") + ErrDefaultAuth = pkgerrors.New("default SSH agent authentication requires SDC_KEY_ID / TRITON_KEY_ID and SSH_AUTH_SOCK") + ErrAccountName = pkgerrors.New("missing account name") + ErrMissingURL = pkgerrors.New("missing API URL") - BadTritonURL = "invalid format of triton URL" - BadMantaURL = "invalid format of manta URL" + InvalidTritonURL = "invalid format of Triton URL" + InvalidMantaURL = "invalid format of Manta URL" ) // Client represents a connection to the Triton Compute or Object Storage APIs. @@ -55,12 +64,12 @@ func New(tritonURL string, mantaURL string, accountName string, signers ...authe cloudURL, err := url.Parse(tritonURL) if err != nil { - return nil, errwrap.Wrapf(BadTritonURL+": {{err}}", err) + return nil, pkgerrors.Wrapf(err, InvalidTritonURL) } storageURL, err := url.Parse(mantaURL) if err != nil { - return nil, errwrap.Wrapf(BadMantaURL+": {{err}}", err) + return nil, pkgerrors.Wrapf(err, InvalidMantaURL) } authorizers := make([]authentication.Signer, 0) @@ -124,7 +133,7 @@ func (c *Client) DefaultAuth() error { } defaultSigner, err := authentication.NewSSHAgentSigner(input) if err != nil { - return errwrap.Wrapf("problem initializing NewSSHAgentSigner: {{err}}", err) + return pkgerrors.Wrapf(err, "unable to initialize NewSSHAgentSigner") } c.Authorizers = append(c.Authorizers, defaultSigner) } @@ -164,19 +173,20 @@ func doNotFollowRedirects(*http.Request, []*http.Request) error { return http.ErrUseLastResponse } -// TODO(justinwr): Deprecated? -// func (c *Client) FormatURL(path string) string { -// return fmt.Sprintf("%s%s", c.Endpoint, path) -// } - -func (c *Client) DecodeError(statusCode int, body io.Reader) error { - err := &TritonError{ - StatusCode: statusCode, +func (c *Client) DecodeError(resp *http.Response, requestMethod string) error { + err := &errors.APIError{ + StatusCode: resp.StatusCode, } - errorDecoder := json.NewDecoder(body) - if err := errorDecoder.Decode(err); err != nil { - return errwrap.Wrapf("Error decoding error response: {{err}}", err) + if requestMethod != http.MethodHead && resp.Body != nil { + errorDecoder := json.NewDecoder(resp.Body) + if err := errorDecoder.Decode(err); err != nil { + return pkgerrors.Wrapf(err, "unable to decode error response") + } + } + + if err.Message == "" { + err.Message = fmt.Sprintf("HTTP response returned status code %d", err.StatusCode) } return err @@ -215,7 +225,7 @@ func (c *Client) ExecuteRequestURIParams(ctx context.Context, inputs RequestInpu req, err := http.NewRequest(method, endpoint.String(), requestBody) if err != nil { - return nil, errwrap.Wrapf("Error constructing HTTP request: {{err}}", err) + return nil, pkgerrors.Wrapf(err, "unable to construct HTTP request") } dateHeader := time.Now().UTC().Format(time.RFC1123) @@ -225,12 +235,12 @@ func (c *Client) ExecuteRequestURIParams(ctx context.Context, inputs RequestInpu // outside that constructor). authHeader, err := c.Authorizers[0].Sign(dateHeader) if err != nil { - return nil, errwrap.Wrapf("Error signing HTTP request: {{err}}", err) + return nil, pkgerrors.Wrapf(err, "unable to sign HTTP request") } req.Header.Set("Authorization", authHeader) req.Header.Set("Accept", "application/json") - req.Header.Set("Accept-Version", "8") - req.Header.Set("User-Agent", "triton-go Client API") + req.Header.Set("Accept-Version", triton.CloudAPIMajorVersion) + req.Header.Set("User-Agent", triton.UserAgent()) if body != nil { req.Header.Set("Content-Type", "application/json") @@ -238,14 +248,16 @@ func (c *Client) ExecuteRequestURIParams(ctx context.Context, inputs RequestInpu resp, err := c.HTTPClient.Do(req.WithContext(ctx)) if err != nil { - return nil, errwrap.Wrapf("Error executing HTTP request: {{err}}", err) + return nil, pkgerrors.Wrapf(err, "unable to execute HTTP request") } + // We will only return a response from the API it is in the HTTP StatusCode 2xx range + // StatusMultipleChoices is StatusCode 300 if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices { return resp.Body, nil } - return nil, c.DecodeError(resp.StatusCode, resp.Body) + return nil, c.DecodeError(resp, req.Method) } func (c *Client) ExecuteRequest(ctx context.Context, inputs RequestInput) (io.ReadCloser, error) { @@ -271,7 +283,7 @@ func (c *Client) ExecuteRequestRaw(ctx context.Context, inputs RequestInput) (*h req, err := http.NewRequest(method, endpoint.String(), requestBody) if err != nil { - return nil, errwrap.Wrapf("Error constructing HTTP request: {{err}}", err) + return nil, pkgerrors.Wrapf(err, "unable to construct HTTP request") } dateHeader := time.Now().UTC().Format(time.RFC1123) @@ -281,12 +293,12 @@ func (c *Client) ExecuteRequestRaw(ctx context.Context, inputs RequestInput) (*h // outside that constructor). authHeader, err := c.Authorizers[0].Sign(dateHeader) if err != nil { - return nil, errwrap.Wrapf("Error signing HTTP request: {{err}}", err) + return nil, pkgerrors.Wrapf(err, "unable to sign HTTP request") } req.Header.Set("Authorization", authHeader) req.Header.Set("Accept", "application/json") - req.Header.Set("Accept-Version", "8") - req.Header.Set("User-Agent", "triton-go c API") + req.Header.Set("Accept-Version", triton.CloudAPIMajorVersion) + req.Header.Set("User-Agent", triton.UserAgent()) if body != nil { req.Header.Set("Content-Type", "application/json") @@ -294,10 +306,16 @@ func (c *Client) ExecuteRequestRaw(ctx context.Context, inputs RequestInput) (*h resp, err := c.HTTPClient.Do(req.WithContext(ctx)) if err != nil { - return nil, errwrap.Wrapf("Error executing HTTP request: {{err}}", err) + return nil, pkgerrors.Wrapf(err, "unable to execute HTTP request") } - return resp, nil + // We will only return a response from the API it is in the HTTP StatusCode 2xx range + // StatusMultipleChoices is StatusCode 300 + if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices { + return resp, nil + } + + return nil, c.DecodeError(resp, req.Method) } func (c *Client) ExecuteRequestStorage(ctx context.Context, inputs RequestInput) (io.ReadCloser, http.Header, error) { @@ -321,7 +339,7 @@ func (c *Client) ExecuteRequestStorage(ctx context.Context, inputs RequestInput) req, err := http.NewRequest(method, endpoint.String(), requestBody) if err != nil { - return nil, nil, errwrap.Wrapf("Error constructing HTTP request: {{err}}", err) + return nil, nil, pkgerrors.Wrapf(err, "unable to construct HTTP request") } if body != nil && (headers == nil || headers.Get("Content-Type") == "") { @@ -340,11 +358,11 @@ func (c *Client) ExecuteRequestStorage(ctx context.Context, inputs RequestInput) authHeader, err := c.Authorizers[0].Sign(dateHeader) if err != nil { - return nil, nil, errwrap.Wrapf("Error signing HTTP request: {{err}}", err) + return nil, nil, pkgerrors.Wrapf(err, "unable to sign HTTP request") } req.Header.Set("Authorization", authHeader) req.Header.Set("Accept", "*/*") - req.Header.Set("User-Agent", "manta-go client API") + req.Header.Set("User-Agent", triton.UserAgent()) if query != nil { req.URL.RawQuery = query.Encode() @@ -352,29 +370,16 @@ func (c *Client) ExecuteRequestStorage(ctx context.Context, inputs RequestInput) resp, err := c.HTTPClient.Do(req.WithContext(ctx)) if err != nil { - return nil, nil, errwrap.Wrapf("Error executing HTTP request: {{err}}", err) + return nil, nil, pkgerrors.Wrapf(err, "unable to execute HTTP request") } + // We will only return a response from the API it is in the HTTP StatusCode 2xx range + // StatusMultipleChoices is StatusCode 300 if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices { return resp.Body, resp.Header, nil } - mantaError := &MantaError{ - StatusCode: resp.StatusCode, - } - - if req.Method != http.MethodHead { - errorDecoder := json.NewDecoder(resp.Body) - if err := errorDecoder.Decode(mantaError); err != nil { - return nil, nil, errwrap.Wrapf("Error decoding error response: {{err}}", err) - } - } - - if mantaError.Message == "" { - mantaError.Message = fmt.Sprintf("HTTP response returned status code %d", resp.StatusCode) - } - - return nil, nil, mantaError + return nil, nil, c.DecodeError(resp, req.Method) } type RequestNoEncodeInput struct { @@ -397,7 +402,7 @@ func (c *Client) ExecuteRequestNoEncode(ctx context.Context, inputs RequestNoEnc req, err := http.NewRequest(method, endpoint.String(), body) if err != nil { - return nil, nil, errwrap.Wrapf("Error constructing HTTP request: {{err}}", err) + return nil, nil, pkgerrors.Wrapf(err, "unable to construct HTTP request") } if headers != nil { @@ -413,11 +418,12 @@ func (c *Client) ExecuteRequestNoEncode(ctx context.Context, inputs RequestNoEnc authHeader, err := c.Authorizers[0].Sign(dateHeader) if err != nil { - return nil, nil, errwrap.Wrapf("Error signing HTTP request: {{err}}", err) + return nil, nil, pkgerrors.Wrapf(err, "unable to sign HTTP request") } req.Header.Set("Authorization", authHeader) req.Header.Set("Accept", "*/*") - req.Header.Set("User-Agent", "manta-go client API") + req.Header.Set("Accept-Version", triton.CloudAPIMajorVersion) + req.Header.Set("User-Agent", triton.UserAgent()) if query != nil { req.URL.RawQuery = query.Encode() @@ -425,20 +431,14 @@ func (c *Client) ExecuteRequestNoEncode(ctx context.Context, inputs RequestNoEnc resp, err := c.HTTPClient.Do(req.WithContext(ctx)) if err != nil { - return nil, nil, errwrap.Wrapf("Error executing HTTP request: {{err}}", err) + return nil, nil, pkgerrors.Wrapf(err, "unable to execute HTTP request") } + // We will only return a response from the API it is in the HTTP StatusCode 2xx range + // StatusMultipleChoices is StatusCode 300 if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices { return resp.Body, resp.Header, nil } - mantaError := &MantaError{ - StatusCode: resp.StatusCode, - } - - errorDecoder := json.NewDecoder(resp.Body) - if err := errorDecoder.Decode(mantaError); err != nil { - return nil, nil, errwrap.Wrapf("Error decoding error response: {{err}}", err) - } - return nil, nil, mantaError + return nil, nil, c.DecodeError(resp, req.Method) } diff --git a/vendor/github.com/joyent/triton-go/client/errors.go b/vendor/github.com/joyent/triton-go/client/errors.go deleted file mode 100644 index 1fc64a095..000000000 --- a/vendor/github.com/joyent/triton-go/client/errors.go +++ /dev/null @@ -1,190 +0,0 @@ -package client - -import ( - "fmt" - - "github.com/hashicorp/errwrap" -) - -// ClientError represents an error code and message along with the status code -// of the HTTP request which resulted in the error message. -type ClientError struct { - StatusCode int - Code string - Message string -} - -// Error implements interface Error on the TritonError type. -func (e ClientError) Error() string { - return fmt.Sprintf("%s: %s", e.Code, e.Message) -} - -// MantaError represents an error code and message along with -// the status code of the HTTP request which resulted in the error -// message. Error codes used by the Manta API are listed at -// https://apidocs.joyent.com/manta/api.html#errors -type MantaError struct { - StatusCode int - Code string `json:"code"` - Message string `json:"message"` -} - -// Error implements interface Error on the MantaError type. -func (e MantaError) Error() string { - return fmt.Sprintf("%s: %s", e.Code, e.Message) -} - -// TritonError represents an error code and message along with -// the status code of the HTTP request which resulted in the error -// message. Error codes used by the Triton API are listed at -// https://apidocs.joyent.com/cloudapi/#cloudapi-http-responses -type TritonError struct { - StatusCode int - Code string `json:"code"` - Message string `json:"message"` -} - -// Error implements interface Error on the TritonError type. -func (e TritonError) Error() string { - return fmt.Sprintf("%s: %s", e.Code, e.Message) -} - -func IsAuthSchemeError(err error) bool { - return isSpecificError(err, "AuthScheme") -} -func IsAuthorizationError(err error) bool { - return isSpecificError(err, "Authorization") -} -func IsBadRequestError(err error) bool { - return isSpecificError(err, "BadRequest") -} -func IsChecksumError(err error) bool { - return isSpecificError(err, "Checksum") -} -func IsConcurrentRequestError(err error) bool { - return isSpecificError(err, "ConcurrentRequest") -} -func IsContentLengthError(err error) bool { - return isSpecificError(err, "ContentLength") -} -func IsContentMD5MismatchError(err error) bool { - return isSpecificError(err, "ContentMD5Mismatch") -} -func IsEntityExistsError(err error) bool { - return isSpecificError(err, "EntityExists") -} -func IsInvalidArgumentError(err error) bool { - return isSpecificError(err, "InvalidArgument") -} -func IsInvalidAuthTokenError(err error) bool { - return isSpecificError(err, "InvalidAuthToken") -} -func IsInvalidCredentialsError(err error) bool { - return isSpecificError(err, "InvalidCredentials") -} -func IsInvalidDurabilityLevelError(err error) bool { - return isSpecificError(err, "InvalidDurabilityLevel") -} -func IsInvalidKeyIdError(err error) bool { - return isSpecificError(err, "InvalidKeyId") -} -func IsInvalidJobError(err error) bool { - return isSpecificError(err, "InvalidJob") -} -func IsInvalidLinkError(err error) bool { - return isSpecificError(err, "InvalidLink") -} -func IsInvalidLimitError(err error) bool { - return isSpecificError(err, "InvalidLimit") -} -func IsInvalidSignatureError(err error) bool { - return isSpecificError(err, "InvalidSignature") -} -func IsInvalidUpdateError(err error) bool { - return isSpecificError(err, "InvalidUpdate") -} -func IsDirectoryDoesNotExistError(err error) bool { - return isSpecificError(err, "DirectoryDoesNotExist") -} -func IsDirectoryExistsError(err error) bool { - return isSpecificError(err, "DirectoryExists") -} -func IsDirectoryNotEmptyError(err error) bool { - return isSpecificError(err, "DirectoryNotEmpty") -} -func IsDirectoryOperationError(err error) bool { - return isSpecificError(err, "DirectoryOperation") -} -func IsInternalError(err error) bool { - return isSpecificError(err, "Internal") -} -func IsJobNotFoundError(err error) bool { - return isSpecificError(err, "JobNotFound") -} -func IsJobStateError(err error) bool { - return isSpecificError(err, "JobState") -} -func IsKeyDoesNotExistError(err error) bool { - return isSpecificError(err, "KeyDoesNotExist") -} -func IsNotAcceptableError(err error) bool { - return isSpecificError(err, "NotAcceptable") -} -func IsNotEnoughSpaceError(err error) bool { - return isSpecificError(err, "NotEnoughSpace") -} -func IsLinkNotFoundError(err error) bool { - return isSpecificError(err, "LinkNotFound") -} -func IsLinkNotObjectError(err error) bool { - return isSpecificError(err, "LinkNotObject") -} -func IsLinkRequiredError(err error) bool { - return isSpecificError(err, "LinkRequired") -} -func IsParentNotDirectoryError(err error) bool { - return isSpecificError(err, "ParentNotDirectory") -} -func IsPreconditionFailedError(err error) bool { - return isSpecificError(err, "PreconditionFailed") -} -func IsPreSignedRequestError(err error) bool { - return isSpecificError(err, "PreSignedRequest") -} -func IsRequestEntityTooLargeError(err error) bool { - return isSpecificError(err, "RequestEntityTooLarge") -} -func IsResourceNotFoundError(err error) bool { - return isSpecificError(err, "ResourceNotFound") -} -func IsRootDirectoryError(err error) bool { - return isSpecificError(err, "RootDirectory") -} -func IsServiceUnavailableError(err error) bool { - return isSpecificError(err, "ServiceUnavailable") -} -func IsSSLRequiredError(err error) bool { - return isSpecificError(err, "SSLRequired") -} -func IsUploadTimeoutError(err error) bool { - return isSpecificError(err, "UploadTimeout") -} -func IsUserDoesNotExistError(err error) bool { - return isSpecificError(err, "UserDoesNotExist") -} - -// isSpecificError checks whether the error represented by err wraps -// an underlying MantaError with code errorCode. -func isSpecificError(err error, errorCode string) bool { - tritonErrorInterface := errwrap.GetType(err.(error), &MantaError{}) - if tritonErrorInterface == nil { - return false - } - - tritonErr := tritonErrorInterface.(*MantaError) - if tritonErr.Code == errorCode { - return true - } - - return false -} diff --git a/vendor/github.com/joyent/triton-go/errors/errors.go b/vendor/github.com/joyent/triton-go/errors/errors.go new file mode 100644 index 000000000..8f2719738 --- /dev/null +++ b/vendor/github.com/joyent/triton-go/errors/errors.go @@ -0,0 +1,297 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + +package errors + +import ( + "fmt" + "net/http" + "strings" + + "github.com/pkg/errors" +) + +// APIError represents an error code and message along with +// the status code of the HTTP request which resulted in the error +// message. Error codes used by the Triton API are listed at +// https://apidocs.joyent.com/cloudapi/#cloudapi-http-responses +// Error codes used by the Manta API are listed at +// https://apidocs.joyent.com/manta/api.html#errors +type APIError struct { + StatusCode int + Code string `json:"code"` + Message string `json:"message"` +} + +// Error implements interface Error on the APIError type. +func (e APIError) Error() string { + return strings.Trim(fmt.Sprintf("%+q", e.Code), `"`) + ": " + strings.Trim(fmt.Sprintf("%+q", e.Message), `"`) +} + +// ClientError represents an error code and message returned +// when connecting to the triton-go client +type ClientError struct { + StatusCode int + Code string `json:"code"` + Message string `json:"message"` +} + +// Error implements interface Error on the ClientError type. +func (e ClientError) Error() string { + return strings.Trim(fmt.Sprintf("%+q", e.Code), `"`) + ": " + strings.Trim(fmt.Sprintf("%+q", e.Message), `"`) +} + +func IsAuthSchemeError(err error) bool { + return IsSpecificError(err, "AuthScheme") +} + +func IsAuthorizationError(err error) bool { + return IsSpecificError(err, "Authorization") +} + +func IsBadRequestError(err error) bool { + return IsSpecificError(err, "BadRequest") +} + +func IsChecksumError(err error) bool { + return IsSpecificError(err, "Checksum") +} + +func IsConcurrentRequestError(err error) bool { + return IsSpecificError(err, "ConcurrentRequest") +} + +func IsContentLengthError(err error) bool { + return IsSpecificError(err, "ContentLength") +} + +func IsContentMD5MismatchError(err error) bool { + return IsSpecificError(err, "ContentMD5Mismatch") +} + +func IsEntityExistsError(err error) bool { + return IsSpecificError(err, "EntityExists") +} + +func IsInvalidArgumentError(err error) bool { + return IsSpecificError(err, "InvalidArgument") +} + +func IsInvalidAuthTokenError(err error) bool { + return IsSpecificError(err, "InvalidAuthToken") +} + +func IsInvalidCredentialsError(err error) bool { + return IsSpecificError(err, "InvalidCredentials") +} + +func IsInvalidDurabilityLevelError(err error) bool { + return IsSpecificError(err, "InvalidDurabilityLevel") +} + +func IsInvalidKeyIdError(err error) bool { + return IsSpecificError(err, "InvalidKeyId") +} + +func IsInvalidJobError(err error) bool { + return IsSpecificError(err, "InvalidJob") +} + +func IsInvalidLinkError(err error) bool { + return IsSpecificError(err, "InvalidLink") +} + +func IsInvalidLimitError(err error) bool { + return IsSpecificError(err, "InvalidLimit") +} + +func IsInvalidSignatureError(err error) bool { + return IsSpecificError(err, "InvalidSignature") +} + +func IsInvalidUpdateError(err error) bool { + return IsSpecificError(err, "InvalidUpdate") +} + +func IsDirectoryDoesNotExistError(err error) bool { + return IsSpecificError(err, "DirectoryDoesNotExist") +} + +func IsDirectoryExistsError(err error) bool { + return IsSpecificError(err, "DirectoryExists") +} + +func IsDirectoryNotEmptyError(err error) bool { + return IsSpecificError(err, "DirectoryNotEmpty") +} + +func IsDirectoryOperationError(err error) bool { + return IsSpecificError(err, "DirectoryOperation") +} + +func IsInternalError(err error) bool { + return IsSpecificError(err, "Internal") +} + +func IsJobNotFoundError(err error) bool { + return IsSpecificError(err, "JobNotFound") +} + +func IsJobStateError(err error) bool { + return IsSpecificError(err, "JobState") +} + +func IsKeyDoesNotExistError(err error) bool { + return IsSpecificError(err, "KeyDoesNotExist") +} + +func IsNotAcceptableError(err error) bool { + return IsSpecificError(err, "NotAcceptable") +} + +func IsNotEnoughSpaceError(err error) bool { + return IsSpecificError(err, "NotEnoughSpace") +} + +func IsLinkNotFoundError(err error) bool { + return IsSpecificError(err, "LinkNotFound") +} + +func IsLinkNotObjectError(err error) bool { + return IsSpecificError(err, "LinkNotObject") +} + +func IsLinkRequiredError(err error) bool { + return IsSpecificError(err, "LinkRequired") +} + +func IsParentNotDirectoryError(err error) bool { + return IsSpecificError(err, "ParentNotDirectory") +} + +func IsPreconditionFailedError(err error) bool { + return IsSpecificError(err, "PreconditionFailed") +} + +func IsPreSignedRequestError(err error) bool { + return IsSpecificError(err, "PreSignedRequest") +} + +func IsRequestEntityTooLargeError(err error) bool { + return IsSpecificError(err, "RequestEntityTooLarge") +} + +func IsResourceNotFoundError(err error) bool { + return IsSpecificError(err, "ResourceNotFound") +} + +func IsRootDirectoryError(err error) bool { + return IsSpecificError(err, "RootDirectory") +} + +func IsServiceUnavailableError(err error) bool { + return IsSpecificError(err, "ServiceUnavailable") +} + +func IsSSLRequiredError(err error) bool { + return IsSpecificError(err, "SSLRequired") +} + +func IsUploadTimeoutError(err error) bool { + return IsSpecificError(err, "UploadTimeout") +} + +func IsUserDoesNotExistError(err error) bool { + return IsSpecificError(err, "UserDoesNotExist") +} + +func IsBadRequest(err error) bool { + return IsSpecificError(err, "BadRequest") +} + +func IsInUseError(err error) bool { + return IsSpecificError(err, "InUseError") +} + +func IsInvalidArgument(err error) bool { + return IsSpecificError(err, "InvalidArgument") +} + +func IsInvalidCredentials(err error) bool { + return IsSpecificError(err, "InvalidCredentials") +} + +func IsInvalidHeader(err error) bool { + return IsSpecificError(err, "InvalidHeader") +} + +func IsInvalidVersion(err error) bool { + return IsSpecificError(err, "InvalidVersion") +} + +func IsMissingParameter(err error) bool { + return IsSpecificError(err, "MissingParameter") +} + +func IsNotAuthorized(err error) bool { + return IsSpecificError(err, "NotAuthorized") +} + +func IsRequestThrottled(err error) bool { + return IsSpecificError(err, "RequestThrottled") +} + +func IsRequestTooLarge(err error) bool { + return IsSpecificError(err, "RequestTooLarge") +} + +func IsRequestMoved(err error) bool { + return IsSpecificError(err, "RequestMoved") +} + +func IsResourceFound(err error) bool { + return IsSpecificError(err, "ResourceFound") +} + +func IsResourceNotFound(err error) bool { + return IsSpecificError(err, "ResourceNotFound") +} + +func IsUnknownError(err error) bool { + return IsSpecificError(err, "UnknownError") +} + +func IsEmptyResponse(err error) bool { + return IsSpecificError(err, "EmptyResponse") +} + +func IsStatusNotFoundCode(err error) bool { + return IsSpecificStatusCode(err, http.StatusNotFound) +} + +func IsSpecificError(myError error, errorCode string) bool { + switch err := errors.Cause(myError).(type) { + case *APIError: + if err.Code == errorCode { + return true + } + } + + return false +} + +func IsSpecificStatusCode(myError error, statusCode int) bool { + switch err := errors.Cause(myError).(type) { + case *APIError: + if err.StatusCode == statusCode { + return true + } + } + + return false +} diff --git a/vendor/github.com/joyent/triton-go/storage/client.go b/vendor/github.com/joyent/triton-go/storage/client.go index 36e87e653..e38569fbc 100644 --- a/vendor/github.com/joyent/triton-go/storage/client.go +++ b/vendor/github.com/joyent/triton-go/storage/client.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package storage import ( diff --git a/vendor/github.com/joyent/triton-go/storage/directory.go b/vendor/github.com/joyent/triton-go/storage/directory.go index 47f2cea19..865b56483 100644 --- a/vendor/github.com/joyent/triton-go/storage/directory.go +++ b/vendor/github.com/joyent/triton-go/storage/directory.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package storage import ( @@ -10,8 +18,8 @@ import ( "strconv" "time" - "github.com/hashicorp/errwrap" "github.com/joyent/triton-go/client" + "github.com/pkg/errors" ) type DirectoryClient struct { @@ -58,7 +66,7 @@ func (s *DirectoryClient) List(ctx context.Context, input *ListDirectoryInput) ( } respBody, respHeader, err := s.client.ExecuteRequestStorage(ctx, reqInput) if err != nil { - return nil, errwrap.Wrapf("Error executing List request: {{err}}", err) + return nil, errors.Wrap(err, "unable to list directory") } defer respBody.Close() @@ -67,14 +75,14 @@ func (s *DirectoryClient) List(ctx context.Context, input *ListDirectoryInput) ( for scanner.Scan() { current := &DirectoryEntry{} if err := json.Unmarshal(scanner.Bytes(), current); err != nil { - return nil, errwrap.Wrapf("error decoding list response: {{err}}", err) + return nil, errors.Wrap(err, "unable to decode list directories response") } results = append(results, current) } if err := scanner.Err(); err != nil { - return nil, errwrap.Wrapf("error decoding list responses: {{err}}", err) + return nil, errors.Wrap(err, "unable to decode list directories response") } output := &ListDirectoryOutput{ @@ -113,7 +121,7 @@ func (s *DirectoryClient) Put(ctx context.Context, input *PutDirectoryInput) err defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing Put request: {{err}}", err) + return errors.Wrap(err, "unable to put directory") } return nil @@ -177,7 +185,7 @@ func deleteDirectory(c DirectoryClient, ctx context.Context, directoryPath _AbsC defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing DeleteDirectory request: {{err}}", err) + return errors.Wrap(err, "unable to delete directory") } return nil diff --git a/vendor/github.com/joyent/triton-go/storage/job.go b/vendor/github.com/joyent/triton-go/storage/job.go index c7be80ca0..51084a439 100644 --- a/vendor/github.com/joyent/triton-go/storage/job.go +++ b/vendor/github.com/joyent/triton-go/storage/job.go @@ -1,18 +1,26 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package storage import ( "context" "encoding/json" - "fmt" "io" "net/http" "net/url" + "path" "strconv" "strings" "time" - "github.com/hashicorp/errwrap" "github.com/joyent/triton-go/client" + "github.com/pkg/errors" ) type JobClient struct { @@ -99,11 +107,11 @@ type CreateJobOutput struct { // CreateJob submits a new job to be executed. This call is not // idempotent, so calling it twice will create two jobs. func (s *JobClient) Create(ctx context.Context, input *CreateJobInput) (*CreateJobOutput, error) { - path := fmt.Sprintf("/%s/jobs", s.client.AccountName) + fullPath := path.Join("/", s.client.AccountName, "jobs") reqInput := client.RequestInput{ Method: http.MethodPost, - Path: path, + Path: fullPath, Body: input, } respBody, respHeaders, err := s.client.ExecuteRequestStorage(ctx, reqInput) @@ -111,7 +119,7 @@ func (s *JobClient) Create(ctx context.Context, input *CreateJobInput) (*CreateJ defer respBody.Close() } if err != nil { - return nil, errwrap.Wrapf("Error executing CreateJob request: {{err}}", err) + return nil, errors.Wrap(err, "unable to create job") } jobURI := respHeaders.Get("Location") @@ -133,7 +141,7 @@ type AddJobInputsInput struct { // AddJobInputs submits inputs to an already created job. func (s *JobClient) AddInputs(ctx context.Context, input *AddJobInputsInput) error { - path := fmt.Sprintf("/%s/jobs/%s/live/in", s.client.AccountName, input.JobID) + fullPath := path.Join("/", s.client.AccountName, "jobs", input.JobID, "live", "in") headers := &http.Header{} headers.Set("Content-Type", "text/plain") @@ -141,7 +149,7 @@ func (s *JobClient) AddInputs(ctx context.Context, input *AddJobInputsInput) err reqInput := client.RequestNoEncodeInput{ Method: http.MethodPost, - Path: path, + Path: fullPath, Headers: headers, Body: reader, } @@ -150,7 +158,7 @@ func (s *JobClient) AddInputs(ctx context.Context, input *AddJobInputsInput) err defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing AddJobInputs request: {{err}}", err) + return errors.Wrap(err, "unable to add job inputs") } return nil @@ -163,18 +171,18 @@ type EndJobInputInput struct { // EndJobInput submits inputs to an already created job. func (s *JobClient) EndInput(ctx context.Context, input *EndJobInputInput) error { - path := fmt.Sprintf("/%s/jobs/%s/live/in/end", s.client.AccountName, input.JobID) + fullPath := path.Join("/", s.client.AccountName, "jobs", input.JobID, "live", "in", "end") reqInput := client.RequestNoEncodeInput{ Method: http.MethodPost, - Path: path, + Path: fullPath, } respBody, _, err := s.client.ExecuteRequestNoEncode(ctx, reqInput) if respBody != nil { defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing EndJobInput request: {{err}}", err) + return errors.Wrap(err, "unable to end job inputs") } return nil @@ -194,18 +202,18 @@ type CancelJobInput struct { // - input is still open // - you have a long-running job func (s *JobClient) Cancel(ctx context.Context, input *CancelJobInput) error { - path := fmt.Sprintf("/%s/jobs/%s/live/cancel", s.client.AccountName, input.JobID) + fullPath := path.Join("/", s.client.AccountName, "jobs", input.JobID, "live", "cancel") reqInput := client.RequestNoEncodeInput{ Method: http.MethodPost, - Path: path, + Path: fullPath, } respBody, _, err := s.client.ExecuteRequestNoEncode(ctx, reqInput) if respBody != nil { defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing CancelJob request: {{err}}", err) + return errors.Wrap(err, "unable to cancel job") } return nil @@ -226,7 +234,7 @@ type ListJobsOutput struct { // ListJobs returns the list of jobs you currently have. func (s *JobClient) List(ctx context.Context, input *ListJobsInput) (*ListJobsOutput, error) { - path := fmt.Sprintf("/%s/jobs", s.client.AccountName) + fullPath := path.Join("/", s.client.AccountName, "jobs") query := &url.Values{} if input.RunningOnly { query.Set("state", "running") @@ -240,7 +248,7 @@ func (s *JobClient) List(ctx context.Context, input *ListJobsInput) (*ListJobsOu reqInput := client.RequestInput{ Method: http.MethodGet, - Path: path, + Path: fullPath, Query: query, } respBody, respHeader, err := s.client.ExecuteRequestStorage(ctx, reqInput) @@ -248,7 +256,7 @@ func (s *JobClient) List(ctx context.Context, input *ListJobsInput) (*ListJobsOu defer respBody.Close() } if err != nil { - return nil, errwrap.Wrapf("Error executing ListJobs request: {{err}}", err) + return nil, errors.Wrap(err, "unable to list jobs") } var results []*JobSummary @@ -259,7 +267,7 @@ func (s *JobClient) List(ctx context.Context, input *ListJobsInput) (*ListJobsOu if err == io.EOF { break } - return nil, errwrap.Wrapf("Error decoding ListJobs response: {{err}}", err) + return nil, errors.Wrap(err, "unable to decode list jobs response") } results = append(results, current) } @@ -288,24 +296,24 @@ type GetJobOutput struct { // GetJob returns the list of jobs you currently have. func (s *JobClient) Get(ctx context.Context, input *GetJobInput) (*GetJobOutput, error) { - path := fmt.Sprintf("/%s/jobs/%s/live/status", s.client.AccountName, input.JobID) + fullPath := path.Join("/", s.client.AccountName, "jobs", input.JobID, "live", "status") reqInput := client.RequestInput{ Method: http.MethodGet, - Path: path, + Path: fullPath, } respBody, _, err := s.client.ExecuteRequestStorage(ctx, reqInput) if respBody != nil { defer respBody.Close() } if err != nil { - return nil, errwrap.Wrapf("Error executing GetJob request: {{err}}", err) + return nil, errors.Wrap(err, "unable to get job") } job := &Job{} decoder := json.NewDecoder(respBody) if err = decoder.Decode(&job); err != nil { - return nil, errwrap.Wrapf("Error decoding GetJob response: {{err}}", err) + return nil, errors.Wrap(err, "unable to decode get job response") } return &GetJobOutput{ @@ -329,18 +337,18 @@ type GetJobOutputOutput struct { // this like `tail -f`. If error is nil (i.e. the operation is successful), it is // your responsibility to close the io.ReadCloser named Items in the output. func (s *JobClient) GetOutput(ctx context.Context, input *GetJobOutputInput) (*GetJobOutputOutput, error) { - path := fmt.Sprintf("/%s/jobs/%s/live/out", s.client.AccountName, input.JobID) + fullPath := path.Join("/", s.client.AccountName, "jobs", input.JobID, "live", "out") reqInput := client.RequestInput{ Method: http.MethodGet, - Path: path, + Path: fullPath, } respBody, respHeader, err := s.client.ExecuteRequestStorage(ctx, reqInput) if respBody != nil { defer respBody.Close() } if err != nil { - return nil, errwrap.Wrapf("Error executing GetJobOutput request: {{err}}", err) + return nil, errors.Wrap(err, "unable to get job output") } output := &GetJobOutputOutput{ @@ -371,18 +379,18 @@ type GetJobInputOutput struct { // this like `tail -f`. If error is nil (i.e. the operation is successful), it is // your responsibility to close the io.ReadCloser named Items in the output. func (s *JobClient) GetInput(ctx context.Context, input *GetJobInputInput) (*GetJobInputOutput, error) { - path := fmt.Sprintf("/%s/jobs/%s/live/in", s.client.AccountName, input.JobID) + fullPath := path.Join("/", s.client.AccountName, "jobs", input.JobID, "live", "in") reqInput := client.RequestInput{ Method: http.MethodGet, - Path: path, + Path: fullPath, } respBody, respHeader, err := s.client.ExecuteRequestStorage(ctx, reqInput) if respBody != nil { defer respBody.Close() } if err != nil { - return nil, errwrap.Wrapf("Error executing GetJobInput request: {{err}}", err) + return nil, errors.Wrap(err, "unable to get job input") } output := &GetJobInputOutput{ @@ -413,18 +421,18 @@ type GetJobFailuresOutput struct { // this like `tail -f`. If error is nil (i.e. the operation is successful), it is // your responsibility to close the io.ReadCloser named Items in the output. func (s *JobClient) GetFailures(ctx context.Context, input *GetJobFailuresInput) (*GetJobFailuresOutput, error) { - path := fmt.Sprintf("/%s/jobs/%s/live/fail", s.client.AccountName, input.JobID) + fullPath := path.Join("/", s.client.AccountName, "jobs", input.JobID, "live", "fail") reqInput := client.RequestInput{ Method: http.MethodGet, - Path: path, + Path: fullPath, } respBody, respHeader, err := s.client.ExecuteRequestStorage(ctx, reqInput) if respBody != nil { defer respBody.Close() } if err != nil { - return nil, errwrap.Wrapf("Error executing GetJobFailures request: {{err}}", err) + return nil, errors.Wrap(err, "unable to get job failures") } output := &GetJobFailuresOutput{ diff --git a/vendor/github.com/joyent/triton-go/storage/objects.go b/vendor/github.com/joyent/triton-go/storage/objects.go index 2c40b2775..ad71e3160 100644 --- a/vendor/github.com/joyent/triton-go/storage/objects.go +++ b/vendor/github.com/joyent/triton-go/storage/objects.go @@ -1,8 +1,15 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package storage import ( "context" - "errors" "io" "net/http" "net/url" @@ -11,8 +18,9 @@ import ( "strings" "time" - "github.com/hashicorp/errwrap" "github.com/joyent/triton-go/client" + tt "github.com/joyent/triton-go/errors" + "github.com/pkg/errors" ) type ObjectsClient struct { @@ -53,7 +61,7 @@ func (s *ObjectsClient) GetInfo(ctx context.Context, input *GetInfoInput) (*GetI } _, respHeaders, err := s.client.ExecuteRequestStorage(ctx, reqInput) if err != nil { - return nil, errwrap.Wrapf("Error executing get info request: {{err}}", err) + return nil, errors.Wrap(err, "unable to get info") } response := &GetInfoOutput{ @@ -135,7 +143,7 @@ func (s *ObjectsClient) Get(ctx context.Context, input *GetObjectInput) (*GetObj } respBody, respHeaders, err := s.client.ExecuteRequestStorage(ctx, reqInput) if err != nil { - return nil, errwrap.Wrapf("Error executing Get request: {{err}}", err) + return nil, errors.Wrap(err, "unable to get object") } response := &GetObjectOutput{ @@ -191,7 +199,7 @@ func (s *ObjectsClient) Delete(ctx context.Context, input *DeleteObjectInput) er defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing Delete request: {{err}}", err) + return errors.Wrap(err, "unable to delete object") } return nil @@ -235,7 +243,7 @@ func (s *ObjectsClient) PutMetadata(ctx context.Context, input *PutObjectMetadat defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing PutMetadata request: {{err}}", err) + return errors.Wrap(err, "unable to put metadata") } return nil @@ -333,7 +341,7 @@ func putObject(c ObjectsClient, ctx context.Context, input *PutObjectInput, absP defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing Put request: {{err}}", err) + return errors.Wrap(err, "unable to put object") } return nil @@ -370,12 +378,8 @@ func createDirectory(c ObjectsClient, ctx context.Context, absPath _AbsCleanPath func checkDirectoryTreeExists(c ObjectsClient, ctx context.Context, absPath _AbsCleanPath) (bool, error) { exists, err := c.IsDir(ctx, string(absPath)) if err != nil { - errType := &client.MantaError{} - if errwrap.ContainsType(err, errType) { - mantaErr := errwrap.GetType(err, errType).(*client.MantaError) - if mantaErr.StatusCode == http.StatusNotFound { - return false, nil - } + if tt.IsResourceNotFoundError(err) { + return false, nil } return false, err } diff --git a/vendor/github.com/joyent/triton-go/storage/signing.go b/vendor/github.com/joyent/triton-go/storage/signing.go index b88005ce8..81111c32c 100644 --- a/vendor/github.com/joyent/triton-go/storage/signing.go +++ b/vendor/github.com/joyent/triton-go/storage/signing.go @@ -1,14 +1,23 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package storage import ( "bytes" "fmt" "net/url" + "path" "strconv" "strings" "time" - "github.com/hashicorp/errwrap" + "github.com/pkg/errors" ) // SignURLInput represents parameters to a SignURL operation. @@ -57,7 +66,7 @@ func (s *StorageClient) SignURL(input *SignURLInput) (*SignURLOutput, error) { Method: input.Method, Algorithm: strings.ToUpper(s.Client.Authorizers[0].DefaultAlgorithm()), Expires: strconv.FormatInt(time.Now().Add(input.ValidityPeriod).Unix(), 10), - KeyID: fmt.Sprintf("/%s/keys/%s", s.Client.AccountName, s.Client.Authorizers[0].KeyFingerprint()), + KeyID: path.Join("/", s.Client.AccountName, "keys", s.Client.Authorizers[0].KeyFingerprint()), } toSign := bytes.Buffer{} @@ -73,7 +82,7 @@ func (s *StorageClient) SignURL(input *SignURLInput) (*SignURLOutput, error) { signature, _, err := s.Client.Authorizers[0].SignRaw(toSign.String()) if err != nil { - return nil, errwrap.Wrapf("Error signing string: {{err}}", err) + return nil, errors.Wrapf(err, "error signing string") } output.Signature = signature diff --git a/vendor/github.com/joyent/triton-go/storage/snaplink.go b/vendor/github.com/joyent/triton-go/storage/snaplink.go index 1330f0a97..ec8510a68 100644 --- a/vendor/github.com/joyent/triton-go/storage/snaplink.go +++ b/vendor/github.com/joyent/triton-go/storage/snaplink.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package storage import ( @@ -5,8 +13,8 @@ import ( "fmt" "net/http" - "github.com/hashicorp/errwrap" "github.com/joyent/triton-go/client" + "github.com/pkg/errors" ) type SnapLinksClient struct { @@ -39,7 +47,7 @@ func (s *SnapLinksClient) Put(ctx context.Context, input *PutSnapLinkInput) erro defer respBody.Close() } if err != nil { - return errwrap.Wrapf("Error executing PutSnapLink request: {{err}}", err) + return errors.Wrapf(err, "unable to put snaplink") } return nil diff --git a/vendor/github.com/joyent/triton-go/triton.go b/vendor/github.com/joyent/triton-go/triton.go index f9202984e..5d74258d4 100644 --- a/vendor/github.com/joyent/triton-go/triton.go +++ b/vendor/github.com/joyent/triton-go/triton.go @@ -1,3 +1,11 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + package triton import ( diff --git a/vendor/github.com/joyent/triton-go/version.go b/vendor/github.com/joyent/triton-go/version.go new file mode 100644 index 000000000..0c1bc8680 --- /dev/null +++ b/vendor/github.com/joyent/triton-go/version.go @@ -0,0 +1,32 @@ +// +// Copyright (c) 2018, Joyent, Inc. All rights reserved. +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// + +package triton + +import ( + "fmt" + "runtime" +) + +// The main version number of the current released Triton-go SDK. +const Version = "0.9.0" + +// A pre-release marker for the version. If this is "" (empty string) +// then it means that it is a final release. Otherwise, this is a pre-release +// such as "dev" (in development), "beta", "rc1", etc. +var Prerelease = "" + +func UserAgent() string { + if Prerelease != "" { + return fmt.Sprintf("triton-go/%s-%s (%s-%s; %s)", Version, Prerelease, runtime.GOARCH, runtime.GOOS, runtime.Version()) + } else { + return fmt.Sprintf("triton-go/%s (%s-%s; %s)", Version, runtime.GOARCH, runtime.GOOS, runtime.Version()) + } +} + +const CloudAPIMajorVersion = "8" diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE new file mode 100644 index 000000000..835ba3e75 --- /dev/null +++ b/vendor/github.com/pkg/errors/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Dave Cheney +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md new file mode 100644 index 000000000..6483ba2af --- /dev/null +++ b/vendor/github.com/pkg/errors/README.md @@ -0,0 +1,52 @@ +# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) + +Package errors provides simple error handling primitives. + +`go get github.com/pkg/errors` + +The traditional error handling idiom in Go is roughly akin to +```go +if err != nil { + return err +} +``` +which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. + +## Adding context to an error + +The errors.Wrap function returns a new error that adds context to the original error. For example +```go +_, err := ioutil.ReadAll(r) +if err != nil { + return errors.Wrap(err, "read failed") +} +``` +## Retrieving the cause of an error + +Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. +```go +type causer interface { + Cause() error +} +``` +`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: +```go +switch err := errors.Cause(err).(type) { +case *MyError: + // handle specifically +default: + // unknown error +} +``` + +[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). + +## Contributing + +We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. + +Before proposing a change, please discuss your change by raising an issue. + +## License + +BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml new file mode 100644 index 000000000..a932eade0 --- /dev/null +++ b/vendor/github.com/pkg/errors/appveyor.yml @@ -0,0 +1,32 @@ +version: build-{build}.{branch} + +clone_folder: C:\gopath\src\github.com\pkg\errors +shallow_clone: true # for startup speed + +environment: + GOPATH: C:\gopath + +platform: + - x64 + +# http://www.appveyor.com/docs/installed-software +install: + # some helpful output for debugging builds + - go version + - go env + # pre-installed MinGW at C:\MinGW is 32bit only + # but MSYS2 at C:\msys64 has mingw64 + - set PATH=C:\msys64\mingw64\bin;%PATH% + - gcc --version + - g++ --version + +build_script: + - go install -v ./... + +test_script: + - set PATH=C:\gopath\bin;%PATH% + - go test -v ./... + +#artifacts: +# - path: '%GOPATH%\bin\*.exe' +deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go new file mode 100644 index 000000000..842ee8045 --- /dev/null +++ b/vendor/github.com/pkg/errors/errors.go @@ -0,0 +1,269 @@ +// Package errors provides simple error handling primitives. +// +// The traditional error handling idiom in Go is roughly akin to +// +// if err != nil { +// return err +// } +// +// which applied recursively up the call stack results in error reports +// without context or debugging information. The errors package allows +// programmers to add context to the failure path in their code in a way +// that does not destroy the original value of the error. +// +// Adding context to an error +// +// The errors.Wrap function returns a new error that adds context to the +// original error by recording a stack trace at the point Wrap is called, +// and the supplied message. For example +// +// _, err := ioutil.ReadAll(r) +// if err != nil { +// return errors.Wrap(err, "read failed") +// } +// +// If additional control is required the errors.WithStack and errors.WithMessage +// functions destructure errors.Wrap into its component operations of annotating +// an error with a stack trace and an a message, respectively. +// +// Retrieving the cause of an error +// +// Using errors.Wrap constructs a stack of errors, adding context to the +// preceding error. Depending on the nature of the error it may be necessary +// to reverse the operation of errors.Wrap to retrieve the original error +// for inspection. Any error value which implements this interface +// +// type causer interface { +// Cause() error +// } +// +// can be inspected by errors.Cause. errors.Cause will recursively retrieve +// the topmost error which does not implement causer, which is assumed to be +// the original cause. For example: +// +// switch err := errors.Cause(err).(type) { +// case *MyError: +// // handle specifically +// default: +// // unknown error +// } +// +// causer interface is not exported by this package, but is considered a part +// of stable public API. +// +// Formatted printing of errors +// +// All error values returned from this package implement fmt.Formatter and can +// be formatted by the fmt package. The following verbs are supported +// +// %s print the error. If the error has a Cause it will be +// printed recursively +// %v see %s +// %+v extended format. Each Frame of the error's StackTrace will +// be printed in detail. +// +// Retrieving the stack trace of an error or wrapper +// +// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are +// invoked. This information can be retrieved with the following interface. +// +// type stackTracer interface { +// StackTrace() errors.StackTrace +// } +// +// Where errors.StackTrace is defined as +// +// type StackTrace []Frame +// +// The Frame type represents a call site in the stack trace. Frame supports +// the fmt.Formatter interface that can be used for printing information about +// the stack trace of this error. For example: +// +// if err, ok := err.(stackTracer); ok { +// for _, f := range err.StackTrace() { +// fmt.Printf("%+s:%d", f) +// } +// } +// +// stackTracer interface is not exported by this package, but is considered a part +// of stable public API. +// +// See the documentation for Frame.Format for more details. +package errors + +import ( + "fmt" + "io" +) + +// New returns an error with the supplied message. +// New also records the stack trace at the point it was called. +func New(message string) error { + return &fundamental{ + msg: message, + stack: callers(), + } +} + +// Errorf formats according to a format specifier and returns the string +// as a value that satisfies error. +// Errorf also records the stack trace at the point it was called. +func Errorf(format string, args ...interface{}) error { + return &fundamental{ + msg: fmt.Sprintf(format, args...), + stack: callers(), + } +} + +// fundamental is an error that has a message and a stack, but no caller. +type fundamental struct { + msg string + *stack +} + +func (f *fundamental) Error() string { return f.msg } + +func (f *fundamental) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + io.WriteString(s, f.msg) + f.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, f.msg) + case 'q': + fmt.Fprintf(s, "%q", f.msg) + } +} + +// WithStack annotates err with a stack trace at the point WithStack was called. +// If err is nil, WithStack returns nil. +func WithStack(err error) error { + if err == nil { + return nil + } + return &withStack{ + err, + callers(), + } +} + +type withStack struct { + error + *stack +} + +func (w *withStack) Cause() error { return w.error } + +func (w *withStack) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v", w.Cause()) + w.stack.Format(s, verb) + return + } + fallthrough + case 's': + io.WriteString(s, w.Error()) + case 'q': + fmt.Fprintf(s, "%q", w.Error()) + } +} + +// Wrap returns an error annotating err with a stack trace +// at the point Wrap is called, and the supplied message. +// If err is nil, Wrap returns nil. +func Wrap(err error, message string) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: message, + } + return &withStack{ + err, + callers(), + } +} + +// Wrapf returns an error annotating err with a stack trace +// at the point Wrapf is call, and the format specifier. +// If err is nil, Wrapf returns nil. +func Wrapf(err error, format string, args ...interface{}) error { + if err == nil { + return nil + } + err = &withMessage{ + cause: err, + msg: fmt.Sprintf(format, args...), + } + return &withStack{ + err, + callers(), + } +} + +// WithMessage annotates err with a new message. +// If err is nil, WithMessage returns nil. +func WithMessage(err error, message string) error { + if err == nil { + return nil + } + return &withMessage{ + cause: err, + msg: message, + } +} + +type withMessage struct { + cause error + msg string +} + +func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } +func (w *withMessage) Cause() error { return w.cause } + +func (w *withMessage) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + if s.Flag('+') { + fmt.Fprintf(s, "%+v\n", w.Cause()) + io.WriteString(s, w.msg) + return + } + fallthrough + case 's', 'q': + io.WriteString(s, w.Error()) + } +} + +// Cause returns the underlying cause of the error, if possible. +// An error value has a cause if it implements the following +// interface: +// +// type causer interface { +// Cause() error +// } +// +// If the error does not implement Cause, the original error will +// be returned. If the error is nil, nil will be returned without further +// investigation. +func Cause(err error) error { + type causer interface { + Cause() error + } + + for err != nil { + cause, ok := err.(causer) + if !ok { + break + } + err = cause.Cause() + } + return err +} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go new file mode 100644 index 000000000..b485761a7 --- /dev/null +++ b/vendor/github.com/pkg/errors/stack.go @@ -0,0 +1,187 @@ +package errors + +import ( + "fmt" + "io" + "path" + "runtime" + "strings" +) + +// Frame represents a program counter inside a stack frame. +type Frame uintptr + +// pc returns the program counter for this frame; +// multiple frames may have the same PC value. +func (f Frame) pc() uintptr { return uintptr(f) - 1 } + +// file returns the full path to the file that contains the +// function for this Frame's pc. +func (f Frame) file() string { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return "unknown" + } + file, _ := fn.FileLine(f.pc()) + return file +} + +// line returns the line number of source code of the +// function for this Frame's pc. +func (f Frame) line() int { + fn := runtime.FuncForPC(f.pc()) + if fn == nil { + return 0 + } + _, line := fn.FileLine(f.pc()) + return line +} + +// Format formats the frame according to the fmt.Formatter interface. +// +// %s source file +// %d source line +// %n function name +// %v equivalent to %s:%d +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+s function name and path of source file relative to the compile time +// GOPATH separated by \n\t (\n\t) +// %+v equivalent to %+s:%d +func (f Frame) Format(s fmt.State, verb rune) { + switch verb { + case 's': + switch { + case s.Flag('+'): + pc := f.pc() + fn := runtime.FuncForPC(pc) + if fn == nil { + io.WriteString(s, "unknown") + } else { + file, _ := fn.FileLine(pc) + fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) + } + default: + io.WriteString(s, path.Base(f.file())) + } + case 'd': + fmt.Fprintf(s, "%d", f.line()) + case 'n': + name := runtime.FuncForPC(f.pc()).Name() + io.WriteString(s, funcname(name)) + case 'v': + f.Format(s, 's') + io.WriteString(s, ":") + f.Format(s, 'd') + } +} + +// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). +type StackTrace []Frame + +// Format formats the stack of Frames according to the fmt.Formatter interface. +// +// %s lists source files for each Frame in the stack +// %v lists the source file and line number for each Frame in the stack +// +// Format accepts flags that alter the printing of some verbs, as follows: +// +// %+v Prints filename, function, and line number for each Frame in the stack. +func (st StackTrace) Format(s fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case s.Flag('+'): + for _, f := range st { + fmt.Fprintf(s, "\n%+v", f) + } + case s.Flag('#'): + fmt.Fprintf(s, "%#v", []Frame(st)) + default: + fmt.Fprintf(s, "%v", []Frame(st)) + } + case 's': + fmt.Fprintf(s, "%s", []Frame(st)) + } +} + +// stack represents a stack of program counters. +type stack []uintptr + +func (s *stack) Format(st fmt.State, verb rune) { + switch verb { + case 'v': + switch { + case st.Flag('+'): + for _, pc := range *s { + f := Frame(pc) + fmt.Fprintf(st, "\n%+v", f) + } + } + } +} + +func (s *stack) StackTrace() StackTrace { + f := make([]Frame, len(*s)) + for i := 0; i < len(f); i++ { + f[i] = Frame((*s)[i]) + } + return f +} + +func callers() *stack { + const depth = 32 + var pcs [depth]uintptr + n := runtime.Callers(3, pcs[:]) + var st stack = pcs[0:n] + return &st +} + +// funcname removes the path prefix component of a function's name reported by func.Name(). +func funcname(name string) string { + i := strings.LastIndex(name, "/") + name = name[i+1:] + i = strings.Index(name, ".") + return name[i+1:] +} + +func trimGOPATH(name, file string) string { + // Here we want to get the source file path relative to the compile time + // GOPATH. As of Go 1.6.x there is no direct way to know the compiled + // GOPATH at runtime, but we can infer the number of path segments in the + // GOPATH. We note that fn.Name() returns the function name qualified by + // the import path, which does not include the GOPATH. Thus we can trim + // segments from the beginning of the file path until the number of path + // separators remaining is one more than the number of path separators in + // the function name. For example, given: + // + // GOPATH /home/user + // file /home/user/src/pkg/sub/file.go + // fn.Name() pkg/sub.Type.Method + // + // We want to produce: + // + // pkg/sub/file.go + // + // From this we can easily see that fn.Name() has one less path separator + // than our desired output. We count separators from the end of the file + // path until it finds two more than in the function name and then move + // one character forward to preserve the initial path segment without a + // leading separator. + const sep = "/" + goal := strings.Count(name, sep) + 2 + i := len(file) + for n := 0; n < goal; n++ { + i = strings.LastIndex(file[:i], sep) + if i == -1 { + // not enough separators found, set i so that the slice expression + // below leaves file unmodified + i = -len(sep) + break + } + } + // get back to 0 or trim the leading separator + file = file[i+len(sep):] + return file +} diff --git a/vendor/vendor.json b/vendor/vendor.json index e131df5a9..394cb14a3 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -256,12 +256,6 @@ "revision": "bd3317b8f6704b1b40e4e705ec9e987a535cd5d3", "revisionTime": "2016-05-16T23:23:31-07:00" }, - { - "checksumSHA1": "cdOCt0Yb+hdErz8NAQqayxPmRsY=", - "path": "github.com/hashicorp/errwrap", - "revision": "7554cd9344cec97297fa6649b055a8c98c2a1e55", - "revisionTime": "2014-10-28T05:47:10Z" - }, { "path": "github.com/hashicorp/go-version", "revision": "7e3c02b30806fa5779d3bdfc152ce4c6f40e7b38", @@ -292,28 +286,34 @@ "revisionTime": "2016-01-12T19:33:35Z" }, { - "checksumSHA1": "oINoQSRkPinChzwEHr3VatB9++Y=", + "checksumSHA1": "Lg8OHK87XRGCaipG+5+zFyN8OMw=", "path": "github.com/joyent/triton-go", - "revision": "86ba9699869b6cd5ea3290faad7be659efc7d6ce", - "revisionTime": "2017-12-28T20:20:46Z" + "revision": "7e6a47b300b10be9449610a6ff4fbae17d6e95b6", + "revisionTime": "2018-01-16T16:19:11Z" }, { - "checksumSHA1": "d6pxw8DLxYehLr92fWZTLEWVws8=", + "checksumSHA1": "Y03+L+I0FVZ2bMGWt1MHTDEyWM4=", "path": "github.com/joyent/triton-go/authentication", - "revision": "86ba9699869b6cd5ea3290faad7be659efc7d6ce", - "revisionTime": "2017-12-28T20:20:46Z" + "revision": "7e6a47b300b10be9449610a6ff4fbae17d6e95b6", + "revisionTime": "2018-01-16T16:19:11Z" }, { - "checksumSHA1": "GCHfn8d1Mhswm7n7IRnT0n/w+dw=", + "checksumSHA1": "MuJsGBr6HlXQYxZY9cM5rBk+Lns=", "path": "github.com/joyent/triton-go/client", - "revision": "86ba9699869b6cd5ea3290faad7be659efc7d6ce", - "revisionTime": "2017-12-28T20:20:46Z" + "revision": "7e6a47b300b10be9449610a6ff4fbae17d6e95b6", + "revisionTime": "2018-01-16T16:19:11Z" }, { - "checksumSHA1": "PJe3Rs8H466xR8o5audO8oWk44Q=", + "checksumSHA1": "d/Py6j/uMgOAFNFGpsQrNnSsO+k=", + "path": "github.com/joyent/triton-go/errors", + "revision": "7e6a47b300b10be9449610a6ff4fbae17d6e95b6", + "revisionTime": "2018-01-16T16:19:11Z" + }, + { + "checksumSHA1": "5v533ELM047YOiwHsyMaVzITpR0=", "path": "github.com/joyent/triton-go/storage", - "revision": "86ba9699869b6cd5ea3290faad7be659efc7d6ce", - "revisionTime": "2017-12-28T20:20:46Z" + "revision": "7e6a47b300b10be9449610a6ff4fbae17d6e95b6", + "revisionTime": "2018-01-16T16:19:11Z" }, { "path": "github.com/klauspost/cpuid", @@ -503,6 +503,12 @@ "revision": "289cccf02c178dc782430d534e3c1f5b72af807f", "revisionTime": "2016-09-27T04:49:45Z" }, + { + "checksumSHA1": "xCv4GBFyw07vZkVtKF/XrUnkHRk=", + "path": "github.com/pkg/errors", + "revision": "e881fd58d78e04cf6d0de1217f8707c8cc2249bc", + "revisionTime": "2017-12-16T07:03:16Z" + }, { "path": "github.com/pkg/profile", "revision": "c78aac22bd43883fd2817833b982153dcac17b3b",