Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

specerror: Add NewRFCError and NewRFCErrorOrPanic #627

Merged
merged 1 commit into from
Apr 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions cmd/runtimetest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,15 +109,13 @@ type complianceTester struct {
}

func (c *complianceTester) Ok(test bool, condition specerror.Code, version string, description string) (rfcError *rfc2119.Error, err error) {
err = specerror.NewError(condition, errors.New(description), version)
runtimeError, ok := err.(*specerror.Error)
if !ok {
return nil, fmt.Errorf("cannot convert %v to a runtime-spec error", err)
rfcError, err = specerror.NewRFCError(condition, errors.New(description), version)
if err != nil {
return nil, err
}
rfcError = &runtimeError.Err
if test {
c.harness.Pass(description)
} else if runtimeError.Err.Level < c.complianceLevel {
} else if rfcError.Level < c.complianceLevel {
c.harness.Skip(1, description)
} else {
c.harness.Fail(description)
Expand Down
37 changes: 30 additions & 7 deletions specerror/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,34 @@ func (err *Error) Error() string {
return err.Err.Error()
}

// NewRFCError creates an rfc2119.Error referencing a spec violation.
//
// A version string (for the version of the spec that was violated)
// must be set to get a working URL.
func NewRFCError(code Code, err error, version string) (*rfc2119.Error, error) {
template := ociErrors[code]
reference, err2 := template.Reference(version)
if err2 != nil {
return nil, err2
}
return &rfc2119.Error{
Level: template.Level,
Reference: reference,
Err: err,
}, nil
}

// NewRFCErrorOrPanic creates an rfc2119.Error referencing a spec
// violation and panics on failure. This is handy for situations
// where you can't be bothered to check NewRFCError for failure.
func NewRFCErrorOrPanic(code Code, err error, version string) *rfc2119.Error {
rfcError, err2 := NewRFCError(code, err, version)
if err2 != nil {
panic(err2.Error())
}
return rfcError
}

// NewError creates an Error referencing a spec violation. The error
// can be cast to an *Error for extracting structured information
// about the level of the violation and a reference to the violated
Expand All @@ -69,17 +97,12 @@ func (err *Error) Error() string {
// A version string (for the version of the spec that was violated)
// must be set to get a working URL.
func NewError(code Code, err error, version string) error {
template := ociErrors[code]
reference, err2 := template.Reference(version)
rfcError, err2 := NewRFCError(code, err, version)
if err2 != nil {
return err2
}
return &Error{
Err: rfc2119.Error{
Level: template.Level,
Reference: reference,
Err: err,
},
Err: *rfcError,
Code: code,
}
}
Expand Down
13 changes: 7 additions & 6 deletions validation/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/mndrix/tap-go"
rspecs "github.com/opencontainers/runtime-spec/specs-go"
rfc2119 "github.com/opencontainers/runtime-tools/error"
"github.com/opencontainers/runtime-tools/specerror"
"github.com/opencontainers/runtime-tools/validation/util"
uuid "github.com/satori/go.uuid"
Expand All @@ -26,11 +27,11 @@ func main() {
id string
action util.LifecycleAction
errExpected bool
err error
err *rfc2119.Error
}{
{"", util.LifecycleActionNone, false, specerror.NewError(specerror.QueryWithoutIDGenError, fmt.Errorf("state MUST generate an error if it is not provided the ID of a container"), rspecs.Version)},
{containerID, util.LifecycleActionNone, false, specerror.NewError(specerror.QueryNonExistGenError, fmt.Errorf("state MUST generate an error if a container that does not exist"), rspecs.Version)},
{containerID, util.LifecycleActionCreate | util.LifecycleActionDelete, true, specerror.NewError(specerror.QueryStateImplement, fmt.Errorf("state MUST return the state of a container as specified in the State section"), rspecs.Version)},
{"", util.LifecycleActionNone, false, specerror.NewRFCErrorOrPanic(specerror.QueryWithoutIDGenError, fmt.Errorf("state MUST generate an error if it is not provided the ID of a container"), rspecs.Version)},
{containerID, util.LifecycleActionNone, false, specerror.NewRFCErrorOrPanic(specerror.QueryNonExistGenError, fmt.Errorf("state MUST generate an error if a container that does not exist"), rspecs.Version)},
{containerID, util.LifecycleActionCreate | util.LifecycleActionDelete, true, specerror.NewRFCErrorOrPanic(specerror.QueryStateImplement, fmt.Errorf("state MUST return the state of a container as specified in the State section"), rspecs.Version)},
}

for _, c := range cases {
Expand All @@ -57,9 +58,9 @@ func main() {
continue
}

t.Ok((err == nil) == c.errExpected, c.err.(*specerror.Error).Err.Err.Error())
t.Ok((err == nil) == c.errExpected, c.err.Error())
diagnostic := map[string]string{
"reference": c.err.(*specerror.Error).Err.Reference,
"reference": c.err.Reference,
}
if err != nil {
diagnostic["error"] = err.Error()
Expand Down