diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/adapter/containers.go | 9 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 24 | ||||
-rw-r--r-- | pkg/adapter/runtime.go | 29 | ||||
-rw-r--r-- | pkg/adapter/runtime_remote.go | 19 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.c | 7 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.go | 14 | ||||
-rw-r--r-- | pkg/spec/spec.go | 3 | ||||
-rw-r--r-- | pkg/varlinkapi/attach.go | 76 | ||||
-rw-r--r-- | pkg/varlinkapi/generate.go | 30 |
9 files changed, 146 insertions, 65 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 1bb1aab87..931c55a57 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -255,14 +255,17 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *libpod.LogOptions) // CreateContainer creates a libpod container func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateValues) (string, error) { - results := shared.NewIntermediateLayer(&c.PodmanCommand) + results := shared.NewIntermediateLayer(&c.PodmanCommand, false) ctr, _, err := shared.CreateContainer(ctx, &results, r.Runtime) - return ctr.ID(), err + if err != nil { + return "", err + } + return ctr.ID(), nil } // Run a libpod container func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode int) (int, error) { - results := shared.NewIntermediateLayer(&c.PodmanCommand) + results := shared.NewIntermediateLayer(&c.PodmanCommand, false) ctr, createConfig, err := shared.CreateContainer(ctx, &results, r.Runtime) if err != nil { diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go index 31727fd0e..50cff9fa0 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -331,7 +331,7 @@ func (r *LocalRuntime) CreateContainer(ctx context.Context, c *cliconfig.CreateV // 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) + results := shared.NewIntermediateLayer(&c.PodmanCommand, true) return iopodman.CreateContainer().Call(r.Conn, results.MakeVarlink()) } @@ -344,23 +344,21 @@ func (r *LocalRuntime) Run(ctx context.Context, c *cliconfig.RunValues, exitCode // being run. // TODO the exit codes for run need to be figured out for remote connections - results := shared.NewIntermediateLayer(&c.PodmanCommand) + results := shared.NewIntermediateLayer(&c.PodmanCommand, true) cid, err := iopodman.CreateContainer().Call(r.Conn, results.MakeVarlink()) if err != nil { return 0, err } - _, err = iopodman.StartContainer().Call(r.Conn, cid) - if err != nil { + if c.Bool("detach") { + _, err := iopodman.StartContainer().Call(r.Conn, cid) + fmt.Println(cid) return 0, err } - errChan, err := r.attach(ctx, os.Stdin, os.Stdout, cid) + + errChan, err := r.attach(ctx, os.Stdin, os.Stdout, cid, true) if err != nil { return 0, err } - if c.Bool("detach") { - fmt.Println(cid) - return 0, err - } finalError := <-errChan return 0, finalError } @@ -441,7 +439,7 @@ func (r *LocalRuntime) Ps(c *cliconfig.PsValues, opts shared.PsOptions) ([]share return psContainers, nil } -func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid string) (chan error, error) { +func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid string, start bool) (chan error, error) { var ( oldTermState *term.State ) @@ -471,8 +469,8 @@ func (r *LocalRuntime) attach(ctx context.Context, stdin, stdout *os.File, cid s term.SetRawTerminal(os.Stdin.Fd()) } - - _, err = iopodman.Attach().Send(r.Conn, varlink.Upgrade, cid) + // TODO add detach keys support + _, err = iopodman.Attach().Send(r.Conn, varlink.Upgrade, cid, "", start) if err != nil { restoreTerminal(oldTermState) return nil, err @@ -533,7 +531,7 @@ func (r *LocalRuntime) Attach(ctx context.Context, c *cliconfig.AttachValues) er if c.NoStdin { inputStream = nil } - errChan, err := r.attach(ctx, inputStream, os.Stdout, c.InputArgs[0]) + errChan, err := r.attach(ctx, inputStream, os.Stdout, c.InputArgs[0], false) if err != nil { return err } diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index d45bdb56d..6aafed550 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -7,6 +7,7 @@ import ( "context" "io" "io/ioutil" + "k8s.io/api/core/v1" "os" "text/template" @@ -404,27 +405,7 @@ func (r *LocalRuntime) Diff(c *cliconfig.DiffValues, to string) ([]archive.Chang return r.Runtime.GetDiff("", to) } -// func (r *LocalRuntime) joinContainerOrCreateRootlessUserNS(ctr *libpod.Container) (bool, int, error) { -// if os.Geteuid() == 0 { -// return false, 0, nil -// } -// s, err := ctr.State() -// if err != nil { -// return false, -1, err -// } -// opts := rootless.Opts{ -// Argument: ctr.ID(), -// } -// if s == libpod.ContainerStateRunning || s == libpod.ContainerStatePaused { -// data, err := ioutil.ReadFile(ctr.Config().ConmonPidFile) -// if err != nil { -// return false, -1, errors.Wrapf(err, "Container %s cannot read conmon PID file %q", ctr.ID(), ctr.Config().ConmonPidFile) -// } -// conmonPid, err := strconv.Atoi(string(data)) -// if err != nil { -// return false, -1, errors.Wrapf(err, "Container %s cannot parse PID %q", ctr.ID(), data) -// } -// return rootless.JoinDirectUserAndMountNSWithOpts(uint(conmonPid), &opts) -// } -// return rootless.BecomeRootInUserNSWithOpts(&opts) -// } +// GenerateKube creates kubernetes email from containers and pods +func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, *v1.Service, error) { + return shared.GenerateKube(c.InputArgs[0], c.Service, r.Runtime) +} diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index 807a9ad8f..71f7380db 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -5,9 +5,11 @@ package adapter import ( "bufio" "context" + "encoding/json" "fmt" "io" "io/ioutil" + v1 "k8s.io/api/core/v1" "os" "strings" "text/template" @@ -858,3 +860,20 @@ func stringToChangeType(change string) archive.ChangeType { return archive.ChangeModify } } + +// GenerateKube creates kubernetes email from containers and pods +func (r *LocalRuntime) GenerateKube(c *cliconfig.GenerateKubeValues) (*v1.Pod, *v1.Service, error) { + var ( + pod v1.Pod + service v1.Service + ) + reply, err := iopodman.GenerateKube().Call(r.Conn, c.InputArgs[0], c.Service) + if err != nil { + return nil, nil, errors.Wrap(err, "unable to create kubernetes YAML") + } + if err := json.Unmarshal([]byte(reply.Pod), &pod); err != nil { + return nil, nil, err + } + err = json.Unmarshal([]byte(reply.Service), &service) + return &pod, &service, err +} diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 9cb79ed4d..d6a2793a7 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -16,6 +16,8 @@ #include <sys/types.h> #include <sys/prctl.h> #include <dirent.h> +#include <termios.h> +#include <sys/ioctl.h> static const char *_max_user_namespaces = "/proc/sys/user/max_user_namespaces"; static const char *_unprivileged_user_namespaces = "/proc/sys/kernel/unprivileged_userns_clone"; @@ -178,6 +180,11 @@ reexec_userns_join (int userns, int mountns) _exit (EXIT_FAILURE); } + if (isatty (1) && ioctl (1, TIOCSCTTY, 0) == -1) { + fprintf (stderr, "cannot ioctl(TIOCSCTTY): %s\n", strerror (errno)); + _exit (EXIT_FAILURE); + } + if (setns (userns, 0) < 0) { fprintf (stderr, "cannot setns: %s\n", strerror (errno)); diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 1d1b1713d..2c99f41a4 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -28,6 +28,10 @@ extern int reexec_userns_join(int userns, int mountns); */ import "C" +const ( + numSig = 65 // max number of signals +) + func runInUser() error { os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done") return nil @@ -283,7 +287,15 @@ func BecomeRootInUserNS() (bool, int, error) { c := make(chan os.Signal, 1) - gosignal.Notify(c) + signals := []os.Signal{} + for sig := 0; sig < numSig; sig++ { + if sig == int(syscall.SIGTSTP) { + continue + } + signals = append(signals, syscall.Signal(sig)) + } + + gosignal.Notify(c, signals...) defer gosignal.Reset() go func() { for s := range c { diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 9b6bd089e..0371b6d4d 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -132,6 +132,9 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint Options: []string{"rprivate", "nosuid", "noexec", "nodev", r, "rbind"}, } g.AddMount(sysMnt) + if !config.Privileged && isRootless { + g.AddLinuxMaskedPaths("/sys/kernel") + } } if isRootless { nGids, err := getAvailableGids() diff --git a/pkg/varlinkapi/attach.go b/pkg/varlinkapi/attach.go index 53c4d1ff6..9e2a265be 100644 --- a/pkg/varlinkapi/attach.go +++ b/pkg/varlinkapi/attach.go @@ -3,29 +3,17 @@ package varlinkapi import ( + "bufio" "io" "github.com/containers/libpod/cmd/podman/varlink" "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/varlinkapi/virtwriter" + "github.com/sirupsen/logrus" "k8s.io/client-go/tools/remotecommand" ) -// Close is method to close the writer - -// Attach ... -func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string) error { - var finalErr error - resize := make(chan remotecommand.TerminalSize) - errChan := make(chan error) - - if !call.WantsUpgrade() { - return call.ReplyErrorOccurred("client must use upgraded connection to attach") - } - ctr, err := i.Runtime.LookupContainer(name) - if err != nil { - return call.ReplyErrorOccurred(err.Error()) - } +func setupStreams(call iopodman.VarlinkCall) (*bufio.Reader, *bufio.Writer, *io.PipeReader, *io.PipeWriter, *libpod.AttachStreams) { // These are the varlink sockets reader := call.Call.Reader @@ -49,6 +37,24 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string) error { // Runc eats the error stream AttachError: true, } + return reader, writer, pr, pw, &streams +} + +// Attach connects to a containers console +func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string, detachKeys string, start bool) error { + var finalErr error + resize := make(chan remotecommand.TerminalSize) + errChan := make(chan error) + + if !call.WantsUpgrade() { + return call.ReplyErrorOccurred("client must use upgraded connection to attach") + } + ctr, err := i.Runtime.LookupContainer(name) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + reader, writer, _, pw, streams := setupStreams(call) go func() { if err := virtwriter.Reader(reader, nil, nil, pw, resize); err != nil { @@ -56,20 +62,42 @@ func (i *LibpodAPI) Attach(call iopodman.VarlinkCall, name string) error { } }() + if start { + finalErr = startAndAttach(ctr, streams, detachKeys, resize, errChan) + } else { + finalErr = attach(ctr, streams, detachKeys, resize, errChan) + } + + if finalErr != libpod.ErrDetach && finalErr != nil { + logrus.Error(finalErr) + } + quitWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.Quit) + _, err = quitWriter.Write([]byte("HANG-UP")) + // TODO error handling is not quite right here yet + return call.Writer.Flush() +} + +func attach(ctr *libpod.Container, streams *libpod.AttachStreams, detachKeys string, resize chan remotecommand.TerminalSize, errChan chan error) error { go func() { - // TODO allow for customizable detach keys - if err := ctr.Attach(&streams, "", resize); err != nil { + if err := ctr.Attach(streams, detachKeys, resize); err != nil { errChan <- err } }() + attachError := <-errChan + return attachError +} +func startAndAttach(ctr *libpod.Container, streams *libpod.AttachStreams, detachKeys string, resize chan remotecommand.TerminalSize, errChan chan error) error { + var finalErr error + attachChan, err := ctr.StartAndAttach(getContext(), streams, detachKeys, resize, false) + if err != nil { + return err + } select { - // Blocking on an error - case finalErr = <-errChan: - // Need to close up shop - _ = finalErr + case attachChanErr := <-attachChan: + finalErr = attachChanErr + case chanError := <-errChan: + finalErr = chanError } - quitWriter := virtwriter.NewVirtWriteCloser(writer, virtwriter.Quit) - _, err = quitWriter.Write([]byte("HANG-UP")) - return call.Writer.Flush() + return finalErr } diff --git a/pkg/varlinkapi/generate.go b/pkg/varlinkapi/generate.go new file mode 100644 index 000000000..bc600c397 --- /dev/null +++ b/pkg/varlinkapi/generate.go @@ -0,0 +1,30 @@ +// +build varlink + +package varlinkapi + +import ( + "encoding/json" + "github.com/containers/libpod/cmd/podman/shared" + iopodman "github.com/containers/libpod/cmd/podman/varlink" +) + +// GenerateKube ... +func (i *LibpodAPI) GenerateKube(call iopodman.VarlinkCall, name string, service bool) error { + pod, serv, err := shared.GenerateKube(name, service, i.Runtime) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + podB, err := json.Marshal(pod) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + servB, err := json.Marshal(serv) + if err != nil { + return call.ReplyErrorOccurred(err.Error()) + } + + return call.ReplyGenerateKube(iopodman.KubePodService{ + Pod: string(podB), + Service: string(servB), + }) +} |