diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index 6a514c4bf..1f940e341 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -2,9 +2,6 @@ "ImportPath": "github.com/opencontainers/runtime-tools", "GoVersion": "go1.4", "GodepVersion": "v75", - "Packages": [ - "./..." - ], "Deps": [ { "ImportPath": "github.com/Sirupsen/logrus", @@ -16,17 +13,9 @@ "Comment": "v3.1.0", "Rev": "aea32c919a18e5ef4537bbd283ff29594b1b0165" }, - { - "ImportPath": "github.com/hashicorp/errwrap", - "Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55" - }, - { - "ImportPath": "github.com/hashicorp/go-multierror", - "Rev": "ed905158d87462226a13fe39ddf685ea65f1c11f" - }, { "ImportPath": "github.com/mndrix/tap-go", - "Rev": "67c9553625499b7e7ed4ac4f2d8bf1cb8f5ecf52" + "Rev": "56cca451570bb0366b29f30e1aeb5cf9736a1e18" }, { "ImportPath": "github.com/opencontainers/runtime-spec/specs-go", diff --git a/Godeps/_workspace/src/github.com/hashicorp/errwrap/LICENSE b/Godeps/_workspace/src/github.com/hashicorp/errwrap/LICENSE deleted file mode 100644 index c33dcc7c9..000000000 --- a/Godeps/_workspace/src/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/Godeps/_workspace/src/github.com/hashicorp/errwrap/README.md b/Godeps/_workspace/src/github.com/hashicorp/errwrap/README.md deleted file mode 100644 index 1c95f5978..000000000 --- a/Godeps/_workspace/src/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/Godeps/_workspace/src/github.com/hashicorp/errwrap/errwrap.go b/Godeps/_workspace/src/github.com/hashicorp/errwrap/errwrap.go deleted file mode 100644 index a733bef18..000000000 --- a/Godeps/_workspace/src/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/Godeps/_workspace/src/github.com/hashicorp/go-multierror/.travis.yml b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/.travis.yml deleted file mode 100644 index 4b865d194..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -sudo: false - -language: go - -go: - - 1.6 - -branches: - only: - - master - -script: make test testrace diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/LICENSE b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/LICENSE deleted file mode 100644 index 82b4de97c..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/LICENSE +++ /dev/null @@ -1,353 +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/Godeps/_workspace/src/github.com/hashicorp/go-multierror/Makefile b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/Makefile deleted file mode 100644 index b97cd6ed0..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -TEST?=./... - -default: test - -# test runs the test suite and vets the code. -test: generate - @echo "==> Running tests..." - @go list $(TEST) \ - | grep -v "/vendor/" \ - | xargs -n1 go test -timeout=60s -parallel=10 ${TESTARGS} - -# testrace runs the race checker -testrace: generate - @echo "==> Running tests (race)..." - @go list $(TEST) \ - | grep -v "/vendor/" \ - | xargs -n1 go test -timeout=60s -race ${TESTARGS} - -# updatedeps installs all the dependencies needed to run and build. -updatedeps: - @sh -c "'${CURDIR}/scripts/deps.sh' '${NAME}'" - -# generate runs `go generate` to build the dynamically generated source files. -generate: - @echo "==> Generating..." - @find . -type f -name '.DS_Store' -delete - @go list ./... \ - | grep -v "/vendor/" \ - | xargs -n1 go generate - -.PHONY: default test testrace updatedeps generate diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/README.md b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/README.md deleted file mode 100644 index ead5830f7..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/README.md +++ /dev/null @@ -1,97 +0,0 @@ -# go-multierror - -[![Build Status](http://img.shields.io/travis/hashicorp/go-multierror.svg?style=flat-square)][travis] -[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)][godocs] - -[travis]: https://travis-ci.org/hashicorp/go-multierror -[godocs]: https://godoc.org/github.com/hashicorp/go-multierror - -`go-multierror` is a package for Go that provides a mechanism for -representing a list of `error` values as a single `error`. - -This allows a function in Go to return an `error` that might actually -be a list of errors. If the caller knows this, they can unwrap the -list and access the errors. If the caller doesn't know, the error -formats to a nice human-readable format. - -`go-multierror` implements the -[errwrap](https://github.com/hashicorp/errwrap) interface so that it can -be used with that library, as well. - -## Installation and Docs - -Install using `go get github.com/hashicorp/go-multierror`. - -Full documentation is available at -http://godoc.org/github.com/hashicorp/go-multierror - -## Usage - -go-multierror is easy to use and purposely built to be unobtrusive in -existing Go applications/libraries that may not be aware of it. - -**Building a list of errors** - -The `Append` function is used to create a list of errors. This function -behaves a lot like the Go built-in `append` function: it doesn't matter -if the first argument is nil, a `multierror.Error`, or any other `error`, -the function behaves as you would expect. - -```go -var result error - -if err := step1(); err != nil { - result = multierror.Append(result, err) -} -if err := step2(); err != nil { - result = multierror.Append(result, err) -} - -return result -``` - -**Customizing the formatting of the errors** - -By specifying a custom `ErrorFormat`, you can customize the format -of the `Error() string` function: - -```go -var result *multierror.Error - -// ... accumulate errors here, maybe using Append - -if result != nil { - result.ErrorFormat = func([]error) string { - return "errors!" - } -} -``` - -**Accessing the list of errors** - -`multierror.Error` implements `error` so if the caller doesn't know about -multierror, it will work just fine. But if you're aware a multierror might -be returned, you can use type switches to access the list of errors: - -```go -if err := something(); err != nil { - if merr, ok := err.(*multierror.Error); ok { - // Use merr.Errors - } -} -``` - -**Returning a multierror only if there are errors** - -If you build a `multierror.Error`, you can use the `ErrorOrNil` function -to return an `error` implementation only if there are errors to return: - -```go -var result *multierror.Error - -// ... accumulate errors here - -// Return the `error` only if errors were added to the multierror, otherwise -// return nil since there are no errors. -return result.ErrorOrNil() -``` diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/append.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/append.go deleted file mode 100644 index 775b6e753..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/append.go +++ /dev/null @@ -1,41 +0,0 @@ -package multierror - -// Append is a helper function that will append more errors -// onto an Error in order to create a larger multi-error. -// -// If err is not a multierror.Error, then it will be turned into -// one. If any of the errs are multierr.Error, they will be flattened -// one level into err. -func Append(err error, errs ...error) *Error { - switch err := err.(type) { - case *Error: - // Typed nils can reach here, so initialize if we are nil - if err == nil { - err = new(Error) - } - - // Go through each error and flatten - for _, e := range errs { - switch e := e.(type) { - case *Error: - if e != nil { - err.Errors = append(err.Errors, e.Errors...) - } - default: - if e != nil { - err.Errors = append(err.Errors, e) - } - } - } - - return err - default: - newErrs := make([]error, 0, len(errs)+1) - if err != nil { - newErrs = append(newErrs, err) - } - newErrs = append(newErrs, errs...) - - return Append(&Error{}, newErrs...) - } -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/flatten.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/flatten.go deleted file mode 100644 index aab8e9abe..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/flatten.go +++ /dev/null @@ -1,26 +0,0 @@ -package multierror - -// Flatten flattens the given error, merging any *Errors together into -// a single *Error. -func Flatten(err error) error { - // If it isn't an *Error, just return the error as-is - if _, ok := err.(*Error); !ok { - return err - } - - // Otherwise, make the result and flatten away! - flatErr := new(Error) - flatten(err, flatErr) - return flatErr -} - -func flatten(err error, flatErr *Error) { - switch err := err.(type) { - case *Error: - for _, e := range err.Errors { - flatten(e, flatErr) - } - default: - flatErr.Errors = append(flatErr.Errors, err) - } -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/format.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/format.go deleted file mode 100644 index 6c7a3cc91..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/format.go +++ /dev/null @@ -1,27 +0,0 @@ -package multierror - -import ( - "fmt" - "strings" -) - -// ErrorFormatFunc is a function callback that is called by Error to -// turn the list of errors into a string. -type ErrorFormatFunc func([]error) string - -// ListFormatFunc is a basic formatter that outputs the number of errors -// that occurred along with a bullet point list of the errors. -func ListFormatFunc(es []error) string { - if len(es) == 1 { - return fmt.Sprintf("1 error occurred:\n\n* %s", es[0]) - } - - points := make([]string, len(es)) - for i, err := range es { - points[i] = fmt.Sprintf("* %s", err) - } - - return fmt.Sprintf( - "%d errors occurred:\n\n%s", - len(es), strings.Join(points, "\n")) -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/multierror.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/multierror.go deleted file mode 100644 index 2ea082732..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/multierror.go +++ /dev/null @@ -1,51 +0,0 @@ -package multierror - -import ( - "fmt" -) - -// Error is an error type to track multiple errors. This is used to -// accumulate errors in cases and return them as a single "error". -type Error struct { - Errors []error - ErrorFormat ErrorFormatFunc -} - -func (e *Error) Error() string { - fn := e.ErrorFormat - if fn == nil { - fn = ListFormatFunc - } - - return fn(e.Errors) -} - -// ErrorOrNil returns an error interface if this Error represents -// a list of errors, or returns nil if the list of errors is empty. This -// function is useful at the end of accumulation to make sure that the value -// returned represents the existence of errors. -func (e *Error) ErrorOrNil() error { - if e == nil { - return nil - } - if len(e.Errors) == 0 { - return nil - } - - return e -} - -func (e *Error) GoString() string { - return fmt.Sprintf("*%#v", *e) -} - -// WrappedErrors returns the list of errors that this Error is wrapping. -// It is an implementatin of the errwrap.Wrapper interface so that -// multierror.Error can be used with that library. -// -// This method is not safe to be called concurrently and is no different -// than accessing the Errors field directly. It is implementd only to -// satisfy the errwrap.Wrapper interface. -func (e *Error) WrappedErrors() []error { - return e.Errors -} diff --git a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/prefix.go b/Godeps/_workspace/src/github.com/hashicorp/go-multierror/prefix.go deleted file mode 100644 index 5c477abe4..000000000 --- a/Godeps/_workspace/src/github.com/hashicorp/go-multierror/prefix.go +++ /dev/null @@ -1,37 +0,0 @@ -package multierror - -import ( - "fmt" - - "github.com/hashicorp/errwrap" -) - -// Prefix is a helper function that will prefix some text -// to the given error. If the error is a multierror.Error, then -// it will be prefixed to each wrapped error. -// -// This is useful to use when appending multiple multierrors -// together in order to give better scoping. -func Prefix(err error, prefix string) error { - if err == nil { - return nil - } - - format := fmt.Sprintf("%s {{err}}", prefix) - switch err := err.(type) { - case *Error: - // Typed nils can reach here, so initialize if we are nil - if err == nil { - err = new(Error) - } - - // Wrap each of the errors - for i, e := range err.Errors { - err.Errors[i] = errwrap.Wrapf(format, e) - } - - return err - default: - return errwrap.Wrapf(format, err) - } -} diff --git a/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile b/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile index dda78b2b2..986541d7c 100644 --- a/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile +++ b/Godeps/_workspace/src/github.com/mndrix/tap-go/Makefile @@ -1,4 +1,4 @@ -TESTS = auto check diagnostic known failing writer +TESTS = auto check diagnostic failing known skip todo writer GOPATH = $(CURDIR)/gopath .PHONY: $(TESTS) diff --git a/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go b/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go index 240542636..477fddc3f 100644 --- a/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go +++ b/Godeps/_workspace/src/github.com/mndrix/tap-go/tap.go @@ -18,7 +18,7 @@ // 1..2 // ok 1 - first test // ok 2 - second test -package tap +package tap // import "github.com/mndrix/tap-go" import ( "fmt" @@ -31,7 +31,10 @@ import "testing/quick" // T is a type to encapsulate test state. Methods on this type generate TAP // output. type T struct { - nextTestNumber int + nextTestNumber *int + + // TODO toggles the TODO directive for Ok, Fail, Pass, and similar. + TODO bool // Writer indicates where TAP output should be sent. The default is os.Stdout. Writer io.Writer @@ -39,8 +42,9 @@ type T struct { // New creates a new Tap value func New() *T { + nextTestNumber := 1 return &T{ - nextTestNumber: 1, + nextTestNumber: &nextTestNumber, } } @@ -74,8 +78,12 @@ func (t *T) Ok(test bool, description string) { ok = "not ok" } - t.printf("%s %d - %s\n", ok, t.nextTestNumber, description) - t.nextTestNumber++ + if t.TODO { + t.printf("%s %d # TODO %s\n", ok, *t.nextTestNumber, description) + } else { + t.printf("%s %d - %s\n", ok, *t.nextTestNumber, description) + } + (*t.nextTestNumber)++ } // Fail indicates that a test has failed. This is typically only used when the @@ -105,7 +113,7 @@ func (t *T) Check(function interface{}, description string) { // Count returns the number of tests completed so far. func (t *T) Count() int { - return t.nextTestNumber - 1 + return *t.nextTestNumber - 1 } // AutoPlan generates a test plan based on the number of tests that were run. @@ -117,6 +125,21 @@ func escapeNewlines(s string) string { return strings.Replace(strings.TrimRight(s, "\n"), "\n", "\n# ", -1) } +// Todo returns copy of the test-state with TODO set. +func (t *T) Todo() *T { + newT := *t + newT.TODO = true + return &newT +} + +// Skip indicates that a test has been skipped. +func (t *T) Skip(count int, description string) { + for i := 0; i < count; i++ { + t.printf("ok %d # SKIP %s\n", *t.nextTestNumber, description) + (*t.nextTestNumber)++ + } +} + // Diagnostic generates a diagnostic from the message, // which may span multiple lines. func (t *T) Diagnostic(message string) { diff --git a/README.md b/README.md index d8d406d96..62fff23c0 100644 --- a/README.md +++ b/README.md @@ -29,25 +29,25 @@ INFO[0000] Bundle validation succeeded. ## Testing OCI runtimes -```sh +You can run [`test_runtime.sh`][test_runtime.sh] with any [TAP consumer][tap-consumer]. +For example, with [prove][]: + +``` $ make $ sudo make install -$ sudo ./test_runtime.sh -r runc ------------------------------------------------------------------------------------ -VALIDATING RUNTIME: runc ------------------------------------------------------------------------------------ -validating container process -validating capabilities -validating hostname -validating rlimits -validating sysctls -Runtime runc passed validation +$ sudo prove ./test_runtime.sh -r /usr/bin/runc +./test_runtime.sh .. ok +All tests successful. +Files=1, Tests=90, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.04 cusr 0.00 csys = 0.06 CPU) +Result: PASS ``` [bundle]: https://github.com/opencontainers/runtime-spec/blob/master/bundle.md [config.json]: https://github.com/opencontainers/runtime-spec/blob/master/config.md +[prove]: http://perldoc.perl.org/prove.html [runC]: https://github.com/opencontainers/runc [runtime-spec]: https://github.com/opencontainers/runtime-spec +[tap-consumer]: https://testanything.org/consumers.html [generate.1]: man/oci-runtime-tool-generate.1.md [validate.1]: man/oci-runtime-tool-validate.1.md diff --git a/cmd/runtimetest/main.go b/cmd/runtimetest/main.go index 371052c3b..d9d302df7 100644 --- a/cmd/runtimetest/main.go +++ b/cmd/runtimetest/main.go @@ -14,7 +14,6 @@ import ( "syscall" "github.com/Sirupsen/logrus" - "github.com/hashicorp/go-multierror" "github.com/mndrix/tap-go" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/cmd/runtimetest/mount" @@ -54,10 +53,7 @@ var ( } ) -type validation struct { - test func(*rspec.Spec) error - description string -} +type validator func(harness *tap.T, config *rspec.Spec) (err error) func loadSpecConfig() (spec *rspec.Spec, err error) { cf, err := os.Open(specConfig) @@ -75,14 +71,17 @@ func loadSpecConfig() (spec *rspec.Spec, err error) { } // should be included by other platform specified process validation -func validateGeneralProcess(spec *rspec.Spec) error { - if spec.Process.Cwd != "" { +func validateGeneralProcess(harness *tap.T, spec *rspec.Spec) error { + if spec.Process.Cwd == "" { + harness.Skip(1, "process.cwd not set") + } else { cwd, err := os.Getwd() if err != nil { return err } + harness.Ok(cwd == spec.Process.Cwd, "has expected working directory") if cwd != spec.Process.Cwd { - return fmt.Errorf("Cwd expected: %v, actual: %v", spec.Process.Cwd, cwd) + harness.Diagnosticf("working directory expected: %v, actual: %v", spec.Process.Cwd, cwd) } } @@ -91,26 +90,28 @@ func validateGeneralProcess(spec *rspec.Spec) error { key := parts[0] expectedValue := parts[1] actualValue := os.Getenv(key) + harness.Ok(expectedValue == actualValue, fmt.Sprintf("has expected environment variable %v", key)) if actualValue != expectedValue { - return fmt.Errorf("Env %v expected: %v, actual: %v", key, expectedValue, actualValue) + harness.Diagnosticf("environment variable %v expected: %v, actual: %v", key, expectedValue, actualValue) } } return nil } -func validateLinuxProcess(spec *rspec.Spec) error { - logrus.Debugf("validating container process") - - validateGeneralProcess(spec) +func validateLinuxProcess(harness *tap.T, spec *rspec.Spec) error { + validateGeneralProcess(harness, spec) uid := os.Getuid() + harness.Ok(uint32(uid) == spec.Process.User.UID, "has expected user ID") if uint32(uid) != spec.Process.User.UID { - return fmt.Errorf("UID expected: %v, actual: %v", spec.Process.User.UID, uid) + harness.Diagnosticf("user ID expected: %v, actual: %v", spec.Process.User.UID, uid) } + gid := os.Getgid() + harness.Ok(uint32(gid) == spec.Process.User.GID, "has expected group ID") if uint32(gid) != spec.Process.User.GID { - return fmt.Errorf("GID expected: %v, actual: %v", spec.Process.User.GID, gid) + harness.Diagnosticf("group ID expected: %v, actual: %v", spec.Process.User.GID, gid) } groups, err := os.Getgroups() @@ -124,9 +125,7 @@ func validateLinuxProcess(spec *rspec.Spec) error { } for _, g := range spec.Process.User.AdditionalGids { - if !groupsMap[int(g)] { - return fmt.Errorf("Groups expected: %v, actual (should be superset): %v", spec.Process.User.AdditionalGids, groups) - } + harness.Ok(groupsMap[int(g)], fmt.Sprintf("has expected additional group ID %v", g)) } cmdlineBytes, err := ioutil.ReadFile("/proc/1/cmdline") @@ -135,12 +134,14 @@ func validateLinuxProcess(spec *rspec.Spec) error { } args := bytes.Split(bytes.Trim(cmdlineBytes, "\x00"), []byte("\x00")) + harness.Ok(len(args) == len(spec.Process.Args), "has expected number of process arguments") if len(args) != len(spec.Process.Args) { - return fmt.Errorf("Process arguments expected: %v, actual: %v", len(spec.Process.Args), len(args)) + harness.Diagnosticf("expected process arguments: %v, actual: %v", spec.Process.Args, args) } for i, a := range args { + harness.Ok(string(a) == spec.Process.Args[i], fmt.Sprintf("has expected process argument %d", i)) if string(a) != spec.Process.Args[i] { - return fmt.Errorf("Process arguments expected: %v, actual: %v", string(a), spec.Process.Args[i]) + harness.Diagnosticf("expected process argument %d: %v, actual: %v", i, spec.Process.Args[i], string(a)) } } @@ -148,19 +149,13 @@ func validateLinuxProcess(spec *rspec.Spec) error { if errno != 0 { return errno } - if spec.Process.NoNewPrivileges && ret != 1 { - return fmt.Errorf("NoNewPrivileges expected: true, actual: false") - } - if !spec.Process.NoNewPrivileges && ret != 0 { - return fmt.Errorf("NoNewPrivileges expected: false, actual: true") - } + noNewPrivileges := ret == 1 + harness.Ok(spec.Process.NoNewPrivileges == noNewPrivileges, "has expected noNewPrivileges") return nil } -func validateCapabilities(spec *rspec.Spec) error { - logrus.Debugf("validating capabilities") - +func validateCapabilities(harness *tap.T, spec *rspec.Spec) error { last := capability.CAP_LAST_CAP // workaround for RHEL6 which has no /proc/sys/kernel/cap_last_cap if last == capability.Cap(63) { @@ -185,31 +180,33 @@ func validateCapabilities(spec *rspec.Spec) error { capKey := fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())) expectedSet := expectedCaps[capKey] actuallySet := processCaps.Get(capability.EFFECTIVE, cap) - if expectedSet != actuallySet { - if expectedSet { - return fmt.Errorf("Expected Capability %v not set for process", cap.String()) - } - return fmt.Errorf("Unexpected Capability %v set for process", cap.String()) + if expectedSet { + harness.Ok(actuallySet, fmt.Sprintf("expected capability %v set", capKey)) + } else { + harness.Ok(!actuallySet, fmt.Sprintf("unexpected capability %v not set", capKey)) } } return nil } -func validateHostname(spec *rspec.Spec) error { - logrus.Debugf("validating hostname") - hostname, err := os.Hostname() - if err != nil { - return err - } - if spec.Hostname != "" && hostname != spec.Hostname { - return fmt.Errorf("Hostname expected: %v, actual: %v", spec.Hostname, hostname) +func validateHostname(harness *tap.T, spec *rspec.Spec) error { + if spec.Hostname == "" { + harness.Skip(1, "hostname not set") + } else { + hostname, err := os.Hostname() + if err != nil { + return err + } + harness.Ok(hostname == spec.Hostname, "hostname matches expected value") + if hostname != spec.Hostname { + harness.Diagnosticf("hostname expected: %v, actual: %v", spec.Hostname, hostname) + } } return nil } -func validateRlimits(spec *rspec.Spec) error { - logrus.Debugf("validating rlimits") +func validateRlimits(harness *tap.T, spec *rspec.Spec) error { for _, r := range spec.Process.Rlimits { rl, err := strToRlimit(r.Type) if err != nil { @@ -221,18 +218,19 @@ func validateRlimits(spec *rspec.Spec) error { return err } + harness.Ok(rlimit.Cur == r.Soft, fmt.Sprintf("has expected soft %v", r.Type)) if rlimit.Cur != r.Soft { - return fmt.Errorf("%v rlimit soft expected: %v, actual: %v", r.Type, r.Soft, rlimit.Cur) + harness.Diagnosticf("soft %v expected: %v, actual: %v", r.Type, r.Soft, rlimit.Cur) } + harness.Ok(rlimit.Max == r.Hard, fmt.Sprintf("has expected hard %v", r.Type)) if rlimit.Max != r.Hard { - return fmt.Errorf("%v rlimit hard expected: %v, actual: %v", r.Type, r.Hard, rlimit.Max) + harness.Diagnosticf("hard %v expected: %v, actual: %v", r.Type, r.Hard, rlimit.Max) } } return nil } -func validateSysctls(spec *rspec.Spec) error { - logrus.Debugf("validating sysctls") +func validateSysctls(harness *tap.T, spec *rspec.Spec) error { for k, v := range spec.Linux.Sysctl { keyPath := filepath.Join("/proc/sys", strings.Replace(k, ".", "/", -1)) vBytes, err := ioutil.ReadFile(keyPath) @@ -240,40 +238,48 @@ func validateSysctls(spec *rspec.Spec) error { return err } value := strings.TrimSpace(string(bytes.Trim(vBytes, "\x00"))) + harness.Ok(value == v, fmt.Sprintf("has expected sysctl %v", k)) if value != v { - return fmt.Errorf("Sysctl %v value expected: %v, actual: %v", k, v, value) + harness.Diagnosticf("sysctl %v expected: %v, actual: %v", k, v, value) } } return nil } -func testWriteAccess(path string) error { +func testReadOnly(harness *tap.T, path string) error { tmpfile, err := ioutil.TempFile(path, "Test") + harness.Ok(err != nil, fmt.Sprintf("%v is readonly (cannot create sub-file)", path)) if err != nil { return err - } + } else { + tmpfile.Close() + if err != nil { + return err + } - tmpfile.Close() - os.RemoveAll(filepath.Join(path, tmpfile.Name())) + err = os.RemoveAll(filepath.Join(path, tmpfile.Name())) + if err != nil { + return err + } + } return nil } -func validateRootFS(spec *rspec.Spec) error { - logrus.Debugf("validating root filesystem") +func validateRootFS(harness *tap.T, spec *rspec.Spec) error { if spec.Root.Readonly { - err := testWriteAccess("/") - if err == nil { - return fmt.Errorf("Rootfs should be readonly") + err := testReadOnly(harness, "/") + if err != nil { + return err } + } else { + harness.Skip(1, "root.readonly falsy") } return nil } -func validateDefaultFS(spec *rspec.Spec) error { - logrus.Debugf("validating linux default filesystem") - +func validateDefaultFS(harness *tap.T, spec *rspec.Spec) error { mountInfos, err := mount.GetMounts() if err != nil { return err @@ -285,17 +291,19 @@ func validateDefaultFS(spec *rspec.Spec) error { } for fs, fstype := range defaultFS { + harness.Ok(mountsMap[fs] == fstype, fmt.Sprintf("mount %v has expected type", fs)) if !(mountsMap[fs] == fstype) { - return fmt.Errorf("%v must exist and expected type is %v", fs, fstype) + harness.Diagnosticf("mount %v type expected: %v, actual: %v", fs, fstype, mountsMap[fs]) } } return nil } -func validateLinuxDevices(spec *rspec.Spec) error { - logrus.Debugf("validating linux devices") - +func validateLinuxDevices(harness *tap.T, spec *rspec.Spec) error { + if len(spec.Linux.Devices) == 0 { + harness.Skip(1, "linux.devices (no devices configured)") + } for _, device := range spec.Linux.Devices { fi, err := os.Stat(device.Path) if err != nil { @@ -319,32 +327,47 @@ func validateLinuxDevices(spec *rspec.Spec) error { default: devType = "unmatched" } - if devType != device.Type || (devType == "c" && device.Type == "u") { - return fmt.Errorf("device %v expected type is %v, actual is %v", device.Path, device.Type, devType) + harness.Ok(devType == device.Type || (devType == "c" && device.Type == "u"), fmt.Sprintf("device %v has expected type", device.Path)) + if devType != device.Type && !(devType == "c" && device.Type == "u") { + harness.Diagnosticf("device %v type expected: %v, actual: %v", device.Path, device.Type, devType) } if devType != "p" { dev := fStat.Rdev major := (dev >> 8) & 0xfff minor := (dev & 0xff) | ((dev >> 12) & 0xfff00) - if int64(major) != device.Major || int64(minor) != device.Minor { - return fmt.Errorf("%v device number expected is %v:%v, actual is %v:%v", device.Path, device.Major, device.Minor, major, minor) + harness.Ok(int64(major) == device.Major, fmt.Sprintf("device %v has expected major number", device.Path)) + if int64(major) != device.Major { + harness.Diagnosticf("device %v major number expected: %v, actual: %v", device.Path, device.Major, major) + } + harness.Ok(int64(minor) == device.Minor, fmt.Sprintf("device %v has expected minor number", device.Path)) + if int64(minor) != device.Minor { + harness.Diagnosticf("device %v minor number expected: %v, actual: %v", device.Path, device.Minor, minor) } } - if device.FileMode != nil { + if device.FileMode == nil { + harness.Skip(1, fmt.Sprintf("device %v has unconfigured permissions", device.Path)) + } else { expectedPerm := *device.FileMode & os.ModePerm actualPerm := fi.Mode() & os.ModePerm - if expectedPerm != actualPerm { - return fmt.Errorf("%v filemode expected is %v, actual is %v", device.Path, expectedPerm, actualPerm) + harness.Ok(actualPerm == expectedPerm, fmt.Sprintf("device %v has expected permissions", device.Path)) + if actualPerm != expectedPerm { + harness.Diagnosticf("device %v permissions expected: %v, actual: %v", device.Path, expectedPerm, actualPerm) } } - if device.UID != nil { - if *device.UID != fStat.Uid { - return fmt.Errorf("%v uid expected is %v, actual is %v", device.Path, *device.UID, fStat.Uid) + if device.UID == nil { + harness.Skip(1, fmt.Sprintf("device %v has an unconfigured user ID", device.Path)) + } else { + harness.Ok(fStat.Uid == *device.UID, fmt.Sprintf("device %v has expected user ID", device.Path)) + if fStat.Uid != *device.UID { + harness.Diagnosticf("device %v user ID epected: %v, actual: %v", device.Path, *device.UID, fStat.Uid) } } - if device.GID != nil { - if *device.GID != fStat.Gid { - return fmt.Errorf("%v uid expected is %v, actual is %v", device.Path, *device.GID, fStat.Gid) + if device.GID == nil { + harness.Skip(1, fmt.Sprintf("device %v has an unconfigured group ID", device.Path)) + } else { + harness.Ok(fStat.Gid == *device.GID, fmt.Sprintf("device %v has expected group ID", device.Path)) + if fStat.Gid != *device.GID { + harness.Diagnosticf("device %v group ID epected: %v, actual: %v", device.Path, *device.GID, fStat.Gid) } } } @@ -352,102 +375,103 @@ func validateLinuxDevices(spec *rspec.Spec) error { return nil } -func validateDefaultSymlinks(spec *rspec.Spec) error { - logrus.Debugf("validating linux default symbolic links") - +func validateDefaultSymlinks(harness *tap.T, spec *rspec.Spec) error { for symlink, dest := range defaultSymlinks { fi, err := os.Lstat(symlink) + harness.Ok(err == nil, fmt.Sprintf("lstat default symlink %v", symlink)) if err != nil { - return err - } - if fi.Mode()&os.ModeSymlink != os.ModeSymlink { - return fmt.Errorf("%v is not a symbolic link as expected", symlink) - } - realDest, err := os.Readlink(symlink) - if err != nil { - return err - } - if realDest != dest { - return fmt.Errorf("link destation of %v expected is %v, actual is %v", symlink, dest, realDest) + harness.Skip(1, fmt.Sprintf("default symlink %v checks (failed lstat)", symlink)) + } else { + harness.Ok(fi.Mode()&os.ModeSymlink == os.ModeSymlink, fmt.Sprintf("default symlink %v is a symlink", symlink)) + realDest, err := os.Readlink(symlink) + if err != nil { + return err + } + harness.Ok(realDest == dest, fmt.Sprintf("default symlink %v has expected target", symlink)) + if realDest != dest { + harness.Diagnosticf("default symlink %v target expected: %v, actual: %v", symlink, dest, realDest) + } } } return nil } -func validateDefaultDevices(spec *rspec.Spec) error { - logrus.Debugf("validating linux default devices") - +func validateDefaultDevices(harness *tap.T, spec *rspec.Spec) error { if spec.Process.Terminal { defaultDevices = append(defaultDevices, "/dev/console") } for _, device := range defaultDevices { fi, err := os.Stat(device) + harness.Ok(err == nil, fmt.Sprintf("stat default device %v", device)) if err != nil { - if os.IsNotExist(err) { - return fmt.Errorf("device node %v not found", device) - } - return err - } - if fi.Mode()&os.ModeDevice != os.ModeDevice { - return fmt.Errorf("file %v is not a device as expected", device) + harness.Skip(1, fmt.Sprintf("default device %v checks (failed stat)", device)) + } else { + harness.Ok(fi.Mode()&os.ModeDevice == os.ModeDevice, fmt.Sprintf("default device %v is a device", device)) } } return nil } -func validateMaskedPaths(spec *rspec.Spec) error { - logrus.Debugf("validating maskedPaths") +func validateMaskedPaths(harness *tap.T, spec *rspec.Spec) error { for _, maskedPath := range spec.Linux.MaskedPaths { f, err := os.Open(maskedPath) + harness.Ok(err == nil, fmt.Sprintf("open masked path %v", maskedPath)) if err != nil { - return err - } - defer f.Close() - b := make([]byte, 1) - _, err = f.Read(b) - if err != io.EOF { - return fmt.Errorf("%v should not be readable", maskedPath) + harness.Skip(1, fmt.Sprintf("masked path %v checks (failed open)", maskedPath)) + } else { + defer f.Close() + b := make([]byte, 1) + _, err = f.Read(b) + harness.Ok(err == io.EOF, fmt.Sprintf("masked path %v is not readable", maskedPath)) } } return nil } -func validateROPaths(spec *rspec.Spec) error { - logrus.Debugf("validating readonlyPaths") +func validateROPaths(harness *tap.T, spec *rspec.Spec) error { for _, v := range spec.Linux.ReadonlyPaths { - err := testWriteAccess(v) - if err == nil { - return fmt.Errorf("%v should be readonly", v) + err := testReadOnly(harness, v) + if err != nil { + return err } } return nil } -func validateOOMScoreAdj(spec *rspec.Spec) error { - logrus.Debugf("validating oomScoreAdj") - if spec.Linux.Resources != nil && spec.Linux.Resources.OOMScoreAdj != nil { +func validateOOMScoreAdj(harness *tap.T, spec *rspec.Spec) error { + if spec.Linux.Resources == nil || spec.Linux.Resources.OOMScoreAdj == nil { + harness.Skip(1, "linux.resources.oomScoreAdj falsy") + } else { expected := *spec.Linux.Resources.OOMScoreAdj f, err := os.Open("/proc/1/oom_score_adj") + harness.Ok(err == nil, "open /proc/1/oom_score_adj") if err != nil { - return err + harness.Skip(1, "oomScoreAdj checks (failed open)") + return nil } defer f.Close() s := bufio.NewScanner(f) for s.Scan() { - if err := s.Err(); err != nil { - return err + err := s.Err() + harness.Ok(err == nil, "scan /proc/1/oom_score_adj") + if err != nil { + harness.Skip(1, "oomScoreAdj checks (failed scan)") + return nil } text := strings.TrimSpace(s.Text()) actual, err := strconv.Atoi(text) + harness.Ok(err == nil, "convert scanned /proc/1/oom_score_adj value to an integer") if err != nil { - return err + harness.Skip(1, "oomScoreAdj checks (failed integer conversion)") + return nil } + harness.Ok(actual == expected, "has expected oomScoreAdj") if actual != expected { - return fmt.Errorf("oomScoreAdj expected: %v, actual: %v", expected, actual) + harness.Diagnosticf("oomScoreAdj expected: %v, actual: %v", expected, actual) } } } @@ -492,13 +516,20 @@ func getIDMappings(path string) ([]rspec.IDMapping, error) { return idMaps, nil } -func validateIDMappings(mappings []rspec.IDMapping, path string, property string) error { +func validateIDMappings(harness *tap.T, mappings []rspec.IDMapping, path string, property string) error { + if len(mappings) == 0 { + harness.Skip(1, fmt.Sprintf("%s checks (no mappings specified)", property)) + return nil + } idMaps, err := getIDMappings(path) + harness.Ok(err == nil, fmt.Sprintf("get ID mappings from %s", path)) if err != nil { - return fmt.Errorf("can not get items: %v", err) + harness.Skip(1, fmt.Sprintf("%s checks (failed to get mappings)", property)) + return nil } - if len(mappings) != 0 && len(mappings) != len(idMaps) { - return fmt.Errorf("expected %d entries in %v, but acutal is %d", len(mappings), path, len(idMaps)) + harness.Ok(len(idMaps) == len(mappings), fmt.Sprintf("%s has expected number of mappings", path)) + if len(idMaps) != len(mappings) { + harness.Diagnosticf("expected %s mappings: %v, actual: %v", property, mappings, idMaps) } for _, v := range mappings { exist := false @@ -508,24 +539,21 @@ func validateIDMappings(mappings []rspec.IDMapping, path string, property string break } } + harness.Ok(exist, fmt.Sprintf("%s has expected mapping %v", path, v)) if !exist { - return fmt.Errorf("%v is not applied as expected", property) + harness.Diagnosticf("expected %s mappings: %v, actual: %v", property, mappings, idMaps) } } return nil } -func validateUIDMappings(spec *rspec.Spec) error { - logrus.Debugf("validating uidMappings") - - return validateIDMappings(spec.Linux.UIDMappings, "/proc/self/uid_map", "linux.uidMappings") +func validateUIDMappings(harness *tap.T, spec *rspec.Spec) error { + return validateIDMappings(harness, spec.Linux.UIDMappings, "/proc/self/uid_map", "linux.uidMappings") } -func validateGIDMappings(spec *rspec.Spec) error { - logrus.Debugf("validating gidMappings") - - return validateIDMappings(spec.Linux.GIDMappings, "/proc/self/gid_map", "linux.gidMappings") +func validateGIDMappings(harness *tap.T, spec *rspec.Spec) error { + return validateIDMappings(harness, spec.Linux.GIDMappings, "/proc/self/gid_map", "linux.gidMappings") } func mountMatch(specMount rspec.Mount, sysMount rspec.Mount) error { @@ -544,9 +572,7 @@ func mountMatch(specMount rspec.Mount, sysMount rspec.Mount) error { return nil } -func validateMountsExist(spec *rspec.Spec) error { - logrus.Debugf("validating mounts exist") - +func validateMountsExist(harness *tap.T, spec *rspec.Spec) error { mountInfos, err := mount.GetMounts() if err != nil { return err @@ -567,11 +593,12 @@ func validateMountsExist(spec *rspec.Spec) error { for _, sysMount := range mountsMap[filepath.Clean(specMount.Destination)] { if err := mountMatch(specMount, sysMount); err == nil { found = true + harness.Pass(fmt.Sprintf("mount %q found", specMount.Destination)) break } } if !found { - return fmt.Errorf("Expected mount %v does not exist", specMount) + harness.Fail(fmt.Sprintf("expected mount %q found", specMount.Destination)) } } @@ -579,112 +606,54 @@ func validateMountsExist(spec *rspec.Spec) error { } func validate(context *cli.Context) error { - logLevelString := context.String("log-level") - logLevel, err := logrus.ParseLevel(logLevelString) - if err != nil { - return err - } - logrus.SetLevel(logLevel) - spec, err := loadSpecConfig() if err != nil { return err } - defaultValidations := []validation{ - { - test: validateRootFS, - description: "root filesystem", - }, - { - test: validateHostname, - description: "hostname", - }, - { - test: validateMountsExist, - description: "mounts", - }, + defaultValidations := []validator{ + validateRootFS, + validateHostname, + validateMountsExist, } - linuxValidations := []validation{ - { - test: validateCapabilities, - description: "capabilities", - }, - { - test: validateDefaultSymlinks, - description: "default symlinks", - }, - { - test: validateDefaultFS, - description: "default file system", - }, - { - test: validateDefaultDevices, - description: "default devices", - }, - { - test: validateLinuxDevices, - description: "linux devices", - }, - { - test: validateLinuxProcess, - description: "linux process", - }, - { - test: validateMaskedPaths, - description: "masked paths", - }, - { - test: validateOOMScoreAdj, - description: "oom score adj", - }, - { - test: validateROPaths, - description: "read only paths", - }, - { - test: validateRlimits, - description: "rlimits", - }, - { - test: validateSysctls, - description: "sysctls", - }, - { - test: validateUIDMappings, - description: "uid mappings", - }, - { - test: validateGIDMappings, - description: "gid mappings", - }, + linuxValidations := []validator{ + validateCapabilities, + validateDefaultSymlinks, + validateDefaultFS, + validateDefaultDevices, + validateLinuxDevices, + validateLinuxProcess, + validateMaskedPaths, + validateOOMScoreAdj, + validateROPaths, + validateRlimits, + validateSysctls, + validateUIDMappings, + validateGIDMappings, } t := tap.New() t.Header(0) - var validationErrors error for _, v := range defaultValidations { - err := v.test(spec) - t.Ok(err == nil, v.description) + err := v(t, spec) if err != nil { - validationErrors = multierror.Append(validationErrors, err) + return err } } if spec.Platform.OS == "linux" { for _, v := range linuxValidations { - err := v.test(spec) - t.Ok(err == nil, v.description) + err := v(t, spec) if err != nil { - validationErrors = multierror.Append(validationErrors, err) + return err } } } t.AutoPlan() - return validationErrors + return nil } func main() { diff --git a/test_runtime.sh b/test_runtime.sh index c1ed0b152..dc5d8eddf 100755 --- a/test_runtime.sh +++ b/test_runtime.sh @@ -23,12 +23,12 @@ usage() { } error() { - echo $* + echo "$*" >&2 exit 1 } info() { - echo $* + echo "$*" >&2 } while getopts "l:r:kh" opt; do @@ -53,10 +53,6 @@ while getopts "l:r:kh" opt; do esac done -info "-----------------------------------------------------------------------------------" -info " VALIDATING RUNTIME: ${RUNTIME}" -info "-----------------------------------------------------------------------------------" - if ! command -v ${RUNTIME} > /dev/null; then error "Runtime ${RUNTIME} not found in the path" fi @@ -79,11 +75,5 @@ cp runtimetest ${TESTDIR} oci-runtime-tool generate --output "${TESTDIR}/config.json" "${TEST_ARGS[@]}" --rootfs-path '.' -TESTCMD="${RUNTIME} start $(uuidgen)" -pushd $TESTDIR > /dev/null -if ! ${TESTCMD}; then - error "Runtime ${RUNTIME} failed validation" -else - info "Runtime ${RUNTIME} passed validation" -fi -popd > /dev/null +cd ${TESTDIR} +${RUNTIME} start $(uuidgen)