diff options
Diffstat (limited to 'pkg/adapter')
-rw-r--r-- | pkg/adapter/containers.go | 26 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 39 | ||||
-rw-r--r-- | pkg/adapter/network.go | 68 |
3 files changed, 90 insertions, 43 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 41607145d..47db5c0dc 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -341,12 +341,7 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode // if the container was created as part of a pod, also start its dependencies, if any. if err := ctr.Start(ctx, c.IsSet("pod")); err != nil { // This means the command did not exist - exitCode = 127 - e := strings.ToLower(err.Error()) - if strings.Contains(e, "permission denied") || strings.Contains(e, "operation not permitted") || strings.Contains(e, "file not found") || strings.Contains(e, "no such file or directory") { - exitCode = 126 - } - return exitCode, err + return define.ExitCode(err), err } fmt.Printf("%s\n", ctr.ID()) @@ -401,21 +396,14 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode // Do not perform cleanup, or wait for container exit code // Just exit immediately if errors.Cause(err) == define.ErrDetach { - exitCode = 0 - return exitCode, nil - } - // This means the command did not exist - exitCode = 127 - e := strings.ToLower(err.Error()) - if strings.Contains(e, "permission denied") || strings.Contains(e, "operation not permitted") { - exitCode = 126 + return 0, nil } if c.IsSet("rm") { if deleteError := r.Runtime.RemoveContainer(ctx, ctr, true, false); deleteError != nil { logrus.Debugf("unable to remove container %s after failing to start and attach to it", ctr.ID()) } } - return exitCode, err + return define.ExitCode(err), err } if ecode, err := ctr.Wait(); err != nil { @@ -424,7 +412,7 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode event, err := r.Runtime.GetLastContainerEvent(ctr.ID(), events.Exited) if err != nil { logrus.Errorf("Cannot get exit code: %v", err) - exitCode = 127 + exitCode = define.ExecErrorCodeNotFound } else { exitCode = event.ContainerExitCode } @@ -576,7 +564,7 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues) // Start will start a container func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigProxy bool) (int, error) { var ( - exitCode = 125 + exitCode = define.ExecErrorCodeGeneric lastError error ) @@ -636,7 +624,7 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP event, err := r.Runtime.GetLastContainerEvent(ctr.ID(), events.Exited) if err != nil { logrus.Errorf("Cannot get exit code: %v", err) - exitCode = 127 + exitCode = define.ExecErrorCodeNotFound } else { exitCode = event.ContainerExitCode } @@ -914,7 +902,7 @@ func (r *LocalRuntime) ExecContainer(ctx context.Context, cli *cliconfig.ExecVal cmd []string ) // default invalid command exit code - ec := 125 + ec := define.ExecErrorCodeGeneric if cli.Latest { if ctr, err = r.GetLatestContainer(); err != nil { diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index 590fef43f..01e008e87 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -464,19 +464,22 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode results := shared.NewIntermediateLayer(&c.PodmanCommand, true) cid, err := iopodman.CreateContainer().Call(r.Conn, results.MakeVarlink()) if err != nil { - return 0, err + return exitCode, err } if c.Bool("detach") { - _, err := iopodman.StartContainer().Call(r.Conn, cid) + if _, err := iopodman.StartContainer().Call(r.Conn, cid); err != nil { + return exitCode, err + } fmt.Println(cid) - return 0, err + return 0, nil } - errChan, err := r.attach(ctx, os.Stdin, os.Stdout, cid, true, c.String("detach-keys")) + exitChan, errChan, err := r.attach(ctx, os.Stdin, os.Stdout, cid, true, c.String("detach-keys")) if err != nil { - return 0, err + return exitCode, err } + exitCode = <-exitChan finalError := <-errChan - return 0, finalError + return exitCode, finalError } func ReadExitFile(runtimeTmp, ctrID string) (int, error) { @@ -572,7 +575,7 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er return err } } - errChan, err := r.attach(ctx, inputStream, os.Stdout, c.InputArgs[0], false, c.DetachKeys) + _, errChan, err := r.attach(ctx, inputStream, os.Stdout, c.InputArgs[0], false, c.DetachKeys) if err != nil { return err } @@ -669,7 +672,7 @@ func (r *LocalRuntime) Restore(ctx context.Context, c *cliconfig.RestoreValues) func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigProxy bool) (int, error) { var ( finalErr error - exitCode = 125 + exitCode = define.ExecErrorCodeGeneric ) // TODO Figure out how to deal with exit codes inputStream := os.Stdin @@ -686,12 +689,13 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP } // start.go makes sure that if attach, there can be only one ctr if c.Attach { - errChan, err := r.attach(ctx, inputStream, os.Stdout, containerIDs[0], true, c.DetachKeys) + exitChan, errChan, err := r.attach(ctx, inputStream, os.Stdout, containerIDs[0], true, c.DetachKeys) if err != nil { return exitCode, nil } + exitCode := <-exitChan err = <-errChan - return 0, err + return exitCode, err } // TODO the notion of starting a pod container and its deps still needs to be worked through @@ -710,13 +714,13 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP return exitCode, finalErr } -func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid string, start bool, detachKeys string) (chan error, error) { +func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid string, start bool, detachKeys string) (chan int, chan error, error) { var ( oldTermState *term.State ) spec, err := r.Spec(cid) if err != nil { - return nil, err + return nil, nil, err } resize := make(chan remotecommand.TerminalSize, 5) haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd())) @@ -726,7 +730,7 @@ func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid s if haveTerminal && spec.Process.Terminal { cancel, oldTermState, err := handleTerminalAttach(ctx, resize) if err != nil { - return nil, err + return nil, nil, err } defer cancel() defer restoreTerminal(oldTermState) @@ -738,7 +742,7 @@ func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid s reply, err := iopodman.Attach().Send(r.Conn, varlink.Upgrade, cid, detachKeys, start) if err != nil { restoreTerminal(oldTermState) - return nil, err + return nil, nil, err } // See if the server accepts the upgraded connection or returns an error @@ -746,11 +750,12 @@ func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid s if err != nil { restoreTerminal(oldTermState) - return nil, err + return nil, nil, err } - errChan := configureVarlinkAttachStdio(r.Conn.Reader, r.Conn.Writer, stdin, stdout, oldTermState, resize, nil) - return errChan, nil + ecChan := make(chan int, 1) + errChan := configureVarlinkAttachStdio(r.Conn.Reader, r.Conn.Writer, stdin, stdout, oldTermState, resize, ecChan) + return ecChan, errChan, nil } // PauseContainers pauses container(s) based on CLI inputs. diff --git a/pkg/adapter/network.go b/pkg/adapter/network.go index e4a160767..d407984ce 100644 --- a/pkg/adapter/network.go +++ b/pkg/adapter/network.go @@ -3,9 +3,9 @@ package adapter import ( + "context" "encoding/json" "fmt" - "github.com/containers/libpod/pkg/util" "io/ioutil" "os" "path/filepath" @@ -14,6 +14,7 @@ import ( cniversion "github.com/containernetworking/cni/pkg/version" "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/pkg/network" + "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" ) @@ -85,16 +86,69 @@ func (r *LocalRuntime) NetworkInspect(cli *cliconfig.NetworkInspectValues) error } // NetworkRemove deletes one or more CNI networks -func (r *LocalRuntime) NetworkRemove(cli *cliconfig.NetworkRmValues) error { +func (r *LocalRuntime) NetworkRemove(ctx context.Context, cli *cliconfig.NetworkRmValues) ([]string, map[string]error, error) { + var ( + networkRmSuccesses []string + lastError error + ) + networkRmErrors := make(map[string]error) + for _, name := range cli.InputArgs { - cniPath, err := network.GetCNIConfigPathByName(name) + containers, err := r.GetAllContainers() if err != nil { - return err + return networkRmSuccesses, networkRmErrors, err } - if err := os.Remove(cniPath); err != nil { - return err + if err := r.removeNetwork(ctx, name, containers, cli.Force); err != nil { + if lastError != nil { + networkRmErrors[name] = lastError + } + lastError = err + } else { + networkRmSuccesses = append(networkRmSuccesses, fmt.Sprintf("Deleted: %s\n", name)) + } + } + return networkRmSuccesses, networkRmErrors, lastError +} + +// removeNetwork removes a single network and its containers given a force bool +func (r *LocalRuntime) removeNetwork(ctx context.Context, name string, containers []*Container, force bool) error { + cniPath, err := network.GetCNIConfigPathByName(name) + if err != nil { + return err + } + // We need to iterate containers looking to see if they belong to the given network + for _, c := range containers { + if util.StringInSlice(name, c.Config().Networks) { + // if user passes force, we nuke containers + if force { + if err := r.RemoveContainer(ctx, c.Container, true, true); err != nil { + return err + } + } else { + // Without the the force option, we return an error + return errors.Errorf("%q has associated containers with it. use -f to forcibly delete containers", name) + } + } - fmt.Printf("Deleted: %s\n", name) + } + // Before we delete the configuration file, we need to make sure we can read and parse + // it to get the network interface name so we can remove that too + interfaceName, err := network.GetInterfaceNameFromConfig(cniPath) + if err != nil { + return errors.Wrapf(err, "failed to find network interface name in %q", cniPath) + } + liveNetworkNames, err := network.GetLiveNetworkNames() + if err != nil { + return errors.Wrapf(err, "failed to get live network names") + } + if util.StringInSlice(interfaceName, liveNetworkNames) { + if err := network.RemoveInterface(interfaceName); err != nil { + return errors.Wrapf(err, "failed to delete the network interface %q", interfaceName) + } + } + // Remove the configuration file + if err := os.Remove(cniPath); err != nil { + return errors.Wrapf(err, "failed to remove network configuration file %q", cniPath) } return nil } |