summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/login.go42
-rw-r--r--cmd/podman/main.go3
-rw-r--r--cmd/podman/shared/container.go14
-rw-r--r--cmd/podman/shared/funcs.go4
-rw-r--r--libpod/image/parts.go12
-rw-r--r--libpod/lock/lock.go3
-rw-r--r--libpod/lock/shm/shm_lock.go4
-rw-r--r--libpod/lock/shm/shm_lock_test.go8
-rw-r--r--libpod/lock/shm_lock_manager_linux.go8
9 files changed, 68 insertions, 30 deletions
diff --git a/cmd/podman/login.go b/cmd/podman/login.go
index 4452651f8..fc7b39ed8 100644
--- a/cmd/podman/login.go
+++ b/cmd/podman/login.go
@@ -62,12 +62,18 @@ func loginCmd(c *cli.Context) error {
return errors.Errorf("too many arguments, login takes only 1 argument")
}
if len(args) == 0 {
- return errors.Errorf("registry must be given")
+ return errors.Errorf("please specify a registry to login to")
}
server := registryFromFullName(scrubServer(args[0]))
authfile := getAuthFile(c.String("authfile"))
sc := common.GetSystemContext("", authfile, false)
+ if c.IsSet("tls-verify") {
+ sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
+ }
+ if c.String("cert-dir") != "" {
+ sc.DockerCertPath = c.String("cert-dir")
+ }
if c.IsSet("get-login") {
user, err := config.GetUserLoggedIn(sc, server)
@@ -87,39 +93,25 @@ func loginCmd(c *cli.Context) error {
// username of user logged in to server (if one exists)
userFromAuthFile, passFromAuthFile, err := config.GetAuthentication(sc, server)
if err != nil {
- return errors.Wrapf(err, "error getting logged-in user")
+ return errors.Wrapf(err, "error reading auth file")
}
ctx := getContext()
-
- var (
- username string
- password string
- )
-
- if userFromAuthFile != "" {
- username = userFromAuthFile
- password = passFromAuthFile
+ // If no username and no password is specified, try to use existing ones.
+ if c.String("username") == "" && c.String("password") == "" {
fmt.Println("Authenticating with existing credentials...")
- if err := docker.CheckAuth(ctx, sc, username, password, server); err == nil {
+ if err := docker.CheckAuth(ctx, sc, userFromAuthFile, passFromAuthFile, server); err == nil {
fmt.Println("Existing credentials are valid. Already logged in to", server)
return nil
}
fmt.Println("Existing credentials are invalid, please enter valid username and password")
}
- username, password, err = getUserAndPass(c.String("username"), c.String("password"), userFromAuthFile)
+ username, password, err := getUserAndPass(c.String("username"), c.String("password"), userFromAuthFile)
if err != nil {
return errors.Wrapf(err, "error getting username and password")
}
- if c.IsSet("tls-verify") {
- sc.DockerInsecureSkipTLSVerify = types.NewOptionalBool(!c.BoolT("tls-verify"))
- }
- if c.String("cert-dir") != "" {
- sc.DockerCertPath = c.String("cert-dir")
- }
-
if err = docker.CheckAuth(ctx, sc, username, password, server); err == nil {
// Write the new credentials to the authfile
if err = config.SetAuthentication(sc, server, username, password); err != nil {
@@ -131,14 +123,15 @@ func loginCmd(c *cli.Context) error {
fmt.Println("Login Succeeded!")
return nil
case docker.ErrUnauthorizedForCredentials:
- return errors.Errorf("error logging into %q: invalid username/password\n", server)
+ return errors.Errorf("error logging into %q: invalid username/password", server)
default:
return errors.Wrapf(err, "error authenticating creds for %q", server)
}
}
// getUserAndPass gets the username and password from STDIN if not given
-// using the -u and -p flags
+// using the -u and -p flags. If the username prompt is left empty, the
+// displayed userFromAuthFile will be used instead.
func getUserAndPass(username, password, userFromAuthFile string) (string, string, error) {
var err error
reader := bufio.NewReader(os.Stdin)
@@ -152,7 +145,10 @@ func getUserAndPass(username, password, userFromAuthFile string) (string, string
if err != nil {
return "", "", errors.Wrapf(err, "error reading username")
}
- // If no username provided, use userFromAuthFile instead.
+ // If the user just hit enter, use the displayed user from the
+ // the authentication file. This allows to do a lazy
+ // `$ podman login -p $NEW_PASSWORD` without specifying the
+ // user.
if strings.TrimSpace(username) == "" {
username = userFromAuthFile
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 7ef22a93b..43804ee35 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -161,6 +161,9 @@ func main() {
logrus.Info("running as rootless")
}
+ // Be sure we can create directories with 0755 mode.
+ syscall.Umask(0022)
+
if logLevel == "debug" {
debug = true
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index 30beb4a49..6c7d8eb52 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
+ "github.com/google/shlex"
"io"
"os"
"path/filepath"
@@ -640,6 +641,14 @@ func GetRunlabel(label string, runlabelImage string, ctx context.Context, runtim
// GenerateRunlabelCommand generates the command that will eventually be execucted by podman
func GenerateRunlabelCommand(runLabel, imageName, name string, opts map[string]string, extraArgs []string) ([]string, []string, error) {
+ // If no name is provided, we use the image's basename instead
+ if name == "" {
+ baseName, err := image.GetImageBaseName(imageName)
+ if err != nil {
+ return nil, nil, err
+ }
+ name = baseName
+ }
// The user provided extra arguments that need to be tacked onto the label's command
if len(extraArgs) > 0 {
runLabel = fmt.Sprintf("%s %s", runLabel, strings.Join(extraArgs, " "))
@@ -665,7 +674,10 @@ func GenerateRunlabelCommand(runLabel, imageName, name string, opts map[string]s
return ""
}
newS := os.Expand(strings.Join(cmd, " "), envmapper)
- cmd = strings.Split(newS, " ")
+ cmd, err = shlex.Split(newS)
+ if err != nil {
+ return nil, nil, err
+ }
return cmd, env, nil
}
diff --git a/cmd/podman/shared/funcs.go b/cmd/podman/shared/funcs.go
index 8770b8ec0..70d041fd2 100644
--- a/cmd/podman/shared/funcs.go
+++ b/cmd/podman/shared/funcs.go
@@ -65,6 +65,8 @@ func GenerateCommand(command, imageName, name string) ([]string, error) {
switch arg {
case "IMAGE":
newArg = imageName
+ case "$IMAGE":
+ newArg = imageName
case "IMAGE=IMAGE":
newArg = fmt.Sprintf("IMAGE=%s", imageName)
case "IMAGE=$IMAGE":
@@ -75,6 +77,8 @@ func GenerateCommand(command, imageName, name string) ([]string, error) {
newArg = fmt.Sprintf("NAME=%s", name)
case "NAME=$NAME":
newArg = fmt.Sprintf("NAME=%s", name)
+ case "$NAME":
+ newArg = name
default:
newArg = arg
}
diff --git a/libpod/image/parts.go b/libpod/image/parts.go
index 1509005e5..9adf26fb9 100644
--- a/libpod/image/parts.go
+++ b/libpod/image/parts.go
@@ -22,6 +22,18 @@ func isRegistry(name string) bool {
return strings.ContainsAny(name, ".:") || name == "localhost"
}
+// GetImageBaseName uses decompose and string splits to obtain the base
+// name of an image. Doing this here because it beats changing the
+// imageParts struct names to be exported as well.
+func GetImageBaseName(input string) (string, error) {
+ decomposedImage, err := decompose(input)
+ if err != nil {
+ return "", err
+ }
+ splitImageName := strings.Split(decomposedImage.name, "/")
+ return splitImageName[len(splitImageName)-1], nil
+}
+
// decompose breaks an input name into an imageParts description
func decompose(input string) (imageParts, error) {
var (
diff --git a/libpod/lock/lock.go b/libpod/lock/lock.go
index 73c1fdcf7..1f94171fe 100644
--- a/libpod/lock/lock.go
+++ b/libpod/lock/lock.go
@@ -43,6 +43,9 @@ type Locker interface {
// encounters a fatal error.
// All errors must be handled internally, as they are not returned. For
// the most part, panicking should be appropriate.
+ // Some lock implementations may require that Lock() and Unlock() occur
+ // within the same goroutine (SHM locking, for example). The usual Go
+ // Lock()/defer Unlock() pattern will still work fine in these cases.
Lock()
// Unlock unlocks the lock.
// All errors must be handled internally, as they are not returned. For
diff --git a/libpod/lock/shm/shm_lock.go b/libpod/lock/shm/shm_lock.go
index be5e5148f..87d28e5c1 100644
--- a/libpod/lock/shm/shm_lock.go
+++ b/libpod/lock/shm/shm_lock.go
@@ -36,7 +36,7 @@ type SHMLocks struct { // nolint
// size used by the underlying implementation.
func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) {
if numLocks == 0 {
- return nil, errors.Wrapf(syscall.EINVAL, "number of locks must greater than 0 0")
+ return nil, errors.Wrapf(syscall.EINVAL, "number of locks must be greater than 0")
}
locks := new(SHMLocks)
@@ -65,7 +65,7 @@ func CreateSHMLock(path string, numLocks uint32) (*SHMLocks, error) {
// segment was created with.
func OpenSHMLock(path string, numLocks uint32) (*SHMLocks, error) {
if numLocks == 0 {
- return nil, errors.Wrapf(syscall.EINVAL, "number of locks must greater than 0")
+ return nil, errors.Wrapf(syscall.EINVAL, "number of locks must be greater than 0")
}
locks := new(SHMLocks)
diff --git a/libpod/lock/shm/shm_lock_test.go b/libpod/lock/shm/shm_lock_test.go
index 0f3a96cca..594eb5d8e 100644
--- a/libpod/lock/shm/shm_lock_test.go
+++ b/libpod/lock/shm/shm_lock_test.go
@@ -256,13 +256,13 @@ func TestLockSemaphoreActuallyLocks(t *testing.T) {
// Ensures that runtime.LockOSThread() is doing its job
func TestLockAndUnlockTwoSemaphore(t *testing.T) {
runLockTest(t, func(t *testing.T, locks *SHMLocks) {
- err := locks.LockSemaphore(0)
+ err := locks.LockSemaphore(5)
assert.NoError(t, err)
- err = locks.LockSemaphore(1)
+ err = locks.LockSemaphore(6)
assert.NoError(t, err)
- err = locks.UnlockSemaphore(1)
+ err = locks.UnlockSemaphore(6)
assert.NoError(t, err)
// Now yield scheduling
@@ -272,7 +272,7 @@ func TestLockAndUnlockTwoSemaphore(t *testing.T) {
// And unlock the last semaphore
// If we are in a different OS thread, this should fail.
// However, runtime.UnlockOSThread() should guarantee we are not
- err = locks.UnlockSemaphore(0)
+ err = locks.UnlockSemaphore(5)
assert.NoError(t, err)
})
}
diff --git a/libpod/lock/shm_lock_manager_linux.go b/libpod/lock/shm_lock_manager_linux.go
index 3e8f4f3d2..94dfd7dd7 100644
--- a/libpod/lock/shm_lock_manager_linux.go
+++ b/libpod/lock/shm_lock_manager_linux.go
@@ -3,7 +3,10 @@
package lock
import (
+ "syscall"
+
"github.com/containers/libpod/libpod/lock/shm"
+ "github.com/pkg/errors"
)
// SHMLockManager manages shared memory locks.
@@ -60,6 +63,11 @@ func (m *SHMLockManager) RetrieveLock(id uint32) (Locker, error) {
lock.lockID = id
lock.manager = m
+ if id >= m.locks.GetMaxLocks() {
+ return nil, errors.Wrapf(syscall.EINVAL, "lock ID %d is too large - max lock size is %d",
+ id, m.locks.GetMaxLocks()-1)
+ }
+
return lock, nil
}