diff options
-rw-r--r-- | RELEASE_NOTES.md | 26 | ||||
-rw-r--r-- | cmd/podman/common.go | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-create.1.md | 3 | ||||
-rw-r--r-- | docs/source/markdown/podman-exec.1.md | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-rmi.1.md | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md | 3 | ||||
-rwxr-xr-x | hack/release.sh | 15 | ||||
-rw-r--r-- | install.md | 2 | ||||
-rw-r--r-- | libpod/container.go | 5 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 13 | ||||
-rw-r--r-- | libpod/options.go | 21 | ||||
-rw-r--r-- | pkg/api/Makefile | 10 | ||||
-rw-r--r-- | pkg/api/handlers/handler.go | 16 | ||||
-rw-r--r-- | pkg/api/handlers/images_build.go | 229 | ||||
-rw-r--r-- | pkg/api/server/register_images.go | 205 | ||||
-rw-r--r-- | pkg/api/server/server.go | 22 | ||||
-rw-r--r-- | pkg/rootless/rootless_linux.c | 9 | ||||
-rw-r--r-- | pkg/spec/namespaces.go | 4 | ||||
-rw-r--r-- | pkg/spec/spec.go | 4 | ||||
-rw-r--r-- | pkg/systemdgen/systemdgen.go | 5 | ||||
-rw-r--r-- | pkg/systemdgen/systemdgen_test.go | 2 |
21 files changed, 445 insertions, 155 deletions
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 7864b9232..0ef3e4322 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,31 @@ # Release Notes +## 1.7.1 +### Features +- Rootless Podman now uses Rootlesskit for port forwarding, which should greatly improve performance and capabilities +- The `podman untag` command has been added to remove tags from images without deleting them +- The `podman service` command has been added to run an API server for managing Podman remotely +- The `podman inspect` command on images now displays previous names they used +- The `podman generate systemd` command now supports a `--new` option to generate service files that create and run new containers instead of managing existing containers +- Support for `--log-opt tag=` to set logging tags has been added to the `journald` log driver +- Added support for using Seccomp profiles embedded in images for `podman run` and `podman create` via the new `--seccomp-policy` CLI flag ([#4806](https://github.com/containers/libpod/pull/4806)) + +### Bugfixes +- Fixed a bug where the `podman cp` command would not copy the contents of directories when paths ending in `/.` were given ([#4717](https://github.com/containers/libpod/issues/4717)) +- Fixed a bug where the `podman play kube` command did not properly locate Seccomp profiles specified relative to localhost ([#4555](https://github.com/containers/libpod/issues/4555)) +- Fixed a bug where the `podman info` command for remote Podman did not show registry information ([#4793](https://github.com/containers/libpod/issues/4793)) +- Fixed a bug where the `podman exec` command did not support having input piped into it ([#3302](https://github.com/containers/libpod/issues/3302)) +- Fixed a bug where the `podman cp` command with rootless Podman on CGroups v2 systems did not properly determine if the container could be paused while copying ([#4813](https://github.com/containers/libpod/issues/4813)) +- Fixed a bug where the `podman container prune --force` command could possible remove running containers if they were started while the command was running ([#4844](https://github.com/containers/libpod/issues/4844)) +- Fixed a bug where Podman, when run as root, would not properly configure `slirp4netns` networking when requested ([#4853](https://github.com/containers/libpod/pull/4853)) +- Fixed a bug where `podman run --userns=keep-id` did not work when the user had a UID over 65535 ([#4838](https://github.com/containers/libpod/issues/4838)) +- Fixed a bug where rootless `podman run` and `podman create` with the `--userns=keep-id` option could change permissions on `/run/user/$UID` and break KDE ([#4846](https://github.com/containers/libpod/issues/4846)) + +### Misc +- Initial work on version 2 of the Podman remote API has been merged, but is still in an alpha state and not ready for use. Read more [here](https://podman.io/releases/2020/01/17/podman-new-api.html) +- Updated vendored Buildah to v1.13.1 +- Updated vendored containers/storage to v1.15.5 + ## 1.7.0 ### Features - Added support for setting a static MAC address for containers diff --git a/cmd/podman/common.go b/cmd/podman/common.go index 8690be64f..f3aff1d49 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -158,7 +158,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { ) createFlags.String( "cgroups", "enabled", - "control container cgroup configuration", + `control container cgroup configuration ("enabled"|"disabled"|"no-conmon")`, ) createFlags.String( "cgroup-parent", "", diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 0236e30ba..7f0c2260c 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -78,8 +78,9 @@ If the host uses cgroups v1, the default is set to **host**. On cgroups v2 the **--cgroups**=*mode* Determines whether the container will create CGroups. -Valid values are *enabled* and *disabled*, which the default being *enabled*. +Valid values are *enabled*, *disabled*, *no-conmon*, which the default being *enabled*. The *disabled* option will force the container to not create CGroups, and thus conflicts with CGroup options (**--cgroupns** and **--cgroup-parent**). +The *no-conmon* option disables a new CGroup only for the conmon process. **--cgroup-parent**=*path* diff --git a/docs/source/markdown/podman-exec.1.md b/docs/source/markdown/podman-exec.1.md index fc67211d1..8c0106d70 100644 --- a/docs/source/markdown/podman-exec.1.md +++ b/docs/source/markdown/podman-exec.1.md @@ -105,9 +105,11 @@ non-zero code, the exit codes follow the `chroot` standard, see below: ## EXAMPLES +``` $ podman exec -it ctrID ls $ podman exec -it -w /tmp myCtr pwd $ podman exec --user root ctrID ls +``` ## SEE ALSO podman(1), podman-run(1) diff --git a/docs/source/markdown/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md index d911ee6cb..3c46bc32c 100644 --- a/docs/source/markdown/podman-rmi.1.md +++ b/docs/source/markdown/podman-rmi.1.md @@ -29,7 +29,7 @@ podman rmi c0ed59d05ff7 Remove an image and its associated containers. ``` podman rmi --force imageID -```` +``` Remove multiple images by their shortened IDs. ``` diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index f613e6668..2b1452b53 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -92,8 +92,9 @@ If the host uses cgroups v1, the default is set to **host**. On cgroups v2 the **--cgroups**=*mode* Determines whether the container will create CGroups. -Valid values are *enabled* and *disabled*, which the default being *enabled*. +Valid values are *enabled*, *disabled*, *no-conmon*, which the default being *enabled*. The *disabled* option will force the container to not create CGroups, and thus conflicts with CGroup options (**--cgroupns** and **--cgroup-parent**). +The *no-conmon* option disables a new CGroup only for the conmon process. **--cgroup-parent**=*cgroup* diff --git a/hack/release.sh b/hack/release.sh index 56a853347..7c22aed42 100755 --- a/hack/release.sh +++ b/hack/release.sh @@ -36,12 +36,6 @@ write_spec_version() sed -i "s/^\(Version: *\).*/\1${LOCAL_VERSION}/" contrib/spec/podman.spec.in } -write_makefile_epoch() -{ - LOCAL_EPOCH="$1" - sed -i "s/^\(EPOCH_TEST_COMMIT ?= \).*/\1${LOCAL_EPOCH}/" Makefile -} - write_changelog() { echo "- Changelog for v${VERSION} (${DATE})" >.changelog.txt && @@ -66,17 +60,8 @@ dev_version_commit() git commit -asm "Bump to v${NEXT_VERSION}-dev" } -epoch_commit() -{ - LOCAL_EPOCH="$1" - write_makefile_epoch "${LOCAL_EPOCH}" && - git commit -asm 'Bump gitvalidation epoch' -} - git fetch origin && git checkout -b "bump-${VERSION}" origin/master && -EPOCH=$(git rev-parse HEAD) && release_commit && git tag -s -m "version ${VERSION}" "v${VERSION}" && dev_version_commit && -epoch_commit "${EPOCH}" diff --git a/install.md b/install.md index 35a931c85..90ad4f233 100644 --- a/install.md +++ b/install.md @@ -140,7 +140,7 @@ The Kubic project provides RC/testing packages for Debian 10, testing and unstable. ```bash -# Debian Untesting/Sid +# Debian Unstable/Sid echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/testing/Debian_Unstable/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:testing.list wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:testing/Debian_Unstable/Release.key -O Release.key diff --git a/libpod/container.go b/libpod/container.go index b3cb6334a..f29cebf20 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -373,8 +373,11 @@ type ContainerConfig struct { // Time container was created CreatedTime time.Time `json:"createdTime"` // NoCgroups indicates that the container will not create CGroups. It is - // incompatible with CgroupParent. + // incompatible with CgroupParent. Deprecated in favor of CgroupsMode. NoCgroups bool `json:"noCgroups,omitempty"` + // CgroupsMode indicates how the container will create cgroups + // (disabled, no-conmon, enabled). It supersedes NoCgroups. + CgroupsMode string `json:"cgroupsMode,omitempty"` // Cgroup parent of the container CgroupParent string `json:"cgroupParent"` // LogPath log location diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 0e8a64865..722012386 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -1425,11 +1425,22 @@ func startCommandGivenSelinux(cmd *exec.Cmd) error { // it then signals for conmon to start by sending nonse data down the start fd func (r *ConmonOCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec.Cmd, startFd *os.File) error { mustCreateCgroup := true - // If cgroup creation is disabled - just signal. + if ctr.config.NoCgroups { mustCreateCgroup = false } + // If cgroup creation is disabled - just signal. + switch ctr.config.CgroupsMode { + case "disabled", "no-conmon": + mustCreateCgroup = false + } + + // $INVOCATION_ID is set by systemd when running as a service. + if os.Getenv("INVOCATION_ID") != "" { + mustCreateCgroup = false + } + if mustCreateCgroup { cgroupParent := ctr.CgroupParent() if r.cgroupManager == define.SystemdCgroupsManager { diff --git a/libpod/options.go b/libpod/options.go index 8bc5a541d..593037382 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1078,25 +1078,26 @@ func WithLogTag(tag string) CtrCreateOption { } -// WithNoCgroups disables the creation of CGroups for the new container. -func WithNoCgroups() CtrCreateOption { +// WithCgroupsMode disables the creation of CGroups for the conmon process. +func WithCgroupsMode(mode string) CtrCreateOption { return func(ctr *Container) error { if ctr.valid { return define.ErrCtrFinalized } - if ctr.config.CgroupParent != "" { - return errors.Wrapf(define.ErrInvalidArg, "NoCgroups conflicts with CgroupParent") - } - - if ctr.config.PIDNsCtr != "" { - return errors.Wrapf(define.ErrInvalidArg, "NoCgroups requires a private PID namespace and cannot be used when PID namespace is shared with another container") + switch mode { + case "disabled": + ctr.config.NoCgroups = true + ctr.config.CgroupsMode = mode + case "enabled", "no-conmon": + ctr.config.CgroupsMode = mode + default: + return errors.Wrapf(define.ErrInvalidArg, "Invalid cgroup mode %q", mode) } - ctr.config.NoCgroups = true - return nil } + } // WithCgroupParent sets the Cgroup Parent of the new container. diff --git a/pkg/api/Makefile b/pkg/api/Makefile index 8a1556800..915f0b9b3 100644 --- a/pkg/api/Makefile +++ b/pkg/api/Makefile @@ -2,6 +2,12 @@ export GO111MODULE=off SWAGGER_OUT ?= swagger.yaml -swagger: +.PHONY: ${SWAGGER_OUT} +${SWAGGER_OUT}: + # generate doesn't remove file on error + rm -f ${SWAGGER_OUT} swagger generate spec -o ${SWAGGER_OUT} -w ./ - cat tags.yaml >> swagger.yaml + +# TODO: when pass validation move it under swagger. +validate: + swagger validate ${SWAGGER_OUT} diff --git a/pkg/api/handlers/handler.go b/pkg/api/handlers/handler.go index 2efeb1379..4f303f6ab 100644 --- a/pkg/api/handlers/handler.go +++ b/pkg/api/handlers/handler.go @@ -36,11 +36,11 @@ func getRuntime(r *http.Request) *libpod.Runtime { return r.Context().Value("runtime").(*libpod.Runtime) } -func getHeader(r *http.Request, k string) string { - return r.Header.Get(k) -} - -func hasHeader(r *http.Request, k string) bool { - _, found := r.Header[k] - return found -} +// func getHeader(r *http.Request, k string) string { +// return r.Header.Get(k) +// } +// +// func hasHeader(r *http.Request, k string) bool { +// _, found := r.Header[k] +// return found +// } diff --git a/pkg/api/handlers/images_build.go b/pkg/api/handlers/images_build.go index c7c746392..b29c45574 100644 --- a/pkg/api/handlers/images_build.go +++ b/pkg/api/handlers/images_build.go @@ -1,6 +1,7 @@ package handlers import ( + "bytes" "encoding/base64" "encoding/json" "fmt" @@ -9,58 +10,66 @@ import ( "net/http" "os" "path/filepath" + "strconv" "strings" "github.com/containers/buildah" "github.com/containers/buildah/imagebuildah" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/storage/pkg/archive" - log "github.com/sirupsen/logrus" + "github.com/gorilla/mux" ) func BuildImage(w http.ResponseWriter, r *http.Request) { authConfigs := map[string]AuthConfig{} - if hasHeader(r, "X-Registry-Config") { - registryHeader := getHeader(r, "X-Registry-Config") - authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(registryHeader)) + if hdr, found := r.Header["X-Registry-Config"]; found && len(hdr) > 0 { + authConfigsJSON := base64.NewDecoder(base64.URLEncoding, strings.NewReader(hdr[0])) if json.NewDecoder(authConfigsJSON).Decode(&authConfigs) != nil { - utils.BadRequest(w, "X-Registry-Config", registryHeader, json.NewDecoder(authConfigsJSON).Decode(&authConfigs)) + utils.BadRequest(w, "X-Registry-Config", hdr[0], json.NewDecoder(authConfigsJSON).Decode(&authConfigs)) return } } + if hdr, found := r.Header["Content-Type"]; found && len(hdr) > 0 { + if hdr[0] != "application/x-tar" { + utils.BadRequest(w, "Content-Type", hdr[0], + fmt.Errorf("Content-Type: %s is not supported. Should be \"application/x-tar\"", hdr[0])) + } + } + anchorDir, err := extractTarFile(r, w) if err != nil { utils.InternalServerError(w, err) return } - // defer os.RemoveAll(anchorDir) + defer os.RemoveAll(anchorDir) query := struct { - Dockerfile string `json:"dockerfile"` - Tag string `json:"t"` - ExtraHosts string `json:"extrahosts"` - Remote string `json:"remote"` - Quiet bool `json:"q"` - NoCache bool `json:"nocache"` - CacheFrom string `json:"cachefrom"` - Pull string `json:"pull"` - Rm bool `json:"rm"` - ForceRm bool `json:"forcerm"` - Memory int `json:"memory"` - MemSwap int `json:"memswap"` - CpuShares int `json:"cpushares"` - CpuSetCpus string `json:"cpusetcpus"` - CpuPeriod int `json:"cpuperiod"` - CpuQuota int `json:"cpuquota"` - BuildArgs string `json:"buildargs"` - ShmSize int `json:"shmsize"` - Squash bool `json:"squash"` - Labels string `json:"labels"` - NetworkMode string `json:"networkmode"` - Platform string `json:"platform"` - Target string `json:"target"` - Outputs string `json:"outputs"` + Dockerfile string `schema:"dockerfile"` + Tag string `schema:"t"` + ExtraHosts string `schema:"extrahosts"` + Remote string `schema:"remote"` + Quiet bool `schema:"q"` + NoCache bool `schema:"nocache"` + CacheFrom string `schema:"cachefrom"` + Pull bool `schema:"pull"` + Rm bool `schema:"rm"` + ForceRm bool `schema:"forcerm"` + Memory int64 `schema:"memory"` + MemSwap int64 `schema:"memswap"` + CpuShares uint64 `schema:"cpushares"` + CpuSetCpus string `schema:"cpusetcpus"` + CpuPeriod uint64 `schema:"cpuperiod"` + CpuQuota int64 `schema:"cpuquota"` + BuildArgs string `schema:"buildargs"` + ShmSize int `schema:"shmsize"` + Squash bool `schema:"squash"` + Labels string `schema:"labels"` + NetworkMode string `schema:"networkmode"` + Platform string `schema:"platform"` + Target string `schema:"target"` + Outputs string `schema:"outputs"` + Registry string `schema:"registry"` }{ Dockerfile: "Dockerfile", Tag: "", @@ -69,7 +78,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { Quiet: false, NoCache: false, CacheFrom: "", - Pull: "", + Pull: false, Rm: true, ForceRm: false, Memory: 0, @@ -86,6 +95,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { Platform: "", Target: "", Outputs: "", + Registry: "docker.io", } if err := decodeQuery(r, &query); err != nil { @@ -93,80 +103,121 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { return } - // Tag is the name with optional tag... - var name = query.Tag - var tag string + var ( + // Tag is the name with optional tag... + name = query.Tag + tag = "latest" + ) if strings.Contains(query.Tag, ":") { tokens := strings.SplitN(query.Tag, ":", 2) name = tokens[0] tag = tokens[1] } + if t, found := mux.Vars(r)["target"]; found { + name = t + } + var buildArgs = map[string]string{} - if found := hasVar(r, "buildargs"); found { - if err := json.Unmarshal([]byte(query.BuildArgs), &buildArgs); err != nil { - utils.BadRequest(w, "buildargs", query.BuildArgs, err) + if a, found := mux.Vars(r)["buildargs"]; found { + if err := json.Unmarshal([]byte(a), &buildArgs); err != nil { + utils.BadRequest(w, "buildargs", a, err) return } } // convert label formats var labels = []string{} - if hasVar(r, "labels") { + if l, found := mux.Vars(r)["labels"]; found { var m = map[string]string{} - if err := json.Unmarshal([]byte(query.Labels), &m); err != nil { - utils.BadRequest(w, "labels", query.Labels, err) + if err := json.Unmarshal([]byte(l), &m); err != nil { + utils.BadRequest(w, "labels", l, err) return } for k, v := range m { - labels = append(labels, fmt.Sprintf("%s=%v", k, v)) + labels = append(labels, k+"="+v) + } + } + + pullPolicy := buildah.PullIfMissing + if _, found := mux.Vars(r)["pull"]; found { + if query.Pull { + pullPolicy = buildah.PullAlways } } + // build events will be recorded here + var ( + buildEvents = []string{} + progress = bytes.Buffer{} + ) + buildOptions := imagebuildah.BuildOptions{ ContextDirectory: filepath.Join(anchorDir, "build"), - PullPolicy: 0, - Registry: "", - IgnoreUnrecognizedInstructions: false, + PullPolicy: pullPolicy, + Registry: query.Registry, + IgnoreUnrecognizedInstructions: true, Quiet: query.Quiet, - Isolation: 0, + Isolation: buildah.IsolationChroot, Runtime: "", RuntimeArgs: nil, TransientMounts: nil, - Compression: 0, + Compression: archive.Gzip, Args: buildArgs, Output: name, AdditionalTags: []string{tag}, - Log: nil, - In: nil, - Out: nil, - Err: nil, - SignaturePolicyPath: "", - ReportWriter: nil, - OutputFormat: "", - SystemContext: nil, - NamespaceOptions: nil, - ConfigureNetwork: 0, - CNIPluginPath: "", - CNIConfigDir: "", - IDMappingOptions: nil, - AddCapabilities: nil, - DropCapabilities: nil, - CommonBuildOpts: &buildah.CommonBuildOptions{}, - DefaultMountsFilePath: "", - IIDFile: "", - Squash: query.Squash, - Labels: labels, - Annotations: nil, - OnBuild: nil, - Layers: false, - NoCache: query.NoCache, - RemoveIntermediateCtrs: query.Rm, - ForceRmIntermediateCtrs: query.ForceRm, - BlobDirectory: "", - Target: query.Target, - Devices: nil, + Log: func(format string, args ...interface{}) { + buildEvents = append(buildEvents, fmt.Sprintf(format, args...)) + }, + In: nil, + Out: &progress, + Err: &progress, + SignaturePolicyPath: "", + ReportWriter: &progress, + OutputFormat: buildah.Dockerv2ImageManifest, + SystemContext: nil, + NamespaceOptions: nil, + ConfigureNetwork: 0, + CNIPluginPath: "", + CNIConfigDir: "", + IDMappingOptions: nil, + AddCapabilities: nil, + DropCapabilities: nil, + CommonBuildOpts: &buildah.CommonBuildOptions{ + AddHost: nil, + CgroupParent: "", + CPUPeriod: query.CpuPeriod, + CPUQuota: query.CpuQuota, + CPUShares: query.CpuShares, + CPUSetCPUs: query.CpuSetCpus, + CPUSetMems: "", + HTTPProxy: false, + Memory: query.Memory, + DNSSearch: nil, + DNSServers: nil, + DNSOptions: nil, + MemorySwap: query.MemSwap, + LabelOpts: nil, + SeccompProfilePath: "", + ApparmorProfile: "", + ShmSize: strconv.Itoa(query.ShmSize), + Ulimit: nil, + Volumes: nil, + }, + DefaultMountsFilePath: "", + IIDFile: "", + Squash: query.Squash, + Labels: labels, + Annotations: nil, + OnBuild: nil, + Layers: false, + NoCache: query.NoCache, + RemoveIntermediateCtrs: query.Rm, + ForceRmIntermediateCtrs: query.ForceRm, + BlobDirectory: "", + Target: query.Target, + Devices: nil, } id, _, err := getRuntime(r).Build(r.Context(), buildOptions, query.Dockerfile) @@ -179,17 +230,13 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { struct { Stream string `json:"stream"` }{ - Stream: fmt.Sprintf("Successfully built %s\n", id), + Stream: progress.String() + "\n" + + strings.Join(buildEvents, "\n") + + fmt.Sprintf("\nSuccessfully built %s\n", id), }) } func extractTarFile(r *http.Request, w http.ResponseWriter) (string, error) { - var ( - // length int64 - // n int64 - copyErr error - ) - // build a home for the request body anchorDir, err := ioutil.TempDir("", "libpod_builder") if err != nil { @@ -204,26 +251,14 @@ func extractTarFile(r *http.Request, w http.ResponseWriter) (string, error) { } defer tarBall.Close() - // if hasHeader(r, "Content-Length") { - // length, err := strconv.ParseInt(getHeader(r, "Content-Length"), 10, 64) - // if err != nil { - // return "", errors.New(fmt.Sprintf("Failed request: unable to parse Content-Length of '%s'", getHeader(r, "Content-Length"))) - // } - // n, copyErr = io.CopyN(tarBall, r.Body, length+1) - // } else { - _, copyErr = io.Copy(tarBall, r.Body) - // } + // Content-Length not used as too many existing API clients didn't honor it + _, err = io.Copy(tarBall, r.Body) r.Body.Close() - if copyErr != nil { + if err != nil { utils.InternalServerError(w, fmt.Errorf("failed Request: Unable to copy tar file from request body %s", r.RequestURI)) } - log.Debugf("Content-Length: %s", getVar(r, "Content-Length")) - - // if hasHeader(r, "Content-Length") && n != length { - // return "", errors.New(fmt.Sprintf("Failed request: Given Content-Length does not match file size %d != %d", n, length)) - // } _, _ = tarBall.Seek(0, 0) if err := archive.Untar(tarBall, buildDir, &archive.TarOptions{}); err != nil { diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index 7f1bb4e5c..8ea079654 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -342,6 +342,210 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/commit"), APIHandler(s.Context, generic.CommitContainer)).Methods(http.MethodPost) + // swagger:operation POST /build images buildImage + // --- + // tags: + // - images + // summary: Create image + // description: Build an image from the given Dockerfile(s) + // parameters: + // - in: query + // name: dockerfile + // type: string + // default: Dockerfile + // description: | + // Path within the build context to the `Dockerfile`. + // This is ignored if remote is specified and points to an external `Dockerfile`. + // - in: query + // name: t + // type: string + // default: latest + // description: A name and optional tag to apply to the image in the `name:tag` format. + // - in: query + // name: extrahosts + // type: string + // default: + // description: | + // TBD Extra hosts to add to /etc/hosts + // (As of version 1.xx) + // - in: query + // name: remote + // type: string + // default: + // description: | + // A Git repository URI or HTTP/HTTPS context URI. + // If the URI points to a single text file, the file’s contents are placed + // into a file called Dockerfile and the image is built from that file. If + // the URI points to a tarball, the file is downloaded by the daemon and the + // contents therein used as the context for the build. If the URI points to a + // tarball and the dockerfile parameter is also specified, there must be a file + // with the corresponding path inside the tarball. + // (As of version 1.xx) + // - in: query + // name: q + // type: boolean + // default: false + // description: | + // Suppress verbose build output + // - in: query + // name: nocache + // type: boolean + // default: false + // description: | + // Do not use the cache when building the image + // (As of version 1.xx) + // - in: query + // name: cachefrom + // type: string + // default: + // description: | + // JSON array of images used to build cache resolution + // (As of version 1.xx) + // - in: query + // name: pull + // type: boolean + // default: false + // description: | + // Attempt to pull the image even if an older image exists locally + // (As of version 1.xx) + // - in: query + // name: rm + // type: boolean + // default: true + // description: | + // Remove intermediate containers after a successful build + // (As of version 1.xx) + // - in: query + // name: forcerm + // type: boolean + // default: false + // description: | + // Always remove intermediate containers, even upon failure + // (As of version 1.xx) + // - in: query + // name: memory + // type: integer + // description: | + // Memory is the upper limit (in bytes) on how much memory running containers can use + // (As of version 1.xx) + // - in: query + // name: memswap + // type: integer + // description: | + // MemorySwap limits the amount of memory and swap together + // (As of version 1.xx) + // - in: query + // name: cpushares + // type: integer + // description: | + // CPUShares (relative weight + // (As of version 1.xx) + // - in: query + // name: cpusetcpus + // type: string + // description: | + // CPUSetCPUs in which to allow execution (0-3, 0,1) + // (As of version 1.xx) + // - in: query + // name: cpuperiod + // type: integer + // description: | + // CPUPeriod limits the CPU CFS (Completely Fair Scheduler) period + // (As of version 1.xx) + // - in: query + // name: cpuquota + // type: integer + // description: | + // CPUQuota limits the CPU CFS (Completely Fair Scheduler) quota + // (As of version 1.xx) + // - in: query + // name: buildargs + // type: string + // default: + // description: | + // JSON map of string pairs denoting build-time variables. + // For example, the build argument `Foo` with the value of `bar` would be encoded in JSON as `["Foo":"bar"]`. + // + // For example, buildargs={"Foo":"bar"}. + // + // Note(s): + // * This should not be used to pass secrets. + // * The value of buildargs should be URI component encoded before being passed to the API. + // + // (As of version 1.xx) + // - in: query + // name: shmsize + // type: integer + // default: 67108864 + // description: | + // ShmSize is the "size" value to use when mounting an shmfs on the container's /dev/shm directory. + // Default is 64MB + // (As of version 1.xx) + // - in: query + // name: squash + // type: boolean + // default: false + // description: | + // Silently ignored. + // Squash the resulting images layers into a single layer + // (As of version 1.xx) + // - in: query + // name: labels + // type: string + // default: + // description: | + // JSON map of key, value pairs to set as labels on the new image + // (As of version 1.xx) + // - in: query + // name: networkmode + // type: string + // default: bridge + // description: | + // Sets the networking mode for the run commands during build. + // Supported standard values are: + // * `bridge` limited to containers within a single host, port mapping required for external access + // * `host` no isolation between host and containers on this network + // * `none` disable all networking for this container + // * container:<nameOrID> share networking with given container + // ---All other values are assumed to be a custom network's name + // (As of version 1.xx) + // - in: query + // name: platform + // type: string + // default: + // description: | + // Platform format os[/arch[/variant]] + // (As of version 1.xx) + // - in: query + // name: target + // type: string + // default: + // description: | + // Target build stage + // (As of version 1.xx) + // - in: query + // name: outputs + // type: string + // default: + // description: | + // output configuration TBD + // (As of version 1.xx) + // produces: + // - application/json + // responses: + // 200: + // description: OK (As of version 1.xx) + // schema: + // type: object + // required: + // - stream + // properties: + // stream: + // type: string + // example: | + // (build details...) + // Successfully built 8ba084515c724cbf90d447a63600c0a6 + r.Handle(VersionedPath("/build"), APIHandler(s.Context, handlers.BuildImage)).Methods(http.MethodPost) /* libpod endpoints */ @@ -603,6 +807,5 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // $ref: '#/responses/InternalError' r.Handle(VersionedPath("/libpod/images/{name:..*}/tag"), APIHandler(s.Context, handlers.TagImage)).Methods(http.MethodPost) - r.Handle(VersionedPath("/build"), APIHandler(s.Context, handlers.BuildImage)).Methods(http.MethodPost) return nil } diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index f3bae0345..69a44f21a 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -1,6 +1,6 @@ -// Package serviceapi Provides a Container compatible interface (EXPERIMENTAL) +// Package api Provides a container compatible interface. // -// This documentation describes the HTTP LibPod interface. It is to be consider +// This documentation describes the HTTP Libpod interface. It is to be consider // only as experimental as this point. The endpoints, parameters, inputs, and // return values can all change. // @@ -25,12 +25,18 @@ // - text/html // // tags: -// - name: "Containers" -// description: manage containers -// - name: "Images" -// description: manage images -// - name: "System" -// description: manage system resources +// - name: containers +// description: Actions related to containers +// - name: images +// description: Actions related to images +// - name: pods +// description: Actions related to pods +// - name: volumes +// description: Actions related to volumes +// - name: containers (compat) +// description: Actions related to containers for the compatibility endpoints +// - name: images (compat) +// description: Actions related to images for the compatibility endpoints // // swagger:meta package server diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 193c788c0..041a161dc 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -266,6 +266,8 @@ static void __attribute__((constructor)) init() char path[PATH_MAX]; const char *const suffix = "/libpod/pause.pid"; char *cwd = getcwd (NULL, 0); + char uid_fmt[16]; + char gid_fmt[16]; if (cwd == NULL) { @@ -324,6 +326,13 @@ static void __attribute__((constructor)) init() exit (EXIT_FAILURE); } + sprintf (uid_fmt, "%d", uid); + sprintf (gid_fmt, "%d", gid); + + setenv ("_CONTAINERS_USERNS_CONFIGURED", "init", 1); + setenv ("_CONTAINERS_ROOTLESS_UID", uid_fmt, 1); + setenv ("_CONTAINERS_ROOTLESS_GID", gid_fmt, 1); + r = setns (fd, 0); if (r < 0) { diff --git a/pkg/spec/namespaces.go b/pkg/spec/namespaces.go index e62d4ed0a..1f98e6e25 100644 --- a/pkg/spec/namespaces.go +++ b/pkg/spec/namespaces.go @@ -213,8 +213,8 @@ func (c *CgroupConfig) ToCreateOptions(runtime *libpod.Runtime) ([]libpod.CtrCre options = append(options, libpod.WithCgroupParent(c.CgroupParent)) } - if c.Cgroups == "disabled" { - options = append(options, libpod.WithNoCgroups()) + if c.Cgroups != "" { + options = append(options, libpod.WithCgroupsMode(c.Cgroups)) } return options, nil diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 7a220012f..cae055bb0 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -358,10 +358,10 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM return nil, errors.New("cannot specify resource limits when cgroups are disabled is specified") } configSpec.Linux.Resources = &spec.LinuxResources{} - case "enabled", "": + case "enabled", "no-conmon", "": // Do nothing default: - return nil, errors.New("unrecognized option for cgroups; supported are 'default' and 'disabled'") + return nil, errors.New("unrecognized option for cgroups; supported are 'default', 'disabled', 'no-conmon'") } // Add annotations diff --git a/pkg/systemdgen/systemdgen.go b/pkg/systemdgen/systemdgen.go index 745b708e4..26b3b3756 100644 --- a/pkg/systemdgen/systemdgen.go +++ b/pkg/systemdgen/systemdgen.go @@ -153,13 +153,14 @@ func CreateContainerSystemdUnit(info *ContainerInfo, opts Options) (string, erro if len(info.CreateCommand) < index+1 { return "", errors.Errorf("container's create command is too short or invalid: %v", info.CreateCommand) } - // We're hard-coding the first four arguments and append the - // CreatCommand with a stripped command and subcomand. + // We're hard-coding the first five arguments and append the + // CreateCommand with a stripped command and subcomand. command := []string{ info.Executable, "run", "--conmon-pidfile", "/%t/%n-pid", "--cidfile", "/%t/%n-cid", + "--cgroups=no-conmon", } command = append(command, info.CreateCommand[index:]...) info.RunCommand = strings.Join(command, " ") diff --git a/pkg/systemdgen/systemdgen_test.go b/pkg/systemdgen/systemdgen_test.go index 9c6933d17..ee2429407 100644 --- a/pkg/systemdgen/systemdgen_test.go +++ b/pkg/systemdgen/systemdgen_test.go @@ -122,7 +122,7 @@ Documentation=man:podman-generate-systemd(1) [Service] Restart=always ExecStartPre=/usr/bin/rm -f /%t/%n-pid /%t/%n-cid -ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN +ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --cgroups=no-conmon --name jadda-jadda --hostname hello-world awesome-image:latest command arg1 ... argN ExecStop=/usr/bin/podman stop --ignore --cidfile /%t/%n-cid -t 42 ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile /%t/%n-cid PIDFile=/%t/%n-pid |