diff --git a/cmd/ocm-backplane/console/console.go b/cmd/ocm-backplane/console/console.go index 159b36b3..790bbe52 100644 --- a/cmd/ocm-backplane/console/console.go +++ b/cmd/ocm-backplane/console/console.go @@ -17,6 +17,7 @@ limitations under the License. package console import ( + "bytes" "context" "encoding/base64" "fmt" @@ -57,6 +58,7 @@ type containerEngineInterface interface { // some container engines have special handlings for different types of containers runConsoleContainer(containerName string, port string, consoleArgs []string, envVars []envVar) error runMonitorPlugin(containerName string, consoleContainerName string, nginxConf string, pluginArgs []string) error + containerIsExist(containerName string) (bool, error) } type podmanLinux struct{} @@ -132,6 +134,8 @@ var ( // Pull Secret saving directory pullSecretConfigDirectory string + + ctx, cancel = context.WithCancel(context.Background()) ) func newConsoleOptions() *consoleOptions { @@ -242,25 +246,43 @@ func (o *consoleOptions) run(cmd *cobra.Command, argv []string) error { if err != nil { return err } - err = o.runConsoleContainer(ce) - if err != nil { - return err - } - err = o.runMonitorPlugin(ce) - if err != nil { - return err - } - err = o.printURL() - if err != nil { + + done := make(chan bool) + errs := make(chan error) + + go o.runContainers(ce, done, errs) + + if len(errs) != 0 { + err := <-errs return err } + err = o.cleanUp(ce) if err != nil { return err } + return nil } +func (o *consoleOptions) runContainers(ce containerEngineInterface, done chan bool, errs chan<- error) { + if err := o.runConsoleContainer(ce); err != nil { + + errs <- err + return + } + + if err := o.runMonitorPlugin(ce); err != nil { + errs <- err + } + + if err := o.printURL(); err != nil { + errs <- err + } + + close(done) +} + // Parse environment variables func (o *consoleOptions) determineOpenBrowser() error { if env, ok := os.LookupEnv(EnvBrowserDefault); ok { @@ -637,14 +659,22 @@ func (o *consoleOptions) cleanUp(ce containerEngineInterface) error { o.terminationFunction = &execActionOnTermStruct{} } + <-ctx.Done() err = o.terminationFunction.execActionOnTerminationFunction(func() error { for _, c := range containersToCleanUp { - err := ce.stopContainer(c) + exist, err := ce.containerIsExist(c) if err != nil { - return fmt.Errorf("failed to stop container %s: %v", c, err) + return fmt.Errorf("failed to check container exist %s: %v", c, err) + } + if exist { + err := ce.stopContainer(c) + if err != nil { + return fmt.Errorf("failed to stop container '%s' during the cleanup process: %v", c, err) + } + + logger.Infoln(fmt.Sprintf("Container removed: %s", c)) } - logger.Infoln(fmt.Sprintf("Container removed: %s", c)) } return nil }) @@ -1023,10 +1053,11 @@ func podmanRunConsoleContainer(containerName string, port string, consoleArgs [] } engRunArgs = append(engRunArgs, consoleArgs...) logger.WithField("Command", fmt.Sprintf("`%s %s`", PODMAN, strings.Join(engRunArgs, " "))).Infoln("Running container") - runCmd := createCommand(PODMAN, engRunArgs...) + + runCmd := exec.CommandContext(ctx, PODMAN, engRunArgs...) + defer cancel() runCmd.Stderr = os.Stderr runCmd.Stdout = nil - err = runCmd.Run() if err != nil { return err @@ -1290,6 +1321,30 @@ func generalStopContainer(containerEngine string, containerName string) error { return nil } +func generalContainerIsExist(containerEngine string, containerName string) (bool, error) { + var out bytes.Buffer + filter := fmt.Sprintf("name=%s", containerName) + existArgs := []string{ + "ps", + "-aq", + "--filter", + filter, + } + existCmd := createCommand(containerEngine, existArgs...) + existCmd.Stderr = os.Stderr + existCmd.Stdout = &out + + err := existCmd.Run() + + if err != nil { + return false, fmt.Errorf("failed to check container exist %s: %s", containerName, err) + } + if out.String() != "" { + return true, nil + } + return false, nil +} + // podman-stop for Linux func (ce *podmanLinux) stopContainer(containerName string) error { return generalStopContainer(PODMAN, containerName) @@ -1309,3 +1364,23 @@ func (ce *dockerLinux) stopContainer(containerName string) error { func (ce *dockerMac) stopContainer(containerName string) error { return generalStopContainer(DOCKER, containerName) } + +// podman-exist for Linux +func (ce *podmanLinux) containerIsExist(containerName string) (bool, error) { + return generalContainerIsExist(PODMAN, containerName) +} + +// podman-exist for MacOS +func (ce *podmanMac) containerIsExist(containerName string) (bool, error) { + return generalContainerIsExist(PODMAN, containerName) +} + +// docker-exist for Linux +func (ce *dockerLinux) containerIsExist(containerName string) (bool, error) { + return generalContainerIsExist(DOCKER, containerName) +} + +// docker-exist for MacOS +func (ce *dockerMac) containerIsExist(containerName string) (bool, error) { + return generalContainerIsExist(DOCKER, containerName) +} diff --git a/cmd/ocm-backplane/console/console_test.go b/cmd/ocm-backplane/console/console_test.go index d0fc4910..39ea44f5 100644 --- a/cmd/ocm-backplane/console/console_test.go +++ b/cmd/ocm-backplane/console/console_test.go @@ -7,7 +7,6 @@ import ( "github.com/golang/mock/gomock" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/spf13/cobra" "github.com/spf13/pflag" appsv1 "k8s.io/api/apps/v1" @@ -438,8 +437,12 @@ var _ = Describe("console command", func() { o.url = "http://127.0.0.2:1447" o.openBrowser = false o.containerEngineFlag = DOCKER - err1 := o.run(&cobra.Command{}, []string{}) - Expect(err1).To(BeNil()) + ce, err := o.getContainerEngineImpl() + Expect(err).To(BeNil()) + done := make(chan bool) + errs := make(chan error) + o.runContainers(ce, done, errs) + Expect(errs).To(BeEmpty()) os.Setenv("BACKPLANE_DEFAULT_OPEN_BROWSER", "") removePath(oldpath) })