diff options
author | Maros Ondrejicka <maros.ondrejicka@pantheon.tech> | 2022-12-14 16:30:04 +0100 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2022-12-19 17:11:52 +0000 |
commit | db823ed6e9543741f6969ff160314093002e037e (patch) | |
tree | bf046f85d1052058da38192687874e361c684e4c /extras/hs-test/container.go | |
parent | aff4d320f0fe9ce68fcb83ee9ab0abc2d8612644 (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.go | 153 |
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 { |