Skip to content

Commit 18b08d4

Browse files
author
Ma Shimiao
committed
split runtimevalidate into inside and outside validaiton
Signed-off-by: Ma Shimiao <[email protected]> test Signed-off-by: Ma Shimiao <[email protected]>
1 parent bcf89dd commit 18b08d4

File tree

2 files changed

+170
-33
lines changed

2 files changed

+170
-33
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ tool:
1212

1313
.PHONY: runtimetest
1414
runtimetest:
15-
go build -tags "$(BUILDTAGS)" -o runtimetest ./cmd/runtimetest
15+
# go build -tags "$(BUILDTAGS)" -o runtimetest ./cmd/runtimetest
16+
CGO_ENABLED=0 go build -installsuffix cgo -tags "$(BUILDTAGS)" -o runtimetest ./cmd/runtimetest
1617

1718
.PHONY: man
1819
man:

validation/validation_test.go

Lines changed: 168 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,88 @@ 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+
return nil
89+
}
90+
91+
func runtimeOutsideValidate(runtime string, g *generate.Generator) error {
92+
// Find the runtime binary in the PATH
93+
runtimePath, err := exec.LookPath(runtime)
5494
if err != nil {
5595
return err
5696
}
5797

58-
// Generate test configuration
59-
err = g.SaveToFile(filepath.Join(bundleDir, "config.json"), generate.ExportOptions{})
98+
bundleDir, _, err := prepareBundle(g)
6099
if err != nil {
61100
return err
62101
}
102+
defer os.RemoveAll(bundleDir)
63103

64-
// TODO: Use a library to split run into create/start
65104
// Launch the OCI runtime
66105
containerID := uuid.NewV4()
67-
runtimeCmd := exec.Command(runtimePath, "run", containerID.String())
106+
runtimeCmd := exec.Command(runtimePath, "create", containerID.String())
68107
runtimeCmd.Dir = bundleDir
69108
runtimeCmd.Stdin = os.Stdin
70109
runtimeCmd.Stdout = os.Stdout
@@ -73,29 +112,126 @@ func runtimeValidate(runtime string, g *generate.Generator) error {
73112
return err
74113
}
75114

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

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

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

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

94-
func TestValidateSysctls(t *testing.T) {
95-
g := getDefaultGenerator()
96-
g.AddLinuxSysctl("net.ipv4.ip_forward", "1")
219+
func getDefaultGenerator() (*generate.Generator, error) {
220+
// Generate testcase template
221+
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")
222+
output, err := generateCmd.CombinedOutput()
223+
if err != nil {
224+
fmt.Println(string(output))
225+
return nil, err
226+
}
97227

98-
if err := runtimeValidate(runtime, g); err != nil {
99-
t.Errorf("%s failed validation: %v", runtime, err)
228+
// Get testcase configuration
229+
g, err := generate.NewFromFile("/tmp/config.json")
230+
if err != nil {
231+
return nil, err
100232
}
233+
234+
g.SetRootPath("rootfs")
235+
236+
return &g, nil
101237
}

0 commit comments

Comments
 (0)