diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | Makefile | 21 | ||||
-rw-r--r-- | docs/links/podman-container-cp.1 | 1 | ||||
-rw-r--r-- | docs/links/podman-container-init.1 | 1 | ||||
-rw-r--r-- | docs/links/podman-help.1 | 1 | ||||
-rw-r--r-- | docs/podman-remote.1.md | 141 | ||||
-rwxr-xr-x | docs/podman-remote.sh | 11 | ||||
-rw-r--r-- | pkg/hooks/hooks.go | 24 | ||||
-rw-r--r-- | pkg/hooks/monitor.go | 49 | ||||
-rw-r--r-- | pkg/hooks/monitor_test.go | 25 | ||||
-rw-r--r-- | pkg/hooks/read.go | 11 | ||||
-rw-r--r-- | test/e2e/common_test.go | 5 |
12 files changed, 215 insertions, 78 deletions
diff --git a/.gitignore b/.gitignore index b26674172..4f1100d8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ /.artifacts/ /_output/ +/brew /conmon/conmon.o /docs/*.[158] /docs/*.[158].gz +/docs/remote *.o *.orig /pause/pause.o @@ -19,3 +21,4 @@ __pycache__ .gopathok test/e2e/e2e.coverprofile /podman*zip +podman*.tar.gz @@ -75,11 +75,13 @@ LIBSECCOMP_COMMIT := release-2.3 GINKGOTIMEOUT ?= -timeout=90m RELEASE_VERSION ?= $(shell git fetch --tags && git describe HEAD 2> /dev/null) +RELEASE_NUMBER ?= $(shell echo $(RELEASE_VERSION) | sed 's/-.*//') RELEASE_DIST ?= $(shell ( source /etc/os-release; echo $$ID )) RELEASE_DIST_VER ?= $(shell ( source /etc/os-release; echo $$VERSION_ID | cut -d '.' -f 1)) RELEASE_ARCH ?= $(shell go env GOARCH 2> /dev/null) RELEASE_BASENAME := $(shell basename $(PROJECT)) + # If GOPATH not specified, use one in the local directory ifeq ($(GOPATH),) export GOPATH := $(CURDIR)/_output @@ -143,7 +145,6 @@ gofmt: ## Verify the source code gofmt find . -name '*.go' ! -path './vendor/*' -exec gofmt -s -w {} \+ git diff --exit-code - test/checkseccomp/checkseccomp: .gopathok $(wildcard test/checkseccomp/*.go) $(GO) build -ldflags '$(LDFLAGS)' -tags "$(BUILDTAGS) containers_image_ostree_stub" -o $@ $(PROJECT)/test/checkseccomp @@ -175,8 +176,10 @@ clean: ## Clean artifacts .gopathok \ _output \ podman*.zip \ + podman*.tar.gz \ bin \ build \ + docs/remote \ test/checkseccomp/checkseccomp \ test/goecho/goecho \ test/testdata/redis-image \ @@ -292,6 +295,22 @@ $(MANPAGES): %: %.md .gopathok docs: $(MANPAGES) ## Generate documentation +install-podman-remote-docs: docs + @(cd docs; ./podman-remote.sh ./remote) + + +brew-pkg: install-podman-remote-docs podman-remote-darwin + @mkdir -p ./brew + @cp ./bin/podman-remote-darwin ./brew/podman + @cp -r ./docs/remote ./brew/docs/ + @cp docs/podman-remote.1 ./brew/docs/podman.1 + @sed -i 's/podman\\*-remote/podman/g' ./brew/docs/podman.1 + @sed -i 's/Podman\\*-remote/Podman\ for\ Mac/g' ./brew/docs/podman.1 + @sed -i 's/podman\.conf/podman\-remote\.conf/g' ./brew/docs/podman.1 + @sed -i 's/A\ remote\ CLI\ for\ Podman\:\ //g' ./brew/docs/podman.1 + tar -czvf podman-${RELEASE_NUMBER}.tar.gz ./brew + @rm -rf ./brew + docker-docs: docs (cd docs; ./dckrman.sh *.1) diff --git a/docs/links/podman-container-cp.1 b/docs/links/podman-container-cp.1 new file mode 100644 index 000000000..6ad859c84 --- /dev/null +++ b/docs/links/podman-container-cp.1 @@ -0,0 +1 @@ +.so man1/podman-cp.1 diff --git a/docs/links/podman-container-init.1 b/docs/links/podman-container-init.1 new file mode 100644 index 000000000..3a8bee249 --- /dev/null +++ b/docs/links/podman-container-init.1 @@ -0,0 +1 @@ +.so man1/podman-init.1 diff --git a/docs/links/podman-help.1 b/docs/links/podman-help.1 new file mode 100644 index 000000000..6b7954b0d --- /dev/null +++ b/docs/links/podman-help.1 @@ -0,0 +1 @@ +.so man1/podman.1 diff --git a/docs/podman-remote.1.md b/docs/podman-remote.1.md new file mode 100644 index 000000000..84042a842 --- /dev/null +++ b/docs/podman-remote.1.md @@ -0,0 +1,141 @@ +% podman-remote(1) + +## NAME +podman-remote - A remote CLI for Podman: A Simple management tool for pods, containers and images. + +## SYNOPSIS +**podman-remote** [*options*] *command* + +## DESCRIPTION +Podman (Pod Manager) is a fully featured container engine that is a simple daemonless tool. +Podman provides a Docker-CLI comparable command line that eases the transition from other +container engines and allows the management of pods, containers and images. Simply put: `alias docker=podman`. +Most Podman commands can be run as a regular user, without requiring additional +privileges. + +Podman uses Buildah(1) internally to create container images. Both tools share image +(not container) storage, hence each can use or manipulate images (but not containers) +created by the other. + +Podman-remote provides a local client interacting with a Podman backend node through a varlink ssh connection. In this context, a Podman node is a Linux system with Podman installed on it and the varlink service activated. Credentials for this session can be passed in using flags, enviroment variables, or in `podman-remote.conf` + +**podman [GLOBAL OPTIONS]** + +## GLOBAL OPTIONS + +**--connection**=*name* + +Remote connection name + +**--help**, **-h** + +Print usage statement + +**--log-level**=*level* + +Log messages above specified level: debug, info, warn, error (default), fatal or panic + +**--remote-config-path**=*path* + +Alternate path for configuration file + +**--remote-host**=*ip* + +Remote host IP + +**--syslog** + +Output logging information to syslog as well as the console + +**--username**=*string* + +Username on the remote host (defaults to current username) + +**--version** + +Print the version + +## Exit Status + +The exit code from `podman` gives information about why the container +failed to run or why it exited. When `podman` commands exit with a non-zero code, +the exit codes follow the `chroot` standard, see below: + +**_125_** if the error is with podman **_itself_** + + $ podman run --foo busybox; echo $? + Error: unknown flag: --foo + 125 + +**_126_** if executing a **_contained command_** and the **_command_** cannot be invoked + + $ podman run busybox /etc; echo $? + Error: container_linux.go:346: starting container process caused "exec: \"/etc\": permission denied": OCI runtime error + 126 + +**_127_** if executing a **_contained command_** and the **_command_** cannot be found + $ podman run busybox foo; echo $? + Error: container_linux.go:346: starting container process caused "exec: \"foo\": executable file not found in $PATH": OCI runtime error + 127 + +**_Exit code_** of **_contained command_** otherwise + + $ podman run busybox /bin/sh -c 'exit 3' + # 3 + + +## COMMANDS + +| Command | Description | +| ------------------------------------------------ | --------------------------------------------------------------------------- | +| [podman-attach(1)](podman-attach.1.md) | Attach to a running container. | +| [podman-build(1)](podman-build.1.md) | Build a container image using a Dockerfile. | +| [podman-commit(1)](podman-commit.1.md) | Create new image based on the changed container. | +| [podman-container(1)](podman-container.1.md) | Manage containers. | +| [podman-cp(1)](podman-cp.1.md) | Copy files/folders between a container and the local filesystem. | +| [podman-create(1)](podman-create.1.md) | Create a new container. | +| [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. | +| [podman-events(1)](podman-events.1.md) | Monitor Podman events | +| [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. | +| [podman-generate(1)](podman-generate.1.md) | Generate structured data based for a containers and pods. | +| [podman-healthcheck(1)](podman-healthcheck.1.md) | Manage healthchecks for containers | +| [podman-history(1)](podman-history.1.md) | Show the history of an image. | +| [podman-image(1)](podman-image.1.md) | Manage images. | +| [podman-images(1)](podman-images.1.md) | List images in local storage. | +| [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. | +| [podman-info(1)](podman-info.1.md) | Displays Podman related system information. | +| [podman-init(1)](podman-init.1.md) | Initialize a container | +| [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. | +| [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. | +| [podman-load(1)](podman-load.1.md) | Load an image from a container image archive into container storage. | +| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. | +| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. | +| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. | +| [podman-port(1)](podman-port.1.md) | List port mappings for a container. | +| [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. | +| [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. | +| [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. | +| [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. | +| [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. | +| [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. | +| [podman-run(1)](podman-run.1.md) | Run a command in a new container. | +| [podman-save(1)](podman-save.1.md) | Save an image to a container archive. | +| [podman-start(1)](podman-start.1.md) | Start one or more containers. | +| [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. | +| [podman-system(1)](podman-system.1.md) | Manage podman. | +| [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. | +| [podman-top(1)](podman-top.1.md) | Display the running processes of a container. | +| [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. | +| [podman-version(1)](podman-version.1.md) | Display the Podman version information. | +| [podman-volume(1)](podman-volume.1.md) | Manage Volumes. | + +## FILES + +**podman-remote.conf** (`~/.config/containers/podman-remote.conf`) + + The podman-remote.conf file is the default configuration file for the podman + remote client. It is in the TOML format. It is primarily used to keep track + of the user's remote connections. + +## SEE ALSO +`podman-remote.conf(5)` diff --git a/docs/podman-remote.sh b/docs/podman-remote.sh new file mode 100755 index 000000000..db3bb6d50 --- /dev/null +++ b/docs/podman-remote.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +BREWDIR=$1 +mkdir -p $BREWDIR +docs() { +[ -z $1 ] || type="-$1" +for i in $(podman-remote $1 --help | sed -n '/^Available Commands:/,/^Flags:/p'| sed -e '1d;$d' -e '/^$/d' | awk '{print $1}'); do install podman$type-$i.1 $BREWDIR 2>/dev/null || install links/podman$type-$i.1 $BREWDIR; done +} +docs + +for cmd in 'container image pod volume'; do docs $cmd; done diff --git a/pkg/hooks/hooks.go b/pkg/hooks/hooks.go index 5ed028b95..b962ffa5c 100644 --- a/pkg/hooks/hooks.go +++ b/pkg/hooks/hooks.go @@ -4,7 +4,6 @@ package hooks import ( "context" "fmt" - "path/filepath" "sort" "strings" "sync" @@ -138,26 +137,3 @@ func (m *Manager) Hooks(config *rspec.Spec, annotations map[string]string, hasBi return extensionStageHooks, nil } - -// remove remove a hook by name. -func (m *Manager) remove(hook string) (ok bool) { - m.lock.Lock() - defer m.lock.Unlock() - _, ok = m.hooks[hook] - if ok { - delete(m.hooks, hook) - } - return ok -} - -// add adds a hook by path -func (m *Manager) add(path string) (err error) { - m.lock.Lock() - defer m.lock.Unlock() - hook, err := Read(path, m.extensionStages) - if err != nil { - return err - } - m.hooks[filepath.Base(path)] = hook - return nil -} diff --git a/pkg/hooks/monitor.go b/pkg/hooks/monitor.go index febe3483f..c50b321f2 100644 --- a/pkg/hooks/monitor.go +++ b/pkg/hooks/monitor.go @@ -2,9 +2,8 @@ package hooks import ( "context" - "os" - "path/filepath" + current "github.com/containers/libpod/pkg/hooks/1.0.0" "github.com/fsnotify/fsnotify" "github.com/sirupsen/logrus" ) @@ -49,47 +48,11 @@ func (m *Manager) Monitor(ctx context.Context, sync chan<- error) { for { select { case event := <-watcher.Events: - filename := filepath.Base(event.Name) - if len(m.directories) <= 1 { - if event.Op&fsnotify.Remove == fsnotify.Remove { - ok := m.remove(filename) - if ok { - logrus.Debugf("removed hook %s", event.Name) - } - } else if event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Write == fsnotify.Write { - err = m.add(event.Name) - if err == nil { - logrus.Debugf("added hook %s", event.Name) - } else if err != ErrNoJSONSuffix { - logrus.Errorf("failed to add hook %s: %v", event.Name, err) - } - } - } else if event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Remove == fsnotify.Remove { - err = nil - found := false - for i := len(m.directories) - 1; i >= 0; i-- { - path := filepath.Join(m.directories[i], filename) - err = m.add(path) - if err == nil { - found = true - logrus.Debugf("(re)added hook %s (triggered activity on %s)", path, event.Name) - break - } else if err == ErrNoJSONSuffix { - found = true - break // this is not going to change for fallback directories - } else if os.IsNotExist(err) { - continue // move on to the next fallback directory - } else { - found = true - logrus.Errorf("failed to (re)add hook %s (triggered by activity on %s): %v", path, event.Name, err) - break - } - } - if (found || event.Op&fsnotify.Remove == fsnotify.Remove) && err != nil { - ok := m.remove(filename) - if ok { - logrus.Debugf("removed hook %s (triggered by activity on %s)", filename, event.Name) - } + m.hooks = make(map[string]*current.Hook) + for _, dir := range m.directories { + err = ReadDir(dir, m.extensionStages, m.hooks) + if err != nil { + logrus.Errorf("failed loading hooks for %s: %v", event.Name, err) } } case <-ctx.Done(): diff --git a/pkg/hooks/monitor_test.go b/pkg/hooks/monitor_test.go index 31d7f9e39..dc67eaf83 100644 --- a/pkg/hooks/monitor_test.go +++ b/pkg/hooks/monitor_test.go @@ -226,7 +226,28 @@ func TestMonitorTwoDirGood(t *testing.T) { assert.Equal(t, primaryInjected, config.Hooks) // masked by primary }) - t.Run("bad-primary-addition", func(t *testing.T) { + primaryPath2 := filepath.Join(primaryDir, "0a.json") //0a because it will be before a.json alphabetically + + t.Run("bad-primary-new-addition", func(t *testing.T) { + err = ioutil.WriteFile(primaryPath2, []byte("{\"version\": \"-1\"}"), 0644) + if err != nil { + t.Fatal(err) + } + + time.Sleep(100 * time.Millisecond) // wait for monitor to notice + + config := &rspec.Spec{} + fmt.Println("expected: ", config.Hooks) + expected := primaryInjected // 0a.json is bad, a.json is still good + _, err = manager.Hooks(config, map[string]string{}, false) + fmt.Println("actual: ", config.Hooks) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, expected, config.Hooks) + }) + + t.Run("bad-primary-same-addition", func(t *testing.T) { err = ioutil.WriteFile(primaryPath, []byte("{\"version\": \"-1\"}"), 0644) if err != nil { t.Fatal(err) @@ -235,7 +256,7 @@ func TestMonitorTwoDirGood(t *testing.T) { time.Sleep(100 * time.Millisecond) // wait for monitor to notice config := &rspec.Spec{} - expected := config.Hooks + expected := fallbackInjected _, err = manager.Hooks(config, map[string]string{}, false) if err != nil { t.Fatal(err) diff --git a/pkg/hooks/read.go b/pkg/hooks/read.go index d3995a0be..560ff1899 100644 --- a/pkg/hooks/read.go +++ b/pkg/hooks/read.go @@ -67,7 +67,7 @@ func ReadDir(path string, extensionStages []string, hooks map[string]*current.Ho if err != nil { return err } - + res := err for _, file := range files { filePath := filepath.Join(path, file.Name()) hook, err := Read(filePath, extensionStages) @@ -80,12 +80,17 @@ func ReadDir(path string, extensionStages []string, hooks map[string]*current.Ho continue } } - return err + if res == nil { + res = err + } else { + res = errors.Wrapf(res, "%v", err) + } + continue } hooks[file.Name()] = hook logrus.Debugf("added hook %s", filePath) } - return nil + return res } func init() { diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index ef1c85518..7e14f9e06 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -214,11 +214,6 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration { cgroupManager = os.Getenv("CGROUP_MANAGER") } - // Ubuntu doesn't use systemd cgroups - if host.Distribution == "ubuntu" { - cgroupManager = "cgroupfs" - } - ociRuntime := os.Getenv("OCI_RUNTIME") if ociRuntime == "" { var err error |