summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/containers.go150
-rw-r--r--pkg/adapter/containers_remote.go30
-rw-r--r--pkg/adapter/sigproxy.go36
-rw-r--r--pkg/adapter/terminal.go159
-rw-r--r--pkg/registrar/registrar_test.go318
-rw-r--r--pkg/varlinkapi/config.go2
-rw-r--r--pkg/varlinkapi/containers.go23
-rw-r--r--pkg/varlinkapi/containers_create.go212
-rw-r--r--pkg/varlinkapi/events.go2
-rw-r--r--pkg/varlinkapi/images.go2
-rw-r--r--pkg/varlinkapi/mount.go2
-rw-r--r--pkg/varlinkapi/pods.go2
-rw-r--r--pkg/varlinkapi/remote_client.go29
-rw-r--r--pkg/varlinkapi/system.go2
-rw-r--r--pkg/varlinkapi/transfers.go2
-rw-r--r--pkg/varlinkapi/util.go2
-rw-r--r--pkg/varlinkapi/volumes.go2
17 files changed, 635 insertions, 340 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index 932d209cd..1bca99cec 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -5,12 +5,17 @@ package adapter
import (
"context"
"fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
"strconv"
+ "strings"
"sync"
"syscall"
"time"
"github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/adapter/shortcuts"
"github.com/pkg/errors"
@@ -154,3 +159,148 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions)
}
return nil
}
+
+// CreateContainer creates a libpod container
+func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) {
+ results := shared.NewIntermediateLayer(&c.PodmanCommand)
+ ctr, _, err := shared.CreateContainer(ctx, &results, r.Runtime)
+ return ctr.ID(), err
+}
+
+// Run a libpod container
+func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode int) (int, error) {
+ results := shared.NewIntermediateLayer(&c.PodmanCommand)
+
+ ctr, createConfig, err := shared.CreateContainer(ctx, &results, r.Runtime)
+ if err != nil {
+ return exitCode, err
+ }
+
+ if logrus.GetLevel() == logrus.DebugLevel {
+ cgroupPath, err := ctr.CGroupPath()
+ if err == nil {
+ logrus.Debugf("container %q has CgroupParent %q", ctr.ID(), cgroupPath)
+ }
+ }
+
+ // Handle detached start
+ if createConfig.Detach {
+ // 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
+ if strings.Index(err.Error(), "permission denied") > -1 {
+ exitCode = 126
+ }
+ return exitCode, err
+ }
+
+ fmt.Printf("%s\n", ctr.ID())
+ exitCode = 0
+ return exitCode, nil
+ }
+
+ outputStream := os.Stdout
+ errorStream := os.Stderr
+ inputStream := os.Stdin
+
+ // If -i is not set, clear stdin
+ if !c.Bool("interactive") {
+ inputStream = nil
+ }
+
+ // If attach is set, clear stdin/stdout/stderr and only attach requested
+ if c.IsSet("attach") || c.IsSet("a") {
+ outputStream = nil
+ errorStream = nil
+ if !c.Bool("interactive") {
+ inputStream = nil
+ }
+
+ attachTo := c.StringSlice("attach")
+ for _, stream := range attachTo {
+ switch strings.ToLower(stream) {
+ case "stdout":
+ outputStream = os.Stdout
+ case "stderr":
+ errorStream = os.Stderr
+ case "stdin":
+ inputStream = os.Stdin
+ default:
+ return exitCode, errors.Wrapf(libpod.ErrInvalidArg, "invalid stream %q for --attach - must be one of stdin, stdout, or stderr", stream)
+ }
+ }
+ }
+ // if the container was created as part of a pod, also start its dependencies, if any.
+ if err := StartAttachCtr(ctx, ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true, c.IsSet("pod")); err != nil {
+ // We've manually detached from the container
+ // Do not perform cleanup, or wait for container exit code
+ // Just exit immediately
+ if errors.Cause(err) == libpod.ErrDetach {
+ exitCode = 0
+ return exitCode, nil
+ }
+ // This means the command did not exist
+ exitCode = 127
+ if strings.Index(err.Error(), "permission denied") > -1 {
+ exitCode = 126
+ }
+ if c.IsSet("rm") {
+ if deleteError := r.Runtime.RemoveContainer(ctx, ctr, true, false); deleteError != nil {
+ logrus.Errorf("unable to remove container %s after failing to start and attach to it", ctr.ID())
+ }
+ }
+ return exitCode, err
+ }
+
+ if ecode, err := ctr.Wait(); err != nil {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ // The container may have been removed
+ // Go looking for an exit file
+ config, err := r.Runtime.GetConfig()
+ if err != nil {
+ return exitCode, err
+ }
+ ctrExitCode, err := ReadExitFile(config.TmpDir, ctr.ID())
+ if err != nil {
+ logrus.Errorf("Cannot get exit code: %v", err)
+ exitCode = 127
+ } else {
+ exitCode = ctrExitCode
+ }
+ }
+ } else {
+ exitCode = int(ecode)
+ }
+
+ if c.IsSet("rm") {
+ r.Runtime.RemoveContainer(ctx, ctr, false, true)
+ }
+
+ return exitCode, nil
+}
+
+// ReadExitFile reads a container's exit file
+func ReadExitFile(runtimeTmp, ctrID string) (int, error) {
+ exitFile := filepath.Join(runtimeTmp, "exits", fmt.Sprintf("%s-old", ctrID))
+
+ logrus.Debugf("Attempting to read container %s exit code from file %s", ctrID, exitFile)
+
+ // Check if it exists
+ if _, err := os.Stat(exitFile); err != nil {
+ return 0, errors.Wrapf(err, "error getting exit file for container %s", ctrID)
+ }
+
+ // File exists, read it in and convert to int
+ statusStr, err := ioutil.ReadFile(exitFile)
+ if err != nil {
+ return 0, errors.Wrapf(err, "error reading exit file for container %s", ctrID)
+ }
+
+ exitCode, err := strconv.Atoi(string(statusStr))
+ if err != nil {
+ return 0, errors.Wrapf(err, "error parsing exit code for container %s", ctrID)
+ }
+
+ return exitCode, nil
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index 2982d6cbb..3730827c7 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -262,3 +262,33 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions)
}
return nil
}
+
+// CreateContainer creates a container from the cli over varlink
+func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) {
+ if !c.Bool("detach") {
+ // TODO need to add attach when that function becomes available
+ return "", errors.New("the remote client only supports detached containers")
+ }
+ results := shared.NewIntermediateLayer(&c.PodmanCommand)
+ return iopodman.CreateContainer().Call(r.Conn, results.MakeVarlink())
+}
+
+// Run creates a container overvarlink and then starts it
+func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode int) (int, error) {
+ // TODO the exit codes for run need to be figured out for remote connections
+ if !c.Bool("detach") {
+ return 0, errors.New("the remote client only supports detached containers")
+ }
+ results := shared.NewIntermediateLayer(&c.PodmanCommand)
+ cid, err := iopodman.CreateContainer().Call(r.Conn, results.MakeVarlink())
+ if err != nil {
+ return 0, err
+ }
+ fmt.Println(cid)
+ _, err = iopodman.StartContainer().Call(r.Conn, cid)
+ return 0, err
+}
+
+func ReadExitFile(runtimeTmp, ctrID string) (int, error) {
+ return 0, libpod.ErrNotImplemented
+}
diff --git a/pkg/adapter/sigproxy.go b/pkg/adapter/sigproxy.go
new file mode 100644
index 000000000..af968cb89
--- /dev/null
+++ b/pkg/adapter/sigproxy.go
@@ -0,0 +1,36 @@
+package adapter
+
+import (
+ "os"
+ "syscall"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/docker/docker/pkg/signal"
+ "github.com/sirupsen/logrus"
+)
+
+// ProxySignals ...
+func ProxySignals(ctr *libpod.Container) {
+ sigBuffer := make(chan os.Signal, 128)
+ signal.CatchAll(sigBuffer)
+
+ logrus.Debugf("Enabling signal proxying")
+
+ go func() {
+ for s := range sigBuffer {
+ // Ignore SIGCHLD and SIGPIPE - these are mostly likely
+ // intended for the podman command itself.
+ if s == signal.SIGCHLD || s == signal.SIGPIPE {
+ continue
+ }
+
+ if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil {
+ logrus.Errorf("Error forwarding signal %d to container %s: %v", s, ctr.ID(), err)
+ signal.StopCatch(sigBuffer)
+ syscall.Kill(syscall.Getpid(), s.(syscall.Signal))
+ }
+ }
+ }()
+
+ return
+}
diff --git a/pkg/adapter/terminal.go b/pkg/adapter/terminal.go
new file mode 100644
index 000000000..0b608decf
--- /dev/null
+++ b/pkg/adapter/terminal.go
@@ -0,0 +1,159 @@
+package adapter
+
+import (
+ "context"
+ "fmt"
+ "os"
+ gosignal "os/signal"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/docker/docker/pkg/signal"
+ "github.com/docker/docker/pkg/term"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/crypto/ssh/terminal"
+ "k8s.io/client-go/tools/remotecommand"
+)
+
+// RawTtyFormatter ...
+type RawTtyFormatter struct {
+}
+
+// StartAttachCtr starts and (if required) attaches to a container
+func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool, recursive bool) error {
+ resize := make(chan remotecommand.TerminalSize)
+
+ haveTerminal := terminal.IsTerminal(int(os.Stdin.Fd()))
+
+ // Check if we are attached to a terminal. If we are, generate resize
+ // events, and set the terminal to raw mode
+ if haveTerminal && ctr.Spec().Process.Terminal {
+ logrus.Debugf("Handling terminal attach")
+
+ subCtx, cancel := context.WithCancel(ctx)
+ defer cancel()
+
+ resizeTty(subCtx, resize)
+
+ oldTermState, err := term.SaveState(os.Stdin.Fd())
+ if err != nil {
+ return errors.Wrapf(err, "unable to save terminal state")
+ }
+
+ logrus.SetFormatter(&RawTtyFormatter{})
+ term.SetRawTerminal(os.Stdin.Fd())
+
+ defer restoreTerminal(oldTermState)
+ }
+
+ streams := new(libpod.AttachStreams)
+ streams.OutputStream = stdout
+ streams.ErrorStream = stderr
+ streams.InputStream = stdin
+ streams.AttachOutput = true
+ streams.AttachError = true
+ streams.AttachInput = true
+
+ if stdout == nil {
+ logrus.Debugf("Not attaching to stdout")
+ streams.AttachOutput = false
+ }
+ if stderr == nil {
+ logrus.Debugf("Not attaching to stderr")
+ streams.AttachError = false
+ }
+ if stdin == nil {
+ logrus.Debugf("Not attaching to stdin")
+ streams.AttachInput = false
+ }
+
+ if !startContainer {
+ if sigProxy {
+ ProxySignals(ctr)
+ }
+
+ return ctr.Attach(streams, detachKeys, resize)
+ }
+
+ attachChan, err := ctr.StartAndAttach(ctx, streams, detachKeys, resize, recursive)
+ if err != nil {
+ return err
+ }
+
+ if sigProxy {
+ ProxySignals(ctr)
+ }
+
+ if stdout == nil && stderr == nil {
+ fmt.Printf("%s\n", ctr.ID())
+ }
+
+ err = <-attachChan
+ if err != nil {
+ return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
+ }
+
+ return nil
+}
+
+// getResize returns a TerminalSize command matching stdin's current
+// size on success, and nil on errors.
+func getResize() *remotecommand.TerminalSize {
+ winsize, err := term.GetWinsize(os.Stdin.Fd())
+ if err != nil {
+ logrus.Warnf("Could not get terminal size %v", err)
+ return nil
+ }
+ return &remotecommand.TerminalSize{
+ Width: winsize.Width,
+ Height: winsize.Height,
+ }
+}
+
+// Helper for prepareAttach - set up a goroutine to generate terminal resize events
+func resizeTty(ctx context.Context, resize chan remotecommand.TerminalSize) {
+ sigchan := make(chan os.Signal, 1)
+ gosignal.Notify(sigchan, signal.SIGWINCH)
+ go func() {
+ defer close(resize)
+ // Update the terminal size immediately without waiting
+ // for a SIGWINCH to get the correct initial size.
+ resizeEvent := getResize()
+ for {
+ if resizeEvent == nil {
+ select {
+ case <-ctx.Done():
+ return
+ case <-sigchan:
+ resizeEvent = getResize()
+ }
+ } else {
+ select {
+ case <-ctx.Done():
+ return
+ case <-sigchan:
+ resizeEvent = getResize()
+ case resize <- *resizeEvent:
+ resizeEvent = nil
+ }
+ }
+ }
+ }()
+}
+
+func restoreTerminal(state *term.State) error {
+ logrus.SetFormatter(&logrus.TextFormatter{})
+ return term.RestoreTerminal(os.Stdin.Fd(), state)
+}
+
+// Format ...
+func (f *RawTtyFormatter) Format(entry *logrus.Entry) ([]byte, error) {
+ textFormatter := logrus.TextFormatter{}
+ bytes, err := textFormatter.Format(entry)
+
+ if err == nil {
+ bytes = append(bytes, '\r')
+ }
+
+ return bytes, err
+}
diff --git a/pkg/registrar/registrar_test.go b/pkg/registrar/registrar_test.go
index 0c1ef312a..50af95915 100644
--- a/pkg/registrar/registrar_test.go
+++ b/pkg/registrar/registrar_test.go
@@ -1,119 +1,213 @@
-package registrar
+package registrar_test
import (
- "reflect"
"testing"
-)
-
-func TestReserve(t *testing.T) {
- r := NewRegistrar()
-
- obj := "test1"
- if err := r.Reserve("test", obj); err != nil {
- t.Fatal(err)
- }
-
- if err := r.Reserve("test", obj); err != nil {
- t.Fatal(err)
- }
-
- obj2 := "test2"
- err := r.Reserve("test", obj2)
- if err == nil {
- t.Fatalf("expected error when reserving an already reserved name to another object")
- }
- if err != ErrNameReserved {
- t.Fatal("expected `ErrNameReserved` error when attempting to reserve an already reserved name")
- }
-}
-
-func TestRelease(t *testing.T) {
- r := NewRegistrar()
- obj := "testing"
-
- if err := r.Reserve("test", obj); err != nil {
- t.Fatal(err)
- }
- r.Release("test")
- r.Release("test") // Ensure there is no panic here
- if err := r.Reserve("test", obj); err != nil {
- t.Fatal(err)
- }
-}
-
-func TestGetNames(t *testing.T) {
- r := NewRegistrar()
- obj := "testing"
- names := []string{"test1", "test2"}
-
- for _, name := range names {
- if err := r.Reserve(name, obj); err != nil {
- t.Fatal(err)
- }
- }
- r.Reserve("test3", "other")
-
- names2, err := r.GetNames(obj)
- if err != nil {
- t.Fatal(err)
- }
-
- if !reflect.DeepEqual(names, names2) {
- t.Fatalf("Exepected: %v, Got: %v", names, names2)
- }
-}
+ "github.com/containers/libpod/pkg/registrar"
+ . "github.com/containers/libpod/test/framework"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
-func TestDelete(t *testing.T) {
- r := NewRegistrar()
- obj := "testing"
- names := []string{"test1", "test2"}
- for _, name := range names {
- if err := r.Reserve(name, obj); err != nil {
- t.Fatal(err)
- }
- }
-
- r.Reserve("test3", "other")
- r.Delete(obj)
-
- _, err := r.GetNames(obj)
- if err == nil {
- t.Fatal("expected error getting names for deleted key")
- }
-
- if err != ErrNoSuchKey {
- t.Fatal("expected `ErrNoSuchKey`")
- }
+// TestRegistrar runs the created specs
+func TestRegistrar(t *testing.T) {
+ RegisterFailHandler(Fail)
+ RunSpecs(t, "Registrar")
}
-func TestGet(t *testing.T) {
- r := NewRegistrar()
- obj := "testing"
- name := "test"
-
- _, err := r.Get(name)
- if err == nil {
- t.Fatal("expected error when key does not exist")
- }
- if err != ErrNameNotReserved {
- t.Fatal(err)
- }
-
- if err := r.Reserve(name, obj); err != nil {
- t.Fatal(err)
- }
-
- if _, err = r.Get(name); err != nil {
- t.Fatal(err)
- }
-
- r.Delete(obj)
- _, err = r.Get(name)
- if err == nil {
- t.Fatal("expected error when key does not exist")
- }
- if err != ErrNameNotReserved {
- t.Fatal(err)
- }
-}
+// nolint: gochecknoglobals
+var t *TestFramework
+
+var _ = BeforeSuite(func() {
+ t = NewTestFramework(NilFunc, NilFunc)
+ t.Setup()
+})
+
+var _ = AfterSuite(func() {
+ t.Teardown()
+})
+
+// The actual test suite
+var _ = t.Describe("Registrar", func() {
+ // Constant test data needed by some tests
+ const (
+ testKey = "testKey"
+ testName = "testName"
+ anotherKey = "anotherKey"
+ )
+
+ // The system under test
+ var sut *registrar.Registrar
+
+ // Prepare the system under test and register a test name and key before
+ // each test
+ BeforeEach(func() {
+ sut = registrar.NewRegistrar()
+ Expect(sut.Reserve(testName, testKey)).To(BeNil())
+ })
+
+ t.Describe("Reserve", func() {
+ It("should succeed to reserve a new registrar", func() {
+ // Given
+ // When
+ err := sut.Reserve("name", "key")
+
+ // Then
+ Expect(err).To(BeNil())
+ })
+
+ It("should succeed to reserve a registrar twice", func() {
+ // Given
+ // When
+ err := sut.Reserve(testName, testKey)
+
+ // Then
+ Expect(err).To(BeNil())
+ })
+
+ It("should fail to reserve an already reserved registrar", func() {
+ // Given
+ // When
+ err := sut.Reserve(testName, anotherKey)
+
+ // Then
+ Expect(err).NotTo(BeNil())
+ Expect(err).To(Equal(registrar.ErrNameReserved))
+ })
+ })
+
+ t.Describe("Release", func() {
+ It("should succeed to release a registered registrar multiple times", func() {
+ // Given
+ // When
+ // Then
+ sut.Release(testName)
+ sut.Release(testName)
+ })
+
+ It("should succeed to release a unknown registrar multiple times", func() {
+ // Given
+ // When
+ // Then
+ sut.Release(anotherKey)
+ sut.Release(anotherKey)
+ })
+
+ It("should succeed to release and re-register a registrar", func() {
+ // Given
+ // When
+ sut.Release(testName)
+ err := sut.Reserve(testName, testKey)
+
+ // Then
+ Expect(err).To(BeNil())
+ })
+ })
+
+ t.Describe("GetNames", func() {
+ It("should succeed to retrieve a single name for a registrar", func() {
+ // Given
+ // When
+ names, err := sut.GetNames(testKey)
+
+ // Then
+ Expect(err).To(BeNil())
+ Expect(len(names)).To(Equal(1))
+ Expect(names[0]).To(Equal(testName))
+ })
+
+ It("should succeed to retrieve all names for a registrar", func() {
+ // Given
+ testNames := []string{"test1", "test2"}
+ for _, name := range testNames {
+ Expect(sut.Reserve(name, anotherKey)).To(BeNil())
+ }
+
+ // When
+ names, err := sut.GetNames(anotherKey)
+
+ // Then
+ Expect(err).To(BeNil())
+ Expect(len(names)).To(Equal(2))
+ Expect(names).To(Equal(testNames))
+ })
+ })
+
+ t.Describe("GetNames", func() {
+ It("should succeed to retrieve a single name for a registrar", func() {
+ // Given
+ // When
+ names, err := sut.GetNames(testKey)
+
+ // Then
+ Expect(err).To(BeNil())
+ Expect(len(names)).To(Equal(1))
+ Expect(names[0]).To(Equal(testName))
+ })
+
+ It("should succeed to retrieve all names for a registrar", func() {
+ // Given
+ anotherKey := "anotherKey"
+ testNames := []string{"test1", "test2"}
+ for _, name := range testNames {
+ Expect(sut.Reserve(name, anotherKey)).To(BeNil())
+ }
+
+ // When
+ names, err := sut.GetNames(anotherKey)
+
+ // Then
+ Expect(err).To(BeNil())
+ Expect(len(names)).To(Equal(2))
+ Expect(names).To(Equal(testNames))
+ })
+ })
+
+ t.Describe("Delete", func() {
+ It("should succeed to delete a registrar", func() {
+ // Given
+ // When
+ sut.Delete(testKey)
+
+ // Then
+ names, err := sut.GetNames(testKey)
+ Expect(len(names)).To(BeZero())
+ Expect(err).To(Equal(registrar.ErrNoSuchKey))
+ })
+ })
+
+ t.Describe("Get", func() {
+ It("should succeed to get a key for a registrar", func() {
+ // Given
+ // When
+ key, err := sut.Get(testName)
+
+ // Then
+ Expect(err).To(BeNil())
+ Expect(key).To(Equal(testKey))
+ })
+
+ It("should fail to get a key for a not existing registrar", func() {
+ // Given
+ // When
+ key, err := sut.Get("notExistingName")
+
+ // Then
+ Expect(key).To(BeEmpty())
+ Expect(err).To(Equal(registrar.ErrNameNotReserved))
+ })
+ })
+
+ t.Describe("GetAll", func() {
+ It("should succeed to get all names", func() {
+ // Given
+ // When
+ names := sut.GetAll()
+
+ // Then
+ Expect(len(names)).To(Equal(1))
+ Expect(len(names[testKey])).To(Equal(1))
+ Expect(names[testKey][0]).To(Equal(testName))
+ })
+ })
+})
diff --git a/pkg/varlinkapi/config.go b/pkg/varlinkapi/config.go
index f557d04e5..e75170547 100644
--- a/pkg/varlinkapi/config.go
+++ b/pkg/varlinkapi/config.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go
index 7a6ae3507..ac1352dac 100644
--- a/pkg/varlinkapi/containers.go
+++ b/pkg/varlinkapi/containers.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
@@ -583,27 +585,6 @@ func (i *LibpodAPI) GetContainerStatsWithHistory(call iopodman.VarlinkCall, prev
return call.ReplyGetContainerStatsWithHistory(cStats)
}
-// ContainerStatsToLibpodContainerStats converts the varlink containerstats to a libpod
-// container stats
-func ContainerStatsToLibpodContainerStats(stats iopodman.ContainerStats) libpod.ContainerStats {
- cstats := libpod.ContainerStats{
- ContainerID: stats.Id,
- Name: stats.Name,
- CPU: stats.Cpu,
- CPUNano: uint64(stats.Cpu_nano),
- SystemNano: uint64(stats.System_nano),
- MemUsage: uint64(stats.Mem_usage),
- MemLimit: uint64(stats.Mem_limit),
- MemPerc: stats.Mem_perc,
- NetInput: uint64(stats.Net_input),
- NetOutput: uint64(stats.Net_output),
- BlockInput: uint64(stats.Block_input),
- BlockOutput: uint64(stats.Block_output),
- PIDs: uint64(stats.Pids),
- }
- return cstats
-}
-
// GetContainersLogs is the varlink endpoint to obtain one or more container logs
func (i *LibpodAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, follow, latest bool, since string, tail int64, timestamps bool) error {
var wg sync.WaitGroup
diff --git a/pkg/varlinkapi/containers_create.go b/pkg/varlinkapi/containers_create.go
index 8990ac001..6b23dce5e 100644
--- a/pkg/varlinkapi/containers_create.go
+++ b/pkg/varlinkapi/containers_create.go
@@ -1,220 +1,18 @@
+// +build varlink
+
package varlinkapi
import (
- "context"
- "encoding/json"
- "fmt"
- "os"
- "strings"
- "syscall"
-
+ "github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/cmd/podman/varlink"
- "github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/image"
- "github.com/containers/libpod/pkg/inspect"
- "github.com/containers/libpod/pkg/namespaces"
- "github.com/containers/libpod/pkg/rootless"
- cc "github.com/containers/libpod/pkg/spec"
- "github.com/containers/libpod/pkg/util"
- "github.com/docker/docker/pkg/signal"
- "github.com/sirupsen/logrus"
)
// CreateContainer ...
func (i *LibpodAPI) CreateContainer(call iopodman.VarlinkCall, config iopodman.Create) error {
- rtc, err := i.Runtime.GetConfig()
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- ctx := getContext()
-
- newImage, err := i.Runtime.ImageRuntime().New(ctx, config.Image, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{}, false, nil)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- data, err := newImage.Inspect(ctx)
-
- createConfig, err := varlinkCreateToCreateConfig(ctx, config, i.Runtime, config.Image, data)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- runtimeSpec, err := cc.CreateConfigToOCISpec(createConfig)
+ generic := shared.VarlinkCreateToGeneric(config)
+ ctr, _, err := shared.CreateContainer(getContext(), &generic, i.Runtime)
if err != nil {
return call.ReplyErrorOccurred(err.Error())
}
-
- // TODO fix when doing remote client and dealing with the ability to create a container
- // within a non-existing pod (i.e. --pod new:foobar)
- options, err := createConfig.GetContainerCreateOptions(i.Runtime, nil)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- ctr, err := i.Runtime.NewContainer(ctx, runtimeSpec, options...)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- createConfigJSON, err := json.Marshal(createConfig)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
- if err := ctr.AddArtifact("create-config", createConfigJSON); err != nil {
- return call.ReplyErrorOccurred(err.Error())
- }
-
- logrus.Debug("new container created ", ctr.ID())
-
return call.ReplyCreateContainer(ctr.ID())
}
-
-// varlinkCreateToCreateConfig takes the varlink input struct and maps it to a pointer
-// of a CreateConfig, which eventually can be used to create the OCI spec.
-func varlinkCreateToCreateConfig(ctx context.Context, create iopodman.Create, runtime *libpod.Runtime, imageName string, data *inspect.ImageData) (*cc.CreateConfig, error) {
- idmappings, err := util.ParseIDMapping(create.Uidmap, create.Gidmap, create.Subuidname, create.Subgidname)
- if err != nil {
- return nil, err
- }
- inputCommand := create.Command
- entrypoint := create.Entrypoint
-
- // ENTRYPOINT
- // User input entrypoint takes priority over image entrypoint
- if len(entrypoint) == 0 {
- entrypoint = data.Config.Entrypoint
- }
- // if entrypoint=, we need to clear the entrypoint
- if len(entrypoint) == 1 && strings.Join(create.Entrypoint, "") == "" {
- entrypoint = []string{}
- }
- // Build the command
- // If we have an entry point, it goes first
- command := entrypoint
- if len(inputCommand) > 0 {
- // User command overrides data CMD
- command = append(command, inputCommand...)
- } else if len(data.Config.Cmd) > 0 && len(command) == 0 {
- // If not user command, add CMD
- command = append(command, data.Config.Cmd...)
- }
-
- stopSignal := syscall.SIGTERM
- if create.Stop_signal > 0 {
- stopSignal, err = signal.ParseSignal(fmt.Sprintf("%d", create.Stop_signal))
- if err != nil {
- return nil, err
- }
- }
-
- user := create.User
- if user == "" {
- user = data.Config.User
- }
-
- // EXPOSED PORTS
- portBindings, err := cc.ExposedPorts(create.Exposed_ports, create.Publish, create.Publish_all, data.Config.ExposedPorts)
- if err != nil {
- return nil, err
- }
-
- // NETWORK MODE
- networkMode := create.Net_mode
- if networkMode == "" {
- if rootless.IsRootless() {
- networkMode = "slirp4netns"
- } else {
- networkMode = "bridge"
- }
- }
-
- // WORKING DIR
- workDir := create.Work_dir
- if workDir == "" {
- workDir = "/"
- }
-
- imageID := data.ID
- var ImageVolumes map[string]struct{}
- if data != nil && create.Image_volume_type != "ignore" {
- ImageVolumes = data.Config.Volumes
- }
-
- config := &cc.CreateConfig{
- Runtime: runtime,
- BuiltinImgVolumes: ImageVolumes,
- ConmonPidFile: create.Conmon_pidfile,
- ImageVolumeType: create.Image_volume_type,
- CapAdd: create.Cap_add,
- CapDrop: create.Cap_drop,
- CgroupParent: create.Cgroup_parent,
- Command: command,
- Detach: create.Detach,
- Devices: create.Devices,
- DNSOpt: create.Dns_opt,
- DNSSearch: create.Dns_search,
- DNSServers: create.Dns_servers,
- Entrypoint: create.Entrypoint,
- Env: create.Env,
- GroupAdd: create.Group_add,
- Hostname: create.Hostname,
- HostAdd: create.Host_add,
- IDMappings: idmappings,
- Image: imageName,
- ImageID: imageID,
- Interactive: create.Interactive,
- Labels: create.Labels,
- LogDriver: create.Log_driver,
- LogDriverOpt: create.Log_driver_opt,
- Name: create.Name,
- Network: networkMode,
- IpcMode: namespaces.IpcMode(create.Ipc_mode),
- NetMode: namespaces.NetworkMode(networkMode),
- UtsMode: namespaces.UTSMode(create.Uts_mode),
- PidMode: namespaces.PidMode(create.Pid_mode),
- Pod: create.Pod,
- Privileged: create.Privileged,
- Publish: create.Publish,
- PublishAll: create.Publish_all,
- PortBindings: portBindings,
- Quiet: create.Quiet,
- ReadOnlyRootfs: create.Readonly_rootfs,
- Resources: cc.CreateResourceConfig{
- BlkioWeight: uint16(create.Resources.Blkio_weight),
- BlkioWeightDevice: create.Resources.Blkio_weight_device,
- CPUShares: uint64(create.Resources.Cpu_shares),
- CPUPeriod: uint64(create.Resources.Cpu_period),
- CPUsetCPUs: create.Resources.Cpuset_cpus,
- CPUsetMems: create.Resources.Cpuset_mems,
- CPUQuota: create.Resources.Cpu_quota,
- CPURtPeriod: uint64(create.Resources.Cpu_rt_period),
- CPURtRuntime: create.Resources.Cpu_rt_runtime,
- CPUs: create.Resources.Cpus,
- DeviceReadBps: create.Resources.Device_read_bps,
- DeviceReadIOps: create.Resources.Device_write_bps,
- DeviceWriteBps: create.Resources.Device_read_iops,
- DeviceWriteIOps: create.Resources.Device_write_iops,
- DisableOomKiller: create.Resources.Disable_oomkiller,
- ShmSize: create.Resources.Shm_size,
- Memory: create.Resources.Memory,
- MemoryReservation: create.Resources.Memory_reservation,
- MemorySwap: create.Resources.Memory_swap,
- MemorySwappiness: int(create.Resources.Memory_swappiness),
- KernelMemory: create.Resources.Kernel_memory,
- OomScoreAdj: int(create.Resources.Oom_score_adj),
- PidsLimit: create.Resources.Pids_limit,
- Ulimit: create.Resources.Ulimit,
- },
- Rm: create.Rm,
- StopSignal: stopSignal,
- StopTimeout: uint(create.Stop_timeout),
- Sysctl: create.Sys_ctl,
- Tmpfs: create.Tmpfs,
- Tty: create.Tty,
- User: user,
- UsernsMode: namespaces.UsernsMode(create.Userns_mode),
- Volumes: create.Volumes,
- WorkDir: workDir,
- }
-
- return config, nil
-}
diff --git a/pkg/varlinkapi/events.go b/pkg/varlinkapi/events.go
index 47c628ead..1e5696fbe 100644
--- a/pkg/varlinkapi/events.go
+++ b/pkg/varlinkapi/events.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index 2e72ec65b..470eadaeb 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/mount.go b/pkg/varlinkapi/mount.go
index 3b4fe87e3..63ce44291 100644
--- a/pkg/varlinkapi/mount.go
+++ b/pkg/varlinkapi/mount.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/pods.go b/pkg/varlinkapi/pods.go
index c79cee4c2..ac8e24747 100644
--- a/pkg/varlinkapi/pods.go
+++ b/pkg/varlinkapi/pods.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/remote_client.go b/pkg/varlinkapi/remote_client.go
new file mode 100644
index 000000000..dd0613494
--- /dev/null
+++ b/pkg/varlinkapi/remote_client.go
@@ -0,0 +1,29 @@
+// +build varlink remoteclient
+
+package varlinkapi
+
+import (
+ "github.com/containers/libpod/cmd/podman/varlink"
+ "github.com/containers/libpod/libpod"
+)
+
+// ContainerStatsToLibpodContainerStats converts the varlink containerstats to a libpod
+// container stats
+func ContainerStatsToLibpodContainerStats(stats iopodman.ContainerStats) libpod.ContainerStats {
+ cstats := libpod.ContainerStats{
+ ContainerID: stats.Id,
+ Name: stats.Name,
+ CPU: stats.Cpu,
+ CPUNano: uint64(stats.Cpu_nano),
+ SystemNano: uint64(stats.System_nano),
+ MemUsage: uint64(stats.Mem_usage),
+ MemLimit: uint64(stats.Mem_limit),
+ MemPerc: stats.Mem_perc,
+ NetInput: uint64(stats.Net_input),
+ NetOutput: uint64(stats.Net_output),
+ BlockInput: uint64(stats.Block_input),
+ BlockOutput: uint64(stats.Block_output),
+ PIDs: uint64(stats.Pids),
+ }
+ return cstats
+}
diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go
index 816143e9f..7f436a954 100644
--- a/pkg/varlinkapi/system.go
+++ b/pkg/varlinkapi/system.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/transfers.go b/pkg/varlinkapi/transfers.go
index 9a97bc810..96f76bcdc 100644
--- a/pkg/varlinkapi/transfers.go
+++ b/pkg/varlinkapi/transfers.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/util.go b/pkg/varlinkapi/util.go
index 7e487c03a..3c4b9b79a 100644
--- a/pkg/varlinkapi/util.go
+++ b/pkg/varlinkapi/util.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (
diff --git a/pkg/varlinkapi/volumes.go b/pkg/varlinkapi/volumes.go
index 02874d2b1..19ba38e7c 100644
--- a/pkg/varlinkapi/volumes.go
+++ b/pkg/varlinkapi/volumes.go
@@ -1,3 +1,5 @@
+// +build varlink
+
package varlinkapi
import (