Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 91 additions & 1 deletion tests/e2e/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ type containerVolume struct {
Dest string
}

type sideContainerNetMode string

const (
// sideContainerNetModeNetwork joins the same named/user-defined
// network as the primary container (docker/nerdctl --network <name>).
sideContainerNetModeNetwork sideContainerNetMode = "network"
// sideContainerNetModeShared joins the primary container's network
// namespace directly, similar to containers sharing a namespace
// inside a Kubernetes pod (docker/nerdctl --network container:<id>).
sideContainerNetModeShared sideContainerNetMode = "shared"
)

type sideContainer struct {
Name string
Image string
Cli string
Volumes []containerVolume
NetMode sideContainerNetMode
}

type containerTestArgs struct {
Name string
Image string
Expand All @@ -63,8 +83,9 @@ type containerTestArgs struct {
Memory string
Cli string
Volumes []containerVolume
Network string
StaticNet bool
SideContainers []string
SideContainers []sideContainer
Skippable bool
TestFunc testMethod
ExpectOut string
Expand All @@ -90,6 +111,9 @@ func commonNewContainerCmd(a containerTestArgs) string {
if a.Memory != "" {
cmdBase += fmt.Sprintf("-m %s ", a.Memory)
}
if a.Network != "" {
cmdBase += fmt.Sprintf("--network %s ", a.Network)
}
if a.UID != 0 && a.GID != 0 {
cmdBase += fmt.Sprintf("-u %d:%d ", a.UID, a.GID)
}
Expand Down Expand Up @@ -136,6 +160,72 @@ func commonCmdExecStderr(command string) (string, string, error) {
return output, errorOut, err
}

func commonSideContainerCmd(sc sideContainer, netArg string) string {
cmdBase := ""
if netArg != "" {
cmdBase += fmt.Sprintf("--network %s ", netArg)
}
for _, vol := range sc.Volumes {
cmdBase += fmt.Sprintf("--mount type=bind,src=%s,dst=%s ", vol.Source, vol.Dest)
}
cmdBase += "--name "
cmdBase += sc.Name + " "
cmdBase += sc.Image + " "
cmdBase += sc.Cli
return cmdBase
}

func commonRunSideContainer(tool string, sc sideContainer, netArg string) (output string, err error) {
cmdBase := tool + " run -d "
cmdBase += commonSideContainerCmd(sc, netArg)
return commonCmdExec(cmdBase)
}

// commonStartSideContainers starts every side container defined and
// joining each one of them int the primary container's network per its NetMode,
// and returns their container IDs for later cleanup.
func commonStartSideContainers(tool string, a containerTestArgs, primaryID string) ([]string, error) {
var ids []string
for _, sc := range a.SideContainers {
var netArg string
switch sc.NetMode {
case sideContainerNetModeNetwork:
// a.Network may be "": docker/nerdctl both attach a
// container to the default "bridge" network when
// --network is omitted.
netArg = a.Network
case sideContainerNetModeShared:
netArg = "container:" + primaryID
default:
return ids, fmt.Errorf("side container %s has unknown network mode %q", sc.Name, sc.NetMode)
}
cID, err := commonRunSideContainer(tool, sc, netArg)
if err != nil {
return ids, fmt.Errorf("failed to start side container %s: %s -- %v", sc.Name, cID, err)
}
ids = append(ids, cID)
}
return ids, nil
}

func commonStopSideContainers(tool string, ids []string) error {
for _, cID := range ids {
if _, err := commonStopContainer(tool, cID); err != nil {
return fmt.Errorf("failed to stop side container %s: %v", cID, err)
}
}
return nil
}

func commonRmSideContainers(tool string, ids []string) error {
for _, cID := range ids {
if _, err := commonRmContainer(tool, cID); err != nil {
return fmt.Errorf("failed to remove side container %s: %v", cID, err)
}
}
return nil
}

func commonPull(tool string, image string) error {
pullCmd := tool + " image pull " + image

Expand Down
97 changes: 94 additions & 3 deletions tests/e2e/crictl.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ const podConfigFilename = "pod.json"
const cntrConfigFilename = "container.json"

type crictlInfo struct {
testArgs containerTestArgs
podID string
containerID string
testArgs containerTestArgs
podID string
containerID string
sideContainerIDs []string
}

func newCrictlTool(args containerTestArgs) *crictlInfo {
Expand Down Expand Up @@ -133,6 +134,39 @@ func crictlNewContainerConfig(path string, a containerTestArgs) (string, error)
return absContConf, nil
}

// crictlNewSideContainerConfig writes a container config for a side container,
// named after it so multiple side containers don't collide on disk.
func crictlNewSideContainerConfig(path string, sc sideContainer) (string, error) {
var mounts []*criruntimeapi.Mount
for _, vol := range sc.Volumes {
mounts = append(mounts, &criruntimeapi.Mount{
ContainerPath: vol.Dest,
HostPath: vol.Source,
Readonly: false,
})
}
containerConfig := criruntimeapi.ContainerConfig{
Metadata: &criruntimeapi.ContainerMetadata{
Name: sc.Name,
},
Image: &criruntimeapi.ImageSpec{
Image: sc.Image,
},
Command: strings.Fields(sc.Cli),
Mounts: mounts,
}
cc, err := json.MarshalIndent(&containerConfig, "", " ")
if err != nil {
return "", fmt.Errorf("Failed to marshal side container config: %v", err)
}
absConf := filepath.Join(path, sc.Name+".json")
err = writeToFile(absConf, string(cc))
if err != nil {
return "", fmt.Errorf("Failed to write side container config: %v", err)
}
return absConf, nil
}

func (i *crictlInfo) Name() string {
return crictlName
}
Expand Down Expand Up @@ -201,14 +235,56 @@ func (i *crictlInfo) createContainer() (string, error) {
return commonCmdExec(cmdBase)
}

// startSideContainers starts every side container declared on the test
// case as an extra container in the SAME pod as the primary container.
func (i *crictlInfo) startSideContainers() error {
if len(i.testArgs.SideContainers) == 0 {
return nil
}

cwd, err := os.Getwd()
if err != nil {
return fmt.Errorf("Failed to get CWD to write side container configs: %v", err)
}
absPodConf := filepath.Join(cwd, podConfigFilename)

for _, sc := range i.testArgs.SideContainers {
if sc.NetMode != sideContainerNetModeShared {
return fmt.Errorf("crictl does not support side container network mode %q: crictl has no named/user-defined network, only pod-shared networking (sideContainerNetModeShared)", sc.NetMode)
}

absSideConf, err := crictlNewSideContainerConfig(cwd, sc)
if err != nil {
return err
}

cmdBase := crictlName + " create " + i.podID + " " + absSideConf + " " + absPodConf
cID, err := commonCmdExec(cmdBase)
if err != nil {
return fmt.Errorf("failed to create side container %s: %s -- %v", sc.Name, cID, err)
}
if output, err := commonCmdExec(crictlName + " start " + cID); err != nil {
return fmt.Errorf("failed to start side container %s: %s -- %v", sc.Name, output, err)
}
i.sideContainerIDs = append(i.sideContainerIDs, cID)
}
return nil
}

func (i *crictlInfo) startContainer(bool) (string, error) {
if err := i.startSideContainers(); err != nil {
return "", err
}
cmdBase := crictlName
cmdBase += " start "
cmdBase += i.containerID
return commonCmdExec(cmdBase)
}

func (i *crictlInfo) runContainer(bool) (string, error) {
if err := i.startSideContainers(); err != nil {
return "", err
}
cwd, err := os.Getwd()
if err != nil {
return "", fmt.Errorf("Failed to get CWD to write Container/Pod config: %v", err)
Expand All @@ -234,6 +310,10 @@ func (i *crictlInfo) runContainer(bool) (string, error) {
}

func (i *crictlInfo) stopContainer() error {
if err := commonStopSideContainers(crictlName, i.sideContainerIDs); err != nil {
return err
}

output, err := commonStopContainer(crictlName, i.containerID)
err = checkExpectedOut(i.containerID, output, err)
if err != nil {
Expand All @@ -257,6 +337,10 @@ func (i *crictlInfo) stopPod() error {
}

func (i *crictlInfo) rmContainer() error {
if err := commonRmSideContainers(crictlName, i.sideContainerIDs); err != nil {
return err
}

output, err := commonRmContainer(crictlName, i.containerID)
err = checkExpectedOut(i.containerID, output, err)
if err != nil {
Expand All @@ -272,6 +356,13 @@ func (i *crictlInfo) rmContainer() error {
if err != nil {
return fmt.Errorf("Could not remove container config file: %v", err)
}

for _, sc := range i.testArgs.SideContainers {
absSideConf := filepath.Join(cwd, sc.Name+".json")
if err := os.Remove(absSideConf); err != nil {
return fmt.Errorf("Could not remove side container %s config file: %v", sc.Name, err)
}
}
return nil
}

Expand Down
4 changes: 4 additions & 0 deletions tests/e2e/crictl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ var _ = Describe("Crictl", Ordered, ContinueOnFailure, func() {
}
})

if len(tc.SideContainers) > 0 {
runDetachedSideContainerTest(tool, tc)
return
}
runDetachedTest(tool, tc)
},
toTableEntries(crictlTestCases()),
Expand Down
14 changes: 14 additions & 0 deletions tests/e2e/ctr.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,28 @@ func (i *ctrInfo) startPod() (string, error) {
return "", errToolDoesNotSupport
}

func (i *ctrInfo) startSideContainers() error {
if len(i.testArgs.SideContainers) == 0 {
return nil
}
// Not supported by ctr
return errToolDoesNotSupport
}

func (i *ctrInfo) startContainer(detach bool) (string, error) {
if err := i.startSideContainers(); err != nil {
return "", err
}
if detach {
i.detached = true
}
return commonStart(ctrName+" t", i.containerID, detach)
}

func (i *ctrInfo) runContainer(detach bool) (string, error) {
if err := i.startSideContainers(); err != nil {
return "", err
}
cmdBase := ctrName
cmdBase += " run "
if detach {
Expand Down
26 changes: 23 additions & 3 deletions tests/e2e/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ import (
const dockerName = "docker"

type dockerInfo struct {
testArgs containerTestArgs
containerID string
testArgs containerTestArgs
containerID string
sideContainerIDs []string
}

func newDockerTool(args containerTestArgs) *dockerInfo {
Expand Down Expand Up @@ -73,14 +74,30 @@ func (i *dockerInfo) startPod() (string, error) {
}

func (i *dockerInfo) startContainer(detach bool) (string, error) {
return commonStart(dockerName, i.containerID, detach)
output, err := commonStart(dockerName, i.containerID, detach)
if err != nil {
return output, err
}
if err := i.startSideContainers(); err != nil {
return output, err
}
return output, nil
}

func (i *dockerInfo) startSideContainers() error {
ids, err := commonStartSideContainers(dockerName, i.testArgs, i.containerID)
i.sideContainerIDs = ids
return err
}

func (i *dockerInfo) runContainer(detach bool) (string, error) {
return commonRun(dockerName, i.testArgs, detach)
}

func (i *dockerInfo) stopContainer() error {
if err := commonStopSideContainers(dockerName, i.sideContainerIDs); err != nil {
return err
}
output, err := commonStopContainer(dockerName, i.containerID)
err = checkExpectedOut(i.containerID, output, err)
if err != nil {
Expand All @@ -95,6 +112,9 @@ func (i *dockerInfo) stopPod() error {
}

func (i *dockerInfo) rmContainer() error {
if err := commonRmSideContainers(dockerName, i.sideContainerIDs); err != nil {
return err
}
output, err := commonRmContainer(dockerName, i.containerID)
err = checkExpectedOut(i.containerID, output, err)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions tests/e2e/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ var _ = Describe("Docker", Ordered, ContinueOnFailure, func() {
func(tc containerTestArgs) {
skipMissingVolumes(tc)
tool = newDockerTool(tc)
if len(tc.SideContainers) > 0 {
runDetachedSideContainerTest(tool, tc)
return
}
runDetachedTest(tool, tc)
},
toTableEntries(dockerTestCases()),
Expand Down
Loading