summaryrefslogtreecommitdiff
path: root/pkg/domain/infra
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/domain/infra')
-rw-r--r--pkg/domain/infra/abi/containers.go116
-rw-r--r--pkg/domain/infra/abi/images.go14
-rw-r--r--pkg/domain/infra/abi/images_list.go24
-rw-r--r--pkg/domain/infra/abi/manifest.go85
-rw-r--r--pkg/domain/infra/abi/network.go16
-rw-r--r--pkg/domain/infra/abi/play.go18
-rw-r--r--pkg/domain/infra/abi/system_varlink.go2
-rw-r--r--pkg/domain/infra/abi/terminal/terminal.go2
-rw-r--r--pkg/domain/infra/abi/volumes.go2
-rw-r--r--pkg/domain/infra/runtime_libpod.go17
-rw-r--r--pkg/domain/infra/tunnel/containers.go108
-rw-r--r--pkg/domain/infra/tunnel/events.go32
-rw-r--r--pkg/domain/infra/tunnel/helpers.go4
-rw-r--r--pkg/domain/infra/tunnel/images.go108
-rw-r--r--pkg/domain/infra/tunnel/network.go11
-rw-r--r--pkg/domain/infra/tunnel/volumes.go2
16 files changed, 325 insertions, 236 deletions
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 21618f555..8b0d53940 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -1142,12 +1142,12 @@ func (ic *ContainerEngine) Shutdown(_ context.Context) {
})
}
-func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []string, options entities.ContainerStatsOptions) error {
- defer close(options.StatChan)
+func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []string, options entities.ContainerStatsOptions) (statsChan chan entities.ContainerStatsReport, err error) {
+ statsChan = make(chan entities.ContainerStatsReport, 1)
+
containerFunc := ic.Libpod.GetRunningContainers
+ queryAll := false
switch {
- case len(namesOrIds) > 0:
- containerFunc = func() ([]*libpod.Container, error) { return ic.Libpod.GetContainersByList(namesOrIds) }
case options.Latest:
containerFunc = func() ([]*libpod.Container, error) {
lastCtr, err := ic.Libpod.GetLatestContainer()
@@ -1156,62 +1156,76 @@ func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []stri
}
return []*libpod.Container{lastCtr}, nil
}
- case options.All:
+ case len(namesOrIds) > 0:
+ containerFunc = func() ([]*libpod.Container, error) { return ic.Libpod.GetContainersByList(namesOrIds) }
+ default:
+ // No containers, no latest -> query all!
+ queryAll = true
containerFunc = ic.Libpod.GetAllContainers
}
- ctrs, err := containerFunc()
- if err != nil {
- return errors.Wrapf(err, "unable to get list of containers")
- }
- containerStats := map[string]*define.ContainerStats{}
- for _, ctr := range ctrs {
- initialStats, err := ctr.GetContainerStats(&define.ContainerStats{})
- if err != nil {
- // when doing "all", don't worry about containers that are not running
- cause := errors.Cause(err)
- if options.All && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) {
- continue
- }
- if cause == cgroups.ErrCgroupV1Rootless {
- err = cause
- }
- return err
+ go func() {
+ defer close(statsChan)
+ var (
+ err error
+ containers []*libpod.Container
+ containerStats map[string]*define.ContainerStats
+ )
+ containerStats = make(map[string]*define.ContainerStats)
+
+ stream: // label to flatten the scope
+ select {
+ case <-ctx.Done():
+ // client cancelled
+ logrus.Debugf("Container stats stopped: context cancelled")
+ return
+ default:
+ // just fall through and do work
}
- containerStats[ctr.ID()] = initialStats
- }
- for {
- reportStats := []*define.ContainerStats{}
- for _, ctr := range ctrs {
- id := ctr.ID()
- if _, ok := containerStats[ctr.ID()]; !ok {
- initialStats, err := ctr.GetContainerStats(&define.ContainerStats{})
- if errors.Cause(err) == define.ErrCtrRemoved || errors.Cause(err) == define.ErrNoSuchCtr || errors.Cause(err) == define.ErrCtrStateInvalid {
- // skip dealing with a container that is gone
- continue
+
+ // Anonymous func to easily use the return values for streaming.
+ computeStats := func() ([]define.ContainerStats, error) {
+ containers, err = containerFunc()
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to get list of containers")
+ }
+
+ reportStats := []define.ContainerStats{}
+ for _, ctr := range containers {
+ prev, ok := containerStats[ctr.ID()]
+ if !ok {
+ prev = &define.ContainerStats{}
}
+
+ stats, err := ctr.GetContainerStats(prev)
if err != nil {
- return err
+ cause := errors.Cause(err)
+ if queryAll && (cause == define.ErrCtrRemoved || cause == define.ErrNoSuchCtr || cause == define.ErrCtrStateInvalid) {
+ continue
+ }
+ if cause == cgroups.ErrCgroupV1Rootless {
+ err = cause
+ }
+ return nil, err
}
- containerStats[id] = initialStats
- }
- stats, err := ctr.GetContainerStats(containerStats[id])
- if err != nil && errors.Cause(err) != define.ErrNoSuchCtr {
- return err
+
+ containerStats[ctr.ID()] = stats
+ reportStats = append(reportStats, *stats)
}
- // replace the previous measurement with the current one
- containerStats[id] = stats
- reportStats = append(reportStats, stats)
+ return reportStats, nil
}
- ctrs, err = containerFunc()
- if err != nil {
- return err
- }
- options.StatChan <- reportStats
- if options.NoStream {
- break
+
+ report := entities.ContainerStatsReport{}
+ report.Stats, report.Error = computeStats()
+ statsChan <- report
+
+ if report.Error != nil || !options.Stream {
+ return
}
+
time.Sleep(time.Second)
- }
- return nil
+ goto stream
+ }()
+
+ return statsChan, nil
}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 23aef9573..d56dc7d94 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -191,6 +191,15 @@ func (ir *ImageEngine) Unmount(ctx context.Context, nameOrIDs []string, options
reports := []*entities.ImageUnmountReport{}
for _, img := range images {
report := entities.ImageUnmountReport{Id: img.ID()}
+ mounted, _, err := img.Mounted()
+ if err != nil {
+ // Errors will be caught in Unmount call below
+ // Default assumption to mounted
+ mounted = true
+ }
+ if !mounted {
+ continue
+ }
if err := img.Unmount(options.Force); err != nil {
if options.All && errors.Cause(err) == storage.ErrLayerNotMounted {
logrus.Debugf("Error umounting image %s, storage.ErrLayerNotMounted", img.ID())
@@ -246,7 +255,7 @@ func pull(ctx context.Context, runtime *image.Runtime, rawImage string, options
}
if !options.AllTags {
- newImage, err := runtime.New(ctx, rawImage, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, label, util.PullImageAlways)
+ newImage, err := runtime.New(ctx, rawImage, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, label, options.PullPolicy)
if err != nil {
return nil, err
}
@@ -467,7 +476,7 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions)
}
func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOptions) (*entities.ImageImportReport, error) {
- id, err := ir.Libpod.Import(ctx, opts.Source, opts.Reference, opts.Changes, opts.Message, opts.Quiet)
+ id, err := ir.Libpod.Import(ctx, opts.Source, opts.Reference, opts.SignaturePolicy, opts.Changes, opts.Message, opts.Quiet)
if err != nil {
return nil, err
}
@@ -535,6 +544,7 @@ func (ir *ImageEngine) Config(_ context.Context) (*config.Config, error) {
}
func (ir *ImageEngine) Build(ctx context.Context, containerFiles []string, opts entities.BuildOptions) (*entities.BuildReport, error) {
+
id, _, err := ir.Libpod.Build(ctx, opts.BuildOptions, containerFiles...)
if err != nil {
return nil, err
diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go
index 7ec84246d..3e47dc67a 100644
--- a/pkg/domain/infra/abi/images_list.go
+++ b/pkg/domain/infra/abi/images_list.go
@@ -23,33 +23,13 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
summaries := []*entities.ImageSummary{}
for _, img := range images {
- var repoTags []string
- if opts.All {
- pairs, err := libpodImage.ReposToMap(img.Names())
- if err != nil {
- return nil, err
- }
-
- for repo, tags := range pairs {
- for _, tag := range tags {
- repoTags = append(repoTags, repo+":"+tag)
- }
- }
- } else {
- repoTags, err = img.RepoTags()
- if err != nil {
- return nil, err
- }
- }
-
digests := make([]string, len(img.Digests()))
for j, d := range img.Digests() {
digests[j] = string(d)
}
e := entities.ImageSummary{
- ID: img.ID(),
-
+ ID: img.ID(),
ConfigDigest: string(img.ConfigDigest),
Created: img.Created().Unix(),
Dangling: img.Dangling(),
@@ -61,7 +41,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
ReadOnly: img.IsReadOnly(),
SharedSize: 0,
VirtualSize: img.VirtualSize,
- RepoTags: repoTags,
+ RepoTags: img.Names(), // may include tags and digests
}
e.Labels, _ = img.Labels(context.TODO())
diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go
index 672d0a69f..6c518e678 100644
--- a/pkg/domain/infra/abi/manifest.go
+++ b/pkg/domain/infra/abi/manifest.go
@@ -3,6 +3,7 @@
package abi
import (
+ "bytes"
"context"
"encoding/json"
"fmt"
@@ -11,15 +12,17 @@ import (
"strings"
"github.com/containers/buildah/manifests"
+ buildahManifests "github.com/containers/buildah/pkg/manifests"
+ "github.com/containers/buildah/util"
buildahUtil "github.com/containers/buildah/util"
cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/manifest"
+ "github.com/containers/image/v5/transports"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
libpodImage "github.com/containers/podman/v2/libpod/image"
"github.com/containers/podman/v2/pkg/domain/entities"
- "github.com/containers/podman/v2/pkg/util"
"github.com/opencontainers/go-digest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
@@ -41,28 +44,82 @@ func (ir *ImageEngine) ManifestCreate(ctx context.Context, names, images []strin
// ManifestInspect returns the content of a manifest list or image
func (ir *ImageEngine) ManifestInspect(ctx context.Context, name string) ([]byte, error) {
- dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
- _, err := alltransports.ParseImageName(name)
+ if newImage, err := ir.Libpod.ImageRuntime().NewFromLocal(name); err == nil {
+ // return the manifest in local storage
+ if list, err := newImage.InspectManifest(); err == nil {
+ buf, err := json.MarshalIndent(list, "", " ")
+ if err != nil {
+ return buf, errors.Wrapf(err, "error rendering manifest %s for display", name)
+ }
+ return buf, nil
+ // no return if local image is not a list of images type
+ // continue on getting valid manifest through remote serice
+ } else if errors.Cause(err) != buildahManifests.ErrManifestTypeNotSupported {
+ return nil, errors.Wrapf(err, "loading manifest %q", name)
+ }
+ }
+ sc := ir.Libpod.SystemContext()
+ refs, err := util.ResolveNameToReferences(ir.Libpod.GetStore(), sc, name)
if err != nil {
- _, err = alltransports.ParseImageName(dockerPrefix + name)
+ return nil, err
+ }
+ var (
+ latestErr error
+ result []byte
+ manType string
+ b bytes.Buffer
+ )
+ appendErr := func(e error) {
+ if latestErr == nil {
+ latestErr = e
+ } else {
+ latestErr = errors.Wrapf(latestErr, "tried %v\n", e)
+ }
+ }
+ for _, ref := range refs {
+ src, err := ref.NewImageSource(ctx, sc)
+ if err != nil {
+ appendErr(errors.Wrapf(err, "reading image %q", transports.ImageName(ref)))
+ continue
+ }
+ defer src.Close()
+
+ manifestBytes, manifestType, err := src.GetManifest(ctx, nil)
if err != nil {
- return nil, errors.Errorf("invalid image reference %q", name)
+ appendErr(errors.Wrapf(err, "loading manifest %q", transports.ImageName(ref)))
+ continue
}
+
+ if !manifest.MIMETypeIsMultiImage(manifestType) {
+ appendErr(errors.Errorf("manifest is of type %s (not a list type)", manifestType))
+ continue
+ }
+ result = manifestBytes
+ manType = manifestType
+ break
}
- image, err := ir.Libpod.ImageRuntime().New(ctx, name, "", "", nil, nil, libpodImage.SigningOptions{}, nil, util.PullImageMissing)
- if err != nil {
- return nil, errors.Wrapf(err, "reading image %q", name)
+ if len(result) == 0 && latestErr != nil {
+ return nil, latestErr
}
+ if manType != manifest.DockerV2ListMediaType {
+ listBlob, err := manifest.ListFromBlob(result, manType)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing manifest blob %q as a %q", string(result), manType)
+ }
+ list, err := listBlob.ConvertToMIMEType(manifest.DockerV2ListMediaType)
+ if err != nil {
+ return nil, err
+ }
+ if result, err = list.Serialize(); err != nil {
+ return nil, err
+ }
- list, err := image.InspectManifest()
- if err != nil {
- return nil, errors.Wrapf(err, "loading manifest %q", name)
}
- buf, err := json.MarshalIndent(list, "", " ")
+ err = json.Indent(&b, result, "", " ")
if err != nil {
- return buf, errors.Wrapf(err, "error rendering manifest for display")
+ return nil, errors.Wrapf(err, "error rendering manifest %s for display", name)
}
- return buf, nil
+ return b.Bytes(), nil
}
// ManifestAdd adds images to the manifest list
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index 807e4b272..5acfea853 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -12,6 +12,7 @@ import (
"github.com/containernetworking/cni/libcni"
cniversion "github.com/containernetworking/cni/pkg/version"
"github.com/containers/podman/v2/libpod"
+ "github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/network"
"github.com/containers/podman/v2/pkg/util"
@@ -82,12 +83,21 @@ func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, o
// 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 user passes force, we nuke containers and pods
if !options.Force {
// Without the force option, we return an error
- return reports, errors.Errorf("%q has associated containers with it. Use -f to forcibly delete containers", name)
+ return reports, errors.Wrapf(define.ErrNetworkInUse, "%q has associated containers with it. Use -f to forcibly delete containers and pods", name)
}
- if err := ic.Libpod.RemoveContainer(ctx, c, true, true); err != nil {
+ if c.IsInfra() {
+ // if we have a infra container we need to remove the pod
+ pod, err := ic.Libpod.GetPod(c.PodID())
+ if err != nil {
+ return reports, err
+ }
+ if err := ic.Libpod.RemovePod(ctx, pod, true, true); err != nil {
+ return reports, err
+ }
+ } else if err := ic.Libpod.RemoveContainer(ctx, c, true, true); err != nil {
return reports, err
}
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 6dfb52c63..aa6aeede2 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -132,6 +132,11 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
libpod.WithInfraContainer(),
libpod.WithPodName(podName),
}
+
+ if podYAML.ObjectMeta.Labels != nil {
+ podOptions = append(podOptions, libpod.WithPodLabels(podYAML.ObjectMeta.Labels))
+ }
+
// TODO we only configure Process namespace. We also need to account for Host{IPC,Network,PID}
// which is not currently possible with pod create
if podYAML.Spec.ShareProcessNamespace != nil && *podYAML.Spec.ShareProcessNamespace {
@@ -294,6 +299,18 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
return nil, err
}
+ var ctrRestartPolicy string
+ switch podYAML.Spec.RestartPolicy {
+ case v1.RestartPolicyAlways:
+ ctrRestartPolicy = libpod.RestartPolicyAlways
+ case v1.RestartPolicyOnFailure:
+ ctrRestartPolicy = libpod.RestartPolicyOnFailure
+ case v1.RestartPolicyNever:
+ ctrRestartPolicy = libpod.RestartPolicyNo
+ default: // Default to Always
+ ctrRestartPolicy = libpod.RestartPolicyAlways
+ }
+
containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers))
for _, container := range podYAML.Spec.Containers {
pullPolicy := util.PullImageMissing
@@ -321,6 +338,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
if err != nil {
return nil, err
}
+ conf.RestartPolicy = ctrRestartPolicy
ctr, err := createconfig.CreateContainerFromCreateConfig(ctx, ic.Libpod, conf, pod)
if err != nil {
return nil, err
diff --git a/pkg/domain/infra/abi/system_varlink.go b/pkg/domain/infra/abi/system_varlink.go
index d0a5c5407..ead84fc84 100644
--- a/pkg/domain/infra/abi/system_varlink.go
+++ b/pkg/domain/infra/abi/system_varlink.go
@@ -22,7 +22,7 @@ func (ic *ContainerEngine) VarlinkService(_ context.Context, opts entities.Servi
service, err := varlink.NewService(
"Atomic",
"podman",
- version.Version,
+ version.Version.String(),
"https://github.com/containers/podman",
)
if err != nil {
diff --git a/pkg/domain/infra/abi/terminal/terminal.go b/pkg/domain/infra/abi/terminal/terminal.go
index 0b6e57f49..48f5749d5 100644
--- a/pkg/domain/infra/abi/terminal/terminal.go
+++ b/pkg/domain/infra/abi/terminal/terminal.go
@@ -6,7 +6,7 @@ import (
"os/signal"
lsignal "github.com/containers/podman/v2/pkg/signal"
- "github.com/docker/docker/pkg/term"
+ "github.com/moby/term"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"k8s.io/client-go/tools/remotecommand"
diff --git a/pkg/domain/infra/abi/volumes.go b/pkg/domain/infra/abi/volumes.go
index 340f00953..946f258af 100644
--- a/pkg/domain/infra/abi/volumes.go
+++ b/pkg/domain/infra/abi/volumes.go
@@ -120,7 +120,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
return reports, nil
}
-func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) {
+func (ic *ContainerEngine) VolumePrune(ctx context.Context) ([]*entities.VolumePruneReport, error) {
return ic.pruneVolumesHelper(ctx)
}
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index f9b8106ef..26c9c7e2e 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -227,23 +227,6 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
// TODO flag to set CNI plugins dir?
- // TODO I don't think these belong here?
- // Will follow up with a different PR to address
- //
- // Pod create options
-
- infraImageFlag := fs.Lookup("infra-image")
- if infraImageFlag != nil && infraImageFlag.Changed {
- infraImage, _ := fs.GetString("infra-image")
- options = append(options, libpod.WithDefaultInfraImage(infraImage))
- }
-
- infraCommandFlag := fs.Lookup("infra-command")
- if infraCommandFlag != nil && infraImageFlag.Changed {
- infraCommand, _ := fs.GetString("infra-command")
- options = append(options, libpod.WithDefaultInfraCommand(infraCommand))
- }
-
if !opts.withFDS {
options = append(options, libpod.WithEnableSDNotify())
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 35550b9be..9b03503c6 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -35,7 +35,7 @@ func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrID string)
}
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
- cons, err := getContainersByContext(ic.ClientCxt, false, namesOrIds)
+ cons, err := getContainersByContext(ic.ClientCxt, false, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -54,7 +54,7 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -67,7 +67,7 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
}
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -89,8 +89,8 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
id := strings.Split(string(content), "\n")[0]
namesOrIds = append(namesOrIds, id)
}
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
- if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) {
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, options.Ignore, namesOrIds)
+ if err != nil {
return nil, err
}
for _, c := range ctrs {
@@ -120,7 +120,7 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -144,7 +144,7 @@ func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []st
timeout = &t
}
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -169,8 +169,8 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
id := strings.Split(string(content), "\n")[0]
namesOrIds = append(namesOrIds, id)
}
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
- if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) {
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, options.Ignore, namesOrIds)
+ if err != nil {
return nil, err
}
// TODO there is no endpoint for container eviction. Need to discuss
@@ -283,7 +283,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
)
if options.All {
- allCtrs, err := getContainersByContext(ic.ClientCxt, true, []string{})
+ allCtrs, err := getContainersByContext(ic.ClientCxt, true, false, []string{})
if err != nil {
return nil, err
}
@@ -295,7 +295,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
}
} else {
- ctrs, err = getContainersByContext(ic.ClientCxt, false, namesOrIds)
+ ctrs, err = getContainersByContext(ic.ClientCxt, false, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -317,7 +317,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
ctrs = []entities.ListContainer{}
)
if options.All {
- allCtrs, err := getContainersByContext(ic.ClientCxt, true, []string{})
+ allCtrs, err := getContainersByContext(ic.ClientCxt, true, false, []string{})
if err != nil {
return nil, err
}
@@ -329,7 +329,7 @@ func (ic *ContainerEngine) ContainerRestore(ctx context.Context, namesOrIds []st
}
} else {
- ctrs, err = getContainersByContext(ic.ClientCxt, false, namesOrIds)
+ ctrs, err = getContainersByContext(ic.ClientCxt, false, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -389,6 +389,15 @@ func (ic *ContainerEngine) ContainerLogs(_ context.Context, nameOrIDs []string,
}
func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrID string, options entities.AttachOptions) error {
+ ctrs, err := getContainersByContext(ic.ClientCxt, false, false, []string{nameOrID})
+ if err != nil {
+ return err
+ }
+ ctr := ctrs[0]
+ if ctr.State != define.ContainerStateRunning.String() {
+ return errors.Errorf("you can only attach to running containers")
+ }
+
return containers.Attach(ic.ClientCxt, nameOrID, &options.DetachKeys, nil, bindings.PTrue, options.Stdin, options.Stdout, options.Stderr, nil)
}
@@ -472,27 +481,67 @@ func startAndAttach(ic *ContainerEngine, name string, detachKeys *string, input,
func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []string, options entities.ContainerStartOptions) ([]*entities.ContainerStartReport, error) {
reports := []*entities.ContainerStartReport{}
- for _, name := range namesOrIds {
+ var exitCode = define.ExecErrorCodeGeneric
+ ctrs, err := getContainersByContext(ic.ClientCxt, false, false, namesOrIds)
+ if err != nil {
+ return nil, err
+ }
+ // There can only be one container if attach was used
+ for i, ctr := range ctrs {
+ name := ctr.ID
report := entities.ContainerStartReport{
Id: name,
- RawInput: name,
- ExitCode: 125,
+ RawInput: namesOrIds[i],
+ ExitCode: exitCode,
}
+ ctrRunning := ctr.State == define.ContainerStateRunning.String()
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)
+ err = startAndAttach(ic, name, &options.DetachKeys, options.Stdin, options.Stdout, options.Stderr)
+ if err == define.ErrDetach {
+ // User manually detached
+ // Exit cleanly immediately
+ report.Err = err
+ reports = append(reports, &report)
+ return reports, nil
+ }
+ if ctrRunning {
+ reports = append(reports, &report)
+ return reports, nil
+ }
+
+ if err != nil {
+ report.ExitCode = define.ExitCode(report.Err)
+ report.Err = err
+ reports = append(reports, &report)
+ return reports, errors.Wrapf(report.Err, "unable to start container %s", name)
+ }
+ exitCode, err := containers.Wait(ic.ClientCxt, name, nil)
+ if err == define.ErrNoSuchCtr {
+ // Check events
+ event, err := ic.GetLastContainerEvent(ctx, name, events.Exited)
+ if err != nil {
+ logrus.Errorf("Cannot get exit code: %v", err)
+ report.ExitCode = define.ExecErrorCodeNotFound
+ } else {
+ report.ExitCode = event.ContainerExitCode
}
} else {
- report.ExitCode = define.ExitCode(report.Err)
+ report.ExitCode = int(exitCode)
}
reports = append(reports, &report)
return reports, nil
}
- report.Err = containers.Start(ic.ClientCxt, name, &options.DetachKeys)
- report.ExitCode = define.ExitCode(report.Err)
+ // Start the container if it's not running already.
+ if !ctrRunning {
+ err = containers.Start(ic.ClientCxt, name, &options.DetachKeys)
+ if err != nil {
+ report.Err = errors.Wrapf(err, "unable to start container %q", name)
+ report.ExitCode = define.ExitCode(err)
+ reports = append(reports, &report)
+ continue
+ }
+ }
+ report.ExitCode = 0
reports = append(reports, &report)
}
return reports, nil
@@ -607,7 +656,7 @@ func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []st
}
func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) {
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -647,7 +696,7 @@ func (ic *ContainerEngine) ContainerPort(ctx context.Context, nameOrID string, o
if len(nameOrID) > 0 {
namesOrIds = append(namesOrIds, nameOrID)
}
- ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, false, namesOrIds)
if err != nil {
return nil, err
}
@@ -673,6 +722,9 @@ func (ic *ContainerEngine) ContainerCp(ctx context.Context, source, dest string,
func (ic *ContainerEngine) Shutdown(_ context.Context) {
}
-func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []string, options entities.ContainerStatsOptions) error {
- return errors.New("not implemented")
+func (ic *ContainerEngine) ContainerStats(ctx context.Context, namesOrIds []string, options entities.ContainerStatsOptions) (statsChan chan entities.ContainerStatsReport, err error) {
+ if options.Latest {
+ return nil, errors.New("latest is not supported for the remote client")
+ }
+ return containers.Stats(ic.ClientCxt, namesOrIds, &options.Stream)
}
diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go
index e6f4834b9..53bae6cef 100644
--- a/pkg/domain/infra/tunnel/events.go
+++ b/pkg/domain/infra/tunnel/events.go
@@ -2,8 +2,10 @@ package tunnel
import (
"context"
+ // "fmt"
"strings"
+ "github.com/containers/podman/v2/libpod/events"
"github.com/containers/podman/v2/pkg/bindings/system"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/pkg/errors"
@@ -29,3 +31,33 @@ func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptio
}()
return system.Events(ic.ClientCxt, binChan, nil, &opts.Since, &opts.Until, filters, &opts.Stream)
}
+
+// GetLastContainerEvent takes a container name or ID and an event status and returns
+// the last occurrence of the container event
+func (ic *ContainerEngine) GetLastContainerEvent(ctx context.Context, nameOrID string, containerEvent events.Status) (*events.Event, error) {
+ // check to make sure the event.Status is valid
+ if _, err := events.StringToStatus(containerEvent.String()); err != nil {
+ return nil, err
+ }
+ var event events.Event
+ return &event, nil
+
+ /*
+ FIXME: We need new bindings for this section
+ filters := []string{
+ fmt.Sprintf("container=%s", nameOrID),
+ fmt.Sprintf("event=%s", containerEvent),
+ "type=container",
+ }
+
+ containerEvents, err := system.GetEvents(ctx, entities.EventsOptions{Filter: filters})
+ if err != nil {
+ return nil, err
+ }
+ if len(containerEvents) < 1 {
+ return nil, errors.Wrapf(events.ErrEventNotFound, "%s not found", containerEvent.String())
+ }
+ // return the last element in the slice
+ return containerEvents[len(containerEvents)-1], nil
+ */
+}
diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go
index 0c38a3326..5944f855a 100644
--- a/pkg/domain/infra/tunnel/helpers.go
+++ b/pkg/domain/infra/tunnel/helpers.go
@@ -13,7 +13,7 @@ import (
"github.com/pkg/errors"
)
-func getContainersByContext(contextWithConnection context.Context, all bool, namesOrIDs []string) ([]entities.ListContainer, error) {
+func getContainersByContext(contextWithConnection context.Context, all, ignore bool, namesOrIDs []string) ([]entities.ListContainer, error) {
var (
cons []entities.ListContainer
)
@@ -36,7 +36,7 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam
break
}
}
- if !found {
+ if !found && !ignore {
return nil, errors.Wrapf(define.ErrNoSuchCtr, "unable to find container %q", id)
}
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 185cc2f9a..61ac2141c 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -1,26 +1,19 @@
package tunnel
import (
- "archive/tar"
- "bytes"
"context"
- "io"
"io/ioutil"
"os"
- "path/filepath"
"strings"
"time"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
- "github.com/containers/podman/v2/pkg/bindings"
images "github.com/containers/podman/v2/pkg/bindings/images"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/utils"
utils2 "github.com/containers/podman/v2/utils"
- "github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
)
func (ir *ImageEngine) Exists(_ context.Context, nameOrID string) (*entities.BoolReport, error) {
@@ -145,13 +138,8 @@ func (ir *ImageEngine) Tag(ctx context.Context, nameOrID string, tags []string,
}
func (ir *ImageEngine) Untag(ctx context.Context, nameOrID string, tags []string, options entities.ImageUntagOptions) error {
- // Remove all tags if none are provided
if len(tags) == 0 {
- newImage, err := images.GetImage(ir.ClientCxt, nameOrID, bindings.PFalse)
- if err != nil {
- return err
- }
- tags = newImage.NamesHistory
+ return images.Untag(ir.ClientCxt, nameOrID, "", "")
}
for _, newTag := range tags {
@@ -205,6 +193,13 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions)
return nil, err
}
defer f.Close()
+ fInfo, err := f.Stat()
+ if err != nil {
+ return nil, err
+ }
+ if fInfo.IsDir() {
+ return nil, errors.Errorf("remote client supports archives only but %q is a directory", opts.Input)
+ }
ref := opts.Name
if len(opts.Tag) > 0 {
ref += ":" + opts.Tag
@@ -311,28 +306,23 @@ func (ir *ImageEngine) Config(_ context.Context) (*config.Config, error) {
return config.Default()
}
-func (ir *ImageEngine) Build(ctx context.Context, containerFiles []string, opts entities.BuildOptions) (*entities.BuildReport, error) {
- var tarReader io.Reader
- tarfile, err := archive.Tar(opts.ContextDirectory, 0)
- if err != nil {
- return nil, err
- }
- tarReader = tarfile
- cwd, err := os.Getwd()
+func (ir *ImageEngine) Build(_ context.Context, containerFiles []string, opts entities.BuildOptions) (*entities.BuildReport, error) {
+ report, err := images.Build(ir.ClientCxt, containerFiles, opts)
if err != nil {
return nil, err
}
- if cwd != opts.ContextDirectory {
- fn := func(h *tar.Header, r io.Reader) (data []byte, update bool, skip bool, err error) {
- h.Name = filepath.Join(filepath.Base(opts.ContextDirectory), h.Name)
- return nil, false, false, nil
- }
- tarReader, err = transformArchive(tarfile, false, fn)
+ // For remote clients, if the option for writing to a file was
+ // selected, we need to write to the *client's* filesystem.
+ if len(opts.IIDFile) > 0 {
+ f, err := os.Create(opts.IIDFile)
if err != nil {
return nil, err
}
+ if _, err := f.WriteString(report.ID); err != nil {
+ return nil, err
+ }
}
- return images.Build(ir.ClientCxt, containerFiles, opts, tarReader)
+ return report, nil
}
func (ir *ImageEngine) Tree(ctx context.Context, nameOrID string, opts entities.ImageTreeOptions) (*entities.ImageTreeReport, error) {
@@ -346,65 +336,3 @@ func (ir *ImageEngine) Shutdown(_ context.Context) {
func (ir *ImageEngine) Sign(ctx context.Context, names []string, options entities.SignOptions) (*entities.SignReport, error) {
return nil, errors.New("not implemented yet")
}
-
-// Sourced from openshift image builder
-
-// TransformFileFunc is given a chance to transform an arbitrary input file.
-type TransformFileFunc func(h *tar.Header, r io.Reader) (data []byte, update bool, skip bool, err error)
-
-// filterArchive transforms the provided input archive to a new archive,
-// giving the fn a chance to transform arbitrary files.
-func filterArchive(r io.Reader, w io.Writer, fn TransformFileFunc) error {
- tr := tar.NewReader(r)
- tw := tar.NewWriter(w)
-
- var body io.Reader = tr
-
- for {
- h, err := tr.Next()
- if err == io.EOF {
- return tw.Close()
- }
- if err != nil {
- return err
- }
-
- name := h.Name
- data, ok, skip, err := fn(h, tr)
- logrus.Debugf("Transform %q -> %q: data=%t ok=%t skip=%t err=%v", name, h.Name, data != nil, ok, skip, err)
- if err != nil {
- return err
- }
- if skip {
- continue
- }
- if ok {
- h.Size = int64(len(data))
- body = bytes.NewBuffer(data)
- }
- if err := tw.WriteHeader(h); err != nil {
- return err
- }
- if _, err := io.Copy(tw, body); err != nil {
- return err
- }
- }
-}
-
-func transformArchive(r io.Reader, compressed bool, fn TransformFileFunc) (io.Reader, error) {
- var cwe error
- pr, pw := io.Pipe()
- go func() {
- if compressed {
- in, err := archive.DecompressStream(r)
- if err != nil {
- cwe = pw.CloseWithError(err)
- return
- }
- r = in
- }
- err := filterArchive(r, pw, fn)
- cwe = pw.CloseWithError(err)
- }()
- return pr, cwe
-}
diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go
index 074425087..d155fdd9e 100644
--- a/pkg/domain/infra/tunnel/network.go
+++ b/pkg/domain/infra/tunnel/network.go
@@ -26,11 +26,16 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri
func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, options entities.NetworkRmOptions) ([]*entities.NetworkRmReport, error) {
reports := make([]*entities.NetworkRmReport, 0, len(namesOrIds))
for _, name := range namesOrIds {
- report, err := network.Remove(ic.ClientCxt, name, &options.Force)
+ response, err := network.Remove(ic.ClientCxt, name, &options.Force)
if err != nil {
- report[0].Err = err
+ report := &entities.NetworkRmReport{
+ Name: name,
+ Err: err,
+ }
+ reports = append(reports, report)
+ } else {
+ reports = append(reports, response...)
}
- reports = append(reports, report...)
}
return reports, nil
}
diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go
index ee2786330..e432d3292 100644
--- a/pkg/domain/infra/tunnel/volumes.go
+++ b/pkg/domain/infra/tunnel/volumes.go
@@ -56,7 +56,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
return reports, nil
}
-func (ic *ContainerEngine) VolumePrune(ctx context.Context, opts entities.VolumePruneOptions) ([]*entities.VolumePruneReport, error) {
+func (ic *ContainerEngine) VolumePrune(ctx context.Context) ([]*entities.VolumePruneReport, error) {
return volumes.Prune(ic.ClientCxt)
}