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.go245
-rw-r--r--pkg/domain/infra/abi/events.go18
-rw-r--r--pkg/domain/infra/abi/images.go77
-rw-r--r--pkg/domain/infra/abi/images_list.go2
-rw-r--r--pkg/domain/infra/abi/pods.go8
-rw-r--r--pkg/domain/infra/abi/system.go215
-rw-r--r--pkg/domain/infra/runtime_abi.go4
-rw-r--r--pkg/domain/infra/runtime_image_proxy.go4
-rw-r--r--pkg/domain/infra/runtime_libpod.go58
-rw-r--r--pkg/domain/infra/runtime_proxy.go4
-rw-r--r--pkg/domain/infra/runtime_tunnel.go4
-rw-r--r--pkg/domain/infra/tunnel/containers.go47
-rw-r--r--pkg/domain/infra/tunnel/events.go31
-rw-r--r--pkg/domain/infra/tunnel/images.go22
-rw-r--r--pkg/domain/infra/tunnel/system.go26
15 files changed, 713 insertions, 52 deletions
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 828ee56f0..50003dbe2 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -4,23 +4,32 @@ package abi
import (
"context"
+ "fmt"
"io/ioutil"
+ "os"
"strconv"
"strings"
+ "sync"
+
+ lpfilters "github.com/containers/libpod/libpod/filters"
"github.com/containers/buildah"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/libpod/logs"
"github.com/containers/libpod/pkg/checkpoint"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi/terminal"
"github.com/containers/libpod/pkg/ps"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/containers/libpod/pkg/signal"
"github.com/containers/libpod/pkg/specgen"
"github.com/containers/libpod/pkg/specgen/generate"
+ "github.com/containers/storage"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -166,6 +175,28 @@ func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []strin
return reports, nil
}
+func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) {
+ var filterFuncs []libpod.ContainerFilter
+ for k, v := range options.Filters {
+ for _, val := range v {
+ generatedFunc, err := lpfilters.GenerateContainerFilterFuncs(k, val, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ filterFuncs = append(filterFuncs, generatedFunc)
+ }
+ }
+ prunedContainers, pruneErrors, err := ic.Libpod.PruneContainers(filterFuncs)
+ if err != nil {
+ return nil, err
+ }
+ report := entities.ContainerPruneReport{
+ ID: prunedContainers,
+ Err: pruneErrors,
+ }
+ return &report, nil
+}
+
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
var (
reports []*entities.KillReport
@@ -599,9 +630,9 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
ExitCode: 125,
}
if err := ctr.Start(ctx, ctr.PodID() != ""); err != nil {
- //if lastError != nil {
+ // if lastError != nil {
// fmt.Fprintln(os.Stderr, lastError)
- //}
+ // }
report.Err = err
if errors.Cause(err) == define.ErrWillDeadlock {
report.Err = errors.Wrapf(err, "please run 'podman system renumber' to resolve deadlocks")
@@ -623,10 +654,20 @@ func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.C
return ps.GetContainerLists(ic.Libpod, options)
}
+// ContainerDiff provides changes to given container
+func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrId string, opts entities.DiffOptions) (*entities.DiffReport, error) {
+ if opts.Latest {
+ ctnr, err := ic.Libpod.GetLatestContainer()
+ if err != nil {
+ return nil, errors.Wrap(err, "unable to get latest container")
+ }
+ nameOrId = ctnr.ID()
+ }
+ changes, err := ic.Libpod.GetDiff("", nameOrId)
+ return &entities.DiffReport{Changes: changes}, err
+}
+
func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.ContainerRunOptions) (*entities.ContainerRunReport, error) {
- var (
- joinPod bool
- )
if err := generate.CompleteSpec(ctx, ic.Libpod, opts.Spec); err != nil {
return nil, err
}
@@ -635,6 +676,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
return nil, err
}
+ var joinPod bool
if len(ctr.PodID()) > 0 {
joinPod = true
}
@@ -694,5 +736,198 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
} else {
report.ExitCode = int(ecode)
}
+ if opts.Rm {
+ if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true); err != nil {
+ if errors.Cause(err) == define.ErrNoSuchCtr ||
+ errors.Cause(err) == define.ErrCtrRemoved {
+ logrus.Warnf("Container %s does not exist: %v", ctr.ID(), err)
+ } else {
+ logrus.Errorf("Error removing container %s: %v", ctr.ID(), err)
+ }
+ }
+ }
return &report, nil
}
+
+func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []string, options entities.ContainerLogsOptions) error {
+ if options.Writer == nil {
+ return errors.New("no io.Writer set for container logs")
+ }
+
+ var wg sync.WaitGroup
+
+ ctrs, err := getContainersByContext(false, options.Latest, containers, ic.Libpod)
+ if err != nil {
+ return err
+ }
+
+ logOpts := &logs.LogOptions{
+ Multi: len(ctrs) > 1,
+ Details: options.Details,
+ Follow: options.Follow,
+ Since: options.Since,
+ Tail: options.Tail,
+ Timestamps: options.Timestamps,
+ UseName: options.Names,
+ WaitGroup: &wg,
+ }
+
+ chSize := len(ctrs) * int(options.Tail)
+ if chSize <= 0 {
+ chSize = 1
+ }
+ logChannel := make(chan *logs.LogLine, chSize)
+
+ if err := ic.Libpod.Log(ctrs, logOpts, logChannel); err != nil {
+ return err
+ }
+
+ go func() {
+ wg.Wait()
+ close(logChannel)
+ }()
+
+ for line := range logChannel {
+ fmt.Fprintln(options.Writer, line.String(logOpts))
+ }
+
+ return nil
+}
+
+func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) {
+ var reports []*entities.ContainerCleanupReport
+ ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ var err error
+ report := entities.ContainerCleanupReport{Id: ctr.ID()}
+ if options.Remove {
+ err = ic.Libpod.RemoveContainer(ctx, ctr, false, true)
+ if err != nil {
+ report.RmErr = errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID())
+ }
+ } else {
+ err := ctr.Cleanup(ctx)
+ if err != nil {
+ report.CleanErr = errors.Wrapf(err, "failed to cleanup container %v", ctr.ID())
+ }
+ }
+
+ if options.RemoveImage {
+ _, imageName := ctr.Image()
+ ctrImage, err := ic.Libpod.ImageRuntime().NewFromLocal(imageName)
+ if err != nil {
+ report.RmiErr = err
+ reports = append(reports, &report)
+ continue
+ }
+ _, err = ic.Libpod.RemoveImage(ctx, ctrImage, false)
+ report.RmiErr = err
+ }
+ reports = append(reports, &report)
+ }
+ return reports, nil
+}
+
+func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) {
+ var reports []*entities.ContainerInitReport
+ ctrs, err := getContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ report := entities.ContainerInitReport{Id: ctr.ID()}
+ report.Err = ctr.Init(ctx)
+ reports = append(reports, &report)
+ }
+ return reports, nil
+}
+
+func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIds []string, options entities.ContainerMountOptions) ([]*entities.ContainerMountReport, error) {
+ if os.Geteuid() != 0 {
+ if driver := ic.Libpod.StorageConfig().GraphDriverName; driver != "vfs" {
+ // Do not allow to mount a graphdriver that is not vfs if we are creating the userns as part
+ // of the mount command.
+ return nil, fmt.Errorf("cannot mount using driver %s in rootless mode", driver)
+ }
+
+ became, ret, err := rootless.BecomeRootInUserNS("")
+ if err != nil {
+ return nil, err
+ }
+ if became {
+ os.Exit(ret)
+ }
+ }
+ var reports []*entities.ContainerMountReport
+ ctrs, err := getContainersByContext(options.All, options.Latest, nameOrIds, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ report := entities.ContainerMountReport{Id: ctr.ID()}
+ report.Path, report.Err = ctr.Mount()
+ reports = append(reports, &report)
+ }
+ if len(reports) > 0 {
+ return reports, nil
+ }
+
+ // No containers were passed, so we send back what is mounted
+ ctrs, err = getContainersByContext(true, false, []string{}, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ mounted, path, err := ctr.Mounted()
+ if err != nil {
+ return nil, err
+ }
+
+ if mounted {
+ reports = append(reports, &entities.ContainerMountReport{
+ Id: ctr.ID(),
+ Name: ctr.Name(),
+ Path: path,
+ })
+ }
+ }
+ return reports, nil
+}
+
+func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []string, options entities.ContainerUnmountOptions) ([]*entities.ContainerUnmountReport, error) {
+ var reports []*entities.ContainerUnmountReport
+ ctrs, err := getContainersByContext(options.All, options.Latest, nameOrIds, ic.Libpod)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ state, err := ctr.State()
+ if err != nil {
+ logrus.Debugf("Error umounting container %s state: %s", ctr.ID(), err.Error())
+ continue
+ }
+ if state == define.ContainerStateRunning {
+ logrus.Debugf("Error umounting container %s, is running", ctr.ID())
+ continue
+ }
+
+ report := entities.ContainerUnmountReport{Id: ctr.ID()}
+ if err := ctr.Unmount(options.Force); err != nil {
+ if options.All && errors.Cause(err) == storage.ErrLayerNotMounted {
+ logrus.Debugf("Error umounting container %s, storage.ErrLayerNotMounted", ctr.ID())
+ continue
+ }
+ report.Err = errors.Wrapf(err, "error unmounting container %s", ctr.ID())
+ }
+ reports = append(reports, &report)
+ }
+ return reports, nil
+}
+
+// GetConfig returns a copy of the configuration used by the runtime
+func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) {
+ return ic.Libpod.GetConfig()
+}
diff --git a/pkg/domain/infra/abi/events.go b/pkg/domain/infra/abi/events.go
new file mode 100644
index 000000000..9540a5b96
--- /dev/null
+++ b/pkg/domain/infra/abi/events.go
@@ -0,0 +1,18 @@
+//+build ABISupport
+
+package abi
+
+import (
+ "context"
+
+ "github.com/containers/libpod/libpod/events"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/sirupsen/logrus"
+)
+
+func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptions) error {
+ readOpts := events.ReadOptions{FromStart: opts.FromStart, Stream: opts.Stream, Filters: opts.Filter, EventChannel: opts.EventChan, Since: opts.Since, Until: opts.Until}
+ err := ic.Libpod.Events(readOpts)
+ logrus.Error(err)
+ return err
+}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 9d706a112..0f710ad28 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -9,12 +9,14 @@ import (
"os"
"strings"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker"
dockerarchive "github.com/containers/image/v5/docker/archive"
"github.com/containers/image/v5/docker/reference"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
+ "github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/libpod/image"
libpodImage "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
@@ -27,10 +29,11 @@ import (
)
func (ir *ImageEngine) Exists(_ context.Context, nameOrId string) (*entities.BoolReport, error) {
- if _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId); err != nil {
- return &entities.BoolReport{}, nil
+ _, err := ir.Libpod.ImageRuntime().NewFromLocal(nameOrId)
+ if err != nil && errors.Cause(err) != define.ErrNoSuchImage {
+ return nil, err
}
- return &entities.BoolReport{Value: true}, nil
+ return &entities.BoolReport{Value: err == nil}, nil
}
func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entities.ImageDeleteOptions) (*entities.ImageDeleteReport, error) {
@@ -43,7 +46,9 @@ func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entit
if err != nil {
return &report, errors.Wrapf(err, "unable to query local images")
}
-
+ if len(targets) == 0 {
+ return &report, nil
+ }
if len(targets) > 0 && len(targets) == len(previousTargets) {
return &report, errors.New("unable to delete all images; re-run the rmi command again.")
}
@@ -140,7 +145,7 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrId string, opts entiti
func ToDomainHistoryLayer(layer *libpodImage.History) entities.ImageHistoryLayer {
l := entities.ImageHistoryLayer{}
l.ID = layer.ID
- l.Created = layer.Created.Unix()
+ l.Created = *layer.Created
l.CreatedBy = layer.CreatedBy
copy(l.Tags, layer.Tags)
l.Size = layer.Size
@@ -392,8 +397,10 @@ func (ir *ImageEngine) Load(ctx context.Context, opts entities.ImageLoadOptions)
if err != nil {
return nil, errors.Wrap(err, "image loaded but no additional tags were created")
}
- if err := newImage.TagImage(opts.Name); err != nil {
- return nil, errors.Wrapf(err, "error adding %q to image %q", opts.Name, newImage.InputName)
+ if len(opts.Name) > 0 {
+ if err := newImage.TagImage(fmt.Sprintf("%s:%s", opts.Name, opts.Tag)); err != nil {
+ return nil, errors.Wrapf(err, "error adding %q to image %q", opts.Name, newImage.InputName)
+ }
}
return &entities.ImageLoadReport{Name: name}, nil
}
@@ -413,3 +420,59 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string,
}
return newImage.Save(ctx, nameOrId, options.Format, options.Output, tags, options.Quiet, options.Compress)
}
+
+func (ir *ImageEngine) Diff(_ context.Context, nameOrId string, _ entities.DiffOptions) (*entities.DiffReport, error) {
+ changes, err := ir.Libpod.GetDiff("", nameOrId)
+ if err != nil {
+ return nil, err
+ }
+ return &entities.DiffReport{Changes: changes}, nil
+}
+
+func (ir *ImageEngine) Search(ctx context.Context, term string, opts entities.ImageSearchOptions) ([]entities.ImageSearchReport, error) {
+ filter, err := image.ParseSearchFilter(opts.Filters)
+ if err != nil {
+ return nil, err
+ }
+
+ searchOpts := image.SearchOptions{
+ Authfile: opts.Authfile,
+ Filter: *filter,
+ Limit: opts.Limit,
+ NoTrunc: opts.NoTrunc,
+ InsecureSkipTLSVerify: opts.TLSVerify,
+ }
+
+ searchResults, err := image.SearchImages(term, searchOpts)
+ if err != nil {
+ return nil, err
+ }
+
+ // Convert from image.SearchResults to entities.ImageSearchReport. We don't
+ // want to leak any low-level packages into the remote client, which
+ // requires converting.
+ reports := make([]entities.ImageSearchReport, len(searchResults))
+ for i := range searchResults {
+ reports[i].Index = searchResults[i].Index
+ reports[i].Name = searchResults[i].Name
+ reports[i].Description = searchResults[i].Index
+ reports[i].Stars = searchResults[i].Stars
+ reports[i].Official = searchResults[i].Official
+ reports[i].Automated = searchResults[i].Automated
+ }
+
+ return reports, nil
+}
+
+// GetConfig returns a copy of the configuration used by the runtime
+func (ir *ImageEngine) Config(_ context.Context) (*config.Config, error) {
+ return ir.Libpod.GetConfig()
+}
+
+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
+ }
+ return &entities.BuildReport{ID: id}, nil
+}
diff --git a/pkg/domain/infra/abi/images_list.go b/pkg/domain/infra/abi/images_list.go
index 2f4020374..68b961cb6 100644
--- a/pkg/domain/infra/abi/images_list.go
+++ b/pkg/domain/infra/abi/images_list.go
@@ -54,7 +54,7 @@ func (ir *ImageEngine) List(ctx context.Context, opts entities.ImageListOptions)
ID: img.ID(),
ConfigDigest: string(img.ConfigDigest),
- Created: img.Created().Unix(),
+ Created: img.Created(),
Dangling: img.Dangling(),
Digest: string(img.Digest()),
Digests: digests,
diff --git a/pkg/domain/infra/abi/pods.go b/pkg/domain/infra/abi/pods.go
index c3e5d59bc..59bf0f636 100644
--- a/pkg/domain/infra/abi/pods.go
+++ b/pkg/domain/infra/abi/pods.go
@@ -5,13 +5,13 @@ package abi
import (
"context"
- lpfilters "github.com/containers/libpod/libpod/filters"
-
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
+ lpfilters "github.com/containers/libpod/libpod/filters"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/signal"
"github.com/containers/libpod/pkg/specgen"
+ "github.com/containers/libpod/pkg/specgen/generate"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -246,7 +246,7 @@ func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, optio
func (ic *ContainerEngine) PodCreate(ctx context.Context, opts entities.PodCreateOptions) (*entities.PodCreateReport, error) {
podSpec := specgen.NewPodSpecGenerator()
opts.ToPodSpecGen(podSpec)
- pod, err := podSpec.MakePod(ic.Libpod)
+ pod, err := generate.MakePod(podSpec, ic.Libpod)
if err != nil {
return nil, err
}
@@ -351,5 +351,5 @@ func (ic *ContainerEngine) PodInspect(ctx context.Context, options entities.PodI
if err != nil {
return nil, err
}
- return &entities.PodInspectReport{PodInspect: inspect}, nil
+ return &entities.PodInspectReport{InspectPodData: inspect}, nil
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
new file mode 100644
index 000000000..67593b2dd
--- /dev/null
+++ b/pkg/domain/infra/abi/system.go
@@ -0,0 +1,215 @@
+// +build ABISupport
+
+package abi
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "net"
+ "os"
+ "strconv"
+ "strings"
+ "syscall"
+
+ "github.com/containers/common/pkg/config"
+ "github.com/containers/libpod/libpod/define"
+ api "github.com/containers/libpod/pkg/api/server"
+ "github.com/containers/libpod/pkg/cgroups"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/util"
+ iopodman "github.com/containers/libpod/pkg/varlink"
+ iopodmanAPI "github.com/containers/libpod/pkg/varlinkapi"
+ "github.com/containers/libpod/utils"
+ "github.com/containers/libpod/version"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+ "github.com/varlink/go/varlink"
+)
+
+func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
+ return ic.Libpod.Info()
+}
+
+func (ic *ContainerEngine) RestService(_ context.Context, opts entities.ServiceOptions) error {
+ var (
+ listener net.Listener
+ err error
+ )
+
+ if opts.URI != "" {
+ fields := strings.Split(opts.URI, ":")
+ if len(fields) == 1 {
+ return errors.Errorf("%s is an invalid socket destination", opts.URI)
+ }
+ address := strings.Join(fields[1:], ":")
+ listener, err = net.Listen(fields[0], address)
+ if err != nil {
+ return errors.Wrapf(err, "unable to create socket %s", opts.URI)
+ }
+ }
+
+ server, err := api.NewServerWithSettings(ic.Libpod, opts.Timeout, &listener)
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err := server.Shutdown(); err != nil {
+ logrus.Warnf("Error when stopping API service: %s", err)
+ }
+ }()
+
+ err = server.Serve()
+ _ = listener.Close()
+ return err
+}
+
+func (ic *ContainerEngine) VarlinkService(_ context.Context, opts entities.ServiceOptions) error {
+ var varlinkInterfaces = []*iopodman.VarlinkInterface{
+ iopodmanAPI.New(opts.Command, ic.Libpod),
+ }
+
+ service, err := varlink.NewService(
+ "Atomic",
+ "podman",
+ version.Version,
+ "https://github.com/containers/libpod",
+ )
+ if err != nil {
+ return errors.Wrapf(err, "unable to create new varlink service")
+ }
+
+ for _, i := range varlinkInterfaces {
+ if err := service.RegisterInterface(i); err != nil {
+ return errors.Errorf("unable to register varlink interface %v", i)
+ }
+ }
+
+ // Run the varlink server at the given address
+ if err = service.Listen(opts.URI, opts.Timeout); err != nil {
+ switch err.(type) {
+ case varlink.ServiceTimeoutError:
+ logrus.Infof("varlink service expired (use --timeout to increase session time beyond %s ms, 0 means never timeout)", opts.Timeout.String())
+ return nil
+ default:
+ return errors.Wrapf(err, "unable to start varlink service")
+ }
+ }
+ return nil
+}
+
+func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command) error {
+ // do it only after podman has already re-execed and running with uid==0.
+ if os.Geteuid() == 0 {
+ ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup()
+ if err != nil {
+ logrus.Warnf("Failed to detect the owner for the current cgroup: %v", err)
+ }
+ if !ownsCgroup {
+ conf, err := ic.Config(context.Background())
+ if err != nil {
+ return err
+ }
+ unitName := fmt.Sprintf("podman-%d.scope", os.Getpid())
+ if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil {
+ if conf.Engine.CgroupManager == config.SystemdCgroupsManager {
+ logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err)
+ } else {
+ logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err)
+ }
+ }
+ }
+ }
+
+ pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+ if err != nil {
+ return errors.Wrapf(err, "could not get pause process pid file path")
+ }
+
+ became, ret, err := rootless.TryJoinPauseProcess(pausePidPath)
+ if err != nil {
+ return err
+ }
+ if became {
+ os.Exit(ret)
+ }
+
+ // if there is no pid file, try to join existing containers, and create a pause process.
+ ctrs, err := ic.Libpod.GetRunningContainers()
+ if err != nil {
+ logrus.Error(err.Error())
+ os.Exit(1)
+ }
+
+ paths := []string{}
+ for _, ctr := range ctrs {
+ paths = append(paths, ctr.Config().ConmonPidFile)
+ }
+
+ became, ret, err = rootless.TryJoinFromFilePaths(pausePidPath, true, paths)
+ if err := movePauseProcessToScope(); err != nil {
+ conf, err := ic.Config(context.Background())
+ if err != nil {
+ return err
+ }
+ if conf.Engine.CgroupManager == config.SystemdCgroupsManager {
+ logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err)
+ } else {
+ logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err)
+ }
+ }
+ if err != nil {
+ logrus.Error(err)
+ os.Exit(1)
+ }
+ if became {
+ os.Exit(ret)
+ }
+ return nil
+}
+
+func movePauseProcessToScope() error {
+ pausePidPath, err := util.GetRootlessPauseProcessPidPath()
+ if err != nil {
+ return errors.Wrapf(err, "could not get pause process pid file path")
+ }
+
+ data, err := ioutil.ReadFile(pausePidPath)
+ if err != nil {
+ return errors.Wrapf(err, "cannot read pause pid file")
+ }
+ pid, err := strconv.ParseUint(string(data), 10, 0)
+ if err != nil {
+ return errors.Wrapf(err, "cannot parse pid file %s", pausePidPath)
+ }
+
+ return utils.RunUnderSystemdScope(int(pid), "user.slice", "podman-pause.scope")
+}
+
+func setRLimits() error { // nolint:deadcode,unused
+ rlimits := new(syscall.Rlimit)
+ rlimits.Cur = 1048576
+ rlimits.Max = 1048576
+ if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ return errors.Wrapf(err, "error getting rlimits")
+ }
+ rlimits.Cur = rlimits.Max
+ if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, rlimits); err != nil {
+ return errors.Wrapf(err, "error setting new rlimits")
+ }
+ }
+ return nil
+}
+
+func setUMask() { // nolint:deadcode,unused
+ // Be sure we can create directories with 0755 mode.
+ syscall.Umask(0022)
+}
+
+// checkInput can be used to verify any of the globalopt values
+func checkInput() error { // nolint:deadcode,unused
+ return nil
+}
diff --git a/pkg/domain/infra/runtime_abi.go b/pkg/domain/infra/runtime_abi.go
index f11026571..7aa6986a7 100644
--- a/pkg/domain/infra/runtime_abi.go
+++ b/pkg/domain/infra/runtime_abi.go
@@ -12,7 +12,7 @@ import (
)
// NewContainerEngine factory provides a libpod runtime for container-related operations
-func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine, error) {
+func NewContainerEngine(facts *entities.PodmanConfig) (entities.ContainerEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
r, err := NewLibpodRuntime(facts.FlagSet, facts)
@@ -25,7 +25,7 @@ func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine,
}
// NewContainerEngine factory provides a libpod runtime for image-related operations
-func NewImageEngine(facts entities.EngineOptions) (entities.ImageEngine, error) {
+func NewImageEngine(facts *entities.PodmanConfig) (entities.ImageEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
r, err := NewLibpodImageRuntime(facts.FlagSet, facts)
diff --git a/pkg/domain/infra/runtime_image_proxy.go b/pkg/domain/infra/runtime_image_proxy.go
index befc66b9a..ea5d0e6f2 100644
--- a/pkg/domain/infra/runtime_image_proxy.go
+++ b/pkg/domain/infra/runtime_image_proxy.go
@@ -10,9 +10,9 @@ import (
"github.com/spf13/pflag"
)
-// ContainerEngine Image Proxy will be EOL'ed after podmanV2 is separated from libpod repo
+// ContainerEngine Image Proxy will be EOL'ed after podman is separated from libpod repo
-func NewLibpodImageRuntime(flags *pflag.FlagSet, opts entities.EngineOptions) (entities.ImageEngine, error) {
+func NewLibpodImageRuntime(flags *pflag.FlagSet, opts *entities.PodmanConfig) (entities.ImageEngine, error) {
r, err := GetRuntime(context.Background(), flags, opts)
if err != nil {
return nil, err
diff --git a/pkg/domain/infra/runtime_libpod.go b/pkg/domain/infra/runtime_libpod.go
index d59759707..dc59fec3d 100644
--- a/pkg/domain/infra/runtime_libpod.go
+++ b/pkg/domain/infra/runtime_libpod.go
@@ -1,3 +1,5 @@
+// +build ABISupport
+
package infra
import (
@@ -22,68 +24,70 @@ type engineOpts struct {
migrate bool
noStore bool
withFDS bool
- flags entities.EngineOptions
+ config *entities.PodmanConfig
}
// GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers
-func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions, newRuntime string) (*libpod.Runtime, error) {
+func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, cfg *entities.PodmanConfig, newRuntime string) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
name: newRuntime,
renumber: false,
migrate: true,
noStore: false,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify
-func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, cfg *entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: false,
migrate: false,
noStore: false,
withFDS: false,
- flags: ef,
+ config: cfg,
})
}
// GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber
-func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, cfg *entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: true,
migrate: false,
noStore: false,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
// GetRuntime generates a new libpod runtime configured by command line options
-func GetRuntime(ctx context.Context, flags *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntime(ctx context.Context, flags *flag.FlagSet, cfg *entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, flags, &engineOpts{
renumber: false,
migrate: false,
noStore: false,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
// GetRuntimeNoStore generates a new libpod runtime configured by command line options
-func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, ef entities.EngineOptions) (*libpod.Runtime, error) {
+func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, cfg *entities.PodmanConfig) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: false,
migrate: false,
noStore: true,
withFDS: true,
- flags: ef,
+ config: cfg,
})
}
func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
storageOpts := storage.StoreOptions{}
+ cfg := opts.config
+
storageSet := false
uidmapFlag := fs.Lookup("uidmap")
@@ -109,25 +113,25 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
if fs.Changed("root") {
storageSet = true
- storageOpts.GraphRoot = opts.flags.Root
+ storageOpts.GraphRoot = cfg.Engine.StaticDir
}
if fs.Changed("runroot") {
storageSet = true
- storageOpts.RunRoot = opts.flags.Runroot
+ storageOpts.RunRoot = cfg.Runroot
}
if len(storageOpts.RunRoot) > 50 {
return nil, errors.New("the specified runroot is longer than 50 characters")
}
if fs.Changed("storage-driver") {
storageSet = true
- storageOpts.GraphDriverName = opts.flags.StorageDriver
+ storageOpts.GraphDriverName = cfg.StorageDriver
// Overriding the default storage driver caused GraphDriverOptions from storage.conf to be ignored
storageOpts.GraphDriverOptions = []string{}
}
// This should always be checked after storage-driver is checked
- if len(opts.flags.StorageOpts) > 0 {
+ if len(cfg.StorageOpts) > 0 {
storageSet = true
- storageOpts.GraphDriverOptions = opts.flags.StorageOpts
+ storageOpts.GraphDriverOptions = cfg.StorageOpts
}
if opts.migrate {
options = append(options, libpod.WithMigrate())
@@ -151,30 +155,30 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
// TODO CLI flags for image config?
// TODO CLI flag for signature policy?
- if len(opts.flags.Namespace) > 0 {
- options = append(options, libpod.WithNamespace(opts.flags.Namespace))
+ if len(cfg.Engine.Namespace) > 0 {
+ options = append(options, libpod.WithNamespace(cfg.Engine.Namespace))
}
if fs.Changed("runtime") {
- options = append(options, libpod.WithOCIRuntime(opts.flags.Runtime))
+ options = append(options, libpod.WithOCIRuntime(cfg.RuntimePath))
}
if fs.Changed("conmon") {
- options = append(options, libpod.WithConmonPath(opts.flags.ConmonPath))
+ options = append(options, libpod.WithConmonPath(cfg.ConmonPath))
}
if fs.Changed("tmpdir") {
- options = append(options, libpod.WithTmpDir(opts.flags.TmpDir))
+ options = append(options, libpod.WithTmpDir(cfg.Engine.TmpDir))
}
if fs.Changed("network-cmd-path") {
- options = append(options, libpod.WithNetworkCmdPath(opts.flags.NetworkCmdPath))
+ options = append(options, libpod.WithNetworkCmdPath(cfg.Engine.NetworkCmdPath))
}
if fs.Changed("events-backend") {
- options = append(options, libpod.WithEventsLogger(opts.flags.EventsBackend))
+ options = append(options, libpod.WithEventsLogger(cfg.Engine.EventsLogger))
}
if fs.Changed("cgroup-manager") {
- options = append(options, libpod.WithCgroupManager(opts.flags.CGroupManager))
+ options = append(options, libpod.WithCgroupManager(cfg.Engine.CgroupManager))
} else {
unified, err := cgroups.IsCgroup2UnifiedMode()
if err != nil {
@@ -189,13 +193,13 @@ func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpo
// TODO flag to set libpod tmp dir?
if fs.Changed("cni-config-dir") {
- options = append(options, libpod.WithCNIConfigDir(opts.flags.CniConfigDir))
+ options = append(options, libpod.WithCNIConfigDir(cfg.Network.NetworkConfigDir))
}
if fs.Changed("default-mounts-file") {
- options = append(options, libpod.WithDefaultMountsFile(opts.flags.DefaultMountsFile))
+ options = append(options, libpod.WithDefaultMountsFile(cfg.Containers.DefaultMountsFile))
}
if fs.Changed("hooks-dir") {
- options = append(options, libpod.WithHooksDir(opts.flags.HooksDir...))
+ options = append(options, libpod.WithHooksDir(cfg.Engine.HooksDir...))
}
// TODO flag to set CNI plugins dir?
diff --git a/pkg/domain/infra/runtime_proxy.go b/pkg/domain/infra/runtime_proxy.go
index 2e38c74b9..41193fd89 100644
--- a/pkg/domain/infra/runtime_proxy.go
+++ b/pkg/domain/infra/runtime_proxy.go
@@ -10,9 +10,9 @@ import (
flag "github.com/spf13/pflag"
)
-// ContainerEngine Proxy will be EOL'ed after podmanV2 is separated from libpod repo
+// ContainerEngine Proxy will be EOL'ed after podman is separated from libpod repo
-func NewLibpodRuntime(flags *flag.FlagSet, opts entities.EngineOptions) (entities.ContainerEngine, error) {
+func NewLibpodRuntime(flags *flag.FlagSet, opts *entities.PodmanConfig) (entities.ContainerEngine, error) {
r, err := GetRuntime(context.Background(), flags, opts)
if err != nil {
return nil, err
diff --git a/pkg/domain/infra/runtime_tunnel.go b/pkg/domain/infra/runtime_tunnel.go
index dc04b4e53..752218aaf 100644
--- a/pkg/domain/infra/runtime_tunnel.go
+++ b/pkg/domain/infra/runtime_tunnel.go
@@ -11,7 +11,7 @@ import (
"github.com/containers/libpod/pkg/domain/infra/tunnel"
)
-func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine, error) {
+func NewContainerEngine(facts *entities.PodmanConfig) (entities.ContainerEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
return nil, fmt.Errorf("direct runtime not supported")
@@ -23,7 +23,7 @@ func NewContainerEngine(facts entities.EngineOptions) (entities.ContainerEngine,
}
// NewImageEngine factory provides a libpod runtime for image-related operations
-func NewImageEngine(facts entities.EngineOptions) (entities.ImageEngine, error) {
+func NewImageEngine(facts *entities.PodmanConfig) (entities.ImageEngine, error) {
switch facts.EngineMode {
case entities.ABIMode:
return nil, fmt.Errorf("direct image runtime not supported")
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index e96200c5b..679bb371b 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -5,6 +5,7 @@ import (
"io"
"os"
+ "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/containers"
@@ -145,6 +146,10 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
return reports, nil
}
+func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.ContainerPruneOptions) (*entities.ContainerPruneReport, error) {
+ return containers.Prune(ic.ClientCxt, options.Filters)
+}
+
func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []string, options entities.InspectOptions) ([]*entities.ContainerInspectReport, error) {
var (
reports []*entities.ContainerInspectReport
@@ -305,6 +310,11 @@ func (ic *ContainerEngine) ContainerCreate(ctx context.Context, s *specgen.SpecG
return &entities.ContainerCreateReport{Id: response.ID}, nil
}
+func (ic *ContainerEngine) ContainerLogs(ctx context.Context, containers []string, options entities.ContainerLogsOptions) error {
+ // The endpoint is not ready yet and requires some more work.
+ return errors.New("not implemented yet")
+}
+
func (ic *ContainerEngine) ContainerAttach(ctx context.Context, nameOrId string, options entities.AttachOptions) error {
return errors.New("not implemented")
}
@@ -324,3 +334,40 @@ 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")
}
+
+func (ic *ContainerEngine) ContainerDiff(ctx context.Context, nameOrId string, _ entities.DiffOptions) (*entities.DiffReport, error) {
+ changes, err := containers.Diff(ic.ClientCxt, nameOrId)
+ return &entities.DiffReport{Changes: changes}, err
+}
+
+func (ic *ContainerEngine) ContainerCleanup(ctx context.Context, namesOrIds []string, options entities.ContainerCleanupOptions) ([]*entities.ContainerCleanupReport, error) {
+ return nil, errors.New("not implemented")
+}
+
+func (ic *ContainerEngine) ContainerInit(ctx context.Context, namesOrIds []string, options entities.ContainerInitOptions) ([]*entities.ContainerInitReport, error) {
+ var reports []*entities.ContainerInitReport
+ ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
+ if err != nil {
+ return nil, err
+ }
+ for _, ctr := range ctrs {
+ err := containers.ContainerInit(ic.ClientCxt, ctr.ID)
+ reports = append(reports, &entities.ContainerInitReport{
+ Err: err,
+ Id: ctr.ID,
+ })
+ }
+ return reports, nil
+}
+
+func (ic *ContainerEngine) ContainerMount(ctx context.Context, nameOrIds []string, options entities.ContainerMountOptions) ([]*entities.ContainerMountReport, error) {
+ return nil, errors.New("mounting containers is not supported for remote clients")
+}
+
+func (ic *ContainerEngine) ContainerUnmount(ctx context.Context, nameOrIds []string, options entities.ContainerUnmountOptions) ([]*entities.ContainerUnmountReport, error) {
+ return nil, errors.New("unmounting containers is not supported for remote clients")
+}
+
+func (ic *ContainerEngine) Config(_ context.Context) (*config.Config, error) {
+ return config.Default()
+}
diff --git a/pkg/domain/infra/tunnel/events.go b/pkg/domain/infra/tunnel/events.go
new file mode 100644
index 000000000..46d88341a
--- /dev/null
+++ b/pkg/domain/infra/tunnel/events.go
@@ -0,0 +1,31 @@
+package tunnel
+
+import (
+ "context"
+ "strings"
+
+ "github.com/containers/libpod/pkg/api/handlers"
+ "github.com/containers/libpod/pkg/bindings/system"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/pkg/errors"
+)
+
+func (ic *ContainerEngine) Events(ctx context.Context, opts entities.EventsOptions) error {
+ filters := make(map[string][]string)
+ if len(opts.Filter) > 0 {
+ for _, filter := range opts.Filter {
+ split := strings.Split(filter, "=")
+ if len(split) < 2 {
+ return errors.Errorf("invalid filter %q", filter)
+ }
+ filters[split[0]] = append(filters[split[0]], strings.Join(split[1:], "="))
+ }
+ }
+ binChan := make(chan handlers.Event)
+ go func() {
+ for e := range binChan {
+ opts.EventChan <- e.ToLibpodEvent()
+ }
+ }()
+ return system.Events(ic.ClientCxt, binChan, nil, &opts.Since, &opts.Until, filters)
+}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 516914a68..6ea2bd9f2 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
+ "github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
images "github.com/containers/libpod/pkg/bindings/images"
"github.com/containers/libpod/pkg/domain/entities"
@@ -241,3 +242,24 @@ func (ir *ImageEngine) Save(ctx context.Context, nameOrId string, tags []string,
}
return utils2.UntarToFileSystem(options.Output, f, nil)
}
+
+// Diff reports the changes to the given image
+func (ir *ImageEngine) Diff(ctx context.Context, nameOrId string, _ entities.DiffOptions) (*entities.DiffReport, error) {
+ changes, err := images.Diff(ir.ClientCxt, nameOrId)
+ if err != nil {
+ return nil, err
+ }
+ return &entities.DiffReport{Changes: changes}, nil
+}
+
+func (ir *ImageEngine) Search(ctx context.Context, term string, opts entities.ImageSearchOptions) ([]entities.ImageSearchReport, error) {
+ return images.Search(ir.ClientCxt, term, opts)
+}
+
+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) {
+ return nil, errors.New("not implemented yet")
+}
diff --git a/pkg/domain/infra/tunnel/system.go b/pkg/domain/infra/tunnel/system.go
index 5bafef1fe..f373525c5 100644
--- a/pkg/domain/infra/tunnel/system.go
+++ b/pkg/domain/infra/tunnel/system.go
@@ -1 +1,27 @@
package tunnel
+
+import (
+ "context"
+ "errors"
+
+ "github.com/containers/libpod/libpod/define"
+ "github.com/containers/libpod/pkg/bindings/system"
+ "github.com/containers/libpod/pkg/domain/entities"
+ "github.com/spf13/cobra"
+)
+
+func (ic *ContainerEngine) Info(ctx context.Context) (*define.Info, error) {
+ return system.Info(ic.ClientCxt)
+}
+
+func (ic *ContainerEngine) RestService(_ context.Context, _ entities.ServiceOptions) error {
+ panic(errors.New("rest service is not supported when tunneling"))
+}
+
+func (ic *ContainerEngine) VarlinkService(_ context.Context, _ entities.ServiceOptions) error {
+ panic(errors.New("varlink service is not supported when tunneling"))
+}
+
+func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command) error {
+ panic(errors.New("rootless engine mode is not supported when tunneling"))
+}