Skip to content

Commit 42fde59

Browse files
committed
complete spec errors of config.md
Signed-off-by: Liang Chenye <liangchenye@huawei.com>
1 parent 11703a7 commit 42fde59

File tree

4 files changed

+208
-57
lines changed

4 files changed

+208
-57
lines changed

cmd/runtimetest/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ func validateRootFS(spec *rspec.Spec) error {
314314
if spec.Root.Readonly {
315315
err := testWriteAccess("/")
316316
if err == nil {
317-
return specerror.NewError(specerror.ReadonlyFilesystem, fmt.Errorf("rootfs must be readonly"), rspec.Version)
317+
return specerror.NewError(specerror.RootReadonlyImplement, fmt.Errorf("rootfs must be readonly"), rspec.Version)
318318
}
319319
}
320320

specerror/error.go

Lines changed: 194 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,90 @@ const (
2626
// ArtifactsInSingleDir represents the error code of artifacts place test
2727
ArtifactsInSingleDir
2828

29-
// SpecVersion represents the error code of specfication version test
30-
SpecVersion
31-
32-
// RootOnNonHyperV represents the error code of root setting test on non hyper-v containers
33-
RootOnNonHyperV
34-
// RootOnHyperV represents the error code of root setting test on hyper-v containers
35-
RootOnHyperV
36-
// PathFormatOnWindows represents the error code of the path format test on Window
37-
PathFormatOnWindows
38-
// PathName represents the error code of the path name test
39-
PathName
40-
// PathExistence represents the error code of the path existence test
41-
PathExistence
42-
// ReadonlyFilesystem represents the error code of readonly test
43-
ReadonlyFilesystem
44-
// ReadonlyOnWindows represents the error code of readonly setting test on Windows
45-
ReadonlyOnWindows
29+
// SpecVersionInSemVer represents "* **`ociVersion`** (string, Required) MUST be in [SemVer v2.0.0][semver-v2.0.0] format and specifies the version of the Open Container Runtime Specification with which the bundle complies."
30+
SpecVersionInSemVer
31+
// RootOnWindowsRequired represents "On Windows, for Windows Server Containers, this field is REQUIRED."
32+
RootOnWindowsRequired
33+
// RootOnHyperVNotSet represents "For [Hyper-V Containers](config-windows.md#hyperv), this field MUST NOT be set."
34+
RootOnHyperVNotSet
35+
// RootOnNonHyperVRequired represents "On all other platforms, this field is REQUIRED."
36+
RootOnNonHyperVRequired
37+
// RootPathOnWindowsGUID represents "* On Windows, `path` MUST be a [volume GUID path][naming-a-volume]."
38+
RootPathOnWindowsGUID
39+
// RootPathOnPosixConvention represents "The value SHOULD be the conventional `rootfs`."
40+
RootPathOnPosixConvention
41+
// RootPathExist represents "A directory MUST exist at the path declared by the field."
42+
RootPathExist
43+
// RootReadonlyImplement represents "* **`readonly`** (bool, OPTIONAL) If true then the root filesystem MUST be read-only inside the container, defaults to false."
44+
RootReadonlyImplement
45+
// RootReadonlyOnWindowsFalse represents "* On Windows, this field MUST be omitted or false."
46+
RootReadonlyOnWindowsFalse
47+
// MountsInOrder represents "The runtime MUST mount entries in the listed order."
48+
MountsInOrder
49+
// MountsDestAbs represents "This value MUST be an absolute path."
50+
MountsDestAbs
51+
// MountsDestOnWindowsNotNested represents "* Windows: one mount destination MUST NOT be nested within another mount (e.g., c:\\foo and c:\\foo\\bar)."
52+
MountsDestOnWindowsNotNested
53+
// MountsOptionsOnWindowsROSupport represents "* Windows: runtimes MUST support `ro`, mounting the filesystem read-only when `ro` is given."
54+
MountsOptionsOnWindowsROSupport
55+
// ProcRequiredAtStart represents "This property is REQUIRED when [`start`](runtime.md#start) is called."
56+
ProcRequiredAtStart
57+
// ProcConsoleSizeIgnore represents "Runtimes MUST ignore `consoleSize` if `terminal` is `false` or unset."
58+
ProcConsoleSizeIgnore
59+
// ProcCwdAbs represents "This value MUST be an absolute path."
60+
ProcCwdAbs
61+
// ProcArgsOneEntryRequired represents "This specification extends the IEEE standard in that at least one entry is REQUIRED, and that entry is used with the same semantics as `execvp`'s *file*."
62+
ProcArgsOneEntryRequired
63+
// PosixProcRlimitsTypeError represents "The runtime MUST [generate an error](runtime.md#errors) for any values which cannot be mapped to a relevant kernel interface"
64+
PosixProcRlimitsTypeError
65+
// PosixProcRlimitsTypeGet represents "For each entry in `rlimits`, a [`getrlimit(3)`][getrlimit.3] on `type` MUST succeed."
66+
PosixProcRlimitsTypeGet
67+
// PosixProcRlimitsSoftMatchCur represents "`rlim.rlim_cur` MUST match the configured value."
68+
PosixProcRlimitsSoftMatchCur
69+
// PosixProcRlimitsHardMatchMax represents "`rlim.rlim_max` MUST match the configured value."
70+
PosixProcRlimitsHardMatchMax
71+
// PosixProcRlimitsErrorOnDup represents "If `rlimits` contains duplicated entries with same `type`, the runtime MUST [generate an error](runtime.md#errors)."
72+
PosixProcRlimitsErrorOnDup
73+
// LinuxProcCapError represents "Any value which cannot be mapped to a relevant kernel interface MUST cause an error."
74+
LinuxProcCapError
75+
// LinuxProcOomScoreAdjSet represents "If `oomScoreAdj` is set, the runtime MUST set `oom_score_adj` to the given value."
76+
LinuxProcOomScoreAdjSet
77+
// LinuxProcOomScoreAdjNotSet represents "If `oomScoreAdj` is not set, the runtime MUST NOT change the value of `oom_score_adj`."
78+
LinuxProcOomScoreAdjNotSet
79+
// PlatformSpecConfOnWindowsSet represents "This MUST be set if the target platform of this spec is `windows`."
80+
PlatformSpecConfOnWindowsSet
81+
// PosixHooksPathAbs represents "This specification extends the IEEE standard in that **`path`** MUST be absolute."
82+
PosixHooksPathAbs
83+
// PosixHooksTimeoutPositive represents "If set, `timeout` MUST be greater than zero."
84+
PosixHooksTimeoutPositive
85+
// PosixHooksCalledInOrder represents "Hooks MUST be called in the listed order."
86+
PosixHooksCalledInOrder
87+
// PosixHooksStateToStdin represents "The [state](runtime.md#state) of the container MUST be passed to hooks over stdin so that they may do work appropriate to the current state of the container."
88+
PosixHooksStateToStdin
89+
// PrestartTiming represents "The pre-start hooks MUST be called after the [`start`](runtime.md#start) operation is called but [before the user-specified program command is executed](runtime.md#lifecycle)."
90+
PrestartTiming
91+
// PoststartTiming represents "The post-start hooks MUST be called [after the user-specified process is executed](runtime.md#lifecycle) but before the [`start`](runtime.md#start) operation returns."
92+
PoststartTiming
93+
// PoststopTiming represents "The post-stop hooks MUST be called [after the container is deleted](runtime.md#lifecycle) but before the [`delete`](runtime.md#delete) operation returns."
94+
PoststopTiming
95+
// AnnotationsKeyValueMap represents "Annotations MUST be a key-value map."
96+
AnnotationsKeyValueMap
97+
// AnnotationsKeyString represents "Keys MUST be strings."
98+
AnnotationsKeyString
99+
// AnnotationsKeyRequired represents "Keys MUST NOT be an empty string."
100+
AnnotationsKeyRequired
101+
// AnnotationsKeyReversedDomain represents "Keys SHOULD be named using a reverse domain notation - e.g. `com.example.myKey`."
102+
AnnotationsKeyReversedDomain
103+
// AnnotationsKeyReservedNS represents "Keys using the `org.opencontainers` namespace are reserved and MUST NOT be used by subsequent specifications."
104+
AnnotationsKeyReservedNS
105+
// AnnotationsKeyIgnoreUnknown represents "Implementations that are reading/processing this configuration file MUST NOT generate an error if they encounter an unknown annotation key."
106+
AnnotationsKeyIgnoreUnknown
107+
// AnnotationsValueString represents "Values MUST be strings."
108+
AnnotationsValueString
109+
// ExtensibilityIgnoreUnknownProp represents "Runtimes that are reading or processing this configuration file MUST NOT generate an error if they encounter an unknown property."
110+
ExtensibilityIgnoreUnknownProp
111+
// ValidValuesError represents "Runtimes that are reading or processing this configuration file MUST generate an error when invalid or unsupported values are encountered."
112+
ValidValuesError
46113

47114
// DefaultFilesystems represents the error code of default filesystems test
48115
DefaultFilesystems
@@ -55,56 +122,140 @@ const (
55122
CreateNewContainer
56123
)
57124

58-
type errorTemplate struct {
59-
Level rfc2119.Level
60-
Reference func(version string) (reference string, err error)
61-
}
62-
63-
// Error represents a runtime-spec violation.
64-
type Error struct {
65-
// Err holds the RFC 2119 violation.
66-
Err rfc2119.Error
67-
68-
// Code is a matchable holds a Code
69-
Code Code
70-
}
71-
72125
var (
73126
containerFormatRef = func(version string) (reference string, err error) {
74127
return fmt.Sprintf(referenceTemplate, version, "bundle.md#container-format"), nil
75128
}
76-
specVersionRef = func(version string) (reference string, err error) {
129+
130+
specificationVersionRef = func(version string) (reference string, err error) {
77131
return fmt.Sprintf(referenceTemplate, version, "config.md#specification-version"), nil
78132
}
79133
rootRef = func(version string) (reference string, err error) {
80134
return fmt.Sprintf(referenceTemplate, version, "config.md#root"), nil
81135
}
136+
mountsRef = func(version string) (reference string, err error) {
137+
return fmt.Sprintf(referenceTemplate, version, "config.md#mounts"), nil
138+
}
139+
processRef = func(version string) (reference string, err error) {
140+
return fmt.Sprintf(referenceTemplate, version, "config.md#process"), nil
141+
}
142+
posixProcessRef = func(version string) (reference string, err error) {
143+
return fmt.Sprintf(referenceTemplate, version, "config.md#posix-process"), nil
144+
}
145+
linuxProcessRef = func(version string) (reference string, err error) {
146+
return fmt.Sprintf(referenceTemplate, version, "config.md#linux-process"), nil
147+
}
148+
platformSpecificConfigurationRef = func(version string) (reference string, err error) {
149+
return fmt.Sprintf(referenceTemplate, version, "config.md#platform-specific-configuration"), nil
150+
}
151+
posixPlatformHooksRef = func(version string) (reference string, err error) {
152+
return fmt.Sprintf(referenceTemplate, version, "config.md#posix-platform-hooks"), nil
153+
}
154+
prestartRef = func(version string) (reference string, err error) {
155+
return fmt.Sprintf(referenceTemplate, version, "config.md#prestart"), nil
156+
}
157+
poststartRef = func(version string) (reference string, err error) {
158+
return fmt.Sprintf(referenceTemplate, version, "config.md#poststart"), nil
159+
}
160+
poststopRef = func(version string) (reference string, err error) {
161+
return fmt.Sprintf(referenceTemplate, version, "config.md#poststop"), nil
162+
}
163+
annotationsRef = func(version string) (reference string, err error) {
164+
return fmt.Sprintf(referenceTemplate, version, "config.md#annotations"), nil
165+
}
166+
extensibilityRef = func(version string) (reference string, err error) {
167+
return fmt.Sprintf(referenceTemplate, version, "config.md#extensibility"), nil
168+
}
169+
validValuesRef = func(version string) (reference string, err error) {
170+
return fmt.Sprintf(referenceTemplate, version, "config.md#valid-values"), nil
171+
}
172+
82173
defaultFSRef = func(version string) (reference string, err error) {
83174
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#default-filesystems"), nil
84175
}
176+
85177
runtimeCreateRef = func(version string) (reference string, err error) {
86178
return fmt.Sprintf(referenceTemplate, version, "runtime.md#create"), nil
87179
}
88180
)
89181

182+
type errorTemplate struct {
183+
Level rfc2119.Level
184+
Reference func(version string) (reference string, err error)
185+
}
186+
187+
// Error represents a runtime-spec violation.
188+
type Error struct {
189+
// Err holds the RFC 2119 violation.
190+
Err rfc2119.Error
191+
192+
// Code is a matchable holds a Code
193+
Code Code
194+
}
195+
90196
var ociErrors = map[Code]errorTemplate{
91197
// Bundle.md
92198
// Container Format
93199
ConfigFileExistence: {Level: rfc2119.Must, Reference: containerFormatRef},
94200
ArtifactsInSingleDir: {Level: rfc2119.Must, Reference: containerFormatRef},
95201

96-
// Config.md
97-
// Specification Version
98-
SpecVersion: {Level: rfc2119.Must, Reference: specVersionRef},
202+
// config.md
203+
// Specification version
204+
SpecVersionInSemVer: {Level: rfc2119.Must, Reference: specificationVersionRef},
99205
// Root
100-
RootOnNonHyperV: {Level: rfc2119.Required, Reference: rootRef},
101-
RootOnHyperV: {Level: rfc2119.Must, Reference: rootRef},
102-
// TODO: add tests for 'PathFormatOnWindows'
103-
PathFormatOnWindows: {Level: rfc2119.Must, Reference: rootRef},
104-
PathName: {Level: rfc2119.Should, Reference: rootRef},
105-
PathExistence: {Level: rfc2119.Must, Reference: rootRef},
106-
ReadonlyFilesystem: {Level: rfc2119.Must, Reference: rootRef},
107-
ReadonlyOnWindows: {Level: rfc2119.Must, Reference: rootRef},
206+
RootOnWindowsRequired: {Level: rfc2119.Required, Reference: rootRef},
207+
RootOnHyperVNotSet: {Level: rfc2119.Must, Reference: rootRef},
208+
RootOnNonHyperVRequired: {Level: rfc2119.Required, Reference: rootRef},
209+
RootPathOnWindowsGUID: {Level: rfc2119.Must, Reference: rootRef},
210+
RootPathOnPosixConvention: {Level: rfc2119.Should, Reference: rootRef},
211+
RootPathExist: {Level: rfc2119.Must, Reference: rootRef},
212+
RootReadonlyImplement: {Level: rfc2119.Must, Reference: rootRef},
213+
RootReadonlyOnWindowsFalse: {Level: rfc2119.Must, Reference: rootRef},
214+
// Mounts
215+
MountsInOrder: {Level: rfc2119.Must, Reference: mountsRef},
216+
MountsDestAbs: {Level: rfc2119.Must, Reference: mountsRef},
217+
MountsDestOnWindowsNotNested: {Level: rfc2119.Must, Reference: mountsRef},
218+
MountsOptionsOnWindowsROSupport: {Level: rfc2119.Must, Reference: mountsRef},
219+
// Proc
220+
ProcRequiredAtStart: {Level: rfc2119.Required, Reference: processRef},
221+
ProcConsoleSizeIgnore: {Level: rfc2119.Must, Reference: processRef},
222+
ProcCwdAbs: {Level: rfc2119.Must, Reference: processRef},
223+
ProcArgsOneEntryRequired: {Level: rfc2119.Required, Reference: processRef},
224+
// POSIX process
225+
PosixProcRlimitsTypeError: {Level: rfc2119.Must, Reference: posixProcessRef},
226+
PosixProcRlimitsTypeGet: {Level: rfc2119.Must, Reference: posixProcessRef},
227+
PosixProcRlimitsSoftMatchCur: {Level: rfc2119.Must, Reference: posixProcessRef},
228+
PosixProcRlimitsHardMatchMax: {Level: rfc2119.Must, Reference: posixProcessRef},
229+
PosixProcRlimitsErrorOnDup: {Level: rfc2119.Must, Reference: posixProcessRef},
230+
// Linux Proc
231+
LinuxProcCapError: {Level: rfc2119.Must, Reference: linuxProcessRef},
232+
LinuxProcOomScoreAdjSet: {Level: rfc2119.Must, Reference: linuxProcessRef},
233+
LinuxProcOomScoreAdjNotSet: {Level: rfc2119.Must, Reference: linuxProcessRef},
234+
// Platform-specific configuration
235+
PlatformSpecConfOnWindowsSet: {Level: rfc2119.Must, Reference: platformSpecificConfigurationRef},
236+
// POSIX-platform Hooks
237+
PosixHooksPathAbs: {Level: rfc2119.Must, Reference: posixPlatformHooksRef},
238+
PosixHooksTimeoutPositive: {Level: rfc2119.Must, Reference: posixPlatformHooksRef},
239+
PosixHooksCalledInOrder: {Level: rfc2119.Must, Reference: posixPlatformHooksRef},
240+
PosixHooksStateToStdin: {Level: rfc2119.Must, Reference: posixPlatformHooksRef},
241+
// Prestart
242+
PrestartTiming: {Level: rfc2119.Must, Reference: prestartRef},
243+
// Poststart
244+
PoststartTiming: {Level: rfc2119.Must, Reference: poststartRef},
245+
// Poststop
246+
PoststopTiming: {Level: rfc2119.Must, Reference: poststopRef},
247+
// Annotations
248+
AnnotationsKeyValueMap: {Level: rfc2119.Must, Reference: annotationsRef},
249+
AnnotationsKeyString: {Level: rfc2119.Must, Reference: annotationsRef},
250+
AnnotationsKeyRequired: {Level: rfc2119.Must, Reference: annotationsRef},
251+
AnnotationsKeyReversedDomain: {Level: rfc2119.Should, Reference: annotationsRef},
252+
AnnotationsKeyReservedNS: {Level: rfc2119.Must, Reference: annotationsRef},
253+
AnnotationsKeyIgnoreUnknown: {Level: rfc2119.Must, Reference: annotationsRef},
254+
AnnotationsValueString: {Level: rfc2119.Must, Reference: annotationsRef},
255+
// Extensibility
256+
ExtensibilityIgnoreUnknownProp: {Level: rfc2119.Must, Reference: extensibilityRef},
257+
// Valid values
258+
ValidValuesError: {Level: rfc2119.Must, Reference: validValuesRef},
108259

109260
// Config-Linux.md
110261
// Default Filesystems

validate/validate.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,13 @@ func (v *Validator) CheckRoot() (errs error) {
172172
if v.platform == "windows" && v.spec.Windows != nil && v.spec.Windows.HyperV != nil {
173173
if v.spec.Root != nil {
174174
errs = multierror.Append(errs,
175-
specerror.NewError(specerror.RootOnHyperV, fmt.Errorf("for Hyper-V containers, Root must not be set"), rspec.Version))
175+
specerror.NewError(specerror.RootOnHyperVNotSet, fmt.Errorf("for Hyper-V containers, Root must not be set"), rspec.Version))
176176
return
177177
}
178178
return
179179
} else if v.spec.Root == nil {
180180
errs = multierror.Append(errs,
181-
specerror.NewError(specerror.RootOnNonHyperV, fmt.Errorf("for non-Hyper-V containers, Root must be set"), rspec.Version))
181+
specerror.NewError(specerror.RootOnNonHyperVRequired, fmt.Errorf("for non-Hyper-V containers, Root must be set"), rspec.Version))
182182
return
183183
}
184184

@@ -207,7 +207,7 @@ func (v *Validator) CheckRoot() (errs error) {
207207

208208
if filepath.Base(v.spec.Root.Path) != "rootfs" {
209209
errs = multierror.Append(errs,
210-
specerror.NewError(specerror.PathName, fmt.Errorf("path name should be the conventional 'rootfs'"), rspec.Version))
210+
specerror.NewError(specerror.RootPathOnPosixConvention, fmt.Errorf("path name should be the conventional 'rootfs'"), rspec.Version))
211211
}
212212

213213
var rootfsPath string
@@ -227,10 +227,10 @@ func (v *Validator) CheckRoot() (errs error) {
227227

228228
if fi, err := os.Stat(rootfsPath); err != nil {
229229
errs = multierror.Append(errs,
230-
specerror.NewError(specerror.PathExistence, fmt.Errorf("cannot find the root path %q", rootfsPath), rspec.Version))
230+
specerror.NewError(specerror.RootPathExist, fmt.Errorf("cannot find the root path %q", rootfsPath), rspec.Version))
231231
} else if !fi.IsDir() {
232232
errs = multierror.Append(errs,
233-
specerror.NewError(specerror.PathExistence, fmt.Errorf("root.path %q is not a directory", rootfsPath), rspec.Version))
233+
specerror.NewError(specerror.RootPathExist, fmt.Errorf("root.path %q is not a directory", rootfsPath), rspec.Version))
234234
}
235235

236236
rootParent := filepath.Dir(absRootPath)
@@ -250,7 +250,7 @@ func (v *Validator) CheckSemVer() (errs error) {
250250
_, err := semver.Parse(version)
251251
if err != nil {
252252
errs = multierror.Append(errs,
253-
specerror.NewError(specerror.SpecVersion, fmt.Errorf("%q is not valid SemVer: %s", version, err.Error()), rspec.Version))
253+
specerror.NewError(specerror.SpecVersionInSemVer, fmt.Errorf("%q is not valid SemVer: %s", version, err.Error()), rspec.Version))
254254
}
255255
if version != rspec.Version {
256256
errs = multierror.Append(errs, fmt.Errorf("validate currently only handles version %s, but the supplied configuration targets %s", rspec.Version, version))

0 commit comments

Comments
 (0)