Skip to content

Commit

Permalink
use rfc code in bundle validate
Browse files Browse the repository at this point in the history
Signed-off-by: Liang Chenye <liangchenye@huawei.com>
  • Loading branch information
liangchenye committed Aug 29, 2017
1 parent 3db644c commit af6946f
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 141 deletions.
6 changes: 2 additions & 4 deletions cmd/oci-runtime-tool/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package main

import (
"fmt"
"strings"

"github.com/opencontainers/runtime-tools/validate"
"github.com/urfave/cli"
Expand All @@ -27,9 +26,8 @@ var bundleValidateCommand = cli.Command{
return err
}

errMsgs := v.CheckAll()
if len(errMsgs) > 0 {
return fmt.Errorf("%d Errors detected:\n%s", len(errMsgs), strings.Join(errMsgs, "\n"))
if err := v.CheckAll(); err != nil {
return err

}
fmt.Println("Bundle validation succeeded.")
Expand Down
1 change: 1 addition & 0 deletions error/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ type Error struct {
Level Level
Reference string
Err error
ErrCode int
}

// ParseLevel takes a string level and returns the OCI compliance level constant.
Expand Down
99 changes: 92 additions & 7 deletions validate/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"fmt"

"github.com/hashicorp/go-multierror"
rfc2119 "github.com/opencontainers/runtime-tools/error"
)

Expand All @@ -13,22 +14,81 @@ const referenceTemplate = "https://github.com/opencontainers/runtime-spec/blob/v
type ErrorCode int

const (
// NonError represents that an input is not an error
NonError ErrorCode = iota
// NonRFCError represents that an error is not a rfc2119 error
NonRFCError

// ConfigFileExistence represents the error code of 'config.json' existence test.
ConfigFileExistence
// ArtifactsInSignleDir represents the error code of artifacts place test.
ArtifactsInSingleDir

// SpecVersion represents the error code of specfication version test.
SpecVersion

// RootOnNonHyperV represents the error code of root setting test on non hyper-v containers
RootOnNonHyperV
// RootOnNonHyperV represents the error code of root setting test on hyper-v containers
RootOnHyperV
// PathFormatOnwindows represents the error code of the path format test on Window
PathFormatOnWindows
// PathName represents the error code of the path name test
PathName
// PathExistence represents the error code of the path existence test
PathExistence
// ReadonlyFilesystem represents the error code of readonly test
ReadonlyFilesystem
// ReadonlyOnWindows represents the error code of readonly setting test on Windows
ReadonlyOnWindows

// DefaultFilesystems represents the error code of default filesystems test.
DefaultFilesystems ErrorCode = iota
DefaultFilesystems
)

type errorTemplate struct {
Level rfc2119.Level
Reference func(version string) (reference string, err error)
}

var (
containerFormatRef = func(version string) (reference string, err error) {
return fmt.Sprintf(referenceTemplate, version, "bundle.md#container-format"), nil
}
specVersionRef = func(version string) (reference string, err error) {
return fmt.Sprintf(referenceTemplate, version, "config.md#specification-version"), nil
}
rootRef = func(version string) (reference string, err error) {
return fmt.Sprintf(referenceTemplate, version, "config.md#root"), nil
}
defaultFSRef = func(version string) (reference string, err error) {
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#default-filesystems"), nil
}
)

var ociErrors = map[ErrorCode]errorTemplate{
DefaultFilesystems: errorTemplate{
Level: rfc2119.Should,
Reference: func(version string) (reference string, err error) {
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#default-filesystems"), nil
},
},
// NonRFCError represents that an error is not a rfc2119 error
// Bundle.md
// Container Format
ConfigFileExistence: errorTemplate{Level: rfc2119.Must, Reference: containerFormatRef},
ArtifactsInSingleDir: errorTemplate{Level: rfc2119.Must, Reference: containerFormatRef},

// Config.md
// Specification Version
SpecVersion: errorTemplate{Level: rfc2119.Must, Reference: specVersionRef},
// Root
RootOnNonHyperV: errorTemplate{Level: rfc2119.Required, Reference: rootRef},
RootOnHyperV: errorTemplate{Level: rfc2119.Must, Reference: rootRef},
// TODO
PathFormatOnWindows: errorTemplate{Level: rfc2119.Must, Reference: rootRef},
PathName: errorTemplate{Level: rfc2119.Should, Reference: rootRef},
PathExistence: errorTemplate{Level: rfc2119.Must, Reference: rootRef},
ReadonlyFilesystem: errorTemplate{Level: rfc2119.Must, Reference: rootRef},
ReadonlyOnWindows: errorTemplate{Level: rfc2119.Must, Reference: rootRef},

// Config-Linux.md
// Default Filesystems
DefaultFilesystems: errorTemplate{Level: rfc2119.Should, Reference: defaultFSRef},
}

// NewError creates an Error referencing a spec violation. The error
Expand All @@ -48,5 +108,30 @@ func NewError(code ErrorCode, msg string, version string) (err error) {
Level: template.Level,
Reference: reference,
Err: errors.New(msg),
ErrCode: int(code),
}
}

// FindError finds an error from a source error (mulitple error) and
// returns the error code if founded.
// If the source error is nil or empty, return NonErr.
// If the source error is not a multiple error, return NonRFCErr.
func FindError(err error, code ErrorCode) ErrorCode {
if err == nil {
return NonError
}

if merr, ok := err.(*multierror.Error); ok {
if merr.ErrorOrNil() == nil {
return NonError
}
for _, e := range merr.Errors {
if rfcErr, ok := e.(*rfc2119.Error); ok {
if rfcErr.ErrCode == int(code) {
return code
}
}
}
}
return NonRFCError
}
Loading

0 comments on commit af6946f

Please sign in to comment.