From ef8df00e6a651b26f886bc527012a2db9b187173 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Thu, 17 Aug 2017 10:23:54 -0400 Subject: [PATCH 1/3] kpod: shut down the storage library before exiting Before exiting, have kpod shut down the storage library if it can. This should keep us from leaving mountpoints for the root (for non-vfs cases) and run directory (with newer containers/storage) busy when testing kpod. Signed-off-by: Nalin Dahyabhai --- cmd/kpod/common.go | 13 +++++++++++++ cmd/kpod/diff.go | 1 + cmd/kpod/inspect.go | 1 + cmd/kpod/logs.go | 1 + cmd/kpod/main.go | 12 +++++++++++- cmd/kpod/rename.go | 1 + cmd/kpod/stats.go | 1 + libkpod/container_server.go | 5 ++++- 8 files changed, 33 insertions(+), 2 deletions(-) diff --git a/cmd/kpod/common.go b/cmd/kpod/common.go index 6d1f5299..d9aab97a 100644 --- a/cmd/kpod/common.go +++ b/cmd/kpod/common.go @@ -10,6 +10,10 @@ import ( "github.com/urfave/cli" ) +var ( + stores = make(map[storage.Store]struct{}) +) + func getStore(c *libkpod.Config) (storage.Store, error) { options := storage.DefaultStoreOptions options.GraphRoot = c.Root @@ -22,9 +26,18 @@ func getStore(c *libkpod.Config) (storage.Store, error) { return nil, err } is.Transport.SetStore(store) + stores[store] = struct{}{} return store, nil } +func shutdownStores() { + for store := range stores { + if _, err := store.Shutdown(false); err != nil { + break + } + } +} + func getConfig(c *cli.Context) (*libkpod.Config, error) { config := libkpod.DefaultConfig() if c.GlobalIsSet("config") { diff --git a/cmd/kpod/diff.go b/cmd/kpod/diff.go index f8592e71..fa8c1d56 100644 --- a/cmd/kpod/diff.go +++ b/cmd/kpod/diff.go @@ -86,6 +86,7 @@ func diffCmd(c *cli.Context) error { if err != nil { return errors.Wrapf(err, "could not get container server") } + defer server.Shutdown() to := c.Args().Get(0) changes, err := server.GetDiff("", to) diff --git a/cmd/kpod/inspect.go b/cmd/kpod/inspect.go index fe8d53b7..5371a495 100644 --- a/cmd/kpod/inspect.go +++ b/cmd/kpod/inspect.go @@ -71,6 +71,7 @@ func inspectCmd(c *cli.Context) error { if err != nil { return errors.Wrapf(err, "could not get container server") } + defer server.Shutdown() if err = server.Update(); err != nil { return errors.Wrapf(err, "could not update list of containers") } diff --git a/cmd/kpod/logs.go b/cmd/kpod/logs.go index 013f7642..995f91cd 100644 --- a/cmd/kpod/logs.go +++ b/cmd/kpod/logs.go @@ -69,6 +69,7 @@ func logsCmd(c *cli.Context) error { if err != nil { return errors.Wrapf(err, "could not create container server") } + defer server.Shutdown() err = server.Update() if err != nil { return errors.Wrapf(err, "could not update list of containers") diff --git a/cmd/kpod/main.go b/cmd/kpod/main.go index 7ee6d854..2aa29845 100644 --- a/cmd/kpod/main.go +++ b/cmd/kpod/main.go @@ -50,6 +50,16 @@ func main() { } return nil } + app.After = func(*cli.Context) error { + // called by Run() when the command handler succeeds + shutdownStores() + return nil + } + cli.OsExiter = func(code int) { + // called by Run() when the command fails, bypassing After() + shutdownStores() + os.Exit(code) + } app.Flags = []cli.Flag{ cli.StringFlag{ Name: "config, c", @@ -82,6 +92,6 @@ func main() { } if err := app.Run(os.Args); err != nil { logrus.Errorf(err.Error()) - os.Exit(1) + cli.OsExiter(1) } } diff --git a/cmd/kpod/rename.go b/cmd/kpod/rename.go index 8ef63419..fe1f08d9 100644 --- a/cmd/kpod/rename.go +++ b/cmd/kpod/rename.go @@ -32,6 +32,7 @@ func renameCmd(c *cli.Context) error { if err != nil { return errors.Wrapf(err, "could not get container server") } + defer server.Shutdown() err = server.Update() if err != nil { return errors.Wrapf(err, "could not update list of containers") diff --git a/cmd/kpod/stats.go b/cmd/kpod/stats.go index 10269f71..416acc93 100644 --- a/cmd/kpod/stats.go +++ b/cmd/kpod/stats.go @@ -70,6 +70,7 @@ func statsCmd(c *cli.Context) error { if err != nil { return errors.Wrapf(err, "could not create container server") } + defer containerServer.Shutdown() err = containerServer.Update() if err != nil { return errors.Wrapf(err, "could not update list of containers") diff --git a/libkpod/container_server.go b/libkpod/container_server.go index a495753e..3cf5e90b 100644 --- a/libkpod/container_server.go +++ b/libkpod/container_server.go @@ -570,7 +570,10 @@ func (c *ContainerServer) ReleasePodName(name string) { // Shutdown attempts to shut down the server's storage cleanly func (c *ContainerServer) Shutdown() error { _, err := c.store.Shutdown(false) - return err + if err != nil && errors.Cause(err) != cstorage.ErrLayerUsedByContainer { + return err + } + return nil } type containerServerState struct { From 178c1e9ccb2965c6edad72edd4753a76babc3161 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Thu, 17 Aug 2017 12:45:08 -0400 Subject: [PATCH 2/3] kpod.bats: correct syntax errors Correct some syntax errors in kpod.bats, ensure that it always checks the exit status of "kpod rmi" commands, correct the order of options when calling "kpod inspect", and test for string equality correctly. Signed-off-by: Nalin Dahyabhai --- test/kpod.bats | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test/kpod.bats b/test/kpod.bats index fd83e774..b851cf24 100644 --- a/test/kpod.bats +++ b/test/kpod.bats @@ -198,8 +198,9 @@ function teardown() { run bash -c "${KPOD_BINARY} $KPOD_OPTIONS inspect redis:alpine | python -m json.tool" echo "$output" [ "$status" -eq 0 ] -} run ${KPOD_BINARY} $KPOD_OPTIONS rmi redis:alpine + [ "$status" -eq 0 ] +} @test "kpod inspect non-existent container" { @@ -211,13 +212,14 @@ function teardown() { @test "kpod inspect with format" { run ${KPOD_BINARY} $KPOD_OPTIONS pull redis:alpine [ "$status" -eq 0 ] - run ${KPOD_BINARY} $KPOD_OPTIONS --format {{.ID}} inspect redis:alpine - [ "$status" -eq 0] + run ${KPOD_BINARY} $KPOD_OPTIONS inspect --format {{.ID}} redis:alpine + [ "$status" -eq 0 ] inspectOutput="$output" run ${KPOD_BINARY} $KPOD_OPTIONS images --quiet redis:alpine - [ "$status" -eq 0] - [ "$output" -eq "$inspectOutput" ] + [ "$status" -eq 0 ] + [ "$output" = "$inspectOutput" ] run ${KPOD_BINARY} $KPOD_OPTIONS rmi redis:alpine + [ "$status" -eq 0 ] } @test "kpod inspect specified type" { @@ -225,8 +227,9 @@ function teardown() { [ "$status" -eq 0 ] run bash -c "${KPOD_BINARY} $KPOD_OPTIONS inspect --type image redis:alpine | python -m json.tool" echo "$output" - [ "$status" -eq 0] + [ "$status" -eq 0 ] run ${KPOD_BINARY} $KPOD_OPTIONS rmi redis:alpine + [ "$status" -eq 0 ] } @test "kpod images" { @@ -245,6 +248,7 @@ function teardown() { @test "kpod images check name json output" { run ${KPOD_BINARY} $KPOD_OPTIONS pull debian:6.0.10 run ${KPOD_BINARY} $KPOD_OPTIONS images --format json + echo "$output" name=$(echo $output | python -c 'import sys; import json; print(json.loads(sys.stdin.read())[0])["names"][0]') - [ "$name" == "docker.io/library/debian:6.0.10" ] + [ "$name" = "docker.io/library/debian:6.0.10" ] } From 6f27dddf93d68cea2a24f76f9ad63588faf74b71 Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Thu, 17 Aug 2017 14:24:25 -0400 Subject: [PATCH 3/3] kpod images: output multiple image names Output multiple image names, if we have more than one. Signed-off-by: Nalin Dahyabhai --- cmd/kpod/images.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/kpod/images.go b/cmd/kpod/images.go index 457f9d8d..775ff679 100644 --- a/cmd/kpod/images.go +++ b/cmd/kpod/images.go @@ -137,9 +137,9 @@ func outputImages(store storage.Store, images []storage.Image, truncate, digests } createdTime := img.Created - name := "" + names := []string{""} if len(img.Names) > 0 { - name = img.Names[0] + names = img.Names } info, imageDigest, size, _ := libkpodimage.InfoAndDigestAndSize(store, img) @@ -149,7 +149,7 @@ func outputImages(store storage.Store, images []storage.Image, truncate, digests params := imageOutputParams{ ID: img.ID, - Name: name, + Name: names, Digest: imageDigest, CreatedAt: createdTime.Format("Jan 2, 2006 15:04"), Size: libkpodimage.FormattedSize(float64(size)), @@ -173,7 +173,7 @@ func outputImages(store storage.Store, images []storage.Image, truncate, digests type imageOutputParams struct { ID string `json:"id"` - Name string `json:"names"` + Name []string `json:"names"` Digest digest.Digest `json:"digest"` CreatedAt string `json:"created"` Size string `json:"size"`