Skip to content

Commit 3a83c2c

Browse files
author
Zhou Hao
authored
Merge pull request #586 from liangchenye/annotation
add annotation and prop tests
2 parents 3532c53 + e43d1ff commit 3a83c2c

File tree

4 files changed

+152
-1
lines changed

4 files changed

+152
-1
lines changed

cmd/oci-runtime-tool/validate.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ var bundleValidateCommand = cli.Command{
4444
for _, e := range levelErrors.Warnings {
4545
logrus.Warn(e)
4646
}
47-
return levelErrors.Error
47+
48+
return levelErrors.Error.ErrorOrNil()
4849
}
4950
fmt.Println("Bundle validation succeeded.")
5051
return nil

validate/validate.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ func (v *Validator) CheckAll() error {
114114
errs = multierror.Append(errs, v.CheckMounts())
115115
errs = multierror.Append(errs, v.CheckProcess())
116116
errs = multierror.Append(errs, v.CheckLinux())
117+
errs = multierror.Append(errs, v.CheckAnnotations())
117118
if v.platform == "linux" || v.platform == "solaris" {
118119
errs = multierror.Append(errs, v.CheckHooks())
119120
}
@@ -655,6 +656,32 @@ func (v *Validator) CheckLinuxResources() (errs error) {
655656
return
656657
}
657658

659+
// CheckAnnotations checks v.spec.Annotations
660+
func (v *Validator) CheckAnnotations() (errs error) {
661+
logrus.Debugf("check annotations")
662+
663+
reversedDomain := regexp.MustCompile(`^[A-Za-z]{2,6}(\.[A-Za-z0-9-]{1,63})+$`)
664+
for key := range v.spec.Annotations {
665+
if strings.HasPrefix(key, "org.opencontainers") {
666+
errs = multierror.Append(errs,
667+
specerror.NewError(
668+
specerror.AnnotationsKeyReservedNS,
669+
fmt.Errorf("key %q is reserved", key),
670+
rspec.Version))
671+
}
672+
673+
if !reversedDomain.MatchString(key) {
674+
errs = multierror.Append(errs,
675+
specerror.NewError(
676+
specerror.AnnotationsKeyReversedDomain,
677+
fmt.Errorf("key %q SHOULD be named using a reverse domain notation", key),
678+
rspec.Version))
679+
}
680+
}
681+
682+
return
683+
}
684+
658685
// CapValid checks whether a capability is valid
659686
func CapValid(c string, hostSpecific bool) error {
660687
isValid := false

validate/validate_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -759,3 +759,47 @@ func TestCheckMandatoryFields(t *testing.T) {
759759
})
760760
}
761761
}
762+
763+
func TestCheckAnnotations(t *testing.T) {
764+
cases := []struct {
765+
val rspec.Spec
766+
expected specerror.Code
767+
}{
768+
{
769+
val: rspec.Spec{},
770+
expected: specerror.NonError,
771+
},
772+
{
773+
val: rspec.Spec{
774+
Annotations: map[string]string{},
775+
},
776+
expected: specerror.NonError,
777+
},
778+
{
779+
val: rspec.Spec{
780+
Annotations: map[string]string{"invalid": ""},
781+
},
782+
expected: specerror.AnnotationsKeyReversedDomain,
783+
},
784+
{
785+
val: rspec.Spec{
786+
Annotations: map[string]string{"org.opencontainers.oci": ""},
787+
},
788+
expected: specerror.AnnotationsKeyReservedNS,
789+
},
790+
{
791+
val: rspec.Spec{
792+
Annotations: map[string]string{"com.example": ""},
793+
},
794+
expected: specerror.NonError,
795+
},
796+
}
797+
for _, c := range cases {
798+
v, err := NewValidator(&c.val, ".", false, "")
799+
if err != nil {
800+
t.Errorf("unexpected NewValidator error: %+v", err)
801+
}
802+
err = v.CheckAnnotations()
803+
assert.Equal(t, c.expected, specerror.FindError(err, c.expected), fmt.Sprintf("failed CheckAnnotations: %v %d", err, c.expected))
804+
}
805+
}

validation/misc_props.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io/ioutil"
7+
"os"
8+
"path/filepath"
9+
"time"
10+
11+
"github.com/mndrix/tap-go"
12+
rspecs "github.com/opencontainers/runtime-spec/specs-go"
13+
"github.com/opencontainers/runtime-tools/specerror"
14+
"github.com/opencontainers/runtime-tools/validation/util"
15+
uuid "github.com/satori/go.uuid"
16+
)
17+
18+
func saveConfig(path string, v interface{}) error {
19+
data, err := json.Marshal(v)
20+
if err != nil {
21+
return err
22+
}
23+
24+
return ioutil.WriteFile(path, data, 0644)
25+
}
26+
27+
func main() {
28+
t := tap.New()
29+
t.Header(0)
30+
bundleDir, err := util.PrepareBundle()
31+
if err != nil {
32+
util.Fatal(err)
33+
}
34+
defer os.RemoveAll(bundleDir)
35+
configFile := filepath.Join(bundleDir, "config.json")
36+
37+
type extendedSpec struct {
38+
rspecs.Spec
39+
Unknown string `json:"unknown,omitempty"`
40+
}
41+
42+
containerID := uuid.NewV4().String()
43+
basicConfig := util.GetDefaultGenerator()
44+
basicConfig.SetProcessArgs([]string{"true"})
45+
annotationConfig := basicConfig
46+
annotationConfig.AddAnnotation(fmt.Sprintf("org.%s", containerID), "")
47+
invalidConfig := basicConfig
48+
invalidConfig.SetVersion("invalid")
49+
50+
cases := []struct {
51+
eSpec extendedSpec
52+
action util.LifecycleAction
53+
errExpected bool
54+
err error
55+
}{
56+
{extendedSpec{Spec: *annotationConfig.Spec()}, util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete, true, specerror.NewError(specerror.AnnotationsKeyIgnoreUnknown, fmt.Errorf("implementations that are reading/processing this configuration file MUST NOT generate an error if they encounter an unknown annotation key"), rspecs.Version)},
57+
{extendedSpec{Spec: *basicConfig.Spec(), Unknown: "unknown"}, util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete, true, specerror.NewError(specerror.ExtensibilityIgnoreUnknownProp, fmt.Errorf("runtimes that are reading or processing this configuration file MUST NOT generate an error if they encounter an unknown property"), rspecs.Version)},
58+
{extendedSpec{Spec: *invalidConfig.Spec()}, util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete, false, specerror.NewError(specerror.ValidValues, fmt.Errorf("runtimes that are reading or processing this configuration file MUST generate an error when invalid or unsupported values are encountered"), rspecs.Version)},
59+
}
60+
61+
for _, c := range cases {
62+
config := util.LifecycleConfig{
63+
BundleDir: bundleDir,
64+
Actions: c.action,
65+
PreCreate: func(r *util.Runtime) error {
66+
r.SetID(containerID)
67+
return saveConfig(configFile, c.eSpec)
68+
},
69+
PreDelete: func(r *util.Runtime) error {
70+
util.WaitingForStatus(*r, util.LifecycleStatusCreated|util.LifecycleStatusStopped, time.Second*10, time.Second*1)
71+
return nil
72+
},
73+
}
74+
err := util.RuntimeLifecycleValidate(config)
75+
util.SpecErrorOK(t, (err == nil) == c.errExpected, c.err, err)
76+
}
77+
78+
t.AutoPlan()
79+
}

0 commit comments

Comments
 (0)