-
Notifications
You must be signed in to change notification settings - Fork 18
/
tests.go
186 lines (159 loc) · 6.93 KB
/
tests.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
// Package tests contains the exported functions that are meant to be imported as test cases.
//
// It should not export any other thing except for a SubcommandOption struct (e.g., LoginOption) that may be added in the future.
//
// Each file contains one subcommand to test and is named after that subcommand.
// Note that the file names are not suffixed with _test so that they can appear in Go Doc.
package tests
import (
"fmt"
"os"
"path/filepath"
"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
"github.com/runfinch/common-tests/fnet"
"github.com/runfinch/common-tests/command"
"github.com/runfinch/common-tests/ffs"
"github.com/runfinch/common-tests/option"
)
const (
alpineImage = "public.ecr.aws/docker/library/alpine:latest"
olderAlpineImage = "public.ecr.aws/docker/library/alpine:3.13"
amazonLinux2Image = "public.ecr.aws/amazonlinux/amazonlinux:2"
nginxImage = "public.ecr.aws/docker/library/nginx:latest"
testImageName = "test:tag"
nonexistentImageName = "ne-repo:ne-tag"
nonexistentContainerName = "ne-ctr"
testContainerName = "ctr-test"
testContainerName2 = "ctr-test-2"
testVolumeName = "testVol"
registryImage = "public.ecr.aws/docker/library/registry:latest"
localRegistryName = "local-registry"
testUser = "testUser"
testPassword = "testPassword"
sha256RegexFull = "^sha256:[a-f0-9]{64}$"
bridgeNetwork = "bridge"
testNetwork = "test-network"
)
var defaultImage = alpineImage
// CGMode is the cgroups mode of the host system.
// We copy the struct from containerd/cgroups [1] instead of using it as a library
// because it only builds on linux,
// while we don't really need the functions that make it only build on linux
// (e.g., determine the cgroup version of the current host).
//
// [1] https://github.com/containerd/cgroups/blob/cc78c6c1e32dc5bde018d92999910fdace3cfa27/utils.go#L38-L50
type CGMode int
const (
// Unavailable cgroup mountpoint.
Unavailable CGMode = iota
// Legacy cgroups v1.
Legacy
// Hybrid with cgroups v1 and v2 controllers mounted.
Hybrid
// Unified with only cgroups v2 mounted.
Unified
)
// SetupLocalRegistry can be invoked before running the tests to save time when pulling defaultImage.
//
// It spins up a local registry, tags the alpine image, pushes the tagged image to local registry,
// and changes defaultImage to be the one pushed to local registry.
//
// After all the tests are done, invoke CleanupLocalRegistry to clean up the local registry.
func SetupLocalRegistry(o *option.Option) {
command.RemoveAll(o)
hostPort := fnet.GetFreePort()
containerID := command.StdoutStr(o, "run", "-d", "-p",
fmt.Sprintf("%d:5000", hostPort), "--name", localRegistryName, registryImage)
imageID := command.StdoutStr(o, "images", "-q")
command.SetLocalRegistryContainerID(containerID)
command.SetLocalRegistryImageID(imageID)
command.SetLocalRegistryImageName(registryImage)
command.Run(o, "pull", alpineImage)
defaultImage = fmt.Sprintf("localhost:%d/alpine:latest", hostPort)
command.Run(o, "tag", alpineImage, defaultImage)
command.Run(o, "push", defaultImage)
command.Run(o, "rmi", alpineImage)
}
// CleanupLocalRegistry removes the local registry container and image. It's used together with SetupLocalRegistry,
// and should be invoked after running all the tests.
func CleanupLocalRegistry(o *option.Option) {
containerID := command.StdoutStr(o, "inspect", localRegistryName, "--format", "{{.ID}}")
command.Run(o, "rm", "-f", containerID)
imageID := command.StdoutStr(o, "images", "-q")
command.Run(o, "rmi", "-f", imageID)
}
func pullImage(o *option.Option, imageName string) {
command.Run(o, "pull", "-q", imageName)
imageID := command.Stdout(o, "images", "--quiet", imageName)
gomega.Expect(imageID).ShouldNot(gomega.BeEmpty())
}
func removeImage(o *option.Option, imageName string) {
command.Run(o, "rmi", "--force", imageName)
imageID := command.Stdout(o, "images", "--quiet", imageName)
gomega.Expect(string(imageID)).Should(gomega.BeEmpty())
}
func containerShouldBeRunning(o *option.Option, containerNames ...string) {
for _, containerName := range containerNames {
gomega.Expect(command.Stdout(o, "ps", "-q", "--filter",
fmt.Sprintf("name=%s", containerName))).NotTo(gomega.BeEmpty())
}
}
func containerShouldNotBeRunning(o *option.Option, containerNames ...string) {
for _, containerName := range containerNames {
gomega.Expect(command.Stdout(o, "ps", "-q", "--filter",
fmt.Sprintf("name=%s", containerName))).To(gomega.BeEmpty())
}
}
func containerShouldExist(o *option.Option, containerNames ...string) {
for _, containerName := range containerNames {
gomega.Expect(command.Stdout(o, "ps", "-a", "-q", "--filter",
fmt.Sprintf("name=%s", containerName))).NotTo(gomega.BeEmpty())
}
}
func containerShouldNotExist(o *option.Option, containerNames ...string) {
for _, containerName := range containerNames {
gomega.Expect(command.Stdout(o, "ps", "-a", "-q", "--filter",
fmt.Sprintf("name=%s", containerName))).To(gomega.BeEmpty())
}
}
func imageShouldExist(o *option.Option, imageName string) {
gomega.Expect(command.Stdout(o, "images", "-q", imageName)).NotTo(gomega.BeEmpty())
}
func imageShouldNotExist(o *option.Option, imageName string) {
gomega.Expect(command.Stdout(o, "images", "-q", imageName)).To(gomega.BeEmpty())
}
func volumeShouldExist(o *option.Option, volumeName string) {
gomega.Expect(command.Stdout(o, "volume", "ls", "-q", "--filter",
fmt.Sprintf("name=%s", volumeName))).NotTo(gomega.BeEmpty())
}
func volumeShouldNotExist(o *option.Option, volumeName string) {
gomega.Expect(command.Stdout(o, "volume", "ls", "-q", "--filter",
fmt.Sprintf("name=%s", volumeName))).To(gomega.BeEmpty())
}
func fileShouldExist(path, content string) {
gomega.Expect(path).To(gomega.BeARegularFile())
actualContent, err := os.ReadFile(filepath.Clean(path))
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Expect(string(actualContent)).To(gomega.Equal(content))
}
func fileShouldNotExist(path string) {
gomega.Expect(path).ToNot(gomega.BeAnExistingFile())
}
func fileShouldExistInContainer(o *option.Option, containerName, path, content string) {
gomega.Expect(command.StdoutStr(o, "exec", containerName, "cat", path)).To(gomega.Equal(content))
}
func fileShouldNotExistInContainer(o *option.Option, containerName, path string) {
cmdOut := command.RunWithoutSuccessfulExit(o, "exec", containerName, "cat", path)
gomega.Expect(cmdOut.Err.Contents()).To(gomega.ContainSubstring("No such file or directory"))
}
func buildImage(o *option.Option, imageName string) {
dockerfile := fmt.Sprintf(`FROM %s
CMD ["echo", "finch-test-dummy-output"]
`, defaultImage)
buildContext := ffs.CreateBuildContext(dockerfile)
ginkgo.DeferCleanup(os.RemoveAll, buildContext)
command.Run(o, "build", "-q", "-t", imageName, buildContext)
}