Skip to content

Commit ce4fbd0

Browse files
committed
add specerror framework; complete rfc errors of bundle.md and config.md
Signed-off-by: Liang Chenye <liangchenye@huawei.com>
1 parent f3c1c70 commit ce4fbd0

9 files changed

Lines changed: 302 additions & 99 deletions

File tree

cmd/runtimetest/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func validateRootFS(spec *rspec.Spec) error {
328328
if spec.Root.Readonly {
329329
err := testWriteAccess("/")
330330
if err == nil {
331-
return specerror.NewError(specerror.ReadonlyFilesystem, fmt.Errorf("rootfs must be readonly"), rspec.Version)
331+
return specerror.NewError(specerror.RootReadonlyImplement, fmt.Errorf("rootfs must be readonly"), rspec.Version)
332332
}
333333
}
334334

specerror/bundle.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Package specerror implements runtime-spec-specific tooling for
2+
// tracking RFC 2119 violations.
3+
package specerror
4+
5+
import (
6+
"fmt"
7+
8+
rfc2119 "github.com/opencontainers/runtime-tools/error"
9+
)
10+
11+
// define error codes
12+
const (
13+
// ConfigInRootBundleDir represents "This REQUIRED file MUST reside in the root of the bundle directory"
14+
ConfigInRootBundleDir = "This REQUIRED file MUST reside in the root of the bundle directory."
15+
// ConfigConstName represents "This REQUIRED file MUST be named `config.json`."
16+
ConfigConstName = "This REQUIRED file MUST be named `config.json`."
17+
// ArtifactsInSingleDir represents "When supplied, while these artifacts MUST all be present in a single directory on the local filesystem, that directory itself is not part of the bundle."
18+
ArtifactsInSingleDir = "When supplied, while these artifacts MUST all be present in a single directory on the local filesystem, that directory itself is not part of the bundle."
19+
)
20+
21+
var (
22+
containerFormatRef = func(version string) (reference string, err error) {
23+
return fmt.Sprintf(referenceTemplate, version, "bundle.md#container-format"), nil
24+
}
25+
)
26+
27+
func init() {
28+
registOCIError(ConfigInRootBundleDir, rfc2119.Must, containerFormatRef)
29+
registOCIError(ConfigConstName, rfc2119.Must, containerFormatRef)
30+
registOCIError(ArtifactsInSingleDir, rfc2119.Must, containerFormatRef)
31+
}

specerror/config-linux.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Package specerror implements runtime-spec-specific tooling for
2+
// tracking RFC 2119 violations.
3+
package specerror
4+
5+
import (
6+
"fmt"
7+
8+
rfc2119 "github.com/opencontainers/runtime-tools/error"
9+
)
10+
11+
// define error codes
12+
const (
13+
// DefaultFilesystems represents "The following filesystems SHOULD be made available in each container's filesystem:"
14+
DefaultFilesystems = "The following filesystems SHOULD be made available in each container's filesystem:"
15+
)
16+
17+
var (
18+
defaultFilesystemsRef = func(version string) (reference string, err error) {
19+
return fmt.Sprintf(referenceTemplate, version, "config-linux.md#default-filesystems"), nil
20+
}
21+
)
22+
23+
func init() {
24+
registOCIError(DefaultFilesystems, rfc2119.Should, defaultFilesystemsRef)
25+
}

specerror/config.go

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// Package specerror implements runtime-spec-specific tooling for
2+
// tracking RFC 2119 violations.
3+
package specerror
4+
5+
import (
6+
"fmt"
7+
8+
rfc2119 "github.com/opencontainers/runtime-tools/error"
9+
)
10+
11+
// define error codes
12+
const (
13+
// 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 Initiative Runtime Specification with which the bundle complies."
14+
SpecVersionInSemVer = "**`ociVersion`** (string, Required) MUST be in [SemVer v2.0.0][semver-v2.0.0] format and specifies the version of the Open Container Initiative Runtime Specification with which the bundle complies."
15+
// RootOnWindowsRequired represents "On Windows, for Windows Server Containers, this field is REQUIRED."
16+
RootOnWindowsRequired = "On Windows, for Windows Server Containers, this field is REQUIRED."
17+
// RootOnHyperVNotSet represents "For [Hyper-V Containers](config-windows.md#hyperv), this field MUST NOT be set."
18+
RootOnHyperVNotSet = "For [Hyper-V Containers](config-windows.md#hyperv), this field MUST NOT be set."
19+
// RootOnNonHyperVRequired represents "On all other platforms, this field is REQUIRED."
20+
RootOnNonHyperVRequired = "On all other platforms, this field is REQUIRED."
21+
// RootPathOnWindowsGUID represents "On Windows, `path` MUST be a [volume GUID path][naming-a-volume]."
22+
RootPathOnWindowsGUID = "On Windows, `path` MUST be a [volume GUID path][naming-a-volume]."
23+
// RootPathOnPosixConvention represents "The value SHOULD be the conventional `rootfs`."
24+
RootPathOnPosixConvention = "The value SHOULD be the conventional `rootfs`."
25+
// RootPathExist represents "A directory MUST exist at the path declared by the field."
26+
RootPathExist = "A directory MUST exist at the path declared by the field."
27+
// RootReadonlyImplement represents "**`readonly`** (bool, OPTIONAL) If true then the root filesystem MUST be read-only inside the container, defaults to false."
28+
RootReadonlyImplement = "**`readonly`** (bool, OPTIONAL) If true then the root filesystem MUST be read-only inside the container, defaults to false."
29+
// RootReadonlyOnWindowsFalse represents "* On Windows, this field MUST be omitted or false."
30+
RootReadonlyOnWindowsFalse = "On Windows, this field MUST be omitted or false."
31+
// MountsInOrder represents "The runtime MUST mount entries in the listed order."
32+
MountsInOrder = "The runtime MUST mount entries in the listed order."
33+
// MountsDestAbs represents "Destination of mount point: path inside container. This value MUST be an absolute path."
34+
MountsDestAbs = "Destination of mount point: path inside container. This value MUST be an absolute path."
35+
// MountsDestOnWindowsNotNested represents "Windows: one mount destination MUST NOT be nested within another mount (e.g., c:\\foo and c:\\foo\\bar)."
36+
MountsDestOnWindowsNotNested = "Windows: one mount destination MUST NOT be nested within another mount (e.g., c:\\foo and c:\\foo\\bar)."
37+
// MountsOptionsOnWindowsROSupport represents "Windows: runtimes MUST support `ro`, mounting the filesystem read-only when `ro` is given."
38+
MountsOptionsOnWindowsROSupport = "Windows: runtimes MUST support `ro`, mounting the filesystem read-only when `ro` is given."
39+
// ProcRequiredAtStart represents "This property is REQUIRED when [`start`](runtime.md#start) is called."
40+
ProcRequiredAtStart = "This property is REQUIRED when [`start`](runtime.md#start) is called."
41+
// ProcessConsoleSizeIgnore represents "Runtimes MUST ignore `consoleSize` if `terminal` is `false` or unset."
42+
ProcessConsoleSizeIgnore = "Runtimes MUST ignore `consoleSize` if `terminal` is `false` or unset."
43+
// ProcCwdAbs represents "** cwd ** (string, REQUIRED) is the working directory that will be set for the executable. This value MUST be an absolute path."
44+
ProcCwdAbs = "** cwd ** (string, REQUIRED) is the working directory that will be set for the executable. This value MUST be an absolute path."
45+
// 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*."
46+
ProcArgsOneEntryRequired = "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*."
47+
// PosixProcRlimitsTypeGeneError represents "The runtime MUST [generate an error](runtime.md#errors) for any values which cannot be mapped to a relevant kernel interface."
48+
PosixProcRlimitsTypeGeneError = "The runtime MUST [generate an error](runtime.md#errors) for any values which cannot be mapped to a relevant kernel interface."
49+
// PosixProcRlimitsTypeGet represents "For each entry in `rlimits`, a [`getrlimit(3)`][getrlimit.3] on `type` MUST succeed."
50+
PosixProcRlimitsTypeGet = "For each entry in `rlimits`, a [`getrlimit(3)`][getrlimit.3] on `type` MUST succeed."
51+
// PosixProcRlimitsSoftMatchCur represents "`rlim.rlim_cur` MUST match the configured value."
52+
PosixProcRlimitsSoftMatchCur = "`rlim.rlim_cur` MUST match the configured value."
53+
// PosixProcRlimitsHardMatchMax represents "`rlim.rlim_max` MUST match the configured value."
54+
PosixProcRlimitsHardMatchMax = "`rlim.rlim_max` MUST match the configured value."
55+
// PosixProcRlimitsErrorOnDup represents "If `rlimits` contains duplicated entries with same `type`, the runtime MUST [generate an error](runtime.md#errors)."
56+
PosixProcRlimitsErrorOnDup = "If `rlimits` contains duplicated entries with same `type`, the runtime MUST [generate an error](runtime.md#errors)."
57+
// LinuxProcCapError represents "Any value which cannot be mapped to a relevant kernel interface MUST cause an error."
58+
LinuxProcCapError = "Any value which cannot be mapped to a relevant kernel interface MUST cause an error."
59+
// LinuxProcOomScoreAdjSet represents "If `oomScoreAdj` is set, the runtime MUST set `oom_score_adj` to the given value."
60+
LinuxProcOomScoreAdjSet = "If `oomScoreAdj` is set, the runtime MUST set `oom_score_adj` to the given value."
61+
// LinuxProcOomScoreAdjNotSet represents "If `oomScoreAdj` is not set, the runtime MUST NOT change the value of `oom_score_adj`."
62+
LinuxProcOomScoreAdjNotSet = "If `oomScoreAdj` is not set, the runtime MUST NOT change the value of `oom_score_adj`."
63+
// PlatformSpecConfOnWindowsSet represents "This MUST be set if the target platform of this spec is `windows`."
64+
PlatformSpecConfOnWindowsSet = "This MUST be set if the target platform of this spec is `windows`."
65+
// PosixHooksPathAbs represents "This specification extends the IEEE standard in that **`path`** MUST be absolute."
66+
PosixHooksPathAbs = "This specification extends the IEEE standard in that **`path`** MUST be absolute."
67+
// PosixHooksTimeoutPositive represents "If set, `timeout` MUST be greater than zero."
68+
PosixHooksTimeoutPositive = "If set, `timeout` MUST be greater than zero."
69+
// PosixHooksCalledInOrder represents "Hooks MUST be called in the listed order."
70+
PosixHooksCalledInOrder = "Hooks MUST be called in the listed order."
71+
// 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."
72+
PosixHooksStateToStdin = "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."
73+
// 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)."
74+
PrestartTiming = "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)."
75+
// 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."
76+
PoststartTiming = "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."
77+
// 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."
78+
PoststopTiming = "The post-stop hooks MUST be called [after the container is deleted](runtime.md#lifecycle) but before the [`delete`](runtime.md#delete) operation returns."
79+
// AnnotationsKeyValueMap represents "Annotations MUST be a key-value map."
80+
AnnotationsKeyValueMap = "Annotations MUST be a key-value map."
81+
// AnnotationsKeyString represents "Keys MUST be strings."
82+
AnnotationsKeyString = "Keys MUST be strings."
83+
// AnnotationsKeyRequired represents "Keys MUST NOT be an empty string."
84+
AnnotationsKeyRequired = "Keys MUST NOT be an empty string."
85+
// AnnotationsKeyReversedDomain represents "Keys SHOULD be named using a reverse domain notation - e.g. `com.example.myKey`."
86+
AnnotationsKeyReversedDomain = "Keys SHOULD be named using a reverse domain notation - e.g. `com.example.myKey`."
87+
// AnnotationsKeyReservedNS represents "Keys using the `org.opencontainers` namespace are reserved and MUST NOT be used by subsequent specifications."
88+
AnnotationsKeyReservedNS = "Keys using the `org.opencontainers` namespace are reserved and MUST NOT be used by subsequent specifications."
89+
// AnnotationsKeyIgnoreUnknown represents "Implementations that are reading/processing this configuration file MUST NOT generate an error if they encounter an unknown annotation key."
90+
AnnotationsKeyIgnoreUnknown = "Implementations that are reading/processing this configuration file MUST NOT generate an error if they encounter an unknown annotation key."
91+
// AnnotationsValueString represents "Values MUST be strings."
92+
AnnotationsValueString = "Values MUST be strings."
93+
// ExtensibilityIgnoreUnknownProp represents "Runtimes that are reading or processing this configuration file MUST NOT generate an error if they encounter an unknown property."
94+
ExtensibilityIgnoreUnknownProp = "Runtimes that are reading or processing this configuration file MUST NOT generate an error if they encounter an unknown property.\nInstead they MUST ignore unknown properties."
95+
// ValidValues represents "Runtimes that are reading or processing this configuration file MUST generate an error when invalid or unsupported values are encountered."
96+
ValidValues = "Runtimes that are reading or processing this configuration file MUST generate an error when invalid or unsupported values are encountered."
97+
)
98+
99+
var (
100+
specificationVersionRef = func(version string) (reference string, err error) {
101+
return fmt.Sprintf(referenceTemplate, version, "config.md#specification-version"), nil
102+
}
103+
rootRef = func(version string) (reference string, err error) {
104+
return fmt.Sprintf(referenceTemplate, version, "config.md#root"), nil
105+
}
106+
mountsRef = func(version string) (reference string, err error) {
107+
return fmt.Sprintf(referenceTemplate, version, "config.md#mounts"), nil
108+
}
109+
processRef = func(version string) (reference string, err error) {
110+
return fmt.Sprintf(referenceTemplate, version, "config.md#process"), nil
111+
}
112+
posixProcessRef = func(version string) (reference string, err error) {
113+
return fmt.Sprintf(referenceTemplate, version, "config.md#posix-process"), nil
114+
}
115+
linuxProcessRef = func(version string) (reference string, err error) {
116+
return fmt.Sprintf(referenceTemplate, version, "config.md#linux-process"), nil
117+
}
118+
platformSpecificConfigurationRef = func(version string) (reference string, err error) {
119+
return fmt.Sprintf(referenceTemplate, version, "config.md#platform-specific-configuration"), nil
120+
}
121+
posixPlatformHooksRef = func(version string) (reference string, err error) {
122+
return fmt.Sprintf(referenceTemplate, version, "config.md#posix-platform-hooks"), nil
123+
}
124+
prestartRef = func(version string) (reference string, err error) {
125+
return fmt.Sprintf(referenceTemplate, version, "config.md#prestart"), nil
126+
}
127+
poststartRef = func(version string) (reference string, err error) {
128+
return fmt.Sprintf(referenceTemplate, version, "config.md#poststart"), nil
129+
}
130+
poststopRef = func(version string) (reference string, err error) {
131+
return fmt.Sprintf(referenceTemplate, version, "config.md#poststop"), nil
132+
}
133+
annotationsRef = func(version string) (reference string, err error) {
134+
return fmt.Sprintf(referenceTemplate, version, "config.md#annotations"), nil
135+
}
136+
extensibilityRef = func(version string) (reference string, err error) {
137+
return fmt.Sprintf(referenceTemplate, version, "config.md#extensibility"), nil
138+
}
139+
validValuesRef = func(version string) (reference string, err error) {
140+
return fmt.Sprintf(referenceTemplate, version, "config.md#valid-values"), nil
141+
}
142+
)
143+
144+
func init() {
145+
registOCIError(SpecVersionInSemVer, rfc2119.Must, specificationVersionRef)
146+
registOCIError(RootOnWindowsRequired, rfc2119.Required, rootRef)
147+
registOCIError(RootOnHyperVNotSet, rfc2119.Must, rootRef)
148+
registOCIError(RootOnNonHyperVRequired, rfc2119.Required, rootRef)
149+
registOCIError(RootPathOnWindowsGUID, rfc2119.Must, rootRef)
150+
registOCIError(RootPathOnPosixConvention, rfc2119.Should, rootRef)
151+
registOCIError(RootPathExist, rfc2119.Must, rootRef)
152+
registOCIError(RootReadonlyImplement, rfc2119.Must, rootRef)
153+
registOCIError(RootReadonlyOnWindowsFalse, rfc2119.Must, rootRef)
154+
registOCIError(MountsInOrder, rfc2119.Must, mountsRef)
155+
registOCIError(MountsDestAbs, rfc2119.Must, mountsRef)
156+
registOCIError(MountsDestOnWindowsNotNested, rfc2119.Must, mountsRef)
157+
registOCIError(MountsOptionsOnWindowsROSupport, rfc2119.Must, mountsRef)
158+
registOCIError(ProcRequiredAtStart, rfc2119.Required, processRef)
159+
registOCIError(ProcessConsoleSizeIgnore, rfc2119.Must, processRef)
160+
registOCIError(ProcCwdAbs, rfc2119.Must, processRef)
161+
registOCIError(ProcArgsOneEntryRequired, rfc2119.Required, processRef)
162+
registOCIError(PosixProcRlimitsTypeGeneError, rfc2119.Must, posixProcessRef)
163+
registOCIError(PosixProcRlimitsTypeGet, rfc2119.Must, posixProcessRef)
164+
registOCIError(PosixProcRlimitsSoftMatchCur, rfc2119.Must, posixProcessRef)
165+
registOCIError(PosixProcRlimitsHardMatchMax, rfc2119.Must, posixProcessRef)
166+
registOCIError(PosixProcRlimitsErrorOnDup, rfc2119.Must, posixProcessRef)
167+
registOCIError(LinuxProcCapError, rfc2119.Must, linuxProcessRef)
168+
registOCIError(LinuxProcOomScoreAdjSet, rfc2119.Must, linuxProcessRef)
169+
registOCIError(LinuxProcOomScoreAdjNotSet, rfc2119.Must, linuxProcessRef)
170+
registOCIError(PlatformSpecConfOnWindowsSet, rfc2119.Must, platformSpecificConfigurationRef)
171+
registOCIError(PosixHooksPathAbs, rfc2119.Must, posixPlatformHooksRef)
172+
registOCIError(PosixHooksTimeoutPositive, rfc2119.Must, posixPlatformHooksRef)
173+
registOCIError(PosixHooksCalledInOrder, rfc2119.Must, posixPlatformHooksRef)
174+
registOCIError(PosixHooksStateToStdin, rfc2119.Must, posixPlatformHooksRef)
175+
registOCIError(PrestartTiming, rfc2119.Must, prestartRef)
176+
registOCIError(PoststartTiming, rfc2119.Must, poststartRef)
177+
registOCIError(PoststopTiming, rfc2119.Must, poststopRef)
178+
registOCIError(AnnotationsKeyValueMap, rfc2119.Must, annotationsRef)
179+
registOCIError(AnnotationsKeyString, rfc2119.Must, annotationsRef)
180+
registOCIError(AnnotationsKeyRequired, rfc2119.Must, annotationsRef)
181+
registOCIError(AnnotationsKeyReversedDomain, rfc2119.Should, annotationsRef)
182+
registOCIError(AnnotationsKeyReservedNS, rfc2119.Must, annotationsRef)
183+
registOCIError(AnnotationsKeyIgnoreUnknown, rfc2119.Must, annotationsRef)
184+
registOCIError(AnnotationsValueString, rfc2119.Must, annotationsRef)
185+
registOCIError(ExtensibilityIgnoreUnknownProp, rfc2119.Must, extensibilityRef)
186+
registOCIError(ValidValues, rfc2119.Must, validValuesRef)
187+
}

0 commit comments

Comments
 (0)