Codebase list golang-github-opencontainers-runtime-tools / 181bf80
Merge tag 'upstream/0.9.0+git20220423.g0105384' Reinhard Tartler 2 years ago
73 changed file(s) with 737 addition(s) and 826 deletion(s). Raw diff Collapse all Expand all
0 name: ci
1 on:
2 push:
3 tags:
4 - v*
5 branches:
6 - master
7 - release-*
8 pull_request:
9
10 jobs:
11
12 lint:
13 runs-on: ubuntu-20.04
14 steps:
15 - uses: actions/checkout@v2
16 - uses: golangci/golangci-lint-action@v2
17 with:
18 version: v1.42
19
20 commit:
21 runs-on: ubuntu-20.04
22 # Only check commits on pull requests.
23 if: github.event_name == 'pull_request'
24 steps:
25 - name: get pr commits
26 id: 'get-pr-commits'
27 uses: tim-actions/get-pr-commits@v1.1.0
28 with:
29 token: ${{ secrets.GITHUB_TOKEN }}
30
31 - name: check subject line length
32 uses: tim-actions/commit-message-checker-with-regex@v0.3.1
33 with:
34 commits: ${{ steps.get-pr-commits.outputs.commits }}
35 pattern: '^.{0,72}(\n.*)*$'
36 error: 'Subject too long (max 72)'
37
38 test:
39 runs-on: ubuntu-20.04
40 strategy:
41 fail-fast: false
42 matrix:
43 go-version: [1.16.x, 1.17.x]
44 race: ["-race", ""]
45
46 steps:
47 - name: checkout
48 uses: actions/checkout@v2
49 - name: install go ${{ matrix.go-version }}
50 uses: actions/setup-go@v2
51 with:
52 stable: '!contains(${{ matrix.go-version }}, "beta") && !contains(${{ matrix.go-version }}, "rc")'
53 go-version: ${{ matrix.go-version }}
54 - name: build
55 run: make EXTRA_FLAGS="${{ matrix.race }}"
56 - name: test
57 run: make TESTFLAGS="${{ matrix.race }}" test
0 # Compiled Object files, Static and Dynamic libs (Shared Objects)
1 *.o
2 *.a
3 *.so
4
5 # Folders
6 _obj
7 _test
8 rootfs
9
10 # Architecture specific extensions/prefixes
11 *.[568vq]
12 [568vq].out
13
14 *.cgo1.go
15 *.cgo2.c
16 _cgo_defun.c
17 _cgo_gotypes.go
18 _cgo_export.*
19
20 _testmain.go
21
22 *.exe
23 *.test
24 *.prof
25
26 # Compiled binaries
27 oci
28 /oci-runtime-tool
29 /runtimetest
30
31 *.1
32 *.patch
33
34 # Temporary symbol links
35 Godeps/_workspace/src/github.com/opencontainers/runtime-tools
0 # For documentation, see https://golangci-lint.run/usage/configuration/
1
2 linters:
3 disable:
4 - errcheck
+0
-19
.travis.yml less more
0 language: go
1 go:
2 - 1.10.x
3 - 1.11.x
4
5 sudo: false
6
7 before_install:
8 - mkdir --parents $GOPATH/src/golang.org/x
9 && git clone --depth=1 https://go.googlesource.com/lint $GOPATH/src/golang.org/x/lint
10 && go get golang.org/x/lint/golint
11 - go get github.com/vbatts/git-validation
12
13 install: true
14
15 script:
16 - git-validation -run DCO,short-subject -v -range ${TRAVIS_COMMIT_RANGE}
17 - make
18 - make test
+0
-97
Godeps/Godeps.json less more
0 {
1 "ImportPath": "github.com/opencontainers/runtime-tools",
2 "GoVersion": "go1.7",
3 "GodepVersion": "v77",
4 "Packages": [
5 "./..."
6 ],
7 "Deps": [
8 {
9 "ImportPath": "github.com/blang/semver",
10 "Comment": "v3.5.0",
11 "Rev": "b38d23b8782a487059e8fc8773e9a5b228a77cb6"
12 },
13 {
14 "ImportPath": "github.com/davecgh/go-spew/spew",
15 "Comment": "v1.1.0-7-ga476722",
16 "Rev": "a476722483882dd40b8111f0eb64e1d7f43f56e4"
17 },
18 {
19 "ImportPath": "github.com/hashicorp/errwrap",
20 "Rev": "7554cd9344cec97297fa6649b055a8c98c2a1e55"
21 },
22 {
23 "ImportPath": "github.com/hashicorp/go-multierror",
24 "Comment": "v1.0.0",
25 "Rev": "886a7fbe3eb1c874d46f623bfa70af45f425b3d1"
26 },
27 {
28 "ImportPath": "github.com/mndrix/tap-go",
29 "Rev": "629fa407e90bbf3781e448e8e9b8931523ec823c"
30 },
31 {
32 "ImportPath": "github.com/mrunalp/fileutils",
33 "Rev": "4ee1cc9a80582a0c75febdd5cfa779ee4361cbca"
34 },
35 {
36 "ImportPath": "github.com/opencontainers/runtime-spec/specs-go",
37 "Comment": "v1.0.1-57-g1722abf",
38 "Rev": "1722abf79c2f8f2675f47367f827c6491472cf27"
39 },
40 {
41 "ImportPath": "github.com/pmezard/go-difflib/difflib",
42 "Comment": "v1.0.0",
43 "Rev": "792786c7400a136282c1664665ae0a8db921c6c2"
44 },
45 {
46 "ImportPath": "github.com/opencontainers/selinux/go-selinux",
47 "Comment": "v1.1-1-g2d93b96",
48 "Rev": "2d93b96e1a01b26e3378c49a974d11f6783ec185"
49 },
50 {
51 "ImportPath": "github.com/opencontainers/selinux/go-selinux/label",
52 "Comment": "v1.1-1-g2d93b96",
53 "Rev": "2d93b96e1a01b26e3378c49a974d11f6783ec185"
54 },
55 {
56 "ImportPath": "github.com/satori/go.uuid",
57 "Comment": "v1.1.0",
58 "Rev": "879c5887cd475cd7864858769793b2ceb0d44feb"
59 },
60 {
61 "ImportPath": "github.com/sirupsen/logrus",
62 "Comment": "1.0.2",
63 "Rev": "a3f95b5c423586578a4e099b11a46c2479628cac"
64 },
65 {
66 "ImportPath": "github.com/stretchr/testify/assert",
67 "Comment": "v1.1.4-71-g890a5c3",
68 "Rev": "890a5c3458b43e6104ff5da8dfa139d013d77544"
69 },
70 {
71 "ImportPath": "github.com/syndtr/gocapability/capability",
72 "Rev": "db04d3cc01c8b54962a58ec7e491717d06cfcc16"
73 },
74 {
75 "ImportPath": "github.com/urfave/cli",
76 "Comment": "v1.19.1",
77 "Rev": "0bdeddeeb0f650497d603c4ad7b20cfe685682f6"
78 },
79 {
80 "ImportPath": "github.com/xeipuuv/gojsonpointer",
81 "Rev": "6fe8760cad3569743d51ddbb243b26f8456742dc"
82 },
83 {
84 "ImportPath": "github.com/xeipuuv/gojsonreference",
85 "Rev": "e02fc20de94c78484cd5ffb007f8af96be030a45"
86 },
87 {
88 "ImportPath": "github.com/xeipuuv/gojsonschema",
89 "Rev": "0c8571ac0ce161a5feb57375a9cdf148c98c0f70"
90 },
91 {
92 "ImportPath": "golang.org/x/sys/unix",
93 "Rev": "f3918c30c5c2cb527c0b071a27c35120a6c0719a"
94 }
95 ]
96 }
+0
-5
Godeps/Readme less more
0 This directory tree is generated automatically by godep.
1
2 Please do not edit.
3
4 See https://github.com/tools/godep for more information.
55 Tianon Gravi <admwiggin@gmail.com> (@tianon)
66 Qiang Huang <h.huangqiang@huawei.com> (@hqhq)
77 Liang Chenye <liangchenye@huawei.com> (@liangchenye)
8 Ma Shimiao <mashimiao.fnst@cn.fujitsu.com> (@Mashimiao)
8 Ma Shimiao <shimiao.ma@gmail.com> (@Mashimiao)
99 Zhou Hao <zhouhao@cn.fujitsu.com> (@q384566678)
10 Kir Kolyshkin <kolyshkin@gmail.com> (@kolyshkin)
00 PREFIX ?= $(DESTDIR)/usr
11 BINDIR ?= $(DESTDIR)/usr/bin
2 TAP ?= tap
2 TAPTOOL ?= tap
33
44 BUILDTAGS=
55 RUNTIME ?= runc
6 COMMIT=$(shell git rev-parse HEAD 2> /dev/null || true)
6 COMMIT ?= $(shell git describe --dirty --long --always --tags 2> /dev/null)
77 VERSION := ${shell cat ./VERSION}
8 BUILD_FLAGS := -tags "$(BUILDTAGS)" -ldflags "-X main.gitCommit=$(COMMIT) -X main.version=$(VERSION)" $(EXTRA_FLAGS)
9 STATIC_BUILD_FLAGS := -tags "$(BUILDTAGS) netgo osusergo" -ldflags "-extldflags -static -X main.gitCommit=$(COMMIT) -X main.version=$(VERSION)" $(EXTRA_FLAGS)
810 VALIDATION_TESTS ?= $(patsubst %.go,%.t,$(shell find ./validation/ -name *.go | grep -v util))
911
1012 all: tool runtimetest validation-executables
1113
1214 tool:
13 go build -tags "$(BUILDTAGS)" -ldflags "-X main.gitCommit=${COMMIT} -X main.version=${VERSION}" -o oci-runtime-tool ./cmd/oci-runtime-tool
15 go build $(BUILD_FLAGS) -o oci-runtime-tool ./cmd/oci-runtime-tool
1416
1517 .PHONY: runtimetest
1618 runtimetest:
17 CGO_ENABLED=0 go build -installsuffix cgo -tags "$(BUILDTAGS)" -ldflags "-X main.gitCommit=${COMMIT} -X main.version=${VERSION}" -o runtimetest ./cmd/runtimetest
19 go build $(STATIC_BUILD_FLAGS) -o runtimetest ./cmd/runtimetest
1820
1921 .PHONY: man
2022 man:
4749 exit 1; \
4850 fi; \
4951 done
50 RUNTIME=$(RUNTIME) $(TAP) $(VALIDATION_TESTS)
52 RUNTIME=$(RUNTIME) $(TAPTOOL) $(VALIDATION_TESTS)
5153
5254 .PHONY: validation-executables
5355 validation-executables: $(VALIDATION_TESTS)
5557 .PRECIOUS: $(VALIDATION_TESTS)
5658 .PHONY: $(VALIDATION_TESTS)
5759 $(VALIDATION_TESTS): %.t: %.go
58 go build -tags "$(BUILDTAGS)" ${TESTFLAGS} -o $@ $<
60 go build $(BUILD_FLAGS) -o $@ $<
5961
6062 print-validation-tests:
6163 @echo $(VALIDATION_TESTS)
6264
63 .PHONY: test .gofmt .govet .golint print-validation-tests
65 .PHONY: test .govet print-validation-tests
6466
6567 PACKAGES = $(shell go list ./... | grep -v vendor)
66 test: .gofmt .govet .golint .gotest
67
68 .gofmt:
69 OUT=$$(go fmt $(PACKAGES)); if test -n "$${OUT}"; then echo "$${OUT}" && exit 1; fi
68 test: .govet .gotest
7069
7170 .govet:
7271 go vet -x $(PACKAGES)
7372
74 .golint:
75 golint -set_exit_status $(PACKAGES)
76
77 UTDIRS = ./filepath/... ./validate/... ./generate/...
7873 .gotest:
79 go test $(UTDIRS)
74 go test $(TESTFLAGS) ./...
112112 For example, with [`prove`][prove]:
113113
114114 ```console
115 $ sudo make TAP='prove -Q -j9' RUNTIME=runc VALIDATION_TESTS=validation/pidfile/pidfile.t localvalidation
115 $ sudo make TAPTOOL='prove -Q -j9' RUNTIME=runc VALIDATION_TESTS=validation/pidfile/pidfile.t localvalidation
116116 RUNTIME=runc prove -Q -j9 validation/pidfile.t
117117 All tests successful.
118118 Files=1, Tests=1, 0 wallclock secs ( 0.01 usr 0.01 sys + 0.03 cusr 0.03 csys = 0.08 CPU)
1616 type CgroupV1 struct {
1717 MountPath string
1818 }
19
20 // HugePageSizeUnitList is a list of the units used by the linux kernel when
21 // naming the HugePage control files.
22 // https://www.kernel.org/doc/Documentation/cgroup-v1/hugetlb.txt
23 var HugePageSizeUnitList = []string{"B", "KB", "MB", "GB", "TB", "PB"}
1924
2025 func getDeviceID(id string) (int64, int64, error) {
2126 elem := strings.Split(id, ":")
392397 return int64(byteSize), nil
393398 }
394399
395 func getHugePageSize() ([]string, error) {
400 // GetHugePageSize returns a list of the supported Hugepage sizes on the same format as
401 // opencontainers/runtime-spec (see pageSize): https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#huge-page-limits
402 // eg. ["64KB", "2MB", "1GB"]
403 func GetHugePageSize() ([]string, error) {
396404 var pageSizes []string
397 sizeList := []string{"B", "kB", "MB", "GB", "TB", "PB"}
398405 files, err := ioutil.ReadDir("/sys/kernel/mm/hugepages")
399406 if err != nil {
400407 return pageSizes, err
408415 size := float64(pageSize)
409416 base := float64(1024.0)
410417 i := 0
411 unitsLimit := len(sizeList) - 1
418 unitsLimit := len(HugePageSizeUnitList) - 1
412419 for size >= base && i < unitsLimit {
413420 size = size / base
414421 i++
415422 }
416 sizeString := fmt.Sprintf("%g%s", size, sizeList[i])
423 sizeString := fmt.Sprintf("%g%s", size, HugePageSizeUnitList[i])
417424 pageSizes = append(pageSizes, sizeString)
418425 }
419426
432439 }
433440 }
434441 lh := []rspec.LinuxHugepageLimit{}
435 pageSizes, err := getHugePageSize()
442 pageSizes, err := GetHugePageSize()
436443 if err != nil {
437444 return lh, err
438445 }
5252 cli.StringSliceFlag{Name: "linux-gidmappings", Usage: "add GIDMappings e.g HostID:ContainerID:Size"},
5353 cli.StringSliceFlag{Name: "linux-hugepage-limits-add", Usage: "add hugepage resource limits"},
5454 cli.StringSliceFlag{Name: "linux-hugepage-limits-drop", Usage: "drop hugepage resource limits"},
55 cli.StringFlag{Name: "linux-intelRdt-closid", Usage: "RDT Class of Service, i.e. group under the resctrl pseudo-filesystem which to associate the container with"},
5556 cli.StringFlag{Name: "linux-intelRdt-l3CacheSchema", Usage: "specifies the schema for L3 cache id and capacity bitmask"},
5657 cli.StringSliceFlag{Name: "linux-masked-paths", Usage: "specifies paths can not be read inside container"},
5758 cli.Uint64Flag{Name: "linux-mem-kernel-limit", Usage: "kernel memory limit (in bytes)"},
117118 cli.BoolFlag{Name: "process-rlimits-remove-all", Usage: "remove all resource limits for processes inside the container. "},
118119 cli.BoolFlag{Name: "process-terminal", Usage: "specifies whether a terminal is attached to the process"},
119120 cli.IntFlag{Name: "process-uid", Usage: "uid for the process"},
121 cli.StringFlag{Name: "process-umask", Usage: "umask for the process"},
120122 cli.StringFlag{Name: "process-username", Usage: "username for the process"},
121123 cli.StringFlag{Name: "rootfs-path", Value: "rootfs", Usage: "path to the root filesystem"},
122124 cli.BoolFlag{Name: "rootfs-readonly", Usage: "make the container's rootfs readonly"},
233235 g.SetProcessUsername(context.String("process-username"))
234236 }
235237
238 if context.IsSet("process-umask") {
239 g.SetProcessUmask(uint32(context.Int("process-umask")))
240 }
241
236242 if context.IsSet("process-gid") {
237243 g.SetProcessGID(uint32(context.Int("process-gid")))
238244 }
523529 if err := json.Unmarshal([]byte(hook), &tmpHook); err != nil {
524530 return err
525531 }
526 if err := g.AddPostStartHook(tmpHook); err != nil {
527 return err
528 }
532 g.AddPostStartHook(tmpHook)
529533 }
530534 }
531535
540544 if err := json.Unmarshal([]byte(hook), &tmpHook); err != nil {
541545 return err
542546 }
543 if err := g.AddPostStopHook(tmpHook); err != nil {
544 return err
545 }
547 g.AddPostStopHook(tmpHook)
546548 }
547549 }
548550
557559 if err := json.Unmarshal([]byte(hook), &tmpHook); err != nil {
558560 return err
559561 }
560 if err := g.AddPreStartHook(tmpHook); err != nil {
561 return err
562 }
562 g.AddPreStartHook(tmpHook)
563563 }
564564 }
565565
738738 for _, v := range pageList {
739739 g.DropLinuxResourcesHugepageLimit(v)
740740 }
741 }
742
743 if context.IsSet("linux-intelRdt-closid") {
744 g.SetLinuxIntelRdtClosID(context.String("linux-intelRdt-closid"))
741745 }
742746
743747 if context.IsSet("linux-intelRdt-l3CacheSchema") {
158158
159159 uid := uint32(os.Getuid())
160160 c.harness.Ok(uid == spec.Process.User.UID, "has expected user ID")
161 c.harness.YAML(map[string]uint32{
161 _ = c.harness.YAML(map[string]uint32{
162162 "expected": spec.Process.User.UID,
163163 "actual": uid,
164164 })
165165
166166 gid := uint32(os.Getgid())
167167 c.harness.Ok(gid == spec.Process.User.GID, "has expected group ID")
168 c.harness.YAML(map[string]uint32{
168 _ = c.harness.YAML(map[string]uint32{
169169 "expected": spec.Process.User.GID,
170170 "actual": gid,
171171 })
201201 return err
202202 }
203203 c.harness.Ok(cwd == spec.Process.Cwd, "has expected working directory")
204 c.harness.YAML(map[string]string{
204 _ = c.harness.YAML(map[string]string{
205205 "expected": spec.Process.Cwd,
206206 "actual": cwd,
207207 })
213213 expectedValue := parts[1]
214214 actualValue := os.Getenv(key)
215215 c.harness.Ok(expectedValue == actualValue, fmt.Sprintf("has expected environment variable %v", key))
216 c.harness.YAML(map[string]string{
216 _ = c.harness.YAML(map[string]string{
217217 "variable": key,
218218 "expected": expectedValue,
219219 "actual": actualValue,
236236
237237 args := bytes.Split(bytes.Trim(cmdlineBytes, "\x00"), []byte("\x00"))
238238 c.harness.Ok(len(args) == len(spec.Process.Args), "has expected number of process arguments")
239 c.harness.YAML(map[string]interface{}{
239 _ = c.harness.YAML(map[string]interface{}{
240240 "expected": spec.Process.Args,
241241 "actual": args,
242242 })
243243 for i, a := range args {
244244 c.harness.Ok(string(a) == spec.Process.Args[i], fmt.Sprintf("has expected process argument %d", i))
245 c.harness.YAML(map[string]interface{}{
245 _ = c.harness.YAML(map[string]interface{}{
246246 "index": i,
247247 "expected": spec.Process.Args[i],
248248 "actual": string(a),
271271 last = capability.CAP_BLOCK_SUSPEND
272272 }
273273
274 processCaps, err := capability.NewPid(0)
275 if err != nil {
274 processCaps, err := capability.NewPid2(0)
275 if err != nil {
276 return err
277 }
278 if err := processCaps.Load(); err != nil {
276279 return err
277280 }
278281
336339 return err
337340 }
338341 c.harness.Ok(spec.Hostname == hostname, "has expected hostname")
339 c.harness.YAML(map[string]string{
342 _ = c.harness.YAML(map[string]string{
340343 "expected": spec.Hostname,
341344 "actual": hostname,
342345 })
364367 if err != nil {
365368 return err
366369 }
367 c.harness.YAML(map[string]interface{}{
370 _ = c.harness.YAML(map[string]interface{}{
368371 "level": rfcError.Level.String(),
369372 "reference": rfcError.Reference,
370373 "type": r.Type,
376379 if err != nil {
377380 return err
378381 }
379 c.harness.YAML(map[string]interface{}{
382 _ = c.harness.YAML(map[string]interface{}{
380383 "level": rfcError.Level.String(),
381384 "reference": rfcError.Reference,
382385 "type": r.Type,
401404 }
402405 value := strings.TrimSpace(string(bytes.Trim(vBytes, "\x00")))
403406 c.harness.Ok(value == v, fmt.Sprintf("has expected sysctl %v", k))
404 c.harness.YAML(map[string]string{
407 _ = c.harness.YAML(map[string]string{
405408 "sysctl": k,
406409 "expected": v,
407410 "actual": value,
521524 if err != nil {
522525 return err
523526 }
524 c.harness.YAML(map[string]string{
527 _ = c.harness.YAML(map[string]string{
525528 "level": rfcError.Level.String(),
526529 "reference": rfcError.Reference,
527530 })
544547 }
545548 defer os.RemoveAll(targetDir)
546549
550 mountErr := unix.Mount("/", targetDir, "", unix.MS_BIND|unix.MS_REC, "")
551 if mountErr == unix.EPERM { //nolint:errcheck // unix errors are bare
552 // This test needs CAP_SYS_ADMIN to perform mounts.
553 // EPERM most probably means it was not granted.
554 c.harness.Skip(1, "unable to perform mount (test requires CAP_SYS_ADMIN)")
555 return nil
556 }
557 if err == nil {
558 defer unix.Unmount(targetDir, unix.MNT_DETACH) //nolint:errcheck
559 }
560
547561 switch spec.Linux.RootfsPropagation {
548562 case "shared", "slave", "private":
563 if mountErr != nil {
564 return fmt.Errorf("bind-mount / %s: %w", targetDir, err)
565 }
549566 mountDir, err := ioutil.TempDir("/", "mount")
550567 if err != nil {
551568 return err
564581 }
565582 defer os.Remove(tmpfile.Name())
566583
567 if err := unix.Mount("/", targetDir, "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
568 return err
569 }
570 defer unix.Unmount(targetDir, unix.MNT_DETACH)
571584 if err := unix.Mount(testDir, mountDir, "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
572 return err
573 }
574 defer unix.Unmount(mountDir, unix.MNT_DETACH)
585 return fmt.Errorf("bind-mount %s %s: %w", testDir, mountDir, err)
586 }
587 defer unix.Unmount(mountDir, unix.MNT_DETACH) //nolint:errcheck
575588 targetFile := filepath.Join(targetDir, filepath.Join(mountDir, filepath.Base(tmpfile.Name())))
576589 var exposed bool
577590 _, err = os.Stat(targetFile)
591604 )
592605 }
593606 case "unbindable":
594 err = unix.Mount("/", targetDir, "", unix.MS_BIND|unix.MS_REC, "")
595 if err == syscall.EINVAL {
607 if mountErr == syscall.EINVAL {
596608 c.harness.Pass("root propagation is unbindable")
597609 return nil
598 } else if err != nil {
599 return err
600 }
601 defer unix.Unmount(targetDir, unix.MNT_DETACH)
610 } else if mountErr != nil {
611 return fmt.Errorf("bind-mount / %s: %w", targetDir, err)
612 }
602613 c.harness.Fail("root propagation is unbindable")
603614 return nil
604615 default:
624635 if err != nil {
625636 return err
626637 }
627 c.harness.YAML(map[string]string{
638 _ = c.harness.YAML(map[string]string{
628639 "level": rfcError.Level.String(),
629640 "reference": rfcError.Reference,
630641 "mount": fs,
670681 if err != nil {
671682 return err
672683 }
673 c.harness.YAML(map[string]string{
684 _ = c.harness.YAML(map[string]string{
674685 "level": rfcError.Level.String(),
675686 "reference": rfcError.Reference,
676687 "path": device.Path,
702713 if err != nil {
703714 return err
704715 }
705 c.harness.YAML(map[string]string{
716 _ = c.harness.YAML(map[string]string{
706717 "level": rfcError.Level.String(),
707718 "reference": rfcError.Reference,
708719 "path": device.Path,
721732 if err != nil {
722733 return err
723734 }
724 c.harness.YAML(map[string]interface{}{
735 _ = c.harness.YAML(map[string]interface{}{
725736 "level": rfcError.Level.String(),
726737 "reference": rfcError.Reference,
727738 "path": device.Path,
732743 if err != nil {
733744 return err
734745 }
735 c.harness.YAML(map[string]interface{}{
746 _ = c.harness.YAML(map[string]interface{}{
736747 "level": rfcError.Level.String(),
737748 "reference": rfcError.Reference,
738749 "path": device.Path,
750761 if err != nil {
751762 return err
752763 }
753 c.harness.YAML(map[string]interface{}{
764 _ = c.harness.YAML(map[string]interface{}{
754765 "level": rfcError.Level.String(),
755766 "reference": rfcError.Reference,
756767 "path": device.Path,
771782 if err != nil {
772783 return err
773784 }
774 c.harness.YAML(map[string]interface{}{
785 _ = c.harness.YAML(map[string]interface{}{
775786 "level": rfcError.Level.String(),
776787 "reference": rfcError.Reference,
777788 "path": device.Path,
787798 if err != nil {
788799 return err
789800 }
790 c.harness.YAML(map[string]interface{}{
801 _ = c.harness.YAML(map[string]interface{}{
791802 "level": rfcError.Level.String(),
792803 "reference": rfcError.Reference,
793804 "path": device.Path,
814825 if err != nil {
815826 return err
816827 }
817 c.harness.YAML(map[string]string{
828 _ = c.harness.YAML(map[string]string{
818829 "level": rfcError.Level.String(),
819830 "reference": rfcError.Reference,
820831 "path": symlink,
832843 if err != nil {
833844 return err
834845 }
835 c.harness.YAML(map[string]interface{}{
846 _ = c.harness.YAML(map[string]interface{}{
836847 "level": rfcError.Level.String(),
837848 "reference": rfcError.Reference,
838849 "path": symlink,
854865 if err != nil {
855866 return err
856867 }
857 c.harness.YAML(map[string]string{
868 _ = c.harness.YAML(map[string]string{
858869 "level": rfcError.Level.String(),
859870 "reference": rfcError.Reference,
860871 "path": symlink,
981992 if err != nil {
982993 return err
983994 }
984 rfcError, err := c.Ok(actual == expected, specerror.LinuxProcOomScoreAdjSet, spec.Version, fmt.Sprintf("has expected OOM score adjustment"))
985 if err != nil {
986 return err
987 }
988 c.harness.YAML(map[string]interface{}{
995 rfcError, err := c.Ok(actual == expected, specerror.LinuxProcOomScoreAdjSet, spec.Version, "has expected OOM score adjustment")
996 if err != nil {
997 return err
998 }
999 _ = c.harness.YAML(map[string]interface{}{
9891000 "level": rfcError.Level.String(),
9901001 "reference": rfcError.Reference,
9911002 "expected": expected,
10461057 return err
10471058 }
10481059 c.harness.Ok(len(idMaps) == len(mappings), fmt.Sprintf("%s has expected number of mappings", path))
1049 c.harness.YAML(map[string]interface{}{
1060 _ = c.harness.YAML(map[string]interface{}{
10501061 "expected": mappings,
10511062 "actual": idMaps,
10521063 })
11781189 rfcError, err = c.Ok(false, specerror.MountsInOrder, spec.Version, fmt.Sprintf("mounts[%d] (%s) found", i, configMount.Destination))
11791190 } else {
11801191 rfcError, err = c.Ok(foundInOrder, specerror.MountsInOrder, spec.Version, fmt.Sprintf("mounts[%d] (%s) found in order", i, configMount.Destination))
1181 c.harness.YAML(map[string]interface{}{
1182 "level": rfcError.Level.String(),
1183 "reference": rfcError.Reference,
1184 "config": configMount,
1185 "indexConfig": i,
1186 "indexSystem": configSys[i],
1187 "earlier": map[string]interface{}{
1188 "config": spec.Mounts[highestMatchedConfig],
1189 "indexConfig": highestMatchedConfig,
1190 "indexSystem": configSys[highestMatchedConfig],
1191 },
1192 })
1193 }
1192 }
1193 _ = c.harness.YAML(map[string]interface{}{
1194 "level": rfcError.Level.String(),
1195 "reference": rfcError.Reference,
1196 "config": configMount,
1197 "indexConfig": i,
1198 "indexSystem": configSys[i],
1199 "earlier": map[string]interface{}{
1200 "config": spec.Mounts[highestMatchedConfig],
1201 "indexConfig": highestMatchedConfig,
1202 "indexSystem": configSys[highestMatchedConfig],
1203 },
1204 })
11941205 }
11951206
11961207 return mountErrs
12301241 return fmt.Errorf("Failed to get mountLabel of %v", mount.Destination)
12311242 }
12321243 c.harness.Ok(spec.Linux.MountLabel == fileLabel, "has expected mountlabel")
1233 c.harness.YAML(map[string]string{
1244 _ = c.harness.YAML(map[string]string{
12341245 "expected": spec.Linux.MountLabel,
12351246 "actual": fileLabel,
12361247 })
0 //go:build linux
01 // +build linux
12
23 package mount
0 //go:build solaris && cgo
01 // +build solaris,cgo
12
23 package mount
0 //go:build (!windows && !linux && !freebsd && !solaris) || (freebsd && !cgo) || (solaris && !cgo)
01 // +build !windows,!linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo
12
23 package mount
334334 --linux-gidmappings
335335 --linux-hugepage-limits-add
336336 --linux-hugepage-limits-drop
337 --linux-intelRdt-closid
337338 --linux-intelRdt-l3CacheSchema
338339 --linux-masked-paths
339340 --linux-mem-kernel-limit
122122 }
123123 }
124124
125 func (g *Generator) initConfigLinuxResourcesUnified() {
126 g.initConfigLinuxResources()
127 if g.Config.Linux.Resources.Unified == nil {
128 g.Config.Linux.Resources.Unified = map[string]string{}
129 }
130 }
131
125132 func (g *Generator) initConfigSolaris() {
126133 g.initConfig()
127134 if g.Config.Solaris == nil {
184191 g.Config.VM = &rspec.VM{}
185192 }
186193 }
187
188 func (g *Generator) initConfigVMHypervisor() {
189 g.initConfigVM()
190 if &g.Config.VM.Hypervisor == nil {
191 g.Config.VM.Hypervisor = rspec.VMHypervisor{}
192 }
193 }
194
195 func (g *Generator) initConfigVMKernel() {
196 g.initConfigVM()
197 if &g.Config.VM.Kernel == nil {
198 g.Config.VM.Kernel = rspec.VMKernel{}
199 }
200 }
201
202 func (g *Generator) initConfigVMImage() {
203 g.initConfigVM()
204 if &g.Config.VM.Image == nil {
205 g.Config.VM.Image = rspec.VMImage{}
206 }
207 }
2828 type Generator struct {
2929 Config *rspec.Spec
3030 HostSpecific bool
31 // This is used to keep a cache of the ENVs added to improve
32 // performance when adding a huge number of ENV variables
33 envMap map[string]int
3134 }
3235
3336 // ExportOptions have toggles for exporting only certain parts of the specification
178181 Destination: "/dev",
179182 Type: "tmpfs",
180183 Source: "tmpfs",
181 Options: []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
184 Options: []string{"nosuid", "noexec", "strictatime", "mode=755", "size=65536k"},
182185 },
183186 {
184187 Destination: "/dev/pts",
235238 }
236239 }
237240
238 return Generator{Config: &config}, nil
241 envCache := map[string]int{}
242 if config.Process != nil {
243 envCache = createEnvCacheMap(config.Process.Env)
244 }
245
246 return Generator{Config: &config, envMap: envCache}, nil
239247 }
240248
241249 // NewFromSpec creates a configuration Generator from a given
245253 //
246254 // generator := Generator{Config: config}
247255 func NewFromSpec(config *rspec.Spec) Generator {
256 envCache := map[string]int{}
257 if config != nil && config.Process != nil {
258 envCache = createEnvCacheMap(config.Process.Env)
259 }
260
248261 return Generator{
249262 Config: config,
263 envMap: envCache,
250264 }
251265 }
252266
272286 if err := json.NewDecoder(r).Decode(&config); err != nil {
273287 return Generator{}, err
274288 }
289
290 envCache := map[string]int{}
291 if config.Process != nil {
292 envCache = createEnvCacheMap(config.Process.Env)
293 }
294
275295 return Generator{
276296 Config: &config,
297 envMap: envCache,
277298 }, nil
299 }
300
301 // createEnvCacheMap creates a hash map with the ENV variables given by the config
302 func createEnvCacheMap(env []string) map[string]int {
303 envMap := make(map[string]int, len(env))
304 for i, val := range env {
305 envMap[val] = i
306 }
307 return envMap
278308 }
279309
280310 // SetSpec sets the configuration in the Generator g.
413443 g.Config.Process.User.Username = username
414444 }
415445
446 // SetProcessUmask sets g.Config.Process.User.Umask.
447 func (g *Generator) SetProcessUmask(umask uint32) {
448 g.initConfigProcess()
449 u := umask
450 g.Config.Process.User.Umask = &u
451 }
452
416453 // SetProcessGID sets g.Config.Process.User.GID.
417454 func (g *Generator) SetProcessGID(gid uint32) {
418455 g.initConfigProcess()
455492 return
456493 }
457494 g.Config.Process.Env = []string{}
495 // Clear out the env cache map as well
496 g.envMap = map[string]int{}
458497 }
459498
460499 // AddProcessEnv adds name=value into g.Config.Process.Env, or replaces an
461500 // existing entry with the given name.
462501 func (g *Generator) AddProcessEnv(name, value string) {
502 if name == "" {
503 return
504 }
505
463506 g.initConfigProcess()
464
465 env := fmt.Sprintf("%s=%s", name, value)
466 for idx := range g.Config.Process.Env {
467 if strings.HasPrefix(g.Config.Process.Env[idx], name+"=") {
468 g.Config.Process.Env[idx] = env
469 return
470 }
471 }
472 g.Config.Process.Env = append(g.Config.Process.Env, env)
507 g.addEnv(fmt.Sprintf("%s=%s", name, value), name)
508 }
509
510 // AddMultipleProcessEnv adds multiple name=value into g.Config.Process.Env, or replaces
511 // existing entries with the given name.
512 func (g *Generator) AddMultipleProcessEnv(envs []string) {
513 g.initConfigProcess()
514
515 for _, val := range envs {
516 split := strings.SplitN(val, "=", 2)
517 g.addEnv(val, split[0])
518 }
519 }
520
521 // addEnv looks through adds ENV to the Process and checks envMap for
522 // any duplicates
523 // This is called by both AddMultipleProcessEnv and AddProcessEnv
524 func (g *Generator) addEnv(env, key string) {
525 if idx, ok := g.envMap[key]; ok {
526 // The ENV exists in the cache, so change its value in g.Config.Process.Env
527 g.Config.Process.Env[idx] = env
528 } else {
529 // else the env doesn't exist, so add it and add it's index to g.envMap
530 g.Config.Process.Env = append(g.Config.Process.Env, env)
531 g.envMap[key] = len(g.Config.Process.Env) - 1
532 }
473533 }
474534
475535 // AddProcessRlimits adds rlimit into g.Config.Process.Rlimits.
541601 func (g *Generator) SetLinuxCgroupsPath(path string) {
542602 g.initConfigLinux()
543603 g.Config.Linux.CgroupsPath = path
604 }
605
606 // SetLinuxIntelRdtClosID sets g.Config.Linux.IntelRdt.ClosID
607 func (g *Generator) SetLinuxIntelRdtClosID(clos string) {
608 g.initConfigLinuxIntelRdt()
609 g.Config.Linux.IntelRdt.ClosID = clos
544610 }
545611
546612 // SetLinuxIntelRdtL3CacheSchema sets g.Config.Linux.IntelRdt.L3CacheSchema
788854 return
789855 }
790856 }
857 }
858
859 // AddLinuxResourcesUnified sets the g.Config.Linux.Resources.Unified
860 func (g *Generator) SetLinuxResourcesUnified(unified map[string]string) {
861 g.initConfigLinuxResourcesUnified()
862 for k, v := range unified {
863 g.Config.Linux.Resources.Unified[k] = v
864 }
865 }
866
867 // AddLinuxResourcesUnified adds or updates the key-value pair from g.Config.Linux.Resources.Unified
868 func (g *Generator) AddLinuxResourcesUnified(key, val string) {
869 g.initConfigLinuxResourcesUnified()
870 g.Config.Linux.Resources.Unified[key] = val
871 }
872
873 // DropLinuxResourcesUnified drops a key-value pair from g.Config.Linux.Resources.Unified
874 func (g *Generator) DropLinuxResourcesUnified(key string) {
875 if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.Unified == nil {
876 return
877 }
878 delete(g.Config.Linux.Resources.Unified, key)
791879 }
792880
793881 // SetLinuxResourcesMemoryLimit sets g.Config.Linux.Resources.Memory.Limit.
9641052 }
9651053
9661054 // AddPreStartHook add a prestart hook into g.Config.Hooks.Prestart.
967 func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) error {
1055 func (g *Generator) AddPreStartHook(preStartHook rspec.Hook) {
9681056 g.initConfigHooks()
9691057 g.Config.Hooks.Prestart = append(g.Config.Hooks.Prestart, preStartHook)
970 return nil
9711058 }
9721059
9731060 // ClearPostStopHooks clear g.Config.Hooks.Poststop.
9791066 }
9801067
9811068 // AddPostStopHook adds a poststop hook into g.Config.Hooks.Poststop.
982 func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) error {
1069 func (g *Generator) AddPostStopHook(postStopHook rspec.Hook) {
9831070 g.initConfigHooks()
9841071 g.Config.Hooks.Poststop = append(g.Config.Hooks.Poststop, postStopHook)
985 return nil
9861072 }
9871073
9881074 // ClearPostStartHooks clear g.Config.Hooks.Poststart.
9941080 }
9951081
9961082 // AddPostStartHook adds a poststart hook into g.Config.Hooks.Poststart.
997 func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) error {
1083 func (g *Generator) AddPostStartHook(postStartHook rspec.Hook) {
9981084 g.initConfigHooks()
9991085 g.Config.Hooks.Poststart = append(g.Config.Hooks.Poststart, postStartHook)
1000 return nil
10011086 }
10021087
10031088 // AddMount adds a mount into g.Config.Mounts.
14411526 g.Config.Linux.Devices[i] = device
14421527 return
14431528 }
1444 if dev.Type == device.Type && dev.Major == device.Major && dev.Minor == device.Minor {
1445 fmt.Fprintln(os.Stderr, "WARNING: The same type, major and minor should not be used for multiple devices.")
1446 }
14471529 }
14481530
14491531 g.Config.Linux.Devices = append(g.Config.Linux.Devices, device)
15021584 return
15031585 }
15041586 }
1505 return
1506 }
1507
1508 // strPtr returns the pointer pointing to the string s.
1509 func strPtr(s string) *string { return &s }
1587 }
15101588
15111589 // SetSyscallAction adds rules for syscalls with the specified action
15121590 func (g *Generator) SetSyscallAction(arguments seccomp.SyscallOpts) error {
16331711 if !strings.HasPrefix(path, "/") {
16341712 return fmt.Errorf("hypervisorPath %v is not an absolute path", path)
16351713 }
1636 g.initConfigVMHypervisor()
1714 g.initConfigVM()
16371715 g.Config.VM.Hypervisor.Path = path
16381716 return nil
16391717 }
16401718
16411719 // SetVMHypervisorParameters sets g.Config.VM.Hypervisor.Parameters
16421720 func (g *Generator) SetVMHypervisorParameters(parameters []string) {
1643 g.initConfigVMHypervisor()
1721 g.initConfigVM()
16441722 g.Config.VM.Hypervisor.Parameters = parameters
16451723 }
16461724
16491727 if !strings.HasPrefix(path, "/") {
16501728 return fmt.Errorf("kernelPath %v is not an absolute path", path)
16511729 }
1652 g.initConfigVMKernel()
1730 g.initConfigVM()
16531731 g.Config.VM.Kernel.Path = path
16541732 return nil
16551733 }
16561734
16571735 // SetVMKernelParameters sets g.Config.VM.Kernel.Parameters
16581736 func (g *Generator) SetVMKernelParameters(parameters []string) {
1659 g.initConfigVMKernel()
1737 g.initConfigVM()
16601738 g.Config.VM.Kernel.Parameters = parameters
16611739 }
16621740
16651743 if !strings.HasPrefix(initrd, "/") {
16661744 return fmt.Errorf("kernelInitrd %v is not an absolute path", initrd)
16671745 }
1668 g.initConfigVMKernel()
1746 g.initConfigVM()
16691747 g.Config.VM.Kernel.InitRD = initrd
16701748 return nil
16711749 }
16751753 if !strings.HasPrefix(path, "/") {
16761754 return fmt.Errorf("imagePath %v is not an absolute path", path)
16771755 }
1678 g.initConfigVMImage()
1756 g.initConfigVM()
16791757 g.Config.VM.Image.Path = path
16801758 return nil
16811759 }
16911769 default:
16921770 return fmt.Errorf("Commonly supported formats are: raw, qcow2, vdi, vmdk, vhd")
16931771 }
1694 g.initConfigVMImage()
1772 g.initConfigVM()
16951773 g.Config.VM.Image.Format = format
16961774 return nil
16971775 }
1010 "github.com/opencontainers/runtime-tools/generate"
1111 "github.com/opencontainers/runtime-tools/specerror"
1212 "github.com/opencontainers/runtime-tools/validate"
13 "github.com/stretchr/testify/assert"
1314 )
1415
1516 // Smoke test to ensure that _at the very least_ our default configuration
9293 t.Errorf("Unable to remove /dev/shm from mounts")
9394 }
9495 }
96
97 func TestEnvCaching(t *testing.T) {
98 // Start with empty ENV and add a few
99 g, err := generate.New("windows")
100 if err != nil {
101 t.Fatal(err)
102 }
103 expected := []string{"k1=v1", "k2=v2"}
104 g.AddProcessEnv("k1", "v1")
105 g.AddProcessEnv("k2", "v2")
106 assert.Equal(t, expected, g.Config.Process.Env)
107
108 // Test override and existing ENV
109 g, err = generate.New("linux")
110 if err != nil {
111 t.Fatal(err)
112 }
113 expected = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "TERM=xterm", "k1=v1", "k2=v4", "k3=v3"}
114 g.AddProcessEnv("k1", "v1")
115 g.AddProcessEnv("k2", "v2")
116 g.AddProcessEnv("k3", "v3")
117 g.AddProcessEnv("k2", "v4")
118 assert.Equal(t, expected, g.Config.Process.Env)
119
120 // Test empty ENV
121 g, err = generate.New("windows")
122 if err != nil {
123 t.Fatal(err)
124 }
125 g.AddProcessEnv("", "")
126 assert.Equal(t, []string(nil), g.Config.Process.Env)
127 }
128
129 func TestMultipleEnvCaching(t *testing.T) {
130 // Start with empty ENV and add a few
131 g, err := generate.New("windows")
132 if err != nil {
133 t.Fatal(err)
134 }
135 newEnvs := []string{"k1=v1", "k2=v2"}
136 expected := []string{"k1=v1", "k2=v2"}
137 g.AddMultipleProcessEnv(newEnvs)
138 assert.Equal(t, expected, g.Config.Process.Env)
139
140 // Test override and existing ENV
141 g, err = generate.New("linux")
142 if err != nil {
143 t.Fatal(err)
144 }
145 newEnvs = []string{"k1=v1", "k2=v2", "k3=v3", "k2=v4"}
146 expected = []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "TERM=xterm", "k1=v1", "k2=v4", "k3=v3"}
147 g.AddMultipleProcessEnv(newEnvs)
148 assert.Equal(t, expected, g.Config.Process.Env)
149
150 // Test empty ENV
151 g, err = generate.New("windows")
152 if err != nil {
153 t.Fatal(err)
154 }
155 g.AddMultipleProcessEnv([]string{})
156 assert.Equal(t, []string(nil), g.Config.Process.Env)
157 }
33 seccompOverwrite = "overwrite"
44 seccompAppend = "append"
55 nothing = "nothing"
6 kill = "kill"
7 trap = "trap"
8 trace = "trace"
9 allow = "allow"
10 errno = "errno"
116 )
302302 "stat64",
303303 "statfs",
304304 "statfs64",
305 "statx",
305306 "symlink",
306307 "symlinkat",
307308 "sync",
565566 },
566567 }...)
567568 /* Flags parameter of the clone syscall is the 2nd on s390 */
569 syscalls = append(syscalls, []rspec.LinuxSyscall{
570 {
571 Names: []string{"clone"},
572 Action: rspec.ActAllow,
573 Args: []rspec.LinuxSeccompArg{
574 {
575 Index: 1,
576 Value: 2080505856,
577 ValueTwo: 0,
578 Op: rspec.OpMaskedEqual,
579 },
580 },
581 },
582 }...)
568583 }
569584
570585 return &rspec.LinuxSeccomp{
0 //go:build linux
01 // +build linux
12
23 package seccomp
0 //go:build !linux
01 // +build !linux
12
23 package seccomp
9191 return reflect.DeepEqual(config1, config2)
9292 }
9393
94 func identicalExceptAction(config1, config2 *rspec.LinuxSyscall) bool {
95 samename := sameName(config1, config2)
96 sameAction := sameAction(config1, config2)
97 sameArgs := sameArgs(config1, config2)
98
99 return samename && !sameAction && sameArgs
100 }
101
102 func identicalExceptArgs(config1, config2 *rspec.LinuxSyscall) bool {
103 samename := sameName(config1, config2)
104 sameAction := sameAction(config1, config2)
105 sameArgs := sameArgs(config1, config2)
106
107 return samename && sameAction && !sameArgs
108 }
109
11094 func sameName(config1, config2 *rspec.LinuxSyscall) bool {
11195 return reflect.DeepEqual(config1.Names, config2.Names)
11296 }
0 module github.com/opencontainers/runtime-tools
1
2 go 1.16
3
4 require (
5 github.com/blang/semver v3.5.0+incompatible
6 github.com/google/uuid v1.3.0
7 github.com/hashicorp/go-multierror v1.1.1
8 github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b
9 github.com/mrunalp/fileutils v0.5.0
10 github.com/opencontainers/runtime-spec v1.0.3-0.20201121164853-7413a7f753e1
11 github.com/opencontainers/selinux v1.9.1
12 github.com/sirupsen/logrus v1.8.1
13 github.com/stretchr/testify v1.3.0
14 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635
15 github.com/urfave/cli v1.19.1
16 github.com/xeipuuv/gojsonschema v1.2.0
17 golang.org/x/sys v0.0.0-20191115151921-52ab43148777
18 )
19
20 require gopkg.in/yaml.v2 v2.4.0 // indirect
0 github.com/blang/semver v3.5.0+incompatible h1:CGxCgetQ64DKk7rdZ++Vfnb1+ogGNnB17OJKJXD2Cfs=
1 github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
2 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5 github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
6 github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7 github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
8 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
9 github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
10 github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
11 github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b h1:Ga1nclDSe8gOw37MVLMhfu2QKWtD6gvtQ298zsKVh8g=
12 github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs=
13 github.com/mrunalp/fileutils v0.5.0 h1:NKzVxiH7eSk+OQ4M+ZYW1K6h27RUV3MI6NUTsHhU6Z4=
14 github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
15 github.com/opencontainers/runtime-spec v1.0.3-0.20201121164853-7413a7f753e1 h1:UAfI7SOCo1CNIu3RevW9B4HQyf7SY5aSzcSeoC7OPs0=
16 github.com/opencontainers/runtime-spec v1.0.3-0.20201121164853-7413a7f753e1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
17 github.com/opencontainers/selinux v1.9.1 h1:b4VPEF3O5JLZgdTDBmGepaaIbAo0GqoF6EBRq5f/g3Y=
18 github.com/opencontainers/selinux v1.9.1/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
19 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
20 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
21 github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
22 github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
23 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
24 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
25 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
26 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
27 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI=
28 github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
29 github.com/urfave/cli v1.19.1 h1:0mKm4ZoB74PxYmZVua162y1dGt1qc10MyymYRBf3lb8=
30 github.com/urfave/cli v1.19.1/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
31 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
32 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
33 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
34 github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
35 github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
36 github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
37 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
38 golang.org/x/sys v0.0.0-20191115151921-52ab43148777 h1:wejkGHRTr38uaKRqECZlsCsJ1/TGxIyFbH32x5zUdu4=
39 golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
40 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
41 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
42 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
43 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
192192 Drop hugepage rsource limits. Just need to specify PAGESIZE. e.g. --linux-hugepage-limits-drop=4MB
193193 This option can be specified multiple times.
194194
195 **--linux-intelRdt-closid**=""
196 RDT Class of Service, i.e. group under the resctrl pseudo-filesystem, which
197 to associate the container with.
198
195199 **--linux-intelRdt-l3CacheSchema**=""
196200 Specifies the schema for L3 cache id and capacity bitmask.
197201
Binary diff not shown
Binary diff not shown
130130 if err != nil {
131131 return "", specerror.NewError(specerror.SpecVersionInSemVer, err, rspec.Version)
132132 }
133 configRenamedToConfigSchemaVersion, err := semver.Parse("1.0.0-rc2") // config.json became config-schema.json in 1.0.0-rc2
134 if ver.Compare(configRenamedToConfigSchemaVersion) == -1 {
135 return "", fmt.Errorf("unsupported configuration version (older than %s)", configRenamedToConfigSchemaVersion)
133 if ver.LT(semver.Version{Major: 1, Minor: 0, Patch: 2}) {
134 return "", errors.New("unsupported configuration version (older than 1.0.2)")
136135 }
137136 return fmt.Sprintf(configSchemaTemplate, version), nil
138137 }
143142 func (v *Validator) CheckJSONSchema() (errs error) {
144143 logrus.Debugf("check JSON schema")
145144
146 url, err := JSONSchemaURL(v.spec.Version)
145 url, err := JSONSchemaURL(strings.TrimSuffix(v.spec.Version, "-dev"))
147146 if err != nil {
148147 errs = multierror.Append(errs, err)
149148 return errs
0 //go:build linux
01 // +build linux
12
23 package validate
4242 }{
4343 {
4444 config: &rspec.Spec{},
45 error: "1 error occurred:\n\t* Version string empty\nRefer to: https://github.com/opencontainers/runtime-spec/blob/v1.0.1/config.md#specification-version\n\n",
46 },
47 {
48 config: &rspec.Spec{
49 Version: "1.0.1-rc1",
45 error: fmt.Sprintf("1 error occurred:\n\t* Version string empty\nRefer to: https://github.com/opencontainers/runtime-spec/blob/v%s/config.md#specification-version\n\n", rspec.Version),
46 },
47 {
48 config: &rspec.Spec{
49 Version: "1.0.99-rc1", // non-existent
5050 },
5151 error: "Could not read schema from HTTP, response status is 404 Not Found",
5252 },
5353 {
5454 config: &rspec.Spec{
55 Version: "1.0.0",
56 },
57 error: "",
58 },
59 {
60 config: &rspec.Spec{
61 Version: "1.0.0",
62 Process: &rspec.Process{},
63 },
64 error: "process.args: Invalid type. Expected: array, given: null",
65 },
66 {
67 config: &rspec.Spec{
68 Version: "1.0.0",
55 Version: "1.0.0", // too old
56 },
57 error: "1 error occurred:\n\t* unsupported configuration version (older than 1.0.2)\n\n",
58 },
59 {
60 config: &rspec.Spec{
61 Version: "1.0.2",
62 },
63 error: "",
64 },
65 {
66 config: &rspec.Spec{
67 Version: "1.0.2",
6968 Linux: &rspec.Linux{},
7069 },
7170 error: "",
7271 },
7372 {
7473 config: &rspec.Spec{
75 Version: "1.0.0",
74 Version: "1.0.2",
7675 Linux: &rspec.Linux{
7776 RootfsPropagation: "",
7877 },
8180 },
8281 {
8382 config: &rspec.Spec{
84 Version: "1.0.0",
83 Version: "1.0.2",
8584 Linux: &rspec.Linux{
8685 RootfsPropagation: "shared",
8786 },
9089 },
9190 {
9291 config: &rspec.Spec{
93 Version: "1.0.0",
92 Version: "1.0.2",
9493 Linux: &rspec.Linux{
9594 RootfsPropagation: "rshared",
9695 },
9998 },
10099 {
101100 config: &rspec.Spec{
102 Version: "1.0.0-rc5",
103 },
104 error: "process: process is required",
105 },
106 {
107 config: &rspec.Spec{
108 Version: "1.0.0",
101 Version: "1.0.2",
109102 Linux: &rspec.Linux{
110103 Namespaces: []rspec.LinuxNamespace{
111104 {
118111 },
119112 {
120113 config: &rspec.Spec{
121 Version: "1.0.0",
114 Version: "1.0.2",
122115 Linux: &rspec.Linux{
123116 Namespaces: []rspec.LinuxNamespace{
124117 {
131124 },
132125 {
133126 config: &rspec.Spec{
134 Version: "1.0.0",
127 Version: "1.0.2",
135128 Linux: &rspec.Linux{
136129 Seccomp: &rspec.LinuxSeccomp{
137130 DefaultAction: "SCMP_ACT_ALLOW",
146139 },
147140 {
148141 config: &rspec.Spec{
149 Version: "1.0.0",
142 Version: "1.0.2",
150143 Linux: &rspec.Linux{
151144 Seccomp: &rspec.LinuxSeccomp{
152145 DefaultAction: "SCMP_ACT_ALLOW",
161154 },
162155 {
163156 config: &rspec.Spec{
164 Version: "1.0.0",
157 Version: "1.0.2",
165158 Linux: &rspec.Linux{
166159 Seccomp: &rspec.LinuxSeccomp{
167160 DefaultAction: "SCMP_ACT_ALLOW",
178171 },
179172 {
180173 config: &rspec.Spec{
181 Version: "1.0.0",
174 Version: "1.0.2",
182175 Linux: &rspec.Linux{
183176 Seccomp: &rspec.LinuxSeccomp{
184177 DefaultAction: "SCMP_ACT_ALLOW",
191184 },
192185 },
193186 },
194 error: "linux.seccomp.syscalls.0.action: linux.seccomp.syscalls.0.action must be one of the following: \"SCMP_ACT_KILL\", \"SCMP_ACT_TRAP\", \"SCMP_ACT_ERRNO\", \"SCMP_ACT_TRACE\", \"SCMP_ACT_ALLOW\"",
195 },
196 {
197 config: &rspec.Spec{
198 Version: "1.0.0",
187 error: "linux.seccomp.syscalls.0.action: linux.seccomp.syscalls.0.action must be one of the following: \"SCMP_ACT_KILL\", \"SCMP_ACT_TRAP\", \"SCMP_ACT_ERRNO\", \"SCMP_ACT_TRACE\", \"SCMP_ACT_ALLOW\", \"SCMP_ACT_LOG\"",
188 },
189 {
190 config: &rspec.Spec{
191 Version: "1.0.2",
199192 Linux: &rspec.Linux{
200193 Seccomp: &rspec.LinuxSeccomp{
201194 DefaultAction: "SCMP_ACT_ALLOW",
219212 },
220213 {
221214 config: &rspec.Spec{
222 Version: "1.0.0",
215 Version: "1.0.2",
223216 Linux: &rspec.Linux{
224217 Seccomp: &rspec.LinuxSeccomp{
225218 DefaultAction: "SCMP_ACT_ALLOW",
321314 expected specerror.Code
322315 }{
323316 {rspec.Version, specerror.NonError},
324 //FIXME: validate currently only handles rpsec.Version
317 // FIXME: validate currently only handles rpsec.Version
325318 {"0.0.1", specerror.NonRFCError},
326319 {"invalid", specerror.SpecVersionInSemVer},
327320 }
0 //go:build !linux
01 // +build !linux
12
23 package validate
55 "path/filepath"
66 "time"
77
8 "github.com/google/uuid"
89 tap "github.com/mndrix/tap-go"
910 "github.com/mrunalp/fileutils"
1011 rspec "github.com/opencontainers/runtime-spec/specs-go"
1112 "github.com/opencontainers/runtime-tools/generate"
1213 "github.com/opencontainers/runtime-tools/specerror"
1314 "github.com/opencontainers/runtime-tools/validation/util"
14 uuid "github.com/satori/go.uuid"
1515 )
1616
1717 func main() {
3030 }
3131
3232 testPath := filepath.Join(bundleDir, "test.json")
33 r.SetID(uuid.NewV4().String())
33 r.SetID(uuid.NewString())
3434 // generate a config has all the testing properties
3535 g, err := util.GetDefaultGenerator()
3636 if err != nil {
6464 util.Fatal(err)
6565 }
6666
67 spec := &rspec.Spec{
67 g.Config = &rspec.Spec{
6868 Version: "1.0.0",
6969 }
70 g.SetSpec(spec)
7170 err = r.SetConfig(g)
7271 if err != nil {
7372 util.Fatal(err)
44 "os/exec"
55 "runtime"
66
7 "github.com/google/uuid"
78 "github.com/mndrix/tap-go"
89 rspecs "github.com/opencontainers/runtime-spec/specs-go"
910 "github.com/opencontainers/runtime-tools/generate"
1011 "github.com/opencontainers/runtime-tools/specerror"
1112 "github.com/opencontainers/runtime-tools/validation/util"
12 "github.com/satori/go.uuid"
1313 )
1414
1515 func main() {
3232 if err != nil {
3333 util.Fatal(err)
3434 }
35 defer r.Clean(true, true)
35 defer r.Clean()
3636
3737 err = r.SetConfig(&g)
3838 if err != nil {
3939 util.Fatal(err)
4040 }
4141
42 containerID := uuid.NewV4().String()
42 containerID := uuid.NewString()
4343 cases := []struct {
4444 id string
4545 errExpected bool
6565 }
6666 }
6767 }
68 t.YAML(diagnostic)
68 _ = t.YAML(diagnostic)
6969
7070 if err == nil {
7171 state, err := r.State()
7272 t.Ok(err == nil && state.ID == c.id, "'state' MUST return the state of a container")
7373 if err == nil {
74 t.YAML(map[string]string{
74 _ = t.YAML(map[string]string{
7575 "container ID": c.id,
7676 "state ID": state.ID,
7777 })
8484 diagnostic["stderr"] = string(e.Stderr)
8585 }
8686 }
87 t.YAML(diagnostic)
87 _ = t.YAML(diagnostic)
8888 }
8989 }
9090 }
99 "github.com/opencontainers/runtime-tools/generate"
1010 "github.com/opencontainers/runtime-tools/specerror"
1111 "github.com/opencontainers/runtime-tools/validation/util"
12 uuid "github.com/satori/go.uuid"
12 "github.com/google/uuid"
1313 )
1414
1515 func main() {
3333 util.Fatal(err)
3434 }
3535 runningConfig.SetProcessArgs([]string{"sleep", "30"})
36 containerID := uuid.NewV4().String()
36 containerID := uuid.NewString()
3737 testRuntime, _ := util.NewRuntime(util.RuntimeCommand, bundleDir)
3838 cases := []struct {
3939 config *generate.Generator
1212 rspec "github.com/opencontainers/runtime-spec/specs-go"
1313 "github.com/opencontainers/runtime-tools/specerror"
1414 "github.com/opencontainers/runtime-tools/validation/util"
15 uuid "github.com/satori/go.uuid"
15 "github.com/google/uuid"
1616 )
1717
1818 func main() {
3636 util.Fatal(err)
3737 }
3838
39 r.SetID(uuid.NewV4().String())
39 r.SetID(uuid.NewString())
4040 g, err := util.GetDefaultGenerator()
4141 if err != nil {
4242 util.Fatal(err)
1111 "github.com/opencontainers/runtime-tools/cgroups"
1212 "github.com/opencontainers/runtime-tools/specerror"
1313 "github.com/opencontainers/runtime-tools/validation/util"
14 uuid "github.com/satori/go.uuid"
14 "github.com/google/uuid"
1515 )
1616
1717 func main() {
2929 util.Fatal(err)
3030 }
3131
32 r.SetID(uuid.NewV4().String())
32 r.SetID(uuid.NewString())
3333 g, err := util.GetDefaultGenerator()
3434 if err != nil {
3535 util.Fatal(err)
5858 if err != nil {
5959 util.Fatal(err)
6060 }
61 if err := util.ValidateLinuxResourcesPids(g.Spec(), t, &state); err != nil {
61 if err := util.ValidateLinuxResourcesPids(g.Config, t, &state); err != nil {
6262 util.Fatal(err)
6363 }
6464
1010 rspec "github.com/opencontainers/runtime-spec/specs-go"
1111 "github.com/opencontainers/runtime-tools/specerror"
1212 "github.com/opencontainers/runtime-tools/validation/util"
13 uuid "github.com/satori/go.uuid"
13 "github.com/google/uuid"
1414 )
1515
1616 func main() {
2121 config := util.LifecycleConfig{
2222 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
2323 PreCreate: func(r *util.Runtime) error {
24 r.SetID(uuid.NewV4().String())
24 r.SetID(uuid.NewString())
2525 g, err := util.GetDefaultGenerator()
2626 if err != nil {
2727 util.Fatal(err)
2828 }
29 output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output")
30 shPath := filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh")
31 err = g.AddPreStartHook(rspec.Hook{
29 output = filepath.Join(r.BundleDir, g.Config.Root.Path, "output")
30 shPath := filepath.Join(r.BundleDir, g.Config.Root.Path, "/bin/sh")
31 g.AddPreStartHook(rspec.Hook{
3232 Path: shPath,
3333 Args: []string{
3434 "sh", "-c", fmt.Sprintf("echo 'pre-start1 called' >> %s", output),
3535 },
3636 })
37 if err != nil {
38 return err
39 }
40 err = g.AddPreStartHook(rspec.Hook{
37 g.AddPreStartHook(rspec.Hook{
4138 Path: shPath,
4239 Args: []string{
4340 "sh", "-c", fmt.Sprintf("echo 'pre-start2 called' >> %s", output),
4441 },
4542 })
46 if err != nil {
47 return err
48 }
49 err = g.AddPostStartHook(rspec.Hook{
43 g.AddPostStartHook(rspec.Hook{
5044 Path: shPath,
5145 Args: []string{
5246 "sh", "-c", fmt.Sprintf("echo 'post-start1 called' >> %s", output),
5347 },
5448 })
55 if err != nil {
56 return err
57 }
58 err = g.AddPostStartHook(rspec.Hook{
49 g.AddPostStartHook(rspec.Hook{
5950 Path: shPath,
6051 Args: []string{
6152 "sh", "-c", fmt.Sprintf("echo 'post-start2 called' >> %s", output),
6253 },
6354 })
64 if err != nil {
65 return err
66 }
67 err = g.AddPostStopHook(rspec.Hook{
55 g.AddPostStopHook(rspec.Hook{
6856 Path: shPath,
6957 Args: []string{
7058 "sh", "-c", fmt.Sprintf("echo 'post-stop1 called' >> %s", output),
7159 },
7260 })
73 if err != nil {
74 return err
75 }
76 err = g.AddPostStopHook(rspec.Hook{
61 g.AddPostStopHook(rspec.Hook{
7762 Path: shPath,
7863 Args: []string{
7964 "sh", "-c", fmt.Sprintf("echo 'post-stop2 called' >> %s", output),
8065 },
8166 })
82 if err != nil {
83 return err
84 }
8567 g.SetProcessArgs([]string{"true"})
8668 return r.SetConfig(g)
8769 },
9880 diagnostic := map[string]string{
9981 "error": err.Error(),
10082 }
101 t.YAML(diagnostic)
83 _ = t.YAML(diagnostic)
10284 } else {
10385 diagnostic := map[string]string{
10486 "error": err.Error(),
10890 diagnostic["stderr"] = string(e.Stderr)
10991 }
11092 }
111 t.YAML(diagnostic)
93 _ = t.YAML(diagnostic)
11294 }
11395
11496 t.AutoPlan()
1414 rspecs "github.com/opencontainers/runtime-spec/specs-go"
1515 "github.com/opencontainers/runtime-tools/specerror"
1616 "github.com/opencontainers/runtime-tools/validation/util"
17 uuid "github.com/satori/go.uuid"
17 "github.com/google/uuid"
1818 )
1919
2020 func stdinStateCheck(outputDir, hookName string, expectedState rspecs.State) (errs *multierror.Error) {
8282 if err != nil {
8383 util.Fatal(err)
8484 }
85 containerID := uuid.NewV4().String()
85 containerID := uuid.NewString()
8686 defer os.RemoveAll(bundleDir)
8787
8888 var containerPid int
9393 if err != nil {
9494 util.Fatal(err)
9595 }
96 outputDir := filepath.Join(bundleDir, g.Spec().Root.Path)
96 outputDir := filepath.Join(bundleDir, g.Config.Root.Path)
9797 timeout := 1
9898 g.AddAnnotation(annotationKey, annotationValue)
9999 g.AddPreStartHook(rspecs.Hook{
100 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
100 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/sh"),
101101 Args: []string{
102102 "sh", "-c", fmt.Sprintf("cat > %s", filepath.Join(outputDir, "prestart")),
103103 },
104104 Timeout: &timeout,
105105 })
106106 g.AddPostStartHook(rspecs.Hook{
107 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
107 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/sh"),
108108 Args: []string{
109109 "sh", "-c", fmt.Sprintf("cat > %s", filepath.Join(outputDir, "poststart")),
110110 },
111111 Timeout: &timeout,
112112 })
113113 g.AddPostStopHook(rspecs.Hook{
114 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
114 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/sh"),
115115 Args: []string{
116116 "sh", "-c", fmt.Sprintf("cat > %s", filepath.Join(outputDir, "poststop")),
117117 },
126126 r.SetID(containerID)
127127 return nil
128128 },
129 PreDelete: func(r *util.Runtime) error {
129 PostCreate: func(r *util.Runtime) error {
130130 state, err := r.State()
131131 if err != nil {
132132 return err
133133 }
134134 containerPid = state.Pid
135 return nil
136 },
137 PreDelete: func(r *util.Runtime) error {
135138 util.WaitingForStatus(*r, util.LifecycleStatusStopped, time.Second*10, time.Second)
136139 return nil
137140 },
3030 defer t.AutoPlan()
3131
3232 if "linux" != runtime.GOOS {
33 t.Skip(1, fmt.Sprintf("linux-specific namespace test"))
33 t.Skip(1, "linux-specific namespace test")
3434 }
3535
3636 hostnames := []string{
99 "github.com/opencontainers/runtime-tools/generate"
1010 "github.com/opencontainers/runtime-tools/specerror"
1111 "github.com/opencontainers/runtime-tools/validation/util"
12 uuid "github.com/satori/go.uuid"
12 "github.com/google/uuid"
1313 )
1414
1515 func main() {
3131 util.Fatal(err)
3232 }
3333 runningConfig.SetProcessArgs([]string{"sleep", "30"})
34 containerID := uuid.NewV4().String()
34 containerID := uuid.NewString()
3535
3636 cases := []struct {
3737 config *generate.Generator
99 rspecs "github.com/opencontainers/runtime-spec/specs-go"
1010 "github.com/opencontainers/runtime-tools/specerror"
1111 "github.com/opencontainers/runtime-tools/validation/util"
12 uuid "github.com/satori/go.uuid"
12 "github.com/google/uuid"
1313 )
1414
1515 func main() {
2222 defer os.RemoveAll(bundleDir)
2323
2424 targetErr := specerror.NewError(specerror.KillNonCreateRunHaveNoEffect, fmt.Errorf("attempting to send a signal to a container that is neither `created` nor `running` MUST have no effect on the container"), rspecs.Version)
25 containerID := uuid.NewV4().String()
25 containerID := uuid.NewString()
2626 g, err := util.GetDefaultGenerator()
2727 if err != nil {
2828 util.Fatal(err)
99 rspecs "github.com/opencontainers/runtime-spec/specs-go"
1010 "github.com/opencontainers/runtime-tools/specerror"
1111 "github.com/opencontainers/runtime-tools/validation/util"
12 uuid "github.com/satori/go.uuid"
12 "github.com/google/uuid"
1313 )
1414
1515 var signals = []string{
2727 }
2828 defer os.RemoveAll(bundleDir)
2929
30 containerID := uuid.NewV4().String()
30 containerID := uuid.NewString()
3131 sigConfig, err := util.GetDefaultGenerator()
3232 if err != nil {
3333 os.RemoveAll(bundleDir)
3434 util.Fatal(err)
3535 }
36 rootDir := filepath.Join(bundleDir, sigConfig.Spec().Root.Path)
36 rootDir := filepath.Join(bundleDir, sigConfig.Config.Root.Path)
3737 for _, signal := range signals {
3838 sigConfig.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("trap 'touch /%s' %s; sleep 10 & wait $!", signal, signal)})
3939 config := util.LifecycleConfig{
1414 t.Header(0)
1515 defer t.AutoPlan()
1616
17 // limit =~ 100 * page size
18 // NOTE: on some systems, pagesize "1GB" doesn't seem to work.
19 // Ideally we should auto-detect the value.
20 cases := []struct {
21 page string
22 limit uint64
23 }{
24 {"2MB", 100 * 2 * 1024 * 1024},
25 {"1GB", 100 * 1024 * 1024 * 1024},
26 {"2MB", 100 * 2 * 1024 * 1024},
27 {"1GB", 100 * 1024 * 1024 * 1024},
17 pageSizes, err := cgroups.GetHugePageSize()
18
19 if err != nil {
20 t.Fail(fmt.Sprintf("error when getting hugepage sizes: %+v", err))
2821 }
2922
30 for _, c := range cases {
23 // When setting the limit just for checking if writing works, the amount of memory
24 // requested does not matter, as all insigned integers will be accepted.
25 // Use 2GiB as an example
26 var limit uint64 = 2 * (1 << 30)
27
28 for _, pageSize := range pageSizes {
3129 g, err := util.GetDefaultGenerator()
3230 if err != nil {
3331 return err
3432 }
3533 g.SetLinuxCgroupsPath(cgroups.AbsCgroupPath)
36 g.AddLinuxResourcesHugepageLimit(c.page, c.limit)
34 g.AddLinuxResourcesHugepageLimit(pageSize, limit)
3735 err = util.RuntimeOutsideValidate(g, t, func(config *rspec.Spec, t *tap.T, state *rspec.State) error {
3836 cg, err := cgroups.FindCgroup()
3937 if err != nil {
4442 return err
4543 }
4644 for _, lhl := range lhd {
47 if lhl.Pagesize != c.page {
45 if lhl.Pagesize != pageSize {
4846 continue
4947 }
50 t.Ok(lhl.Limit == c.limit, "hugepage limit is set correctly")
51 t.Diagnosticf("expect: %d, actual: %d", c.limit, lhl.Limit)
48 t.Ok(lhl.Limit == limit, fmt.Sprintf("hugepage limit is set correctly for size: %s", pageSize))
49 t.Diagnosticf("expect: %d, actual: %d", limit, lhl.Limit)
5250 }
5351 return nil
5452 })
6260
6361 func testWrongHugetlb() error {
6462 // We deliberately set the page size to a wrong value, "3MB", to see
65 // if the container really returns an error.
63 // if the container really returns an error. Page sizes will always be a
64 // on the format 2^(integer)
6665 page := "3MB"
6766 var limit uint64 = 100 * 3 * 1024 * 1024
6867
00 package main
11
22 import (
3 "fmt"
34 "github.com/mndrix/tap-go"
45 rspec "github.com/opencontainers/runtime-spec/specs-go"
56 "github.com/opencontainers/runtime-tools/cgroups"
78 )
89
910 func main() {
10 page := "1GB"
11 var limit uint64 = 56892210544640
12
1311 t := tap.New()
1412 t.Header(0)
1513 defer t.AutoPlan()
1614
17 g, err := util.GetDefaultGenerator()
18 if err != nil {
19 util.Fatal(err)
20 }
21 g.SetLinuxCgroupsPath(cgroups.RelCgroupPath)
22 g.AddLinuxResourcesHugepageLimit(page, limit)
23 err = util.RuntimeOutsideValidate(g, t, func(config *rspec.Spec, t *tap.T, state *rspec.State) error {
24 cg, err := cgroups.FindCgroup()
25 t.Ok((err == nil), "find hugetlb cgroup")
26 if err != nil {
27 t.Diagnostic(err.Error())
28 return nil
29 }
30
31 lhd, err := cg.GetHugepageLimitData(state.Pid, config.Linux.CgroupsPath)
32 t.Ok((err == nil), "get hugetlb cgroup data")
33 if err != nil {
34 t.Diagnostic(err.Error())
35 return nil
36 }
37
38 found := false
39 for _, lhl := range lhd {
40 if lhl.Pagesize == page {
41 found = true
42 t.Ok(lhl.Limit == limit, "hugepage limit is set correctly")
43 t.Diagnosticf("expect: %d, actual: %d", limit, lhl.Limit)
44 }
45 }
46 t.Ok(found, "hugepage limit found")
47
48 return nil
49 })
15 pageSizes, err := cgroups.GetHugePageSize()
5016
5117 if err != nil {
52 t.Fail(err.Error())
18 t.Fail(fmt.Sprintf("error when getting hugepage sizes: %+v", err))
19 }
20 // When setting the limit just for checking if writing works, the amount of memory
21 // requested does not matter, as all insigned integers will be accepted.
22 // Use 2GiB as an example
23 var limit uint64 = 2 * (1 << 30)
24
25 for _, pageSize := range pageSizes {
26 g, err := util.GetDefaultGenerator()
27 if err != nil {
28 util.Fatal(err)
29 }
30 g.SetLinuxCgroupsPath(cgroups.RelCgroupPath)
31 g.AddLinuxResourcesHugepageLimit(pageSize, limit)
32 err = util.RuntimeOutsideValidate(g, t, func(config *rspec.Spec, t *tap.T, state *rspec.State) error {
33 cg, err := cgroups.FindCgroup()
34 t.Ok((err == nil), "find hugetlb cgroup")
35 if err != nil {
36 t.Diagnostic(err.Error())
37 return nil
38 }
39
40 lhd, err := cg.GetHugepageLimitData(state.Pid, config.Linux.CgroupsPath)
41 t.Ok((err == nil), "get hugetlb cgroup data")
42 if err != nil {
43 t.Diagnostic(err.Error())
44 return nil
45 }
46
47 found := false
48 for _, lhl := range lhd {
49 if lhl.Pagesize == pageSize {
50 found = true
51 t.Ok(lhl.Limit == limit, fmt.Sprintf("hugepage limit is set correctly for size: %s", pageSize))
52 t.Diagnosticf("expect: %d, actual: %d", limit, lhl.Limit)
53 }
54 }
55 t.Ok(found, "hugepage limit found")
56
57 return nil
58 })
59
60 if err != nil {
61 t.Fail(err.Error())
62 }
5363 }
5464 }
2121 "level": specErr.(*specerror.Error).Err.Level.String(),
2222 "reference": specErr.(*specerror.Error).Err.Reference,
2323 }
24 t.YAML(diagnostic)
24 _ = t.YAML(diagnostic)
2525 }
2626
2727 func testNamespaceInheritType(t *tap.T) error {
118118 t.Header(0)
119119
120120 if "linux" != runtime.GOOS {
121 t.Skip(1, fmt.Sprintf("linux-specific namespace test"))
121 t.Skip(1, "linux-specific namespace test")
122122 }
123123
124124 err := testNamespaceInheritType(t)
2121 "level": specErr.(*specerror.Error).Err.Level.String(),
2222 "reference": specErr.(*specerror.Error).Err.Reference,
2323 }
24 t.YAML(diagnostic)
24 _ = t.YAML(diagnostic)
2525 }
2626
2727 func testNamespaceNoPath(t *tap.T) error {
119119 t.Header(0)
120120
121121 if "linux" != runtime.GOOS {
122 t.Skip(1, fmt.Sprintf("linux-specific namespace test"))
122 t.Skip(1, "linux-specific namespace test")
123123 }
124124
125125 err := testNamespaceNoPath(t)
165165 "level": rfcError.Level.String(),
166166 "reference": rfcError.Reference,
167167 }
168 t.YAML(diagnostic)
168 _ = t.YAML(diagnostic)
169169 }
170170 }
171171
4141 "level": rfcError.Level.String(),
4242 "reference": rfcError.Reference,
4343 }
44 t.YAML(diagnostic)
44 _ = t.YAML(diagnostic)
4545
4646 return fmt.Errorf("cannot validate path with wrong type")
4747 }
99 if err != nil {
1010 util.Fatal(err)
1111 }
12 g.SetupPrivileged(true)
12 // Test case validateRootfsPropagation needs CAP_SYS_ADMIN to perform mounts.
13 g.AddProcessCapability("CAP_SYS_ADMIN")
14 // The generated seccomp profile does not enable mount/umount/umount2 syscalls.
15 g.Config.Linux.Seccomp = nil
16
1317 g.SetLinuxRootPropagation(propMode)
14 g.AddAnnotation("TestName", "check root propagation")
18 g.AddAnnotation("TestName", "check root propagation: "+propMode)
1519 return util.RuntimeInsideValidate(g, t, nil)
1620 }
1721
1111 rspecs "github.com/opencontainers/runtime-spec/specs-go"
1212 "github.com/opencontainers/runtime-tools/specerror"
1313 "github.com/opencontainers/runtime-tools/validation/util"
14 uuid "github.com/satori/go.uuid"
14 "github.com/google/uuid"
1515 )
1616
1717 func saveConfig(path string, v interface{}) error {
3838 Unknown string `json:"unknown,omitempty"`
3939 }
4040
41 containerID := uuid.NewV4().String()
41 containerID := uuid.NewString()
4242 basicConfig, err := util.GetDefaultGenerator()
4343 if err != nil {
4444 util.Fatal(err)
6161 errExpected bool
6262 err error
6363 }{
64 {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)},
65 {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)},
66 {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)},
64 {extendedSpec{Spec: *annotationConfig.Config}, 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)},
65 {extendedSpec{Spec: *basicConfig.Config, 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)},
66 {extendedSpec{Spec: *invalidConfig.Config}, 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)},
6767 }
6868
6969 for _, c := range cases {
1010
1111 tap "github.com/mndrix/tap-go"
1212 "github.com/opencontainers/runtime-tools/validation/util"
13 uuid "github.com/satori/go.uuid"
13 "github.com/google/uuid"
1414 )
1515
1616 func main() {
3333 Config: g,
3434 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
3535 PreCreate: func(r *util.Runtime) error {
36 r.SetID(uuid.NewV4().String())
36 r.SetID(uuid.NewString())
3737 r.PidFile = tempPidFile
3838 return nil
3939 },
7575 diagnostic["stderr"] = string(e.Stderr)
7676 }
7777 }
78 t.YAML(diagnostic)
78 _ = t.YAML(diagnostic)
7979 }
8080
8181 t.AutoPlan()
1212 rspec "github.com/opencontainers/runtime-spec/specs-go"
1313 "github.com/opencontainers/runtime-tools/specerror"
1414 "github.com/opencontainers/runtime-tools/validation/util"
15 uuid "github.com/satori/go.uuid"
15 "github.com/google/uuid"
1616 )
1717
1818 func main() {
2323 config := util.LifecycleConfig{
2424 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
2525 PreCreate: func(r *util.Runtime) error {
26 r.SetID(uuid.NewV4().String())
26 r.SetID(uuid.NewString())
2727 g, err := util.GetDefaultGenerator()
2828 if err != nil {
2929 util.Fatal(err)
3030 }
31 output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output")
32 err = g.AddPostStartHook(rspec.Hook{
33 Path: filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh"),
31 output = filepath.Join(r.BundleDir, g.Config.Root.Path, "output")
32 g.AddPostStartHook(rspec.Hook{
33 Path: filepath.Join(r.BundleDir, g.Config.Root.Path, "/bin/sh"),
3434 Args: []string{
3535 "sh", "-c", fmt.Sprintf("echo 'post-start called' >> %s", output),
3636 },
3737 })
38 if err != nil {
39 return err
40 }
4138 g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("echo 'process called' >> %s", "/output")})
4239 return r.SetConfig(g)
4340 },
8582 diagnostic["stderr"] = string(e.Stderr)
8683 }
8784 }
88 t.YAML(diagnostic)
85 _ = t.YAML(diagnostic)
8986 }
9087
9188 t.AutoPlan()
1010 rspec "github.com/opencontainers/runtime-spec/specs-go"
1111 "github.com/opencontainers/runtime-tools/specerror"
1212 "github.com/opencontainers/runtime-tools/validation/util"
13 uuid "github.com/satori/go.uuid"
13 "github.com/google/uuid"
1414 )
1515
1616 func main() {
2727 if err != nil {
2828 util.Fatal(err)
2929 }
30 output := filepath.Join(bundleDir, g.Spec().Root.Path, "output")
30 output := filepath.Join(bundleDir, g.Config.Root.Path, "output")
3131 poststart := rspec.Hook{
32 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/false"),
32 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/false"),
3333 Args: []string{"false"},
3434 }
3535 g.AddPostStartHook(poststart)
3636 poststartOK := rspec.Hook{
37 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
37 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/sh"),
3838 Args: []string{
3939 "sh", "-c", fmt.Sprintf("echo 'post-start called' >> %s", output),
4040 },
4646 BundleDir: bundleDir,
4747 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
4848 PreCreate: func(r *util.Runtime) error {
49 r.SetID(uuid.NewV4().String())
49 r.SetID(uuid.NewString())
5050 return nil
5151 },
5252 PreDelete: func(r *util.Runtime) error {
6565 diagnostic := map[string]string{
6666 "error": err.Error(),
6767 }
68 t.YAML(diagnostic)
68 _ = t.YAML(diagnostic)
6969 }
7070
7171 t.AutoPlan()
1313 rspec "github.com/opencontainers/runtime-spec/specs-go"
1414 "github.com/opencontainers/runtime-tools/specerror"
1515 "github.com/opencontainers/runtime-tools/validation/util"
16 uuid "github.com/satori/go.uuid"
16 "github.com/google/uuid"
1717 )
1818
1919 func main() {
2424 config := util.LifecycleConfig{
2525 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
2626 PreCreate: func(r *util.Runtime) error {
27 r.SetID(uuid.NewV4().String())
27 r.SetID(uuid.NewString())
2828 g, err := util.GetDefaultGenerator()
2929 if err != nil {
3030 util.Fatal(err)
3131 }
32 output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output")
33 err = g.AddPostStopHook(rspec.Hook{
34 Path: filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh"),
32 output = filepath.Join(r.BundleDir, g.Config.Root.Path, "output")
33 g.AddPostStopHook(rspec.Hook{
34 Path: filepath.Join(r.BundleDir, g.Config.Root.Path, "/bin/sh"),
3535 Args: []string{
3636 "sh", "-c", fmt.Sprintf("echo 'post-stop called' >> %s", output),
3737 },
3838 })
39 if err != nil {
40 return err
41 }
4239 g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("echo 'process called' >> %s", "/output")})
4340 return r.SetConfig(g)
4441 },
10299 diagnostic["stderr"] = string(e.Stderr)
103100 }
104101 }
105 t.YAML(diagnostic)
102 _ = t.YAML(diagnostic)
106103 }
107104
108105 t.AutoPlan()
1010 rspec "github.com/opencontainers/runtime-spec/specs-go"
1111 "github.com/opencontainers/runtime-tools/specerror"
1212 "github.com/opencontainers/runtime-tools/validation/util"
13 uuid "github.com/satori/go.uuid"
13 "github.com/google/uuid"
1414 )
1515
1616 func main() {
2727 if err != nil {
2828 util.Fatal(err)
2929 }
30 output := filepath.Join(bundleDir, g.Spec().Root.Path, "output")
30 output := filepath.Join(bundleDir, g.Config.Root.Path, "output")
3131 poststop := rspec.Hook{
32 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/false"),
32 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/false"),
3333 Args: []string{"false"},
3434 }
3535 g.AddPostStopHook(poststop)
3636 poststopOK := rspec.Hook{
37 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/sh"),
37 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/sh"),
3838 Args: []string{
3939 "sh", "-c", fmt.Sprintf("echo 'post-stop called' >> %s", output),
4040 },
4747 BundleDir: bundleDir,
4848 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
4949 PreCreate: func(r *util.Runtime) error {
50 r.SetID(uuid.NewV4().String())
50 r.SetID(uuid.NewString())
5151 return nil
5252 },
5353 PreDelete: func(r *util.Runtime) error {
6565 diagnostic := map[string]string{
6666 "error": err.Error(),
6767 }
68 t.YAML(diagnostic)
68 _ = t.YAML(diagnostic)
6969 }
7070
7171 t.AutoPlan()
1111 rspec "github.com/opencontainers/runtime-spec/specs-go"
1212 "github.com/opencontainers/runtime-tools/specerror"
1313 "github.com/opencontainers/runtime-tools/validation/util"
14 uuid "github.com/satori/go.uuid"
14 "github.com/google/uuid"
1515 )
1616
1717 func main() {
2222 config := util.LifecycleConfig{
2323 Actions: util.LifecycleActionCreate | util.LifecycleActionStart | util.LifecycleActionDelete,
2424 PreCreate: func(r *util.Runtime) error {
25 r.SetID(uuid.NewV4().String())
25 r.SetID(uuid.NewString())
2626 g, err := util.GetDefaultGenerator()
2727 if err != nil {
2828 util.Fatal(err)
2929 }
30 output = filepath.Join(r.BundleDir, g.Spec().Root.Path, "output")
31 err = g.AddPreStartHook(rspec.Hook{
32 Path: filepath.Join(r.BundleDir, g.Spec().Root.Path, "/bin/sh"),
30 output = filepath.Join(r.BundleDir, g.Config.Root.Path, "output")
31 g.AddPreStartHook(rspec.Hook{
32 Path: filepath.Join(r.BundleDir, g.Config.Root.Path, "/bin/sh"),
3333 Args: []string{
3434 "sh", "-c", fmt.Sprintf("echo 'pre-start called' >> %s", output),
3535 },
3636 })
37 if err != nil {
38 return err
39 }
4037 g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("echo 'process called' >> %s", "/output")})
4138 return r.SetConfig(g)
4239 },
8481 diagnostic["stderr"] = string(e.Stderr)
8582 }
8683 }
87 t.YAML(diagnostic)
84 _ = t.YAML(diagnostic)
8885 }
8986
9087 t.AutoPlan()
88 rspec "github.com/opencontainers/runtime-spec/specs-go"
99 "github.com/opencontainers/runtime-tools/specerror"
1010 "github.com/opencontainers/runtime-tools/validation/util"
11 uuid "github.com/satori/go.uuid"
11 "github.com/google/uuid"
1212 )
1313
1414 func main() {
2626 util.Fatal(err)
2727 }
2828 prestart := rspec.Hook{
29 Path: filepath.Join(bundleDir, g.Spec().Root.Path, "/bin/false"),
29 Path: filepath.Join(bundleDir, g.Config.Root.Path, "/bin/false"),
3030 Args: []string{"false"},
3131 }
3232 g.AddPreStartHook(prestart)
3333 g.SetProcessArgs([]string{"sh", "-c", fmt.Sprintf("touch %s", "/output")})
34 containerID := uuid.NewV4().String()
34 containerID := uuid.NewString()
3535
3636 config := util.LifecycleConfig{
3737 Config: g,
4444 }
4545
4646 runErr := util.RuntimeLifecycleValidate(config)
47 _, outputErr := os.Stat(filepath.Join(bundleDir, g.Spec().Root.Path, "output"))
47 _, outputErr := os.Stat(filepath.Join(bundleDir, g.Config.Root.Path, "output"))
4848
4949 // query the state
5050 r, _ := util.NewRuntime(util.RuntimeCommand, "")
6363 diagnostic := map[string]string{
6464 "error": err.Error(),
6565 }
66 t.YAML(diagnostic)
66 _ = t.YAML(diagnostic)
6767 }
6868
6969 t.AutoPlan()
1616 g.SetProcessUID(10)
1717 g.SetProcessGID(10)
1818 g.AddProcessAdditionalGid(5)
19 g.SetProcessUmask(002)
1920 case "windows":
2021 g.SetProcessUsername("test")
2122 default:
1010 rspecs "github.com/opencontainers/runtime-spec/specs-go"
1111 "github.com/opencontainers/runtime-tools/specerror"
1212 "github.com/opencontainers/runtime-tools/validation/util"
13 uuid "github.com/satori/go.uuid"
13 "github.com/google/uuid"
1414 )
1515
1616 func main() {
2424 }
2525 defer os.RemoveAll(bundleDir)
2626
27 containerID := uuid.NewV4().String()
27 containerID := uuid.NewString()
2828
2929 r, err := util.NewRuntime(util.RuntimeCommand, bundleDir)
3030 if err != nil {
3939 if err != nil {
4040 util.Fatal(err)
4141 }
42 output := filepath.Join(bundleDir, g.Spec().Root.Path, "output")
42 output := filepath.Join(bundleDir, g.Config.Root.Path, "output")
4343
4444 // start without id
4545 err = r.Start()
9797 return
9898 }
9999
100 g.Spec().Process = nil
100 g.Config.Process = nil
101101 err = r.SetConfig(g)
102102 if err != nil {
103103 util.Fatal(err)
99 rfc2119 "github.com/opencontainers/runtime-tools/error"
1010 "github.com/opencontainers/runtime-tools/specerror"
1111 "github.com/opencontainers/runtime-tools/validation/util"
12 uuid "github.com/satori/go.uuid"
12 "github.com/google/uuid"
1313 )
1414
1515 func main() {
2121 util.Fatal(err)
2222 }
2323 g.SetProcessArgs([]string{"true"})
24 containerID := uuid.NewV4().String()
24 containerID := uuid.NewString()
2525
2626 cases := []struct {
2727 id string
5656 "reference": e.Err.Reference,
5757 "error": e.Err.Error(),
5858 }
59 t.YAML(diagnostic)
59 _ = t.YAML(diagnostic)
6060 continue
6161 }
6262
7272 }
7373 }
7474 }
75 t.YAML(diagnostic)
75 _ = t.YAML(diagnostic)
7676 }
7777
7878 t.AutoPlan()
33 "encoding/json"
44 "errors"
55 "fmt"
6 "io"
76 "io/ioutil"
87 "os"
98 "os/exec"
109 "path/filepath"
11 "time"
12
10
11 "github.com/google/uuid"
1312 rspecs "github.com/opencontainers/runtime-spec/specs-go"
1413 "github.com/opencontainers/runtime-tools/generate"
1514 "github.com/opencontainers/runtime-tools/specerror"
16 "github.com/satori/go.uuid"
1715 )
1816
1917 // Runtime represents the basic requirement of a container runtime
7977 args = append(args, r.ID)
8078 }
8179 cmd := exec.Command(r.RuntimeCommand, args...)
82 id := uuid.NewV4().String()
80 id := uuid.NewString()
8381 r.stdout, err = os.OpenFile(filepath.Join(r.bundleDir(), fmt.Sprintf("stdout-%s", id)), os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600)
8482 if err != nil {
8583 return err
109107
110108 // ReadStandardStreams collects content from the stdout and stderr buffers.
111109 func (r *Runtime) ReadStandardStreams() (stdout []byte, stderr []byte, err error) {
112 _, err = r.stdout.Seek(0, io.SeekStart)
113 stdout, err2 := ioutil.ReadAll(r.stdout)
110 stdout, err = ioutil.ReadFile(r.stdout.Name())
111 stderr, err2 := ioutil.ReadFile(r.stderr.Name())
114112 if err == nil && err2 != nil {
115113 err = err2
116114 }
117 _, err = r.stderr.Seek(0, io.SeekStart)
118 stderr, err2 = ioutil.ReadAll(r.stderr)
119 if err == nil && err2 != nil {
120 err = err2
121 }
122 return stdout, stderr, err
115 return
123116 }
124117
125118 // Start a container
180173 return execWithStderrFallbackToStdout(cmd)
181174 }
182175
183 // Delete a container
184 func (r *Runtime) Delete() (err error) {
176 // Delete removes a (stopped) container.
177 func (r *Runtime) Delete() error {
178 return r.del(false)
179 }
180
181 // ForceDelete removes a container (killing it if necessary).
182 func (r *Runtime) ForceDelete() error {
183 return r.del(true)
184 }
185
186 func (r *Runtime) del(force bool) (err error) {
185187 var args []string
186188 args = append(args, "delete")
189 if force {
190 args = append(args, "--force")
191 }
187192 if r.ID != "" {
188193 args = append(args, r.ID)
189194 }
192197 return execWithStderrFallbackToStdout(cmd)
193198 }
194199
195 // Clean deletes the container. If removeBundle is set, the bundle
196 // directory is removed after the container is deleted successfully or, if
197 // forceRemoveBundle is true, after the deletion attempt regardless of
198 // whether it was successful or not.
199 func (r *Runtime) Clean(removeBundle bool, forceRemoveBundle bool) error {
200 r.Kill("KILL")
201 WaitingForStatus(*r, LifecycleStatusStopped, time.Second*10, time.Second/10)
202
203 err := r.Delete()
204
205 if removeBundle && (err == nil || forceRemoveBundle) {
206 err2 := os.RemoveAll(r.bundleDir())
207 if err2 != nil && err == nil {
208 err = err2
209 }
210 }
211
212 return err
200 // Clean kills and removes the container and its bundle directory.
201 func (r *Runtime) Clean() {
202 err := r.ForceDelete()
203 if err != nil {
204 fmt.Fprintln(os.Stderr, "Clean: Delete: ", err)
205 }
206
207 err = os.RemoveAll(r.bundleDir())
208 if err != nil {
209 fmt.Fprintln(os.Stderr, "Clean: ", err)
210 }
213211 }
214212
215213 func execWithStderrFallbackToStdout(cmd *exec.Cmd) (err error) {
2525 }
2626
2727 for i, device := range config.Linux.Resources.Devices {
28 if device.Allow == true {
28 if device.Allow {
2929 found := false
3030 if lnd[i-1].Type == device.Type && *lnd[i-1].Major == *device.Major && *lnd[i-1].Minor == *device.Minor && lnd[i-1].Access == device.Access {
3131 found = true
1010 "strings"
1111 "time"
1212
13 "github.com/google/uuid"
1314 "github.com/mndrix/tap-go"
1415 "github.com/mrunalp/fileutils"
1516 rspec "github.com/opencontainers/runtime-spec/specs-go"
1617 "github.com/opencontainers/runtime-tools/generate"
1718 "github.com/opencontainers/runtime-tools/specerror"
18 "github.com/satori/go.uuid"
1919 )
2020
21 var (
22 // RuntimeCommand is the default runtime command.
23 RuntimeCommand = "runc"
24 )
21 // RuntimeCommand is the default runtime command.
22 var RuntimeCommand = "runc"
2523
2624 // LifecycleAction defines the phases will be called.
2725 type LifecycleAction int
5149 LifecycleStatusStopped
5250 )
5351
54 var lifecycleStatusMap = map[string]LifecycleStatus{
55 "creating": LifecycleStatusCreating,
56 "created": LifecycleStatusCreated,
57 "running": LifecycleStatusRunning,
58 "stopped": LifecycleStatusStopped,
52 var lifecycleStatusMap = map[rspec.ContainerState]LifecycleStatus{
53 rspec.StateCreating: LifecycleStatusCreating,
54 rspec.StateCreated: LifecycleStatusCreated,
55 rspec.StateRunning: LifecycleStatusRunning,
56 rspec.StateStopped: LifecycleStatusStopped,
5957 }
6058
6159 // LifecycleConfig includes
9997 t.Header(1)
10098 t.Skip(1, message)
10199 if diagnostic != nil {
102 t.YAML(diagnostic)
100 _ = t.YAML(diagnostic)
103101 }
104102 }
105103
118116 }
119117 }
120118 }
121 t.YAML(diagnostic)
119 _ = t.YAML(diagnostic)
122120 }
123121
124122 // PrepareBundle creates a test bundle in a temporary directory.
193191 os.RemoveAll(bundleDir)
194192 return err
195193 }
196 defer r.Clean(true, true)
194 defer r.Clean()
197195 err = r.SetConfig(g)
198196 if err != nil {
199197 return err
203201 return err
204202 }
205203
206 r.SetID(uuid.NewV4().String())
204 r.SetID(uuid.NewString())
207205 err = r.Create()
208206 if err != nil {
209207 os.Stderr.WriteString("failed to create the container\n")
246244 if err != nil {
247245 diagnostic["error"] = fmt.Sprintf("%v", err)
248246 }
249 t.YAML(diagnostic)
247 _ = t.YAML(diagnostic)
250248 t.Ok(err == nil && !strings.Contains(string(stdout), "not ok"), g.Config.Annotations["TestName"])
251249 } else {
252250 if runtimeInsideValidateCalled {
270268 os.RemoveAll(bundleDir)
271269 return err
272270 }
273 defer r.Clean(true, true)
271 defer r.Clean()
274272 err = r.SetConfig(g)
275273 if err != nil {
276274 return err
280278 return err
281279 }
282280
283 r.SetID(uuid.NewV4().String())
281 r.SetID(uuid.NewString())
284282 err = r.Create()
285283 if err != nil {
286284 os.Stderr.WriteString("failed to create the container\n")
295293 if err != nil {
296294 return err
297295 }
298 if err := f(g.Spec(), t, &state); err != nil {
296 if err := f(g.Config, t, &state); err != nil {
299297 return err
300298 }
301299 }
+0
-3
vendor/github.com/mndrix/tap-go/.gitignore less more
0 gopath/pkg
1 test/*/test
2 /TAGS
+0
-24
vendor/github.com/mndrix/tap-go/LICENSE less more
0 This is free and unencumbered software released into the public domain.
1
2 Anyone is free to copy, modify, publish, use, compile, sell, or
3 distribute this software, either in source code form or as a compiled
4 binary, for any purpose, commercial or non-commercial, and by any
5 means.
6
7 In jurisdictions that recognize copyright laws, the author or authors
8 of this software dedicate any and all copyright interest in the
9 software to the public domain. We make this dedication for the benefit
10 of the public at large and to the detriment of our heirs and
11 successors. We intend this dedication to be an overt act of
12 relinquishment in perpetuity of all present and future rights to this
13 software under copyright law.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 OTHER DEALINGS IN THE SOFTWARE.
22
23 For more information, please refer to <http://unlicense.org>
+0
-16
vendor/github.com/mndrix/tap-go/Makefile less more
0 TESTS = auto check diagnostic failing known skip todo writer yaml
1 GOPATH ?= $(CURDIR)/gopath
2
3 .PHONY: $(TESTS)
4
5 all: $(foreach t,$(TESTS),test/$(t)/test)
6 prove -v -e '' test/*/test
7
8 clean:
9 rm -f test/*/test
10
11 test/%/test: test/%/*.go tap.go yaml_json.go yaml_yaml.go
12 go build -o $@ -tags yaml ./test/$*
13
14 $(TESTS): %: test/%/test
15 prove -v -e '' test/$@/test
+0
-7
vendor/github.com/mndrix/tap-go/README.md less more
0 # Test Anything Protocol for Go
1
2 The [Test Anything Protocol](http://testanything.org/) ("TAP") is a text-based
3 interface between tests and a test harness. This package helps Go to generate
4 TAP output.
5
6 Read the [full package documentation](https://godoc.org/github.com/mndrix/tap-go)
+0
-165
vendor/github.com/mndrix/tap-go/tap.go less more
0 // Package tap provides support for automated Test Anything Protocol ("TAP")
1 // tests in Go. For example:
2 //
3 // package main
4 //
5 // import "github.com/mndrix/tap-go"
6 //
7 // func main() {
8 // t := tap.New()
9 // t.Header(2)
10 // t.Ok(true, "first test")
11 // t.Ok(true, "second test")
12 // }
13 //
14 // generates the following output
15 //
16 // TAP version 13
17 // 1..2
18 // ok 1 - first test
19 // ok 2 - second test
20 package tap
21
22 import (
23 "fmt"
24 "io"
25 "os"
26 "strings"
27 )
28 import "testing/quick"
29
30 // T is a type to encapsulate test state. Methods on this type generate TAP
31 // output.
32 type T struct {
33 nextTestNumber *int
34
35 // TODO toggles the TODO directive for Ok, Fail, Pass, and similar.
36 TODO bool
37
38 // Writer indicates where TAP output should be sent. The default is os.Stdout.
39 Writer io.Writer
40 }
41
42 // New creates a new Tap value
43 func New() *T {
44 nextTestNumber := 1
45 return &T{
46 nextTestNumber: &nextTestNumber,
47 }
48 }
49
50 func (t *T) w() io.Writer {
51 if t.Writer == nil {
52 return os.Stdout
53 }
54 return t.Writer
55 }
56
57 func (t *T) printf(format string, a ...interface{}) {
58 fmt.Fprintf(t.w(), format, a...)
59 }
60
61 // Header displays a TAP header including version number and expected
62 // number of tests to run. For an unknown number of tests, set
63 // testCount to zero (in which case the plan is not written); this is
64 // useful with AutoPlan.
65 func (t *T) Header(testCount int) {
66 t.printf("TAP version 13\n")
67 if testCount > 0 {
68 t.printf("1..%d\n", testCount)
69 }
70 }
71
72 // Ok generates TAP output indicating whether a test passed or failed.
73 func (t *T) Ok(test bool, description string) {
74 // did the test pass or not?
75 ok := "ok"
76 if !test {
77 ok = "not ok"
78 }
79
80 if t.TODO {
81 t.printf("%s %d # TODO %s\n", ok, *t.nextTestNumber, description)
82 } else {
83 t.printf("%s %d - %s\n", ok, *t.nextTestNumber, description)
84 }
85 (*t.nextTestNumber)++
86 }
87
88 // Fail indicates that a test has failed. This is typically only used when the
89 // logic is too complex to fit naturally into an Ok() call.
90 func (t *T) Fail(description string) {
91 t.Ok(false, description)
92 }
93
94 // Pass indicates that a test has passed. This is typically only used when the
95 // logic is too complex to fit naturally into an Ok() call.
96 func (t *T) Pass(description string) {
97 t.Ok(true, description)
98 }
99
100 // Check runs randomized tests against a function just as "testing/quick.Check"
101 // does. Success or failure generate appropriate TAP output.
102 func (t *T) Check(function interface{}, description string) {
103 err := quick.Check(function, nil)
104 if err == nil {
105 t.Ok(true, description)
106 return
107 }
108
109 t.Diagnostic(err.Error())
110 t.Ok(false, description)
111 }
112
113 // Count returns the number of tests completed so far.
114 func (t *T) Count() int {
115 return *t.nextTestNumber - 1
116 }
117
118 // AutoPlan generates a test plan based on the number of tests that were run.
119 func (t *T) AutoPlan() {
120 t.printf("1..%d\n", t.Count())
121 }
122
123 func escapeNewlines(s string) string {
124 return strings.Replace(strings.TrimRight(s, "\n"), "\n", "\n# ", -1)
125 }
126
127 // Todo returns copy of the test-state with TODO set.
128 func (t *T) Todo() *T {
129 newT := *t
130 newT.TODO = true
131 return &newT
132 }
133
134 // Skip indicates that a test has been skipped.
135 func (t *T) Skip(count int, description string) {
136 for i := 0; i < count; i++ {
137 t.printf("ok %d # SKIP %s\n", *t.nextTestNumber, description)
138 (*t.nextTestNumber)++
139 }
140 }
141
142 // Diagnostic generates a diagnostic from the message,
143 // which may span multiple lines.
144 func (t *T) Diagnostic(message string) {
145 t.printf("# %s\n", escapeNewlines(message))
146 }
147
148 // Diagnosticf generates a diagnostic from the format string and arguments,
149 // which may span multiple lines.
150 func (t *T) Diagnosticf(format string, a ...interface{}) {
151 t.printf("# "+escapeNewlines(format)+"\n", a...)
152 }
153
154 // YAML generates a YAML block from the message.
155 func (t *T) YAML(message interface{}) error {
156 bytes, err := yaml(message, " ")
157 if err != nil {
158 return err
159 }
160 t.printf(" ---\n ")
161 t.printf(string(bytes))
162 t.printf(" ...\n")
163 return nil
164 }
+0
-22
vendor/github.com/mndrix/tap-go/yaml_json.go less more
0 // +build !yaml
1
2 package tap
3
4 import (
5 "encoding/json"
6 )
7
8 // yaml serializes a message to YAML. This implementation uses JSON,
9 // which is a subset of YAML [1] and is implemented by Go's standard
10 // library.
11 //
12 // [1]: http://www.yaml.org/spec/1.2/spec.html#id2759572
13 func yaml(message interface{}, prefix string) (marshaled []byte, err error) {
14 marshaled, err = json.MarshalIndent(message, prefix, " ")
15 if err != nil {
16 return marshaled, err
17 }
18
19 marshaled = append(marshaled, []byte("\n")...)
20 return marshaled, err
21 }
+0
-23
vendor/github.com/mndrix/tap-go/yaml_yaml.go less more
0 // +build yaml
1
2 package tap
3
4 import (
5 "bytes"
6
7 goyaml "gopkg.in/yaml.v2"
8 )
9
10 // yaml serializes a message to YAML. This implementation uses
11 // non-JSON YAML, which has better prove support [1].
12 //
13 // [1]: https://rt.cpan.org/Public/Bug/Display.html?id=121606
14 func yaml(message interface{}, prefix string) (marshaled []byte, err error) {
15 marshaled, err = goyaml.Marshal(message)
16 if err != nil {
17 return marshaled, err
18 }
19
20 marshaled = bytes.Replace(marshaled, []byte("\n"), []byte("\n"+prefix), -1)
21 return marshaled[:len(marshaled)-len(prefix)], err
22 }