diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | cmd/podman/exec.go | 11 | ||||
-rw-r--r-- | cmd/podman/info.go | 12 | ||||
-rw-r--r-- | cmd/podman/shared/container.go | 14 | ||||
-rw-r--r-- | cmd/podman/shared/funcs.go | 4 | ||||
-rwxr-xr-x | contrib/cirrus/ooe.sh | 6 | ||||
-rw-r--r-- | libpod/adapter/client.go | 16 | ||||
-rw-r--r-- | libpod/adapter/info_remote.go | 56 | ||||
-rw-r--r-- | libpod/adapter/runtime.go | 26 | ||||
-rw-r--r-- | libpod/adapter/runtime_remote.go | 28 | ||||
-rw-r--r-- | libpod/image/parts.go | 12 | ||||
-rw-r--r-- | libpod/lock/lock.go | 3 | ||||
-rw-r--r-- | libpod/lock/shm/shm_lock.go | 4 | ||||
-rw-r--r-- | libpod/lock/shm/shm_lock_test.go | 8 | ||||
-rw-r--r-- | libpod/lock/shm_lock_manager_linux.go | 8 | ||||
-rw-r--r-- | pkg/varlinkapi/system.go | 1 | ||||
-rw-r--r-- | vendor.conf | 2 | ||||
-rw-r--r-- | vendor/github.com/containers/buildah/common.go | 14 | ||||
-rw-r--r-- | vendor/github.com/containers/buildah/util.go | 23 |
19 files changed, 187 insertions, 64 deletions
@@ -111,6 +111,9 @@ test/goecho/goecho: .gopathok $(wildcard test/goecho/*.go) podman: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) $(GO) build -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS)" -o bin/$@ $(PROJECT)/cmd/podman +podman-remote: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) + $(GO) build -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS) remoteclient" -o bin/$@ $(PROJECT)/cmd/podman + local-cross: $(CROSS_BUILD_TARGETS) bin/podman.cross.%: .gopathok diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go index 1dcb88dbd..c03834dea 100644 --- a/cmd/podman/exec.go +++ b/cmd/podman/exec.go @@ -3,7 +3,6 @@ package main import ( "fmt" "os" - "strings" "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod" @@ -99,15 +98,7 @@ func execCmd(c *cli.Context) error { } // ENVIRONMENT VARIABLES - env := defaultEnvVariables - for _, e := range c.StringSlice("env") { - split := strings.SplitN(e, "=", 2) - if len(split) > 1 { - env[split[0]] = split[1] - } else { - env[split[0]] = "" - } - } + env := map[string]string{} if err := readKVStrings(env, []string{}, c.StringSlice("env")); err != nil { return errors.Wrapf(err, "unable to process environment variables") diff --git a/cmd/podman/info.go b/cmd/podman/info.go index c0639725e..4b80f94db 100644 --- a/cmd/podman/info.go +++ b/cmd/podman/info.go @@ -1,10 +1,10 @@ package main import ( + "github.com/containers/libpod/libpod/adapter" "runtime" "github.com/containers/libpod/cmd/podman/formats" - "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod" "github.com/pkg/errors" "github.com/urfave/cli" @@ -39,18 +39,20 @@ func infoCmd(c *cli.Context) error { } info := map[string]interface{}{} - runtime, err := libpodruntime.GetRuntime(c) + localRuntime, err := adapter.GetRuntime(c) if err != nil { return errors.Wrapf(err, "could not get runtime") } - defer runtime.Shutdown(false) + defer localRuntime.Runtime.Shutdown(false) - infoArr, err := runtime.Info() + infoArr, err := localRuntime.Runtime.Info() if err != nil { return errors.Wrapf(err, "error getting info") } - if c.Bool("debug") { + // TODO This is no a problem child because we don't know if we should add information + // TODO about the client or the backend. Only do for traditional podman for now. + if !localRuntime.Remote && c.Bool("debug") { debugInfo := debugInfo(c) infoArr = append(infoArr, libpod.InfoData{Type: "debug", Data: debugInfo}) } 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/contrib/cirrus/ooe.sh b/contrib/cirrus/ooe.sh index d79e574b2..3c8a0409d 100755 --- a/contrib/cirrus/ooe.sh +++ b/contrib/cirrus/ooe.sh @@ -7,10 +7,10 @@ set -eo pipefail -SCRIPT_PATH="$0" +SCRIPT_BASEDIR="$(basename $0)" badusage() { - echo "Incorrect usage: $(basename $SCRIPT_PATH) <command> [options]" > /dev/stderr + echo "Incorrect usage: $SCRIPT_BASEDIR) <command> [options]" > /dev/stderr echo "ERROR: $1" exit 121 } @@ -18,7 +18,7 @@ badusage() { COMMAND="$@" [[ -n "$COMMAND" ]] || badusage "No command specified" -OUTPUT_TMPFILE="$(mktemp -p '' $(basename $0)_output_XXXX)" +OUTPUT_TMPFILE="$(mktemp -p '' ${SCRIPT_BASEDIR}_output_XXXX)" output_on_error() { RET=$? set +e diff --git a/libpod/adapter/client.go b/libpod/adapter/client.go new file mode 100644 index 000000000..383c242c9 --- /dev/null +++ b/libpod/adapter/client.go @@ -0,0 +1,16 @@ +// +build remoteclient + +package adapter + +import ( + "github.com/varlink/go/varlink" +) + +// Connect provides a varlink connection +func (r RemoteRuntime) Connect() (*varlink.Connection, error) { + connection, err := varlink.NewConnection("unix:/run/podman/io.podman") + if err != nil { + return nil, err + } + return connection, nil +} diff --git a/libpod/adapter/info_remote.go b/libpod/adapter/info_remote.go new file mode 100644 index 000000000..3b691ed17 --- /dev/null +++ b/libpod/adapter/info_remote.go @@ -0,0 +1,56 @@ +// +build remoteclient + +package adapter + +import ( + "encoding/json" + + "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/libpod" +) + +// Info returns information for the host system and its components +func (r RemoteRuntime) Info() ([]libpod.InfoData, error) { + // TODO the varlink implementation for info should be updated to match the output for regular info + var ( + reply []libpod.InfoData + hostInfo map[string]interface{} + store map[string]interface{} + ) + + registries := make(map[string]interface{}) + insecureRegistries := make(map[string]interface{}) + conn, err := r.Connect() + if err != nil { + return nil, err + } + defer conn.Close() + info, err := iopodman.GetInfo().Call(conn) + if err != nil { + return nil, err + } + + // info.host -> map[string]interface{} + h, err := json.Marshal(info.Host) + if err != nil { + return nil, err + } + json.Unmarshal(h, &hostInfo) + + // info.store -> map[string]interface{} + s, err := json.Marshal(info.Store) + if err != nil { + return nil, err + } + json.Unmarshal(s, &store) + + registries["registries"] = info.Registries + insecureRegistries["registries"] = info.Insecure_registries + + // Add everything to the reply + reply = append(reply, libpod.InfoData{Type: "host", Data: hostInfo}) + reply = append(reply, libpod.InfoData{Type: "registries", Data: registries}) + reply = append(reply, libpod.InfoData{Type: "insecure registries", Data: insecureRegistries}) + reply = append(reply, libpod.InfoData{Type: "store", Data: store}) + return reply, nil +} diff --git a/libpod/adapter/runtime.go b/libpod/adapter/runtime.go new file mode 100644 index 000000000..b6db51071 --- /dev/null +++ b/libpod/adapter/runtime.go @@ -0,0 +1,26 @@ +// +build !remoteclient + +package adapter + +import ( + "github.com/containers/libpod/cmd/podman/libpodruntime" + "github.com/containers/libpod/libpod" + "github.com/urfave/cli" +) + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + Runtime *libpod.Runtime + Remote bool +} + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cli.Context) (*LocalRuntime, error) { + runtime, err := libpodruntime.GetRuntime(c) + if err != nil { + return nil, err + } + return &LocalRuntime{ + Runtime: runtime, + }, nil +} diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go new file mode 100644 index 000000000..715728d21 --- /dev/null +++ b/libpod/adapter/runtime_remote.go @@ -0,0 +1,28 @@ +// +build remoteclient + +package adapter + +import "github.com/urfave/cli" + +// RemoteRuntime describes a wrapper runtime struct +type RemoteRuntime struct{} + +// LocalRuntime describes a typical libpod runtime +type LocalRuntime struct { + Runtime *RemoteRuntime + Remote bool +} + +// GetRuntime returns a LocalRuntime struct with the actual runtime embedded in it +func GetRuntime(c *cli.Context) (*LocalRuntime, error) { + runtime := RemoteRuntime{} + return &LocalRuntime{ + Runtime: &runtime, + Remote: true, + }, nil +} + +// Shutdown is a bogus wrapper for compat with the libpod runtime +func (r RemoteRuntime) Shutdown(force bool) error { + return nil +} 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 } diff --git a/pkg/varlinkapi/system.go b/pkg/varlinkapi/system.go index a29d22e7d..e50643dd0 100644 --- a/pkg/varlinkapi/system.go +++ b/pkg/varlinkapi/system.go @@ -102,6 +102,5 @@ func (i *LibpodAPI) GetInfo(call iopodman.VarlinkCall) error { podmanInfo.Podman = pmaninfo podmanInfo.Registries = registries podmanInfo.Insecure_registries = insecureRegistries - return call.ReplyGetInfo(podmanInfo) } diff --git a/vendor.conf b/vendor.conf index c215f8294..9af218d15 100644 --- a/vendor.conf +++ b/vendor.conf @@ -92,7 +92,7 @@ k8s.io/kube-openapi 275e2ce91dec4c05a4094a7b1daee5560b555ac9 https://github.com/ k8s.io/utils 258e2a2fa64568210fbd6267cf1d8fd87c3cb86e https://github.com/kubernetes/utils github.com/mrunalp/fileutils master github.com/varlink/go master -github.com/containers/buildah bb710f39d01868e47224f35f48a128fbea6539c4 +github.com/containers/buildah a4200ae6b590c4b08b223e45513b1894636d1d02 github.com/Nvveen/Gotty master github.com/fsouza/go-dockerclient master github.com/openshift/imagebuilder master diff --git a/vendor/github.com/containers/buildah/common.go b/vendor/github.com/containers/buildah/common.go index dfdc33a22..e369dc407 100644 --- a/vendor/github.com/containers/buildah/common.go +++ b/vendor/github.com/containers/buildah/common.go @@ -6,10 +6,8 @@ import ( "path/filepath" cp "github.com/containers/image/copy" - "github.com/containers/image/transports" "github.com/containers/image/types" "github.com/containers/libpod/pkg/rootless" - "github.com/sirupsen/logrus" ) const ( @@ -34,12 +32,6 @@ func getCopyOptions(reportWriter io.Writer, sourceReference types.ImageReference } } - sourceInsecure, err := isReferenceInsecure(sourceReference, sourceCtx) - if err != nil { - logrus.Debugf("error determining if registry for %q is insecure: %v", transports.ImageName(sourceReference), err) - } else if sourceInsecure { - sourceCtx.OCIInsecureSkipTLSVerify = true - } destinationCtx := &types.SystemContext{} if destinationSystemContext != nil { @@ -51,12 +43,6 @@ func getCopyOptions(reportWriter io.Writer, sourceReference types.ImageReference } } } - destinationInsecure, err := isReferenceInsecure(destinationReference, destinationCtx) - if err != nil { - logrus.Debugf("error determining if registry for %q is insecure: %v", transports.ImageName(destinationReference), err) - } else if destinationInsecure { - destinationCtx.OCIInsecureSkipTLSVerify = true - } return &cp.Options{ ReportWriter: reportWriter, diff --git a/vendor/github.com/containers/buildah/util.go b/vendor/github.com/containers/buildah/util.go index 66a4e535a..5dadec7c2 100644 --- a/vendor/github.com/containers/buildah/util.go +++ b/vendor/github.com/containers/buildah/util.go @@ -173,24 +173,6 @@ func (b *Builder) tarPath() func(path string) (io.ReadCloser, error) { } } -// isRegistryInsecure checks if the named registry is marked as not secure -func isRegistryInsecure(registry string, sc *types.SystemContext) (bool, error) { - reginfo, err := sysregistriesv2.FindRegistry(sc, registry) - if err != nil { - return false, errors.Wrapf(err, "unable to parse the registries configuration (%s)", sysregistries.RegistriesConfPath(sc)) - } - if reginfo != nil { - if reginfo.Insecure { - logrus.Debugf("registry %q is marked insecure in registries configuration %q", registry, sysregistries.RegistriesConfPath(sc)) - } else { - logrus.Debugf("registry %q is not marked insecure in registries configuration %q", registry, sysregistries.RegistriesConfPath(sc)) - } - return reginfo.Insecure, nil - } - logrus.Debugf("registry %q is not listed in registries configuration %q, assuming it's secure", registry, sysregistries.RegistriesConfPath(sc)) - return false, nil -} - // isRegistryBlocked checks if the named registry is marked as blocked func isRegistryBlocked(registry string, sc *types.SystemContext) (bool, error) { reginfo, err := sysregistriesv2.FindRegistry(sc, registry) @@ -221,11 +203,6 @@ func isReferenceSomething(ref types.ImageReference, sc *types.SystemContext, wha return false, nil } -// isReferenceInsecure checks if the registry part of a reference is insecure -func isReferenceInsecure(ref types.ImageReference, sc *types.SystemContext) (bool, error) { - return isReferenceSomething(ref, sc, isRegistryInsecure) -} - // isReferenceBlocked checks if the registry part of a reference is blocked func isReferenceBlocked(ref types.ImageReference, sc *types.SystemContext) (bool, error) { if ref != nil && ref.Transport() != nil { |