af0a494251
Kubelet can send cap add/drop ALL. Handle that in CRI-O as well. Also, this PR is re-vendoring runtime-tools to fix capabilities add to add caps to _all_ caps set **and** fix a shared memory issue (caps set were initialized with the same slice, if one modifies one slice, it's reflected on the other slices, the vendoring fixes this as well) Signed-off-by: Antonio Murdaca <runcom@redhat.com>
170 lines
5.5 KiB
Go
170 lines
5.5 KiB
Go
// Package specerror implements runtime-spec-specific tooling for
|
|
// tracking RFC 2119 violations.
|
|
package specerror
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/go-multierror"
|
|
rfc2119 "github.com/opencontainers/runtime-tools/error"
|
|
)
|
|
|
|
const referenceTemplate = "https://github.com/opencontainers/runtime-spec/blob/v%s/%s"
|
|
|
|
// Code represents the spec violation, enumerating both
|
|
// configuration violations and runtime violations.
|
|
type Code int
|
|
|
|
const (
|
|
// NonError represents that an input is not an error
|
|
NonError Code = 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
|
|
|
|
// CreateWithID represents the error code of 'create' lifecyle test with 'id' provided
|
|
CreateWithID
|
|
// CreateWithUniqueID represents the error code of 'create' lifecyle test with unique 'id' provided
|
|
CreateWithUniqueID
|
|
// CreateNewContainer represents the error code 'create' lifecyle test that creates new container
|
|
CreateNewContainer
|
|
)
|
|
|
|
type errorTemplate struct {
|
|
Level rfc2119.Level
|
|
Reference func(version string) (reference string, err error)
|
|
}
|
|
|
|
// Error represents a runtime-spec violation.
|
|
type Error struct {
|
|
// Err holds the RFC 2119 violation.
|
|
Err rfc2119.Error
|
|
|
|
// Code is a matchable holds a Code
|
|
Code Code
|
|
}
|
|
|
|
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
|
|
}
|
|
runtimeCreateRef = func(version string) (reference string, err error) {
|
|
return fmt.Sprintf(referenceTemplate, version, "runtime.md#create"), nil
|
|
}
|
|
)
|
|
|
|
var ociErrors = map[Code]errorTemplate{
|
|
// Bundle.md
|
|
// Container Format
|
|
ConfigFileExistence: {Level: rfc2119.Must, Reference: containerFormatRef},
|
|
ArtifactsInSingleDir: {Level: rfc2119.Must, Reference: containerFormatRef},
|
|
|
|
// Config.md
|
|
// Specification Version
|
|
SpecVersion: {Level: rfc2119.Must, Reference: specVersionRef},
|
|
// Root
|
|
RootOnNonHyperV: {Level: rfc2119.Required, Reference: rootRef},
|
|
RootOnHyperV: {Level: rfc2119.Must, Reference: rootRef},
|
|
// TODO: add tests for 'PathFormatOnWindows'
|
|
PathFormatOnWindows: {Level: rfc2119.Must, Reference: rootRef},
|
|
PathName: {Level: rfc2119.Should, Reference: rootRef},
|
|
PathExistence: {Level: rfc2119.Must, Reference: rootRef},
|
|
ReadonlyFilesystem: {Level: rfc2119.Must, Reference: rootRef},
|
|
ReadonlyOnWindows: {Level: rfc2119.Must, Reference: rootRef},
|
|
|
|
// Config-Linux.md
|
|
// Default Filesystems
|
|
DefaultFilesystems: {Level: rfc2119.Should, Reference: defaultFSRef},
|
|
|
|
// Runtime.md
|
|
// Create
|
|
CreateWithID: {Level: rfc2119.Must, Reference: runtimeCreateRef},
|
|
CreateWithUniqueID: {Level: rfc2119.Must, Reference: runtimeCreateRef},
|
|
CreateNewContainer: {Level: rfc2119.Must, Reference: runtimeCreateRef},
|
|
}
|
|
|
|
// Error returns the error message with specification reference.
|
|
func (err *Error) Error() string {
|
|
return err.Err.Error()
|
|
}
|
|
|
|
// 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
|
|
// 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 Code, err error, version string) error {
|
|
template := ociErrors[code]
|
|
reference, err2 := template.Reference(version)
|
|
if err2 != nil {
|
|
return err2
|
|
}
|
|
return &Error{
|
|
Err: rfc2119.Error{
|
|
Level: template.Level,
|
|
Reference: reference,
|
|
Err: err,
|
|
},
|
|
Code: code,
|
|
}
|
|
}
|
|
|
|
// FindError finds an error from a source error (multiple error) and
|
|
// returns the error code if found.
|
|
// 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 Code) Code {
|
|
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.Code == code {
|
|
return code
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NonRFCError
|
|
}
|