summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/bindings/connection.go2
-rw-r--r--pkg/bindings/images/build.go4
-rw-r--r--pkg/domain/entities/play.go2
-rw-r--r--pkg/domain/infra/abi/play.go131
-rw-r--r--pkg/rootlessport/rootlessport_linux.go35
-rw-r--r--pkg/specgen/generate/storage.go57
-rw-r--r--pkg/specgen/volumes.go12
-rw-r--r--pkg/systemd/dbus.go98
8 files changed, 263 insertions, 78 deletions
diff --git a/pkg/bindings/connection.go b/pkg/bindings/connection.go
index 62b1655ac..cd118cbb2 100644
--- a/pkg/bindings/connection.go
+++ b/pkg/bindings/connection.go
@@ -117,7 +117,7 @@ func NewConnectionWithIdentity(ctx context.Context, uri string, identity string)
ctx = context.WithValue(ctx, clientKey, &connection)
if err := pingNewConnection(ctx); err != nil {
- return nil, errors.Wrap(err, "cannot connect to the Podman socket, please verify that Podman REST API service is running")
+ return nil, errors.Wrap(err, "cannot connect to the Podman socket, please verify the connection to the Linux system, or use `podman machine` to create/start a Linux VM.")
}
return ctx, nil
}
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index e1aeae244..39e0fc5df 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -481,9 +481,9 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
return nil // skip root dir
}
- name := strings.TrimPrefix(path, s+string(filepath.Separator))
+ name := filepath.ToSlash(strings.TrimPrefix(path, s+string(filepath.Separator)))
- excluded, err := pm.Matches(filepath.ToSlash(name)) // nolint:staticcheck
+ excluded, err := pm.Matches(name) // nolint:staticcheck
if err != nil {
return errors.Wrapf(err, "error checking if %q is excluded", name)
}
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 89dfc08e9..01de73ebe 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -10,6 +10,8 @@ import (
type PlayKubeOptions struct {
// Authfile - path to an authentication file.
Authfile string
+ // Indicator to build all images with Containerfile or Dockerfile
+ Build bool
// CertDir - to a directory containing TLS certifications and keys.
CertDir string
// Username for authenticating against the registry.
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index d257bad18..6224feff5 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -7,9 +7,11 @@ import (
"io"
"io/ioutil"
"os"
+ "path/filepath"
"strconv"
"strings"
+ buildahDefine "github.com/containers/buildah/define"
"github.com/containers/common/libimage"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/types"
@@ -266,39 +268,69 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
containers := make([]*libpod.Container, 0, len(podYAML.Spec.Containers))
+ cwd, err := os.Getwd()
+ if err != nil {
+ return nil, err
+ }
for _, container := range podYAML.Spec.Containers {
// Contains all labels obtained from kube
labels := make(map[string]string)
-
- // NOTE: set the pull policy to "newer". This will cover cases
- // where the "latest" tag requires a pull and will also
- // transparently handle "localhost/" prefixed files which *may*
- // refer to a locally built image OR an image running a
- // registry on localhost.
- pullPolicy := config.PullPolicyNewer
- if len(container.ImagePullPolicy) > 0 {
- // Make sure to lower the strings since K8s pull policy
- // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905).
- rawPolicy := string(container.ImagePullPolicy)
- pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy))
- if err != nil {
- return nil, err
- }
+ var pulledImage *libimage.Image
+ buildFile, err := getBuildFile(container.Image, cwd)
+ if err != nil {
+ return nil, err
}
- // This ensures the image is the image store
- pullOptions := &libimage.PullOptions{}
- pullOptions.AuthFilePath = options.Authfile
- pullOptions.CertDirPath = options.CertDir
- pullOptions.SignaturePolicyPath = options.SignaturePolicy
- pullOptions.Writer = writer
- pullOptions.Username = options.Username
- pullOptions.Password = options.Password
- pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
-
- pulledImages, err := ic.Libpod.LibimageRuntime().Pull(ctx, container.Image, pullPolicy, pullOptions)
+ existsLocally, err := ic.Libpod.LibimageRuntime().Exists(container.Image)
if err != nil {
return nil, err
}
+ if (len(buildFile) > 0 && !existsLocally) || (len(buildFile) > 0 && options.Build) {
+ buildOpts := new(buildahDefine.BuildOptions)
+ commonOpts := new(buildahDefine.CommonBuildOptions)
+ buildOpts.ConfigureNetwork = buildahDefine.NetworkDefault
+ buildOpts.Isolation = buildahDefine.IsolationChroot
+ buildOpts.CommonBuildOpts = commonOpts
+ buildOpts.Output = container.Image
+ if _, _, err := ic.Libpod.Build(ctx, *buildOpts, []string{buildFile}...); err != nil {
+ return nil, err
+ }
+ i, _, err := ic.Libpod.LibimageRuntime().LookupImage(container.Image, new(libimage.LookupImageOptions))
+ if err != nil {
+ return nil, err
+ }
+ pulledImage = i
+ } else {
+ // NOTE: set the pull policy to "newer". This will cover cases
+ // where the "latest" tag requires a pull and will also
+ // transparently handle "localhost/" prefixed files which *may*
+ // refer to a locally built image OR an image running a
+ // registry on localhost.
+ pullPolicy := config.PullPolicyNewer
+ if len(container.ImagePullPolicy) > 0 {
+ // Make sure to lower the strings since K8s pull policy
+ // may be capitalized (see bugzilla.redhat.com/show_bug.cgi?id=1985905).
+ rawPolicy := string(container.ImagePullPolicy)
+ pullPolicy, err = config.ParsePullPolicy(strings.ToLower(rawPolicy))
+ if err != nil {
+ return nil, err
+ }
+ }
+ // This ensures the image is the image store
+ pullOptions := &libimage.PullOptions{}
+ pullOptions.AuthFilePath = options.Authfile
+ pullOptions.CertDirPath = options.CertDir
+ pullOptions.SignaturePolicyPath = options.SignaturePolicy
+ pullOptions.Writer = writer
+ pullOptions.Username = options.Username
+ pullOptions.Password = options.Password
+ pullOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
+
+ pulledImages, err := ic.Libpod.LibimageRuntime().Pull(ctx, container.Image, pullPolicy, pullOptions)
+ if err != nil {
+ return nil, err
+ }
+ pulledImage = pulledImages[0]
+ }
// Handle kube annotations
for k, v := range annotations {
@@ -318,7 +350,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
specgenOpts := kube.CtrSpecGenOptions{
Container: container,
- Image: pulledImages[0],
+ Image: pulledImage,
Volumes: volumes,
PodID: pod.ID(),
PodName: podName,
@@ -509,3 +541,48 @@ func sortKubeKinds(documentList [][]byte) ([][]byte, error) {
return sortedDocumentList, nil
}
+func imageNamePrefix(imageName string) string {
+ prefix := imageName
+ s := strings.Split(prefix, ":")
+ if len(s) > 0 {
+ prefix = s[0]
+ }
+ s = strings.Split(prefix, "/")
+ if len(s) > 0 {
+ prefix = s[len(s)-1]
+ }
+ s = strings.Split(prefix, "@")
+ if len(s) > 0 {
+ prefix = s[0]
+ }
+ return prefix
+}
+
+func getBuildFile(imageName string, cwd string) (string, error) {
+ buildDirName := imageNamePrefix(imageName)
+ containerfilePath := filepath.Join(cwd, buildDirName, "Containerfile")
+ dockerfilePath := filepath.Join(cwd, buildDirName, "Dockerfile")
+
+ _, err := os.Stat(filepath.Join(containerfilePath))
+ if err == nil {
+ logrus.Debugf("building %s with %s", imageName, containerfilePath)
+ return containerfilePath, nil
+ }
+ // If the error is not because the file does not exist, take
+ // a mulligan and try Dockerfile. If that also fails, return that
+ // error
+ if err != nil && !os.IsNotExist(err) {
+ logrus.Errorf("%v: unable to check for %s", err, containerfilePath)
+ }
+
+ _, err = os.Stat(filepath.Join(dockerfilePath))
+ if err == nil {
+ logrus.Debugf("building %s with %s", imageName, dockerfilePath)
+ return dockerfilePath, nil
+ }
+ // Strike two
+ if os.IsNotExist(err) {
+ return "", nil
+ }
+ return "", err
+}
diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go
index ede216bfe..9a2f93f8e 100644
--- a/pkg/rootlessport/rootlessport_linux.go
+++ b/pkg/rootlessport/rootlessport_linux.go
@@ -20,7 +20,6 @@ import (
"net"
"os"
"os/exec"
- "os/signal"
"path/filepath"
"github.com/containernetworking/plugins/pkg/ns"
@@ -106,30 +105,6 @@ func parent() error {
return err
}
- exitC := make(chan os.Signal, 1)
- defer close(exitC)
-
- go func() {
- sigC := make(chan os.Signal, 1)
- signal.Notify(sigC, unix.SIGPIPE)
- defer func() {
- signal.Stop(sigC)
- close(sigC)
- }()
-
- select {
- case s := <-sigC:
- if s == unix.SIGPIPE {
- if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil {
- unix.Dup2(int(f.Fd()), 1) // nolint:errcheck
- unix.Dup2(int(f.Fd()), 2) // nolint:errcheck
- f.Close()
- }
- }
- case <-exitC:
- }
- }()
-
socketDir := filepath.Join(cfg.TmpDir, "rp")
err = os.MkdirAll(socketDir, 0700)
if err != nil {
@@ -251,8 +226,16 @@ outer:
go serve(socket, driver)
}
- // write and close ReadyFD (convention is same as slirp4netns --ready-fd)
logrus.Info("ready")
+
+ // https://github.com/containers/podman/issues/11248
+ // Copy /dev/null to stdout and stderr to prevent SIGPIPE errors
+ if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil {
+ unix.Dup2(int(f.Fd()), 1) // nolint:errcheck
+ unix.Dup2(int(f.Fd()), 2) // nolint:errcheck
+ f.Close()
+ }
+ // write and close ReadyFD (convention is same as slirp4netns --ready-fd)
if _, err := readyW.Write([]byte("1")); err != nil {
return err
}
diff --git a/pkg/specgen/generate/storage.go b/pkg/specgen/generate/storage.go
index 13f336594..de655ad7d 100644
--- a/pkg/specgen/generate/storage.go
+++ b/pkg/specgen/generate/storage.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/common/libimage"
"github.com/containers/common/pkg/config"
+ "github.com/containers/common/pkg/parse"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/specgen"
@@ -59,6 +60,9 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
for _, m := range s.Mounts {
// Ensure that mount dest is clean, so that it can be
// compared against named volumes and avoid duplicate mounts.
+ if err = parse.ValidateVolumeCtrDir(m.Destination); err != nil {
+ return nil, nil, nil, err
+ }
cleanDestination := filepath.Clean(m.Destination)
if _, ok := unifiedMounts[cleanDestination]; ok {
return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified mounts - multiple mounts at %q", cleanDestination)
@@ -67,34 +71,54 @@ func finalizeMounts(ctx context.Context, s *specgen.SpecGenerator, rt *libpod.Ru
}
for _, m := range commonMounts {
- if _, ok := unifiedMounts[m.Destination]; !ok {
- unifiedMounts[m.Destination] = m
+ if err = parse.ValidateVolumeCtrDir(m.Destination); err != nil {
+ return nil, nil, nil, err
+ }
+ cleanDestination := filepath.Clean(m.Destination)
+ if _, ok := unifiedMounts[cleanDestination]; !ok {
+ unifiedMounts[cleanDestination] = m
}
}
for _, v := range s.Volumes {
- if _, ok := unifiedVolumes[v.Dest]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Dest)
+ if err = parse.ValidateVolumeCtrDir(v.Dest); err != nil {
+ return nil, nil, nil, err
}
- unifiedVolumes[v.Dest] = v
+ cleanDestination := filepath.Clean(v.Dest)
+ if _, ok := unifiedVolumes[cleanDestination]; ok {
+ return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination)
+ }
+ unifiedVolumes[cleanDestination] = v
}
for _, v := range commonVolumes {
- if _, ok := unifiedVolumes[v.Dest]; !ok {
- unifiedVolumes[v.Dest] = v
+ if err = parse.ValidateVolumeCtrDir(v.Dest); err != nil {
+ return nil, nil, nil, err
+ }
+ cleanDestination := filepath.Clean(v.Dest)
+ if _, ok := unifiedVolumes[cleanDestination]; !ok {
+ unifiedVolumes[cleanDestination] = v
}
}
for _, v := range s.OverlayVolumes {
- if _, ok := unifiedOverlays[v.Destination]; ok {
- return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", v.Destination)
+ if err = parse.ValidateVolumeCtrDir(v.Destination); err != nil {
+ return nil, nil, nil, err
}
- unifiedOverlays[v.Destination] = v
+ cleanDestination := filepath.Clean(v.Destination)
+ if _, ok := unifiedOverlays[cleanDestination]; ok {
+ return nil, nil, nil, errors.Wrapf(errDuplicateDest, "conflict in specified volumes - multiple volumes at %q", cleanDestination)
+ }
+ unifiedOverlays[cleanDestination] = v
}
for _, v := range commonOverlayVolumes {
- if _, ok := unifiedOverlays[v.Destination]; ok {
- unifiedOverlays[v.Destination] = v
+ if err = parse.ValidateVolumeCtrDir(v.Destination); err != nil {
+ return nil, nil, nil, err
+ }
+ cleanDestination := filepath.Clean(v.Destination)
+ if _, ok := unifiedOverlays[cleanDestination]; !ok {
+ unifiedOverlays[cleanDestination] = v
}
}
@@ -190,6 +214,9 @@ func getImageVolumes(ctx context.Context, img *libimage.Image, s *specgen.SpecGe
}
for volume := range inspect.Config.Volumes {
logrus.Debugf("Image has volume at %q", volume)
+ if err = parse.ValidateVolumeCtrDir(volume); err != nil {
+ return nil, nil, err
+ }
cleanDest := filepath.Clean(volume)
switch mode {
case "", "anonymous":
@@ -304,9 +331,13 @@ func getVolumesFrom(volumesFrom []string, runtime *libpod.Runtime) (map[string]s
if _, ok := finalMounts[namedVol.Dest]; ok {
logrus.Debugf("Overriding named volume mount to %s with new named volume from container %s", namedVol.Dest, ctr.ID())
}
+ if err = parse.ValidateVolumeCtrDir(namedVol.Dest); err != nil {
+ return nil, nil, err
+ }
+ cleanDest := filepath.Clean(namedVol.Dest)
newVol := new(specgen.NamedVolume)
- newVol.Dest = namedVol.Dest
+ newVol.Dest = cleanDest
newVol.Options = namedVol.Options
newVol.Name = namedVol.Name
diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go
index d85d2bdd1..eca8c0c35 100644
--- a/pkg/specgen/volumes.go
+++ b/pkg/specgen/volumes.go
@@ -1,7 +1,6 @@
package specgen
import (
- "path/filepath"
"strings"
"github.com/containers/common/pkg/parse"
@@ -93,11 +92,6 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
return nil, nil, nil, errors.New("host directory cannot be empty")
}
}
- if err := parse.ValidateVolumeCtrDir(dest); err != nil {
- return nil, nil, nil, err
- }
-
- cleanDest := filepath.Clean(dest)
if strings.HasPrefix(src, "/") || strings.HasPrefix(src, ".") {
// This is not a named volume
@@ -120,7 +114,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
if overlayFlag {
// This is a overlay volume
newOverlayVol := new(OverlayVolume)
- newOverlayVol.Destination = cleanDest
+ newOverlayVol.Destination = dest
newOverlayVol.Source = src
newOverlayVol.Options = options
@@ -130,7 +124,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
overlayVolumes[newOverlayVol.Destination] = newOverlayVol
} else {
newMount := spec.Mount{
- Destination: cleanDest,
+ Destination: dest,
Type: "bind",
Source: src,
Options: options,
@@ -144,7 +138,7 @@ func GenVolumeMounts(volumeFlag []string) (map[string]spec.Mount, map[string]*Na
// This is a named volume
newNamedVol := new(NamedVolume)
newNamedVol.Name = src
- newNamedVol.Dest = cleanDest
+ newNamedVol.Dest = dest
newNamedVol.Options = options
if _, ok := volumes[newNamedVol.Dest]; ok {
diff --git a/pkg/systemd/dbus.go b/pkg/systemd/dbus.go
index 718082526..c49f537b6 100644
--- a/pkg/systemd/dbus.go
+++ b/pkg/systemd/dbus.go
@@ -9,8 +9,106 @@ import (
"github.com/containers/podman/v3/pkg/rootless"
"github.com/coreos/go-systemd/v22/dbus"
godbus "github.com/godbus/dbus/v5"
+ "github.com/sirupsen/logrus"
)
+// IsSystemdSessionValid checks if sessions is valid for provided rootless uid.
+func IsSystemdSessionValid(uid int) bool {
+ var conn *godbus.Conn
+ var err error
+ var object godbus.BusObject
+ var seat0Path godbus.ObjectPath
+ dbusDest := "org.freedesktop.login1"
+ dbusInterface := "org.freedesktop.login1.Manager"
+ dbusPath := "/org/freedesktop/login1"
+
+ if rootless.IsRootless() {
+ conn, err = GetLogindConnection(rootless.GetRootlessUID())
+ object = conn.Object(dbusDest, godbus.ObjectPath(dbusPath))
+ if err != nil {
+ //unable to fetch systemd object for logind
+ logrus.Debugf("systemd-logind: %s", err)
+ return false
+ }
+ object = conn.Object(dbusDest, godbus.ObjectPath(dbusPath))
+ if err := object.Call(dbusInterface+".GetSeat", 0, "seat0").Store(&seat0Path); err != nil {
+ //unable to get seat0 path.
+ logrus.Debugf("systemd-logind: %s", err)
+ return false
+ }
+ seat0Obj := conn.Object(dbusDest, seat0Path)
+ activeSession, err := seat0Obj.GetProperty(dbusDest + ".Seat.ActiveSession")
+ if err != nil {
+ //unable to get active sessions.
+ logrus.Debugf("systemd-logind: %s", err)
+ return false
+ }
+ activeSessionMap, ok := activeSession.Value().([]interface{})
+ if !ok || len(activeSessionMap) < 2 {
+ //unable to get active session map.
+ logrus.Debugf("systemd-logind: %s", err)
+ return false
+ }
+ activeSessionPath, ok := activeSessionMap[1].(godbus.ObjectPath)
+ if !ok {
+ //unable to fetch active session path.
+ logrus.Debugf("systemd-logind: %s", err)
+ return false
+ }
+ activeSessionObj := conn.Object(dbusDest, activeSessionPath)
+ sessionUser, err := activeSessionObj.GetProperty(dbusDest + ".Session.User")
+ if err != nil {
+ //unable to fetch session user from activeSession path.
+ logrus.Debugf("systemd-logind: %s", err)
+ return false
+ }
+ dbusUser, ok := sessionUser.Value().([]interface{})
+ if !ok {
+ // not a valid user.
+ return false
+ }
+ if len(dbusUser) < 2 {
+ // not a valid session user.
+ return false
+ }
+ activeUID, ok := dbusUser[0].(uint32)
+ if !ok {
+ return false
+ }
+ //active session found which belongs to following rootless user
+ if activeUID == uint32(uid) {
+ return true
+ }
+ return false
+ }
+ return true
+}
+
+// GetDbusConnection returns an user connection to D-BUS
+func GetLogindConnection(uid int) (*godbus.Conn, error) {
+ return dbusAuthConnectionLogind(uid)
+}
+
+func dbusAuthConnectionLogind(uid int) (*godbus.Conn, error) {
+ var conn *godbus.Conn
+ var err error
+ conn, err = godbus.SystemBusPrivate()
+ if err != nil {
+ return nil, err
+ }
+ methods := []godbus.Auth{godbus.AuthExternal(strconv.Itoa(uid))}
+ if err = conn.Auth(methods); err != nil {
+ conn.Close()
+ return nil, err
+ }
+ err = conn.Hello()
+ if err != nil {
+ conn.Close()
+ return nil, err
+ }
+ return conn, nil
+}
+
func dbusAuthRootlessConnection(createBus func(opts ...godbus.ConnOption) (*godbus.Conn, error)) (*godbus.Conn, error) {
conn, err := createBus()
if err != nil {