Skip to content

Commit ddef754

Browse files
author
Ma Shimiao
committed
split runtimevalidate into inside and outside validaiton
Signed-off-by: Ma Shimiao <[email protected]>
1 parent 6bcd3b4 commit ddef754

File tree

1 file changed

+172
-32
lines changed

1 file changed

+172
-32
lines changed

validation/validation_test.go

Lines changed: 172 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package validation
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"io/ioutil"
67
"os"
78
"os/exec"
89
"path/filepath"
10+
"strings"
911
"testing"
1012

13+
"github.com/hashicorp/go-multierror"
14+
"github.com/mndrix/tap-go"
1115
"github.com/mrunalp/fileutils"
16+
rspec "github.com/opencontainers/runtime-spec/specs-go"
1217
"github.com/opencontainers/runtime-tools/generate"
1318
"github.com/satori/go.uuid"
1419
)
@@ -17,54 +22,92 @@ var (
1722
runtime = "runc"
1823
)
1924

25+
type validation struct {
26+
test func(string, string, *rspec.Spec) error
27+
description string
28+
}
29+
2030
func init() {
2131
runtime = os.Getenv("RUNTIME")
2232
}
2333

24-
func runtimeValidate(runtime string, g *generate.Generator) error {
34+
func TestValidateRuntimeInside(t *testing.T) {
35+
g, err := getDefaultGenerator()
36+
if err != nil {
37+
t.Errorf("%s failed validation: %v", runtime, err)
38+
}
39+
g.SetProcessArgs([]string{"/runtimetest"})
40+
41+
if err := runtimeInsideValidate(runtime, g); err != nil {
42+
t.Errorf("%s failed validation: %v", runtime, err)
43+
}
44+
}
45+
46+
func TestValidateRuntimeOutside(t *testing.T) {
47+
g, err := getDefaultGenerator()
48+
if err != nil {
49+
t.Errorf("%s failed validation: %v", runtime, err)
50+
}
51+
52+
if err := runtimeOutsideValidate(runtime, g); err != nil {
53+
t.Errorf("%s failed validation: %v", runtime, err)
54+
}
55+
}
56+
57+
func runtimeInsideValidate(runtime string, g *generate.Generator) error {
2558
// Find the runtime binary in the PATH
2659
runtimePath, err := exec.LookPath(runtime)
2760
if err != nil {
2861
return err
2962
}
3063

31-
// Setup a temporary test directory
32-
tmpDir, err := ioutil.TempDir("", "ocitest")
64+
bundleDir, rootfsDir, err := prepareBundle(g)
3365
if err != nil {
3466
return err
3567
}
36-
defer os.RemoveAll(tmpDir)
68+
// defer os.RemoveAll(bundleDir)
3769

38-
// Create bundle directory for the test container
39-
bundleDir := tmpDir + "/busybox"
40-
if err := os.MkdirAll(bundleDir, 0755); err != nil {
70+
// Copy the runtimetest binary to the rootfs
71+
err = fileutils.CopyFile("../runtimetest", filepath.Join(rootfsDir, "runtimetest"))
72+
if err != nil {
4173
return err
4274
}
4375

44-
// Untar the root fs
45-
untarCmd := exec.Command("tar", "-xf", "../rootfs.tar.gz", "-C", bundleDir)
46-
output, err := untarCmd.CombinedOutput()
47-
if err != nil {
48-
fmt.Println(string(output))
76+
// TODO: Use a library to split run into create/start
77+
// Launch the OCI runtime
78+
containerID := uuid.NewV4()
79+
runtimeCmd := exec.Command(runtimePath, "run", containerID.String())
80+
runtimeCmd.Dir = bundleDir
81+
runtimeCmd.Stdin = os.Stdin
82+
runtimeCmd.Stdout = os.Stdout
83+
runtimeCmd.Stderr = os.Stderr
84+
if err = runtimeCmd.Run(); err != nil {
4985
return err
5086
}
5187

52-
// Copy the runtimetest binary to the rootfs
53-
err = fileutils.CopyFile("../runtimetest", filepath.Join(bundleDir, "runtimetest"))
88+
if err = cleanup(runtimePath, containerID.String()); err != nil {
89+
return err
90+
}
91+
92+
return nil
93+
}
94+
95+
func runtimeOutsideValidate(runtime string, g *generate.Generator) error {
96+
// Find the runtime binary in the PATH
97+
runtimePath, err := exec.LookPath(runtime)
5498
if err != nil {
5599
return err
56100
}
57101

58-
// Generate test configuration
59-
err = g.SaveToFile(filepath.Join(bundleDir, "config.json"), generate.ExportOptions{})
102+
bundleDir, _, err := prepareBundle(g)
60103
if err != nil {
61104
return err
62105
}
106+
defer os.RemoveAll(bundleDir)
63107

64-
// TODO: Use a library to split run into create/start
65108
// Launch the OCI runtime
66109
containerID := uuid.NewV4()
67-
runtimeCmd := exec.Command(runtimePath, "run", containerID.String())
110+
runtimeCmd := exec.Command(runtimePath, "create", containerID.String())
68111
runtimeCmd.Dir = bundleDir
69112
runtimeCmd.Stdin = os.Stdin
70113
runtimeCmd.Stdout = os.Stdout
@@ -73,29 +116,126 @@ func runtimeValidate(runtime string, g *generate.Generator) error {
73116
return err
74117
}
75118

119+
outsideValidations := []validation{
120+
{
121+
test: validateLabels,
122+
description: "labels",
123+
},
124+
// Add more container outside validation
125+
}
126+
127+
t := tap.New()
128+
t.Header(0)
129+
130+
var validationErrors error
131+
for _, v := range outsideValidations {
132+
err := v.test(runtimePath, containerID.String(), g.Spec())
133+
t.Ok(err == nil, v.description)
134+
if err != nil {
135+
validationErrors = multierror.Append(validationErrors, err)
136+
}
137+
}
138+
t.AutoPlan()
139+
140+
if err = cleanup(runtimePath, containerID.String()); err != nil {
141+
validationErrors = multierror.Append(validationErrors, err)
142+
}
143+
144+
return validationErrors
145+
}
146+
147+
func validateLabels(runtimePath, id string, spec *rspec.Spec) error {
148+
runtimeCmd := exec.Command(runtimePath, "state", id)
149+
output, err := runtimeCmd.Output()
150+
if err != nil {
151+
return err
152+
}
153+
154+
var state rspec.State
155+
if err := json.NewDecoder(strings.NewReader(string(output))).Decode(&state); err != nil {
156+
return err
157+
}
158+
for key, value := range spec.Annotations {
159+
if state.Annotations[key] == value {
160+
continue
161+
}
162+
return fmt.Errorf("Expected annotation %s:%s not set", key, value)
163+
}
76164
return nil
77165
}
78166

79-
func getDefaultGenerator() *generate.Generator {
80-
g := generate.New()
81-
g.SetRootPath(".")
82-
g.SetProcessArgs([]string{"/runtimetest"})
83-
return &g
167+
func cleanup(runtimePath, id string) error {
168+
runtimeCmd := exec.Command(runtimePath, "kill", id, "KILL")
169+
if err := runtimeCmd.Run(); err != nil {
170+
return fmt.Errorf("Failed to kill container %s: %v", id, err)
171+
}
172+
173+
runtimeCmd = exec.Command(runtimePath, "delete", id)
174+
if err := runtimeCmd.Run(); err != nil {
175+
return fmt.Errorf("Failed to kill container %s: %v", id, err)
176+
}
177+
178+
return nil
84179
}
85180

86-
func TestValidateBasic(t *testing.T) {
87-
g := getDefaultGenerator()
181+
func prepareBundle(g *generate.Generator) (string, string, error) {
182+
// Setup a temporary test directory
183+
tmpDir, err := ioutil.TempDir("", "ocitest")
184+
if err != nil {
185+
return "", "", err
186+
}
88187

89-
if err := runtimeValidate(runtime, g); err != nil {
90-
t.Errorf("%s failed validation: %v", runtime, err)
188+
// Create bundle directory for the test container
189+
bundleDir := tmpDir
190+
if err := os.MkdirAll(bundleDir, 0755); err != nil {
191+
return "", "", err
192+
}
193+
194+
// Create rootfs directory for the test container
195+
rootfsDir := bundleDir + "/rootfs"
196+
if err := os.MkdirAll(rootfsDir, 0755); err != nil {
197+
return "", "", err
198+
}
199+
200+
// Untar the root fs
201+
untarCmd := exec.Command("tar", "-xf", "../rootfs.tar.gz", "-C", rootfsDir)
202+
output, err := untarCmd.CombinedOutput()
203+
if err != nil {
204+
fmt.Println(string(output))
205+
return "", "", err
206+
}
207+
208+
// Generate test configuration
209+
err = g.SaveToFile(filepath.Join(bundleDir, "config.json"), generate.ExportOptions{})
210+
if err != nil {
211+
return "", "", err
91212
}
213+
214+
// Copy the configuration file to the rootfs
215+
err = fileutils.CopyFile(filepath.Join(bundleDir, "config.json"), filepath.Join(rootfsDir, "config.json"))
216+
if err != nil {
217+
return "", "", err
218+
}
219+
220+
return bundleDir, rootfsDir, nil
92221
}
93222

94-
func TestValidateSysctls(t *testing.T) {
95-
g := getDefaultGenerator()
96-
g.AddLinuxSysctl("net.ipv4.ip_forward", "1")
223+
func getDefaultGenerator() (*generate.Generator, error) {
224+
// Generate testcase template
225+
generateCmd := exec.Command("oci-runtime-tool", "generate", "--mount-bind=/tmp:/volume/testing:rw", "--linux-cgroups-path=/tmp/testcgroup", "--linux-device-add=c:80:500:/dev/test:fileMode=438", "--linux-disable-oom-kill=true", "--env=testvar=vartest", "--hostname=localvalidation", "--label=testlabel=nonevar", "--linux-cpu-shares=1024", "--output", "/tmp/config.json")
226+
output, err := generateCmd.CombinedOutput()
227+
if err != nil {
228+
fmt.Println(string(output))
229+
return nil, err
230+
}
97231

98-
if err := runtimeValidate(runtime, g); err != nil {
99-
t.Errorf("%s failed validation: %v", runtime, err)
232+
// Get testcase configuration
233+
g, err := generate.NewFromFile("/tmp/config.json")
234+
if err != nil {
235+
return nil, err
100236
}
237+
238+
g.SetRootPath("rootfs")
239+
240+
return &g, nil
101241
}

0 commit comments

Comments
 (0)