summaryrefslogtreecommitdiffstats
path: root/extras/hs-test/container.go
diff options
context:
space:
mode:
authorMaros Ondrejicka <maros.ondrejicka@pantheon.tech>2022-12-14 16:30:04 +0100
committerFlorin Coras <florin.coras@gmail.com>2022-12-19 17:11:52 +0000
commitdb823ed6e9543741f6969ff160314093002e037e (patch)
treebf046f85d1052058da38192687874e361c684e4c /extras/hs-test/container.go
parentaff4d320f0fe9ce68fcb83ee9ab0abc2d8612644 (diff)
hs-test: abstract away topology from test cases
Definition of shared volumes and containers has been moved to yaml files to be together with network topology. Containers are automatically run at the beginning of each test case and stopped afterward. Type: test Signed-off-by: Maros Ondrejicka <maros.ondrejicka@pantheon.tech> Change-Id: I264cbb4f1355f8bd7aade221e9609fb5b9bd693e
Diffstat (limited to 'extras/hs-test/container.go')
-rw-r--r--extras/hs-test/container.go153
1 files changed, 138 insertions, 15 deletions
diff --git a/extras/hs-test/container.go b/extras/hs-test/container.go
index e9aa7b261c4..1dc65fff308 100644
--- a/extras/hs-test/container.go
+++ b/extras/hs-test/container.go
@@ -2,18 +2,73 @@ package main
import (
"fmt"
+ "os"
+ "strings"
"github.com/edwarnicke/exechelper"
)
type Volume struct {
- name string
- path string
+ hostDir string
+ containerDir string
}
type Container struct {
- name string
- volumes []*Volume
+ isOptional bool
+ name string
+ image string
+ workDir string
+ volumes map[string]Volume
+ envVars map[string]string
+}
+
+func NewContainer(yamlInput ContainerConfig) (*Container, error) {
+ containerName := yamlInput["name"].(string)
+ if len(containerName) == 0 {
+ err := fmt.Errorf("container name must not be blank")
+ return nil, err
+ }
+
+ var container = new(Container)
+ container.volumes = make(map[string]Volume)
+ container.envVars = make(map[string]string)
+ container.name = containerName
+
+ if image, ok := yamlInput["image"]; ok {
+ container.image = image.(string)
+ } else {
+ container.image = "hs-test/vpp"
+ }
+
+ if isOptional, ok := yamlInput["is-optional"]; ok {
+ container.isOptional = isOptional.(bool)
+ } else {
+ container.isOptional = false
+ }
+
+ if _, ok := yamlInput["volumes"]; ok {
+ r:= strings.NewReplacer("$HST_DIR", workDir)
+ for _, volu := range yamlInput["volumes"].([]interface{}) {
+ volumeMap := volu.(ContainerConfig)
+ hostDir := r.Replace(volumeMap["host-dir"].(string))
+ containerDir := volumeMap["container-dir"].(string)
+ container.addVolume(hostDir, containerDir)
+
+ if isDefaultWorkDir, ok := volumeMap["is-default-work-dir"]; ok &&
+ isDefaultWorkDir.(bool) &&
+ len(container.workDir) == 0 {
+ container.workDir = containerDir
+ }
+
+ }
+ }
+
+ if _, ok := yamlInput["vars"]; ok {
+ for _, envVar := range yamlInput["vars"].([]interface{}) {
+ container.addEnvVar(envVar)
+ }
+ }
+ return container, nil
}
func (c *Container) run() error {
@@ -22,34 +77,102 @@ func (c *Container) run() error {
}
exechelper.Run(fmt.Sprintf("mkdir -p /tmp/%s/sync", c.name))
- syncPath := fmt.Sprintf("-v /tmp/%s/sync:/tmp/sync", c.name)
- cmd := "docker run --cap-add=all -d --privileged --network host --rm "
+ syncPath := fmt.Sprintf(" -v %s:/tmp/sync", c.getSyncPath())
+ cmd := "docker run --cap-add=all -d --privileged --network host --rm"
cmd += syncPath
- cmd += c.getVolumes()
- cmd += " --name " + c.name + " hs-test/vpp"
+ cmd += c.getVolumesAsCliOption()
+ cmd += c.getEnvVarsAsCliOption()
+ cmd += " --name " + c.name + " " + c.image
fmt.Println(cmd)
err := exechelper.Run(cmd)
if err != nil {
- return fmt.Errorf("create volume failed: %s", err)
+ return fmt.Errorf("container run failed: %s", err)
}
return nil
}
-func (c *Container) addVolume(name string, containerPath string) {
- c.volumes = append(c.volumes, &Volume{name, containerPath})
+func (c *Container) addVolume(hostDir string, containerDir string) {
+ var volume Volume
+ volume.hostDir = hostDir
+ volume.containerDir = containerDir
+ c.volumes[hostDir] = volume
}
-func (c *Container) getVolumes() string {
- dockerOption := ""
+func (c *Container) getVolumeByHostDir(hostDir string) Volume {
+ return c.volumes[hostDir]
+}
+
+func (c *Container) getVolumesAsCliOption() string {
+ cliOption := ""
if len(c.volumes) > 0 {
for _, volume := range c.volumes {
- dockerOption += fmt.Sprintf(" -v %s:%s", volume.name, volume.path)
+ cliOption += fmt.Sprintf(" -v %s:%s", volume.hostDir, volume.containerDir)
}
}
- return dockerOption
+ return cliOption
+}
+
+func (c *Container) getWorkDirAsCliOption() string {
+ if len(c.workDir) == 0 {
+ return ""
+ }
+ return fmt.Sprintf(" --workdir=\"%s\"", c.workDir)
+}
+
+func (c *Container) addEnvVar(envVar interface{}) {
+ envVarMap := envVar.(ContainerConfig)
+ name := envVarMap["name"].(string)
+ value := envVarMap["value"].(string)
+ c.envVars[name] = value
+}
+
+func (c *Container) getEnvVarsAsCliOption() string {
+ cliOption := ""
+ if len(c.envVars) == 0 {
+ return cliOption
+ }
+
+ for name, value := range c.envVars {
+ cliOption += fmt.Sprintf(" -e %s=%s", name, value)
+ }
+ return cliOption
+}
+
+func (c *Container) getSyncPath() string {
+ return fmt.Sprintf("/tmp/%s/sync", c.name)
+}
+
+func (c *Container) exec(command string) (string, error) {
+ cliCommand := "docker exec -d " + c.name + " " + command
+ byteOutput, err := exechelper.CombinedOutput(cliCommand)
+ return string(byteOutput), err
+}
+
+func (c *Container) execAction(args string) (string, error) {
+ syncFile := c.getSyncPath() + "/rc"
+ os.Remove(syncFile)
+
+ workDir := c.getWorkDirAsCliOption()
+ cmd := fmt.Sprintf("docker exec -d %s %s hs-test %s",
+ workDir,
+ c.name,
+ args)
+ err := exechelper.Run(cmd)
+ if err != nil {
+ return "", err
+ }
+ res, err := waitForSyncFile(syncFile)
+ if err != nil {
+ return "", fmt.Errorf("failed to read sync file while executing 'hs-test %s': %v", args, err)
+ }
+ o := res.StdOutput + res.ErrOutput
+ if res.Code != 0 {
+ return o, fmt.Errorf("cmd resulted in non-zero value %d: %s", res.Code, res.Desc)
+ }
+ return o, err
}
func (c *Container) stop() error {