summaryrefslogtreecommitdiff
path: root/pkg/domain/infra/tunnel/containers.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/domain/infra/tunnel/containers.go')
-rw-r--r--pkg/domain/infra/tunnel/containers.go132
1 files changed, 122 insertions, 10 deletions
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 49a3069d6..30c4a8359 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -4,14 +4,17 @@ import (
"context"
"io"
"os"
+ "strings"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/specgen"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
func (ic *ContainerEngine) ContainerRunlabel(ctx context.Context, label string, image string, args []string, options entities.ContainerRunlabelOptions) error {
@@ -84,10 +87,25 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
}
for _, c := range ctrs {
report := entities.StopReport{Id: c.ID}
- report.Err = containers.Stop(ic.ClientCxt, c.ID, &options.Timeout)
- // TODO we need to associate errors returned by http with common
- // define.errors so that we can equity tests. this will allow output
- // to be the same as the native client
+ if err = containers.Stop(ic.ClientCxt, c.ID, &options.Timeout); err != nil {
+ // These first two are considered non-fatal under the right conditions
+ if errors.Cause(err).Error() == define.ErrCtrStopped.Error() {
+ logrus.Debugf("Container %s is already stopped", c.ID)
+ reports = append(reports, &report)
+ continue
+ } else if options.All && errors.Cause(err).Error() == define.ErrCtrStateInvalid.Error() {
+ logrus.Debugf("Container %s is not running, could not stop", c.ID)
+ reports = append(reports, &report)
+ continue
+ }
+
+ // TODO we need to associate errors returned by http with common
+ // define.errors so that we can equity tests. this will allow output
+ // to be the same as the native client
+ report.Err = err
+ reports = append(reports, &report)
+ continue
+ }
reports = append(reports, &report)
}
return reports, nil
@@ -267,7 +285,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
}
}
for _, c := range ctrs {
- report, err := containers.Checkpoint(ic.ClientCxt, c.ID, &options.Keep, &options.LeaveRuninng, &options.TCPEstablished, &options.IgnoreRootFS, &options.Export)
+ report, err := containers.Checkpoint(ic.ClientCxt, c.ID, &options.Keep, &options.LeaveRunning, &options.TCPEstablished, &options.IgnoreRootFS, &options.Export)
if err != nil {
reports = append(reports, &entities.CheckpointReport{Id: c.ID, Err: err})
}
@@ -324,15 +342,59 @@ func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []strin
}
func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error {
- return errors.New("not implemented")
+ return containers.Attach(ic.ClientCxt, nameOrId, &options.DetachKeys, nil, bindings.PTrue, options.Stdin, options.Stdout, options.Stderr, nil)
}
-func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions) (int, error) {
+func (ic *ContainerEngine) ContainerExec(ctx context.Context, nameOrId string, options entities.ExecOptions, streams define.AttachStreams) (int, error) {
return 125, errors.New("not implemented")
}
+func (ic *ContainerEngine) ContainerExecDetached(ctx context.Context, nameOrID string, options entities.ExecOptions) (string, error) {
+ return "", errors.New("not implemented")
+}
+
+func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, input, output, errput *os.File) error { //nolint
+ attachErr := make(chan error)
+ attachReady := make(chan bool)
+ go func() {
+ err := containers.Attach(ic.ClientCxt, name, detachKeys, bindings.PFalse, bindings.PTrue, input, output, errput, attachReady)
+ attachErr <- err
+ }()
+ // Wait for the attach to actually happen before starting
+ // the container.
+ <-attachReady
+ if err := containers.Start(ic.ClientCxt, name, detachKeys); err != nil {
+ return err
+ }
+ return <-attachErr
+}
+
func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
- return nil, errors.New("not implemented")
+ var reports []*entities.ContainerStartReport
+ for _, name := range namesOrIds {
+ report := entities.ContainerStartReport{
+ Id: name,
+ RawInput: name,
+ ExitCode: 125,
+ }
+ if options.Attach {
+ report.Err = startAndAttach(ic, name, &options.DetachKeys, options.Stdin, options.Stdout, options.Stderr)
+ if report.Err == nil {
+ exitCode, err := containers.Wait(ic.ClientCxt, name, nil)
+ if err == nil {
+ report.ExitCode = int(exitCode)
+ }
+ } else {
+ report.ExitCode = define.ExitCode(report.Err)
+ }
+ reports = append(reports, &report)
+ return reports, nil
+ }
+ report.Err = containers.Start(ic.ClientCxt, name, &options.DetachKeys)
+ report.ExitCode = define.ExitCode(report.Err)
+ reports = append(reports, &report)
+ }
+ return reports, nil
}
func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.ContainerListOptions) ([]entities.ListContainer, error) {
@@ -340,7 +402,30 @@ func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.C
}
func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.ContainerRunOptions) (*entities.ContainerRunReport, error) {
- return nil, errors.New("not implemented")
+ if opts.Rm {
+ logrus.Info("the remote client does not support --rm yet")
+ }
+ con, err := containers.CreateWithSpec(ic.ClientCxt, opts.Spec)
+ if err != nil {
+ return nil, err
+ }
+ report := entities.ContainerRunReport{Id: con.ID}
+ // Attach
+ if !opts.Detach {
+ err = startAndAttach(ic, con.ID, &opts.DetachKeys, opts.InputStream, opts.OutputStream, opts.ErrorStream)
+ if err == nil {
+ exitCode, err := containers.Wait(ic.ClientCxt, con.ID, nil)
+ if err == nil {
+ report.ExitCode = int(exitCode)
+ }
+ }
+ } else {
+ err = containers.Start(ic.ClientCxt, con.ID, nil)
+ }
+ if err != nil {
+ report.ExitCode = define.ExitCode(err)
+ }
+ return &report, err
}
func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrId string, _ entities.DiffOptions) (*entities.DiffReport, error) {
@@ -360,6 +445,11 @@ func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []strin
}
for _, ctr := range ctrs {
err := containers.ContainerInit(ic.ClientCxt, ctr.ID)
+ // When using all, it is NOT considered an error if a container
+ // has already been init'd.
+ if err != nil && options.All && strings.Contains(errors.Cause(err).Error(), define.ErrCtrStateInvalid.Error()) {
+ err = nil
+ }
reports = append(reports, &entities.ContainerInitReport{
Err: err,
Id: ctr.ID,
@@ -381,7 +471,29 @@ func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) {
}
func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrId string, options entities.ContainerPortOptions) ([]*entities.ContainerPortReport, error) {
- return nil, errors.New("not implemented")
+ var (
+ reports []*entities.ContainerPortReport
+ namesOrIds []string
+ )
+ if len(nameOrId) > 0 {
+ namesOrIds = append(namesOrIds, nameOrId)
+ }
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ if err != nil {
+ return nil, err
+ }
+ for _, con := range ctrs {
+ if con.State != define.ContainerStateRunning.String() {
+ continue
+ }
+ if len(con.Ports) > 0 {
+ reports = append(reports, &entities.ContainerPortReport{
+ Id: con.ID,
+ Ports: con.Ports,
+ })
+ }
+ }
+ return reports, nil
}
func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string, options entities.ContainerCpOptions) (*entities.ContainerCpReport, error) {