Skip to content

Commit

Permalink
add stretchr/testify/assert pkgs; use rfc code in bundle validation
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 30, 2017
1 parent 3767027 commit 2520212
Show file tree
Hide file tree
Showing 24 changed files with 4,728 additions and 200 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
17 changes: 8 additions & 9 deletions cmd/runtimetest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ import (
"github.com/urfave/cli"

"github.com/opencontainers/runtime-tools/cmd/runtimetest/mount"
rfc2119 "github.com/opencontainers/runtime-tools/error"
"github.com/opencontainers/runtime-tools/validate"
rerr "github.com/opencontainers/runtime-tools/error"
)

// PrGetNoNewPrivs isn't exposed in Golang so we define it ourselves copying the value from
Expand Down Expand Up @@ -314,7 +313,7 @@ func validateRootFS(spec *rspec.Spec) error {
if spec.Root.Readonly {
err := testWriteAccess("/")
if err == nil {
return fmt.Errorf("Rootfs should be readonly")
return rerr.NewError(rerr.ReadonlyFilesystem, "Rootfs should be readonly", rspec.Version)
}
}

Expand All @@ -326,7 +325,7 @@ func validateDefaultFS(spec *rspec.Spec) error {

mountInfos, err := mount.GetMounts()
if err != nil {
validate.NewError(validate.DefaultFilesystems, err.Error(), spec.Version)
rerr.NewError(rerr.DefaultFilesystems, err.Error(), spec.Version)
}

mountsMap := make(map[string]string)
Expand All @@ -336,7 +335,7 @@ func validateDefaultFS(spec *rspec.Spec) error {

for fs, fstype := range defaultFS {
if !(mountsMap[fs] == fstype) {
return validate.NewError(validate.DefaultFilesystems, fmt.Sprintf("%v SHOULD exist and expected type is %v", fs, fstype), spec.Version)
return rerr.NewError(rerr.DefaultFilesystems, fmt.Sprintf("%v SHOULD exist and expected type is %v", fs, fstype), rspec.Version)
}
}

Expand Down Expand Up @@ -720,17 +719,17 @@ func run(context *cli.Context) error {
t.Header(0)

complianceLevelString := context.String("compliance-level")
complianceLevel, err := rfc2119.ParseLevel(complianceLevelString)
complianceLevel, err := rerr.ParseLevel(complianceLevelString)
if err != nil {
complianceLevel = rfc2119.Must
complianceLevel = rerr.Must
logrus.Warningf("%s, using 'MUST' by default.", err.Error())
}
var validationErrors error
for _, v := range defaultValidations {
err := v.test(spec)
t.Ok(err == nil, v.description)
if err != nil {
if e, ok := err.(*rfc2119.Error); ok && e.Level < complianceLevel {
if e, ok := err.(*rerr.Error); ok && e.Level < complianceLevel {
continue
}
validationErrors = multierror.Append(validationErrors, err)
Expand All @@ -742,7 +741,7 @@ func run(context *cli.Context) error {
err := v.test(spec)
t.Ok(err == nil, v.description)
if err != nil {
if e, ok := err.(*rfc2119.Error); ok && e.Level < complianceLevel {
if e, ok := err.(*rerr.Error); ok && e.Level < complianceLevel {
continue
}
validationErrors = multierror.Append(validationErrors, err)
Expand Down
1 change: 1 addition & 0 deletions error/error.go → error/rfc2199.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
135 changes: 135 additions & 0 deletions error/runtime_spec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
package error

import (
"errors"
"fmt"

"github.com/hashicorp/go-multierror"
)

const referenceTemplate = "https://github.com/opencontainers/runtime-spec/blob/v%s/%s"

// SpecErrorCode represents the compliance content.
type SpecErrorCode int

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

// ConfigFileExistence represents the error code of 'config.json' existence test
ConfigFileExistence
// ArtifactsInSingleDir 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
// RootOnHyperV 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
)

type errorTemplate struct {
Level 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[SpecErrorCode]errorTemplate{
// Bundle.md
// Container Format
ConfigFileExistence: errorTemplate{Level: Must, Reference: containerFormatRef},
ArtifactsInSingleDir: errorTemplate{Level: Must, Reference: containerFormatRef},

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

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

// NewError creates an Error referencing a spec violation. The error
// can be cast to a *runtime-tools.error.Error for extracting
// structured information about the level of the violation and a
// reference to the violated spec condition.
//
// A version string (for the version of the spec that was violated)
// must be set to get a working URL.
func NewError(code SpecErrorCode, msg string, version string) (err error) {
template := ociErrors[code]
reference, err := template.Reference(version)
if err != nil {
return err
}
return &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 NonError.
// If the source error is not a multiple error, return NonRFCError.
func FindError(err error, code SpecErrorCode) SpecErrorCode {
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.(*Error); ok {
if rfcErr.ErrCode == int(code) {
return code
}
}
}
}
return NonRFCError
}
52 changes: 0 additions & 52 deletions validate/error.go

This file was deleted.

Loading

0 comments on commit 2520212

Please sign in to comment.