Skip to content
Merged
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
34 changes: 25 additions & 9 deletions validation/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"fmt"
"os/exec"

"github.com/mndrix/tap-go"
rspecs "github.com/opencontainers/runtime-spec/specs-go"
Expand Down Expand Up @@ -48,26 +49,41 @@ func main() {

for _, c := range cases {
r.SetID(c.id)
stderr, err := r.Create()
err := r.Create()
t.Ok((err == nil) == c.errExpected, c.err.(*specerror.Error).Err.Err.Error())
diagnostic := map[string]string{
"reference": c.err.(*specerror.Error).Err.Reference,
}
if err != nil {
diagnostic["error"] = err.Error()
}
if len(stderr) > 0 {
diagnostic["stderr"] = string(stderr)
if e, ok := err.(*exec.ExitError); ok {
if len(e.Stderr) > 0 {
diagnostic["stderr"] = string(e.Stderr)
}
}
t.YAML(diagnostic)

if err == nil {
state, _ := r.State()
t.Ok(state.ID == c.id, "'state' MUST return the state of a container")
t.YAML(map[string]string{
"container ID": c.id,
"state ID": state.ID,
})
state, err := r.State()
if err == nil {
t.Ok(state.ID == c.id, "'state' MUST return the state of a container")
t.YAML(map[string]string{
"container ID": c.id,
"state ID": state.ID,
})
} else {
t.Skip(1, "'state' MUST return the state of a container")
diagnostic = map[string]string{
"error": err.Error(),
}
if e, ok := err.(*exec.ExitError); ok {
if len(e.Stderr) > 0 {
diagnostic["stderr"] = string(e.Stderr)
}
}
t.YAML(diagnostic)
}
}
}

Expand Down
68 changes: 38 additions & 30 deletions validation/util/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (r *Runtime) SetID(id string) {
}

// Create a container
func (r *Runtime) Create() (stderr []byte, err error) {
func (r *Runtime) Create() (err error) {
var args []string
args = append(args, "create")
if r.ID != "" {
Expand All @@ -74,25 +74,29 @@ func (r *Runtime) Create() (stderr []byte, err error) {
id := uuid.NewV4().String()
r.stdout, err = os.OpenFile(filepath.Join(r.bundleDir(), fmt.Sprintf("stdout-%s", id)), os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600)
if err != nil {
return []byte(""), err
return err
}
cmd.Stdout = r.stdout
r.stderr, err = os.OpenFile(filepath.Join(r.bundleDir(), fmt.Sprintf("stderr-%s", id)), os.O_CREATE|os.O_EXCL|os.O_RDWR, 0600)
if err != nil {
return []byte(""), err
return err
}
cmd.Stderr = r.stderr

err = cmd.Run()
if err == nil {
return []byte(""), err
return err
}

stdout, stderr, _ := r.ReadStandardStreams()
if len(stderr) == 0 {
stderr = stdout
if e, ok := err.(*exec.ExitError); ok {
stdout, stderr, _ := r.ReadStandardStreams()
if len(stderr) == 0 {
stderr = stdout
}
e.Stderr = stderr
return e
}
return stderr, err
return err
}

// ReadStandardStreams collects content from the stdout and stderr buffers.
Expand All @@ -111,23 +115,15 @@ func (r *Runtime) ReadStandardStreams() (stdout []byte, stderr []byte, err error
}

// Start a container
func (r *Runtime) Start() (stderr []byte, err error) {
func (r *Runtime) Start() (err error) {
var args []string
args = append(args, "start")
if r.ID != "" {
args = append(args, r.ID)
}

cmd := exec.Command(r.RuntimeCommand, args...)
stdout, err := cmd.Output()
if e, ok := err.(*exec.ExitError); ok {
stderr = e.Stderr
}
if err != nil && len(stderr) == 0 {
stderr = stdout
}

return stderr, err
return execWithStderrFallbackToStdout(cmd)
}

// State a container information
Expand All @@ -140,6 +136,12 @@ func (r *Runtime) State() (rspecs.State, error) {

out, err := exec.Command(r.RuntimeCommand, args...).Output()
if err != nil {
if e, ok := err.(*exec.ExitError); ok {
if len(e.Stderr) == 0 {
e.Stderr = out
return rspecs.State{}, e
}
}
return rspecs.State{}, err
}

Expand All @@ -149,32 +151,23 @@ func (r *Runtime) State() (rspecs.State, error) {
}

// Delete a container
func (r *Runtime) Delete() ([]byte, error) {
func (r *Runtime) Delete() (err error) {
var args []string
var stderr []byte
args = append(args, "delete")
if r.ID != "" {
args = append(args, r.ID)
}

cmd := exec.Command(r.RuntimeCommand, args...)
stdout, err := cmd.Output()
if e, ok := err.(*exec.ExitError); ok {
stderr = e.Stderr
}
if err != nil && len(stderr) == 0 {
stderr = stdout
}

return stderr, err
return execWithStderrFallbackToStdout(cmd)
}

// Clean deletes the container. If removeBundle is set, the bundle
// directory is removed after the container is deleted succesfully or, if
// forceRemoveBundle is true, after the deletion attempt regardless of
// whether it was successful or not.
func (r *Runtime) Clean(removeBundle bool, forceRemoveBundle bool) error {
_, err := r.Delete()
err := r.Delete()

if removeBundle && (err == nil || forceRemoveBundle) {
err2 := os.RemoveAll(r.bundleDir())
Expand All @@ -185,3 +178,18 @@ func (r *Runtime) Clean(removeBundle bool, forceRemoveBundle bool) error {

return err
}

func execWithStderrFallbackToStdout(cmd *exec.Cmd) (err error) {
stdout, err := cmd.Output()
if err == nil {
return err
}

if e, ok := err.(*exec.ExitError); ok {
if len(e.Stderr) == 0 {
e.Stderr = stdout
return e
}
}
return err
}
36 changes: 24 additions & 12 deletions validation/util/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,12 @@ func RuntimeInsideValidate(g *generate.Generator, f PreFunc) (err error) {
}

r.SetID(uuid.NewV4().String())
stderr, err := r.Create()
err = r.Create()
if err != nil {
os.Stderr.WriteString("failed to create the container\n")
os.Stderr.Write(stderr)
if e, ok := err.(*exec.ExitError); ok && len(e.Stderr) > 0 {
os.Stderr.Write(e.Stderr)
}
return err
}

Expand All @@ -186,10 +188,12 @@ func RuntimeInsideValidate(g *generate.Generator, f PreFunc) (err error) {
// container "..." does not exist
time.Sleep(1 * time.Second)

stderr, err = r.Start()
err = r.Start()
if err != nil {
os.Stderr.WriteString("failed to start the container\n")
os.Stderr.Write(stderr)
if e, ok := err.(*exec.ExitError); ok && len(e.Stderr) > 0 {
os.Stderr.Write(e.Stderr)
}
return err
}

Expand Down Expand Up @@ -233,10 +237,12 @@ func RuntimeOutsideValidate(g *generate.Generator, f AfterFunc) error {
}

r.SetID(uuid.NewV4().String())
stderr, err := r.Create()
err = r.Create()
if err != nil {
os.Stderr.WriteString("failed to create the container\n")
os.Stderr.Write(stderr)
if e, ok := err.(*exec.ExitError); ok && len(e.Stderr) > 0 {
os.Stderr.Write(e.Stderr)
}
return err
}

Expand Down Expand Up @@ -277,10 +283,12 @@ func RuntimeLifecycleValidate(g *generate.Generator, config LifecycleConfig) err
}

if config.Actions&LifecycleActionCreate != 0 {
stderr, err := r.Create()
err := r.Create()
if err != nil {
os.Stderr.WriteString("failed to create the container\n")
os.Stderr.Write(stderr)
if e, ok := err.(*exec.ExitError); ok && len(e.Stderr) > 0 {
os.Stderr.Write(e.Stderr)
}
return err
}
}
Expand All @@ -292,10 +300,12 @@ func RuntimeLifecycleValidate(g *generate.Generator, config LifecycleConfig) err
}

if config.Actions&LifecycleActionStart != 0 {
stderr, err := r.Start()
err := r.Start()
if err != nil {
os.Stderr.WriteString("failed to start the container\n")
os.Stderr.Write(stderr)
if e, ok := err.(*exec.ExitError); ok && len(e.Stderr) > 0 {
os.Stderr.Write(e.Stderr)
}
return err
}
}
Expand All @@ -307,10 +317,12 @@ func RuntimeLifecycleValidate(g *generate.Generator, config LifecycleConfig) err
}

if config.Actions&LifecycleActionDelete != 0 {
stderr, err := r.Delete()
err := r.Delete()
if err != nil {
os.Stderr.WriteString("failed to delete the container\n")
os.Stderr.Write(stderr)
if e, ok := err.(*exec.ExitError); ok && len(e.Stderr) > 0 {
os.Stderr.Write(e.Stderr)
}
return err
}
}
Expand Down