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
|
package main
import (
"fmt"
"os"
"time"
"github.com/mndrix/tap-go"
rspecs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate"
"github.com/opencontainers/runtime-tools/specerror"
"github.com/opencontainers/runtime-tools/validation/util"
"github.com/google/uuid"
)
func main() {
t := tap.New()
t.Header(0)
defer t.AutoPlan()
bundleDir, err := util.PrepareBundle()
if err != nil {
util.Fatal(err)
}
defer os.RemoveAll(bundleDir)
stoppedConfig, err := util.GetDefaultGenerator()
if err != nil {
util.Fatal(err)
}
stoppedConfig.SetProcessArgs([]string{"true"})
runningConfig, err := util.GetDefaultGenerator()
if err != nil {
util.Fatal(err)
}
runningConfig.SetProcessArgs([]string{"sleep", "30"})
containerID := uuid.NewString()
testRuntime, _ := util.NewRuntime(util.RuntimeCommand, bundleDir)
cases := []struct {
config *generate.Generator
id string
action util.LifecycleAction
errExpected bool
// set true to check whether 'delete' takes effect and just check if 'delete' DOES NOT take effect
effectCheck bool
err error
}{
// Note: the nil config test case should run first since we are re-using the bundle
// delete without id
{nil, "", util.LifecycleActionNone, false, false, specerror.NewError(specerror.DeleteWithoutIDGenError, fmt.Errorf("`delete` operation MUST generate an error if it is not provided the container ID"), rspecs.Version)},
// delete a created container
{stoppedConfig, containerID, util.LifecycleActionCreate, false, true, specerror.NewError(specerror.DeleteNonStopGenError, fmt.Errorf("attempting to `delete` a container that is not `stopped` MUST generate an error"), rspecs.Version)},
// delete a running container
{runningConfig, containerID, util.LifecycleActionCreate | util.LifecycleActionStart, false, true, specerror.NewError(specerror.DeleteNonStopGenError, fmt.Errorf("attempting to `delete` a container that is not `stopped` MUST generate an error"), rspecs.Version)},
}
for _, c := range cases {
config := util.LifecycleConfig{
Config: c.config,
BundleDir: bundleDir,
Actions: c.action,
PreCreate: func(r *util.Runtime) error {
r.SetID(c.id)
return nil
},
}
util.RuntimeLifecycleValidate(config)
// waiting the 'stoppedConfig' testcase to stop
// the 'runningConfig' testcase sleeps 30 seconds, so 10 seconds are enough for this case
testRuntime.SetID(c.id)
util.WaitingForStatus(testRuntime, util.LifecycleStatusCreated|util.LifecycleStatusStopped, time.Second*10, time.Second*1)
deletedErr := testRuntime.Delete()
util.SpecErrorOK(t, (deletedErr == nil) == c.errExpected, c.err, deletedErr)
if c.effectCheck {
// waiting for the error of State, just in case the delete operation takes time
util.WaitingForStatus(testRuntime, util.LifecycleActionNone, time.Second*3, time.Second/2)
_, err = testRuntime.State()
// err == nil means the 'delete' operation does NOT take effect
util.SpecErrorOK(t, err == nil, specerror.NewError(specerror.DeleteNonStopHaveNoEffect, fmt.Errorf("attempting to `delete` a container that is not `stopped` MUST have no effect on the container"), rspecs.Version), err)
}
// created and but deleted
if (c.action&util.LifecycleActionCreate != 0) && (deletedErr != nil) {
testRuntime.Kill("KILL")
// waiting for the container to be killed, just in case the kill operation takes time
util.WaitingForStatus(testRuntime, util.LifecycleStatusStopped, time.Second*10, time.Second*1)
err = testRuntime.Delete()
if err != nil {
t.Fail(err.Error())
}
}
}
}
|