summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorOpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com>2020-08-21 12:58:55 +0200
committerGitHub <noreply@github.com>2020-08-21 12:58:55 +0200
commit11372c4c4d75d731f346c6be06e41bfe9600ce81 (patch)
tree79a8f85f2f8ac32613ce86db3601b355595cf852 /pkg
parent84180d99bc808795a1f91747436a42745ddececb (diff)
parent7fc3c25410bd5ee053473ffd5df2209f41840ec0 (diff)
downloadpodman-11372c4c4d75d731f346c6be06e41bfe9600ce81.tar.gz
podman-11372c4c4d75d731f346c6be06e41bfe9600ce81.tar.bz2
podman-11372c4c4d75d731f346c6be06e41bfe9600ce81.zip
Merge pull request #7363 from mheon/lets_try_this_again
Lets try this again: v2.0.5 backports, round 2
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/libpod/containers.go3
-rw-r--r--pkg/api/server/register_containers.go3
-rw-r--r--pkg/api/server/server.go27
-rw-r--r--pkg/bindings/containers/containers.go5
-rw-r--r--pkg/bindings/test/containers_test.go19
-rw-r--r--pkg/domain/infra/abi/images.go2
-rw-r--r--pkg/domain/infra/abi/network.go2
-rw-r--r--pkg/domain/infra/abi/system.go7
-rw-r--r--pkg/domain/infra/tunnel/containers.go2
-rw-r--r--pkg/domain/infra/tunnel/helpers.go2
-rw-r--r--pkg/domain/infra/tunnel/images.go13
-rw-r--r--pkg/env/env.go14
-rw-r--r--pkg/namespaces/namespaces.go2
-rw-r--r--pkg/network/ip.go5
-rw-r--r--pkg/network/netconflist.go15
-rw-r--r--pkg/network/netconflist_test.go38
-rw-r--r--pkg/network/network.go9
-rw-r--r--pkg/ps/ps.go7
-rw-r--r--pkg/rootless/rootless_linux.go4
-rw-r--r--pkg/spec/spec.go4
-rw-r--r--pkg/specgen/container_validate.go8
-rw-r--r--pkg/specgen/generate/container.go24
-rw-r--r--pkg/specgen/generate/container_create.go13
-rw-r--r--pkg/specgen/generate/oci.go5
-rw-r--r--pkg/specgen/generate/security.go5
-rw-r--r--pkg/systemd/generate/common.go13
-rw-r--r--pkg/systemd/generate/common_test.go25
-rw-r--r--pkg/systemd/generate/containers.go1
-rw-r--r--pkg/systemd/generate/containers_test.go4
-rw-r--r--pkg/systemd/generate/pods.go1
-rw-r--r--pkg/systemd/generate/pods_test.go4
-rw-r--r--pkg/varlinkapi/create.go7
32 files changed, 237 insertions, 56 deletions
diff --git a/pkg/api/handlers/libpod/containers.go b/pkg/api/handlers/libpod/containers.go
index 2303ff17a..abfc79a0b 100644
--- a/pkg/api/handlers/libpod/containers.go
+++ b/pkg/api/handlers/libpod/containers.go
@@ -39,7 +39,6 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
Filters map[string][]string `schema:"filters"`
Last int `schema:"last"`
Namespace bool `schema:"namespace"`
- Pod bool `schema:"pod"`
Size bool `schema:"size"`
Sync bool `schema:"sync"`
}{
@@ -59,7 +58,7 @@ func ListContainers(w http.ResponseWriter, r *http.Request) {
Size: query.Size,
Sort: "",
Namespace: query.Namespace,
- Pod: query.Pod,
+ Pod: true,
Sync: query.Sync,
}
pss, err := ps.GetContainerLists(runtime, opts)
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 18ff2f423..a0c9ac574 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -661,11 +661,10 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// type: boolean
// description: Include namespace information
// default: false
- // - in: query
// name: pod
// type: boolean
// default: false
- // description: Include Pod ID and Name if applicable
+ // description: Ignored. Previously included details on pod name and ID that are currently included by default.
// - in: query
// name: size
// type: boolean
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index 1c6007745..bfa5fcdce 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -2,6 +2,7 @@ package server
import (
"context"
+ "fmt"
"log"
"net"
"net/http"
@@ -17,6 +18,7 @@ import (
"github.com/containers/libpod/v2/pkg/api/handlers"
"github.com/containers/libpod/v2/pkg/api/server/idletracker"
"github.com/coreos/go-systemd/v22/activation"
+ "github.com/coreos/go-systemd/v22/daemon"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@@ -147,8 +149,31 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
return &server, nil
}
-// Serve starts responding to HTTP requests
+// If the NOTIFY_SOCKET is set, communicate the PID and readiness, and
+// further unset NOTIFY_SOCKET to prevent containers from sending
+// messages and unset INVOCATION_ID so conmon and containers are in
+// the correct cgroup.
+func setupSystemd() {
+ if len(os.Getenv("NOTIFY_SOCKET")) == 0 {
+ return
+ }
+ payload := fmt.Sprintf("MAINPID=%d", os.Getpid())
+ payload += "\n"
+ payload += daemon.SdNotifyReady
+ if sent, err := daemon.SdNotify(true, payload); err != nil {
+ logrus.Errorf("Error notifying systemd of Conmon PID: %s", err.Error())
+ } else if sent {
+ logrus.Debugf("Notify sent successfully")
+ }
+
+ if err := os.Unsetenv("INVOCATION_ID"); err != nil {
+ logrus.Errorf("Error unsetting INVOCATION_ID: %s", err.Error())
+ }
+}
+
+// Serve starts responding to HTTP requests.
func (s *APIServer) Serve() error {
+ setupSystemd()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
errChan := make(chan error, 1)
diff --git a/pkg/bindings/containers/containers.go b/pkg/bindings/containers/containers.go
index c479e5dcb..d7e67567b 100644
--- a/pkg/bindings/containers/containers.go
+++ b/pkg/bindings/containers/containers.go
@@ -24,7 +24,7 @@ var (
// the most recent number of containers. The pod and size booleans indicate that pod information and rootfs
// size information should also be included. Finally, the sync bool synchronizes the OCI runtime and
// container state.
-func List(ctx context.Context, filters map[string][]string, all *bool, last *int, pod, size, sync *bool) ([]entities.ListContainer, error) { // nolint:typecheck
+func List(ctx context.Context, filters map[string][]string, all *bool, last *int, size, sync *bool) ([]entities.ListContainer, error) { // nolint:typecheck
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
@@ -37,9 +37,6 @@ func List(ctx context.Context, filters map[string][]string, all *bool, last *int
if last != nil {
params.Set("last", strconv.Itoa(*last))
}
- if pod != nil {
- params.Set("pod", strconv.FormatBool(*pod))
- }
if size != nil {
params.Set("size", strconv.FormatBool(*size))
}
diff --git a/pkg/bindings/test/containers_test.go b/pkg/bindings/test/containers_test.go
index 4b2c78353..0685a3377 100644
--- a/pkg/bindings/test/containers_test.go
+++ b/pkg/bindings/test/containers_test.go
@@ -509,7 +509,7 @@ var _ = Describe("Podman containers ", func() {
Expect(err).To(BeNil())
_, err = bt.RunTopContainer(&name2, bindings.PFalse, nil)
Expect(err).To(BeNil())
- containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil, nil)
+ containerLatestList, err := containers.List(bt.conn, nil, nil, &latestContainers, nil, nil)
Expect(err).To(BeNil())
err = containers.Kill(bt.conn, containerLatestList[0].Names[0], "SIGTERM")
Expect(err).To(BeNil())
@@ -754,8 +754,23 @@ var _ = Describe("Podman containers ", func() {
// Validate list container with id filter
filters := make(map[string][]string)
filters["id"] = []string{cid}
- c, err := containers.List(bt.conn, filters, bindings.PTrue, nil, nil, nil, nil)
+ c, err := containers.List(bt.conn, filters, bindings.PTrue, nil, nil, nil)
Expect(err).To(BeNil())
Expect(len(c)).To(Equal(1))
})
+
+ It("List containers always includes pod information", func() {
+ podName := "testpod"
+ ctrName := "testctr"
+ bt.Podcreate(&podName)
+ _, err := bt.RunTopContainer(&ctrName, bindings.PTrue, &podName)
+ Expect(err).To(BeNil())
+
+ lastNum := 1
+
+ c, err := containers.List(bt.conn, nil, bindings.PTrue, &lastNum, nil, nil)
+ Expect(err).To(BeNil())
+ Expect(len(c)).To(Equal(1))
+ Expect(c[0].PodName).To(Equal(podName))
+ })
})
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 5f19f416a..a4dc92820 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -108,7 +108,7 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, options entiti
if err != nil {
imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, rawImage))
if err != nil {
- return nil, errors.Errorf("invalid image reference %q", rawImage)
+ return nil, errors.Wrapf(err, "invalid image reference %q", rawImage)
}
}
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index 26383129c..fd63fc80f 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -191,7 +191,7 @@ func createBridge(r *libpod.Runtime, name string, options entities.NetworkCreate
var plugins []network.CNIPlugins
var routes []network.IPAMRoute
- defaultRoute, err := network.NewIPAMDefaultRoute()
+ defaultRoute, err := network.NewIPAMDefaultRoute(network.IsIPv6(subnet.IP))
if err != nil {
return "", err
}
diff --git a/pkg/domain/infra/abi/system.go b/pkg/domain/infra/abi/system.go
index 435902ded..043dfe49e 100644
--- a/pkg/domain/infra/abi/system.go
+++ b/pkg/domain/infra/abi/system.go
@@ -70,8 +70,13 @@ func (ic *ContainerEngine) SetupRootless(_ context.Context, cmd *cobra.Command)
if err != nil {
return err
}
+
+ initCommand, err := ioutil.ReadFile("/proc/1/comm")
+ // On errors, default to systemd
+ runsUnderSystemd := err != nil || string(initCommand) == "systemd"
+
unitName := fmt.Sprintf("podman-%d.scope", os.Getpid())
- if conf.Engine.CgroupManager == config.SystemdCgroupsManager {
+ if runsUnderSystemd || conf.Engine.CgroupManager == config.SystemdCgroupsManager {
if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil {
logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err)
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 8835248ca..dd72064a3 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -496,7 +496,7 @@ func (ic *ContainerEngine) ContainerStart(ctx context.Context, namesOrIds []stri
}
func (ic *ContainerEngine) ContainerList(ctx context.Context, options entities.ContainerListOptions) ([]entities.ListContainer, error) {
- return containers.List(ic.ClientCxt, options.Filters, &options.All, &options.Last, &options.Pod, &options.Size, &options.Sync)
+ return containers.List(ic.ClientCxt, options.Filters, &options.All, &options.Last, &options.Size, &options.Sync)
}
func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.ContainerRunOptions) (*entities.ContainerRunReport, error) {
diff --git a/pkg/domain/infra/tunnel/helpers.go b/pkg/domain/infra/tunnel/helpers.go
index 9974c4d1d..90e52c5c0 100644
--- a/pkg/domain/infra/tunnel/helpers.go
+++ b/pkg/domain/infra/tunnel/helpers.go
@@ -20,7 +20,7 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam
if all && len(namesOrIDs) > 0 {
return nil, errors.New("cannot lookup containers and all")
}
- c, err := containers.List(contextWithConnection, nil, bindings.PTrue, nil, nil, nil, bindings.PTrue)
+ c, err := containers.List(contextWithConnection, nil, bindings.PTrue, nil, nil, bindings.PTrue)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 2e30621c5..2e027a6e1 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -9,6 +9,7 @@ import (
"os"
"path/filepath"
"strings"
+ "time"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
@@ -65,8 +66,16 @@ func (ir *ImageEngine) History(ctx context.Context, nameOrID string, opts entiti
}
for i, layer := range results {
- hold := entities.ImageHistoryLayer{}
- _ = utils.DeepCopy(&hold, layer)
+ // Created time comes over as an int64 so needs conversion to time.time
+ t := time.Unix(layer.Created, 0)
+ hold := entities.ImageHistoryLayer{
+ ID: layer.ID,
+ Created: t.UTC(),
+ CreatedBy: layer.CreatedBy,
+ Tags: layer.Tags,
+ Size: layer.Size,
+ Comment: layer.Comment,
+ }
history.Layers[i] = hold
}
return &history, nil
diff --git a/pkg/env/env.go b/pkg/env/env.go
index a16007a50..0d55e5560 100644
--- a/pkg/env/env.go
+++ b/pkg/env/env.go
@@ -12,14 +12,16 @@ import (
"github.com/pkg/errors"
)
-// DefaultEnvVariables sets $PATH and $TERM.
-var DefaultEnvVariables = map[string]string{
- "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
- "TERM": "xterm",
-}
-
const whiteSpaces = " \t"
+// DefaultEnvVariables returns a default environment, with $PATH and $TERM set.
+func DefaultEnvVariables() map[string]string {
+ return map[string]string{
+ "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
+ "TERM": "xterm",
+ }
+}
+
// Slice transforms the specified map of environment variables into a
// slice. If a value is non-empty, the key and value are joined with '='.
func Slice(m map[string]string) []string {
diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go
index 2ffbde977..c2f255530 100644
--- a/pkg/namespaces/namespaces.go
+++ b/pkg/namespaces/namespaces.go
@@ -91,7 +91,7 @@ func (n UsernsMode) IsHost() bool {
return n == hostType
}
-// IsKeepID indicates whether container uses a mapping where the (uid, gid) on the host is lept inside of the namespace.
+// IsKeepID indicates whether container uses a mapping where the (uid, gid) on the host is kept inside of the namespace.
func (n UsernsMode) IsKeepID() bool {
return n == "keep-id"
}
diff --git a/pkg/network/ip.go b/pkg/network/ip.go
index 1798cd939..ba93a0d05 100644
--- a/pkg/network/ip.go
+++ b/pkg/network/ip.go
@@ -12,3 +12,8 @@ func CalcGatewayIP(ipn *net.IPNet) net.IP {
nid := ipn.IP.Mask(ipn.Mask)
return ip.NextIP(nid)
}
+
+// IsIPv6 returns if netIP is IPv6.
+func IsIPv6(netIP net.IP) bool {
+ return netIP != nil && netIP.To4() == nil
+}
diff --git a/pkg/network/netconflist.go b/pkg/network/netconflist.go
index 4271d3f54..8187fdb39 100644
--- a/pkg/network/netconflist.go
+++ b/pkg/network/netconflist.go
@@ -6,6 +6,11 @@ import (
"path/filepath"
)
+const (
+ defaultIPv4Route = "0.0.0.0/0"
+ defaultIPv6Route = "::/0"
+)
+
// NcList describes a generic map
type NcList map[string]interface{}
@@ -86,9 +91,13 @@ func NewIPAMRoute(r *net.IPNet) IPAMRoute { //nolint:interfacer
}
// NewIPAMDefaultRoute creates a new IPAMDefault route of
-// 0.0.0.0/0
-func NewIPAMDefaultRoute() (IPAMRoute, error) {
- _, n, err := net.ParseCIDR("0.0.0.0/0")
+// 0.0.0.0/0 for IPv4 or ::/0 for IPv6
+func NewIPAMDefaultRoute(isIPv6 bool) (IPAMRoute, error) {
+ route := defaultIPv4Route
+ if isIPv6 {
+ route = defaultIPv6Route
+ }
+ _, n, err := net.ParseCIDR(route)
if err != nil {
return IPAMRoute{}, err
}
diff --git a/pkg/network/netconflist_test.go b/pkg/network/netconflist_test.go
new file mode 100644
index 000000000..a82a0140a
--- /dev/null
+++ b/pkg/network/netconflist_test.go
@@ -0,0 +1,38 @@
+package network
+
+import (
+ "reflect"
+ "testing"
+)
+
+func TestNewIPAMDefaultRoute(t *testing.T) {
+
+ tests := []struct {
+ name string
+ isIPv6 bool
+ want IPAMRoute
+ }{
+ {
+ name: "IPv4 default route",
+ isIPv6: false,
+ want: IPAMRoute{defaultIPv4Route},
+ },
+ {
+ name: "IPv6 default route",
+ isIPv6: true,
+ want: IPAMRoute{defaultIPv6Route},
+ },
+ }
+ for _, tt := range tests {
+ tt := tt
+ t.Run(tt.name, func(t *testing.T) {
+ got, err := NewIPAMDefaultRoute(tt.isIPv6)
+ if err != nil {
+ t.Errorf("no errorr expected: %v", err)
+ }
+ if !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("NewIPAMDefaultRoute() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/pkg/network/network.go b/pkg/network/network.go
index 37f3f721a..4da6bc969 100644
--- a/pkg/network/network.go
+++ b/pkg/network/network.go
@@ -137,6 +137,15 @@ func networkIntersect(n1, n2 *net.IPNet) bool {
// ValidateUserNetworkIsAvailable returns via an error if a network is available
// to be used
func ValidateUserNetworkIsAvailable(config *config.Config, userNet *net.IPNet) error {
+ if len(userNet.IP) == 0 || len(userNet.Mask) == 0 {
+ return errors.Errorf("network %s's ip or mask cannot be empty", userNet.String())
+ }
+
+ ones, bit := userNet.Mask.Size()
+ if ones == 0 || bit == 0 {
+ return errors.Errorf("network %s's mask is invalid", userNet.String())
+ }
+
networks, err := GetNetworksFromFilesystem(config)
if err != nil {
return err
diff --git a/pkg/ps/ps.go b/pkg/ps/ps.go
index 2b81311af..d4fd96596 100644
--- a/pkg/ps/ps.go
+++ b/pkg/ps/ps.go
@@ -175,11 +175,14 @@ func ListContainerBatch(rt *libpod.Runtime, ctr *libpod.Container, opts entities
State: conState.String(),
}
if opts.Pod && len(conConfig.Pod) > 0 {
- pod, err := rt.GetPod(conConfig.Pod)
+ podName, err := rt.GetName(conConfig.Pod)
if err != nil {
+ if errors.Cause(err) == define.ErrNoSuchCtr {
+ return entities.ListContainer{}, errors.Wrapf(define.ErrNoSuchPod, "could not find container %s pod (id %s) in state", conConfig.ID, conConfig.Pod)
+ }
return entities.ListContainer{}, err
}
- ps.PodName = pod.Name()
+ ps.PodName = podName
}
if opts.Namespace {
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 2e580347d..fb9f3e156 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -363,14 +363,12 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st
lastErr = nil
break
} else {
- fds, err := unix.Socketpair(unix.AF_UNIX, unix.SOCK_DGRAM, 0)
+ r, w, err := os.Pipe()
if err != nil {
lastErr = err
continue
}
- r, w := os.NewFile(uintptr(fds[0]), "read file"), os.NewFile(uintptr(fds[1]), "write file")
-
defer errorhandling.CloseQuiet(r)
if _, _, err := becomeRootInUserNS("", path, w); err != nil {
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index b974772d5..0dbdc76bb 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -321,13 +321,13 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
// config.
var defaultEnv map[string]string
if runtimeConfig == nil {
- defaultEnv = env.DefaultEnvVariables
+ defaultEnv = env.DefaultEnvVariables()
} else {
defaultEnv, err = env.ParseSlice(runtimeConfig.Containers.Env)
if err != nil {
return nil, errors.Wrap(err, "Env fields in containers.conf failed ot parse")
}
- defaultEnv = env.Join(env.DefaultEnvVariables, defaultEnv)
+ defaultEnv = env.Join(env.DefaultEnvVariables(), defaultEnv)
}
if err := addRlimits(config, &g); err != nil {
diff --git a/pkg/specgen/container_validate.go b/pkg/specgen/container_validate.go
index 57dd2aba7..4dd2ab0b3 100644
--- a/pkg/specgen/container_validate.go
+++ b/pkg/specgen/container_validate.go
@@ -43,6 +43,9 @@ func (s *SpecGenerator) Validate() error {
}
// Cannot set hostname and utsns
if len(s.ContainerBasicConfig.Hostname) > 0 && !s.ContainerBasicConfig.UtsNS.IsPrivate() {
+ if s.ContainerBasicConfig.UtsNS.IsPod() {
+ return errors.Wrap(ErrInvalidSpecConfig, "cannot set hostname when joining the pod UTS namespace")
+ }
return errors.Wrap(ErrInvalidSpecConfig, "cannot set hostname when running in the host UTS namespace")
}
// systemd values must be true, false, or always
@@ -135,11 +138,6 @@ func (s *SpecGenerator) Validate() error {
return err
}
- // The following are defaults as needed by container creation
- if len(s.WorkDir) < 1 {
- s.WorkDir = "/"
- }
-
// Set defaults if network info is not provided
if s.NetNS.NSMode == "" {
s.NetNS.NSMode = Bridge
diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go
index f0d52d0c3..06ffa3df6 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -86,6 +86,15 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
s.Env = envLib.Join(envLib.Join(defaultEnvs, envs), s.Env)
+ // Ensure that default environment variables are populated.
+ // Container must have PATH and TERM set, even if nothing else set them.
+ baseEnv := envLib.DefaultEnvVariables()
+ for k, v := range baseEnv {
+ if _, ok := s.Env[k]; !ok {
+ s.Env[k] = v
+ }
+ }
+
// Labels and Annotations
annotations := make(map[string]string)
if newImage != nil {
@@ -135,15 +144,18 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat
s.Annotations = annotations
// workdir
- if newImage != nil {
- workingDir, err := newImage.WorkingDir(ctx)
- if err != nil {
- return nil, err
- }
- if len(s.WorkDir) < 1 && len(workingDir) > 1 {
+ if s.WorkDir == "" {
+ if newImage != nil {
+ workingDir, err := newImage.WorkingDir(ctx)
+ if err != nil {
+ return nil, err
+ }
s.WorkDir = workingDir
}
}
+ if s.WorkDir == "" {
+ s.WorkDir = "/"
+ }
if len(s.SeccompProfilePath) < 1 {
p, err := libpod.DefaultSeccompPath()
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index be1e3b48e..6c0a702d6 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -153,13 +153,19 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
}
if len(command) > 0 {
- if command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (filepath.Base(command[0]) == "systemd") {
+ useSystemdCommands := map[string]bool{
+ "/sbin/init": true,
+ "/usr/sbin/init": true,
+ "/usr/local/sbin/init": true,
+ }
+ if useSystemdCommands[command[0]] || (filepath.Base(command[0]) == "systemd") {
useSystemd = true
}
}
default:
return nil, errors.Wrapf(err, "invalid value %q systemd option requires 'true, false, always'", s.Systemd)
}
+ logrus.Debugf("using systemd mode: %t", useSystemd)
if useSystemd {
// is StopSignal was not set by the user then set it to systemd
// expected StopSigal
@@ -209,6 +215,11 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen.
if s.Entrypoint != nil {
options = append(options, libpod.WithEntrypoint(s.Entrypoint))
}
+ // If the user did not set an workdir but the image did, ensure it is
+ // created.
+ if s.WorkDir == "" && img != nil {
+ options = append(options, libpod.WithCreateWorkingDir())
+ }
if s.StopSignal != nil {
options = append(options, libpod.WithStopSignal(*s.StopSignal))
}
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index f279aac1c..aefc7204c 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -96,8 +96,10 @@ func makeCommand(ctx context.Context, s *specgen.SpecGenerator, img *image.Image
finalCommand = append(finalCommand, entrypoint...)
+ // Only use image command if the user did not manually set an
+ // entrypoint.
command := s.Command
- if command == nil && img != nil {
+ if command == nil && img != nil && s.Entrypoint == nil {
newCmd, err := img.Cmd(ctx)
if err != nil {
return nil, err
@@ -258,7 +260,6 @@ func SpecGenToOCI(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Runt
for key, val := range s.Annotations {
g.AddAnnotation(key, val)
}
- g.AddProcessEnv("container", "podman")
g.Config.Linux.Resources = s.ResourceLimits
diff --git a/pkg/specgen/generate/security.go b/pkg/specgen/generate/security.go
index fcd1622f9..840dcb72d 100644
--- a/pkg/specgen/generate/security.go
+++ b/pkg/specgen/generate/security.go
@@ -158,8 +158,9 @@ func securityConfigureGenerator(s *specgen.SpecGenerator, g *generate.Generator,
configSpec.Linux.Seccomp = seccompConfig
}
- // Clear default Seccomp profile from Generator for privileged containers
- if s.SeccompProfilePath == "unconfined" || s.Privileged {
+ // Clear default Seccomp profile from Generator for unconfined containers
+ // and privileged containers which do not specify a seccomp profile.
+ if s.SeccompProfilePath == "unconfined" || (s.Privileged && (s.SeccompProfilePath == config.SeccompOverridePath || s.SeccompProfilePath == config.SeccompDefaultPath)) {
configSpec.Linux.Seccomp = nil
}
diff --git a/pkg/systemd/generate/common.go b/pkg/systemd/generate/common.go
index d6d18a810..1fc4479ff 100644
--- a/pkg/systemd/generate/common.go
+++ b/pkg/systemd/generate/common.go
@@ -1,6 +1,7 @@
package generate
import (
+ "strconv"
"strings"
"github.com/pkg/errors"
@@ -53,3 +54,15 @@ func filterPodFlags(command []string) []string {
}
return processed
}
+
+// quoteArguments makes sure that all arguments with at least one whitespace
+// are quoted to make sure those are interpreted as one argument instead of
+// multiple ones.
+func quoteArguments(command []string) []string {
+ for i := range command {
+ if strings.ContainsAny(command[i], " \t") {
+ command[i] = strconv.Quote(command[i])
+ }
+ }
+ return command
+}
diff --git a/pkg/systemd/generate/common_test.go b/pkg/systemd/generate/common_test.go
index 389c30f59..d0ec5637c 100644
--- a/pkg/systemd/generate/common_test.go
+++ b/pkg/systemd/generate/common_test.go
@@ -28,3 +28,28 @@ func TestFilterPodFlags(t *testing.T) {
}
}
}
+
+func TestQuoteArguments(t *testing.T) {
+ tests := []struct {
+ input []string
+ output []string
+ }{
+ {
+ []string{"foo", "bar=\"arg\""},
+ []string{"foo", "bar=\"arg\""},
+ },
+ {
+ []string{"foo", "bar=\"arg with space\""},
+ []string{"foo", "\"bar=\\\"arg with space\\\"\""},
+ },
+ {
+ []string{"foo", "bar=\"arg with\ttab\""},
+ []string{"foo", "\"bar=\\\"arg with\\ttab\\\"\""},
+ },
+ }
+
+ for _, test := range tests {
+ quoted := quoteArguments(test.input)
+ assert.Equal(t, test.output, quoted)
+ }
+}
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index b77fb5e11..068bb3c82 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -241,6 +241,7 @@ func executeContainerTemplate(info *containerInfo, options entities.GenerateSyst
startCommand = append(startCommand, "--replace")
}
startCommand = append(startCommand, info.CreateCommand[index:]...)
+ startCommand = quoteArguments(startCommand)
info.ExecStartPre = "/bin/rm -f {{.PIDFile}} {{.ContainerIDFile}}"
info.ExecStart = strings.Join(startCommand, " ")
diff --git a/pkg/systemd/generate/containers_test.go b/pkg/systemd/generate/containers_test.go
index 13138c0cd..73fc5e856 100644
--- a/pkg/systemd/generate/containers_test.go
+++ b/pkg/systemd/generate/containers_test.go
@@ -117,7 +117,7 @@ After=network-online.target
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=always
ExecStartPre=/bin/rm -f %t/jadda-jadda.pid %t/jadda-jadda.ctr-id
-ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon -d --replace --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN
+ExecStart=/usr/bin/podman run --conmon-pidfile %t/jadda-jadda.pid --cidfile %t/jadda-jadda.ctr-id --cgroups=no-conmon -d --replace --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN "foo=arg \"with \" space"
ExecStop=/usr/bin/podman stop --ignore --cidfile %t/jadda-jadda.ctr-id -t 42
ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/jadda-jadda.ctr-id
PIDFile=%t/jadda-jadda.pid
@@ -296,7 +296,7 @@ WantedBy=multi-user.target default.target`
PIDFile: "/var/run/containers/storage/overlay-containers/639c53578af4d84b8800b4635fa4e680ee80fd67e0e6a2d4eea48d1e3230f401/userdata/conmon.pid",
StopTimeout: 42,
PodmanVersion: "CI",
- CreateCommand: []string{"I'll get stripped", "container", "run", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN"},
+ CreateCommand: []string{"I'll get stripped", "container", "run", "--name", "jadda-jadda", "--hostname", "hello-world", "awesome-image:latest", "command", "arg1", "...", "argN", "foo=arg \"with \" space"},
EnvVariable: EnvVariable,
},
goodWithNameAndGeneric,
diff --git a/pkg/systemd/generate/pods.go b/pkg/systemd/generate/pods.go
index 1c7ef7792..df807585a 100644
--- a/pkg/systemd/generate/pods.go
+++ b/pkg/systemd/generate/pods.go
@@ -292,6 +292,7 @@ func executePodTemplate(info *podInfo, options entities.GenerateSystemdOptions)
}
startCommand = append(startCommand, podCreateArgs...)
+ startCommand = quoteArguments(startCommand)
info.ExecStartPre1 = "/bin/rm -f {{.PIDFile}} {{.PodIDFile}}"
info.ExecStartPre2 = strings.Join(startCommand, " ")
diff --git a/pkg/systemd/generate/pods_test.go b/pkg/systemd/generate/pods_test.go
index 4089b44e5..9754d3215 100644
--- a/pkg/systemd/generate/pods_test.go
+++ b/pkg/systemd/generate/pods_test.go
@@ -75,7 +75,7 @@ Before=container-1.service container-2.service
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
ExecStartPre=/bin/rm -f %t/pod-123abc.pid %t/pod-123abc.pod-id
-ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo --replace
+ExecStartPre=/usr/bin/podman pod create --infra-conmon-pidfile %t/pod-123abc.pid --pod-id-file %t/pod-123abc.pod-id --name foo "bar=arg with space" --replace
ExecStart=/usr/bin/podman pod start --pod-id-file %t/pod-123abc.pod-id
ExecStop=/usr/bin/podman pod stop --ignore --pod-id-file %t/pod-123abc.pod-id -t 10
ExecStopPost=/usr/bin/podman pod rm --ignore -f --pod-id-file %t/pod-123abc.pod-id
@@ -118,7 +118,7 @@ WantedBy=multi-user.target default.target`
StopTimeout: 10,
PodmanVersion: "CI",
RequiredServices: []string{"container-1", "container-2"},
- CreateCommand: []string{"podman", "pod", "create", "--name", "foo"},
+ CreateCommand: []string{"podman", "pod", "create", "--name", "foo", "bar=arg with space"},
},
podGoodNamedNew,
true,
diff --git a/pkg/varlinkapi/create.go b/pkg/varlinkapi/create.go
index ac93939d9..7661173b8 100644
--- a/pkg/varlinkapi/create.go
+++ b/pkg/varlinkapi/create.go
@@ -704,7 +704,12 @@ func ParseCreateOpts(ctx context.Context, c *GenericCLIResults, runtime *libpod.
if err != nil {
return nil, errors.Wrapf(err, "cannot parse bool %s", c.String("systemd"))
}
- if x && (command[0] == "/usr/sbin/init" || command[0] == "/sbin/init" || (filepath.Base(command[0]) == "systemd")) {
+ useSystemdCommands := map[string]bool{
+ "/sbin/init": true,
+ "/usr/sbin/init": true,
+ "/usr/local/sbin/init": true,
+ }
+ if x && (useSystemdCommands[command[0]] || (filepath.Base(command[0]) == "systemd")) {
systemd = true
}
}