diff options
34 files changed, 599 insertions, 125 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index c44277b05..3f3ab2ff4 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -420,9 +420,6 @@ testing_task: integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP} | ${LOGFORMAT} integration_test' system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP} | ${LOGFORMAT} system_test' apiv2_test_script: '$SCRIPT_BASE/apiv2_test.sh |& ${TIMESTAMP} | ${LOGFORMAT} apiv2_test' - build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}' - # For PRs this confirms uploading releases after merge, is functional. - upload_release_archive_script: '$SCRIPT_BASE/upload_release_archive.sh |& ${TIMESTAMP}' # When examining a particular run, provide convenient access to release files. tar_artifacts: @@ -552,7 +549,6 @@ special_testing_cross_task: networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh' setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}' build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}' - upload_release_archive_script: '$SCRIPT_BASE/upload_release_archive.sh |& ${TIMESTAMP}' on_failure: failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh' @@ -697,7 +693,6 @@ verify_test_built_images_task: # "probably" work. A full round of testing will happen again after $*_CACHE_IMAGE_NAME # are updated in this or another PR (w/o '***CIRRUS: TEST IMAGES***'). integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}' - build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}' system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}' always: @@ -141,7 +141,7 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in [func Ps(opts: PsOpts) PsContainer](#Ps) -[func PullImage(name: string) MoreResponse](#PullImage) +[func PullImage(name: string, creds: AuthConfig) MoreResponse](#PullImage) [func PushImage(name: string, tag: string, compress: bool, format: string, removeSignatures: bool, signBy: string) MoreResponse](#PushImage) @@ -197,6 +197,8 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in [func WaitContainer(name: string, interval: int) int](#WaitContainer) +[type AuthConfig](#AuthConfig) + [type BuildInfo](#BuildInfo) [type BuildOptions](#BuildOptions) @@ -1027,7 +1029,7 @@ method Ps(opts: [PsOpts](#PsOpts)) [PsContainer](#PsContainer)</div> ### <a name="PullImage"></a>func PullImage <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> -method PullImage(name: [string](https://godoc.org/builtin#string)) [MoreResponse](#MoreResponse)</div> +method PullImage(name: [string](https://godoc.org/builtin#string), creds: [AuthConfig](#AuthConfig)) [MoreResponse](#MoreResponse)</div> PullImage pulls an image from a repository to local storage. After a successful pull, the image id and logs are returned as a [MoreResponse](#MoreResponse). This connection also will handle a WantsMores request to send status as it occurs. @@ -1283,6 +1285,13 @@ WaitContainer takes the name or ID of a container and waits the given interval i stops. Upon stopping, the return code of the container is returned. If the container container cannot be found by ID or name, a [ContainerNotFound](#ContainerNotFound) error is returned. ## Types +### <a name="AuthConfig"></a>type AuthConfig + + + +username [string](https://godoc.org/builtin#string) + +password [string](https://godoc.org/builtin#string) ### <a name="BuildInfo"></a>type BuildInfo BuildInfo is used to describe user input for building images @@ -527,6 +527,11 @@ install.systemd: # For user units the default.target that's the default is fine. sed -e 's,^WantedBy=.*,WantedBy=default.target,' < contrib/varlink/io.podman.service > ${DESTDIR}${USERSYSTEMDDIR}/io.podman.service install ${SELINUXOPT} -m 644 contrib/varlink/podman.conf ${DESTDIR}${TMPFILESDIR}/podman.conf + # Install APIV2 services + install ${SELINUXOPT} -m 644 contrib/systemd/user/podman.socket ${DESTDIR}${USERSYSTEMDDIR}/podman.socket + install ${SELINUXOPT} -m 644 contrib/systemd/user/podman.service ${DESTDIR}${USERSYSTEMDDIR}/podman.service + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.socket ${DESTDIR}${SYSTEMDDIR}/podman.socket + install ${SELINUXOPT} -m 644 contrib/systemd/system/podman.service ${DESTDIR}${SYSTEMDDIR}/podman.service .PHONY: uninstall uninstall: @@ -545,6 +550,10 @@ uninstall: rm -f ${DESTDIR}${SYSTEMDDIR}/io.podman.socket rm -f ${DESTDIR}${USERSYSTEMDDIR}/io.podman.socket rm -f ${DESTDIR}${SYSTEMDDIR}/io.podman.service + rm -f ${DESTDIR}${SYSTEMDDIR}/podman.service + rm -f ${DESTDIR}${SYSTEMDDIR}/podman.socket + rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.socket + rm -f ${DESTDIR}${USERSYSTEMDDIR}/podman.service .PHONY: .gitvalidation .gitvalidation: .gopathok diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 41790a5aa..ed33402ab 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -13,8 +13,8 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/adapter" - "github.com/docker/go-units" - "github.com/opencontainers/go-digest" + units "github.com/docker/go-units" + digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -34,14 +34,15 @@ type imagesTemplateParams struct { } type imagesJSONParams struct { - ID string `json:"id"` - Name []string `json:"names"` - Digest digest.Digest `json:"digest"` - Digests []digest.Digest `json:"digests"` - Created time.Time `json:"created"` - Size *uint64 `json:"size"` - ReadOnly bool `json:"readonly"` - History []string `json:"history"` + ID string `json:"ID"` + Name []string `json:"Names"` + Created string `json:"Created"` + Digest digest.Digest `json:"Digest"` + Digests []digest.Digest `json:"Digests"` + CreatedAt time.Time `json:"CreatedAt"` + Size *uint64 `json:"Size"` + ReadOnly bool `json:"ReadOnly"` + History []string `json:"History"` } type imagesOptions struct { @@ -344,14 +345,15 @@ func getImagesJSONOutput(ctx context.Context, images []*adapter.ContainerImage) size = nil } params := imagesJSONParams{ - ID: img.ID(), - Name: img.Names(), - Digest: img.Digest(), - Digests: img.Digests(), - Created: img.Created(), - Size: size, - ReadOnly: img.IsReadOnly(), - History: img.NamesHistory(), + ID: img.ID(), + Name: img.Names(), + Digest: img.Digest(), + Digests: img.Digests(), + Created: units.HumanDuration(time.Since(img.Created())) + " ago", + CreatedAt: img.Created(), + Size: size, + ReadOnly: img.IsReadOnly(), + History: img.NamesHistory(), } imagesOutput = append(imagesOutput, params) } diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index e9792fa8f..0ef350fc2 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -105,6 +105,11 @@ type ImageSearchFilter ( star_count: int ) +type AuthConfig ( + username: string, + password: string +) + type KubePodService ( pod: string, service: string @@ -932,7 +937,7 @@ method ExportImage(name: string, destination: string, compress: bool, tags: []st # PullImage pulls an image from a repository to local storage. After a successful pull, the image id and logs # are returned as a [MoreResponse](#MoreResponse). This connection also will handle a WantsMores request to send # status as it occurs. -method PullImage(name: string) -> (reply: MoreResponse) +method PullImage(name: string, creds: AuthConfig) -> (reply: MoreResponse) # CreatePod creates a new empty pod. It uses a [PodCreate](#PodCreate) type for input. # On success, the ID of the newly created pod will be returned. diff --git a/contrib/cirrus/upload_release_archive.sh b/contrib/cirrus/upload_release_archive.sh index a94a5cc82..e1b8937b7 100755 --- a/contrib/cirrus/upload_release_archive.sh +++ b/contrib/cirrus/upload_release_archive.sh @@ -19,36 +19,19 @@ then BUCKET="libpod-pr-releases" elif [[ -n "$CIRRUS_BRANCH" ]] then - # Only release binaries for tagged commit ranges, unless working on docs - if is_release || [[ $CIRRUS_TASK_NAME =~ "docs" ]] + # Only release binaries for docs + if [[ $CIRRUS_TASK_NAME =~ "docs" ]] then PR_OR_BRANCH="$CIRRUS_BRANCH" BUCKET="libpod-$CIRRUS_BRANCH-releases" else - warn "" "Skipping release processing: Commit range|CIRRUS_TAG is development tagged." + warn "" "Skipping release processing for non-docs task." exit 0 fi else die 1 "Expecting either \$CIRRUS_PR or \$CIRRUS_BRANCH to be non-empty." fi -echo "Parsing actual_release.txt contents: $(< actual_release.txt)" -cd $GOSRC -RELEASETXT=$(<actual_release.txt) # see build_release.sh -[[ -n "$RELEASETXT" ]] || \ - die 3 "Could not obtain metadata from actual_release.txt" -RELEASE_INFO=$(echo "$RELEASETXT" | grep -m 1 'X-RELEASE-INFO:' | sed -r -e 's/X-RELEASE-INFO:\s*(.+)/\1/') -if [[ "$?" -ne "0" ]] || [[ -z "$RELEASE_INFO" ]] -then - die 4 "Metadata is empty or invalid: '$RELEASETXT'" -fi -# Format specified in Makefile -# e.g. libpod v1.3.1-166-g60df124e fedora 29 amd64 -# or libpod-remote v1.3.1-166-g60df124e windows - amd64 -FIELDS="RELEASE_BASENAME RELEASE_VERSION RELEASE_DIST RELEASE_DIST_VER RELEASE_ARCH" -read $FIELDS <<< $RELEASE_INFO -req_env_var $FIELDS - # Functional local podman required for uploading echo "Verifying a local, functional podman, building one if necessary." [[ -n "$(type -P podman)" ]] || \ @@ -64,7 +47,7 @@ echo "$RELEASE_GCPJSON" > "$TMPF" unset RELEASE_GCPJSON cd $GOSRC -for filename in $(ls -1 *.tar.gz *.zip *.msi $SWAGGER_FILEPATH) +for filename in $(ls -1 $SWAGGER_FILEPATH) do unset EXT EXT=$(echo "$filename" | sed -r -e 's/.+\.(.+$)/\1/g') @@ -85,19 +68,7 @@ do # For doc. ref. this must always be a static filename, e.g. swagger-latest-master.yaml ALSO_FILENAME="swagger-latest-${PR_OR_BRANCH}.yaml" else - # Form the generic "latest" file for this branch or pr - TO_PREFIX="${RELEASE_BASENAME}-latest-${PR_OR_BRANCH}-${RELEASE_DIST}" - # Form the fully-versioned filename for historical sake - ALSO_PREFIX="${RELEASE_BASENAME}-${RELEASE_VERSION}-${PR_OR_BRANCH}-${RELEASE_DIST}" - TO_SUFFIX="${RELEASE_ARCH}.${EXT}" - if [[ "$RELEASE_DIST" == "windows" ]] || [[ "$RELEASE_DIST" == "darwin" ]] - then - TO_FILENAME="${TO_PREFIX}-${TO_SUFFIX}" - ALSO_FILENAME="${ALSO_PREFIX}-${TO_SUFFIX}" - else - TO_FILENAME="${TO_PREFIX}-${RELEASE_DIST_VER}-${TO_SUFFIX}" - ALSO_FILENAME="${ALSO_PREFIX}-${TO_SUFFIX}" - fi + die "Uploading non-docs files has been disabled" fi [[ "$OS_RELEASE_ID" == "ubuntu" ]] || \ diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index 635de0c7e..817be31b7 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -524,6 +524,10 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath} %{_unitdir}/io.podman.socket %{_usr}/lib/systemd/user/io.podman.service %{_usr}/lib/systemd/user/io.podman.socket +%{_unitdir}/podman.service +%{_unitdir}/podman.socket +%{_usr}/lib/systemd/user/podman.service +%{_usr}/lib/systemd/user/podman.socket %{_usr}/lib/tmpfiles.d/%{name}.conf %if 0%{?with_devel} diff --git a/docs/dckrman.sh b/docs/dckrman.sh index 8ae7fd40d..c69524a7e 100755 --- a/docs/dckrman.sh +++ b/docs/dckrman.sh @@ -1,5 +1,6 @@ #!/bin/sh for i in $@; do - filename=$(echo $i | sed 's/podman/docker/g') - echo .so man1/$i > $filename + b=$(basename $i) + filename=$(echo $i | sed 's/podman/docker/g') + echo .so man1/$b > $filename done diff --git a/docs/tutorials/README.md b/docs/tutorials/README.md index bcd1b01d9..191d7a4b5 100644 --- a/docs/tutorials/README.md +++ b/docs/tutorials/README.md @@ -23,3 +23,7 @@ A brief how-to on using the Podman remote-client. **[How to use libpod for custom/derivative projects](podman-derivative-api.md)** How the libpod API can be used within your own project. + +**[Image Signing](image_signing.md)** + +Learn how to setup and use image signing with Podman. diff --git a/docs/tutorials/image_signing.md b/docs/tutorials/image_signing.md new file mode 100644 index 000000000..f0adca9af --- /dev/null +++ b/docs/tutorials/image_signing.md @@ -0,0 +1,194 @@ +# How to sign and distribute container images using Podman + +Signing container images originates from the motivation of trusting only +dedicated image providers to mitigate man-in-the-middle (MITM) attacks or +attacks on container registries. One way to sign images is to utilize a GNU +Privacy Guard ([GPG][0]) key. This technique is generally compatible with any +OCI compliant container registry like [Quay.io][1]. It is worth mentioning that +the OpenShift integrated container registry supports this signing mechanism out +of the box, which makes separate signature storage unnecessary. + +[0]: https://gnupg.org +[1]: https://quay.io + +From a technical perspective, we can utilize Podman to sign the image before +pushing it into a remote registry. After that, all systems running Podman have +to be configured to retrieve the signatures from a remote server, which can +be any simple web server. This means that every unsigned image will be rejected +during an image pull operation. But how does this work? + +First of all, we have to create a GPG key pair or select an already locally +available one. To generate a new GPG key, just run `gpg --full-gen-key` and +follow the interactive dialog. Now we should be able to verify that the key +exists locally: + +```bash +> gpg --list-keys sgrunert@suse.com +pub rsa2048 2018-11-26 [SC] [expires: 2020-11-25] + XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX +uid [ultimate] Sascha Grunert <sgrunert@suse.com> +sub rsa2048 2018-11-26 [E] [expires: 2020-11-25] +``` + +Now let’s assume that we run a container registry. For example we could simply +start one on our local machine: + +```bash +> sudo podman run -d -p 5000:5000 docker.io/registry +``` + +The registry does not know anything about image signing, it just provides the remote +storage for the container images. This means if we want to sign an image, we +have to take care of how to distribute the signatures. + +Let’s choose a standard `alpine` image for our signing experiment: + +```bash +> sudo podman pull docker://docker.io/alpine:latest +``` + +```bash +> sudo podman images alpine +REPOSITORY TAG IMAGE ID CREATED SIZE +docker.io/library/alpine latest e7d92cdc71fe 6 weeks ago 5.86 MB +``` + +Now we can re-tag the image to point it to our local registry: + +```bash +> sudo podman tag alpine localhost:5000/alpine +``` + +```bash +> sudo podman images alpine +REPOSITORY TAG IMAGE ID CREATED SIZE +localhost:5000/alpine latest e7d92cdc71fe 6 weeks ago 5.86 MB +docker.io/library/alpine latest e7d92cdc71fe 6 weeks ago 5.86 MB +``` + +Podman would now be able to push the image and sign it in one command. But to +let this work, we have to modify our system-wide registries configuration at +`/etc/containers/registries.d/default.yaml`: + +```yaml +default-docker: + sigstore: http://localhost:8000 # Added by us + sigstore-staging: file:///var/lib/containers/sigstore +``` + +We can see that we have two signature stores configured: + +- `sigstore`: referencing a web server for signature reading +- `sigstore-staging`: referencing a file path for signature writing + +Now, let’s push and sign the image: + +```bash +> sudo -E GNUPGHOME=$HOME/.gnupg \ + podman push \ + --tls-verify=false \ + --sign-by sgrunert@suse.com \ + localhost:5000/alpine +… +Storing signatures +``` + +If we now take a look at the systems signature storage, then we see that there +is a new signature available, which was caused by the image push: + +```bash +> sudo ls /var/lib/containers/sigstore +'alpine@sha256=e9b65ef660a3ff91d28cc50eba84f21798a6c5c39b4dd165047db49e84ae1fb9' +``` + +The default signature store in our edited version of +`/etc/containers/registries.d/default.yaml` references a web server listening at +`http://localhost:8000`. For our experiment, we simply start a new server inside +the local staging signature store: + +```bash +> sudo bash -c 'cd /var/lib/containers/sigstore && python3 -m http.server' +Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... +``` + +Let’s remove the local images for our verification test: + +``` +> sudo podman rmi docker.io/alpine localhost:5000/alpine +``` + +We have to write a policy to enforce that the signature has to be valid. This +can be done by adding a new rule in `/etc/containers/policy.json`. From the +below example, copy the `"docker"` entry into the `"transports"` section of your +`policy.json`. + +```json +{ + "default": [{ "type": "insecureAcceptAnything" }], + "transports": { + "docker": { + "localhost:5000": [ + { + "type": "signedBy", + "keyType": "GPGKeys", + "keyPath": "/tmp/key.gpg" + } + ] + } + } +} +``` + +The `keyPath` does not exist yet, so we have to put the GPG key there: + +```bash +> gpg --output /tmp/key.gpg --armor --export sgrunert@suse.com +``` + +If we now pull the image: + +```bash +> sudo podman pull --tls-verify=false localhost:5000/alpine +… +Storing signatures +e7d92cdc71feacf90708cb59182d0df1b911f8ae022d29e8e95d75ca6a99776a +``` + +Then we can see in the logs of the web server that the signature has been +accessed: + +``` +127.0.0.1 - - [04/Mar/2020 11:18:21] "GET /alpine@sha256=e9b65ef660a3ff91d28cc50eba84f21798a6c5c39b4dd165047db49e84ae1fb9/signature-1 HTTP/1.1" 200 - +``` + +As an counterpart example, if we specify the wrong key at `/tmp/key.gpg`: + +```bash +> gpg --output /tmp/key.gpg --armor --export mail@saschagrunert.de +File '/tmp/key.gpg' exists. Overwrite? (y/N) y +``` + +Then a pull is not possible any more: + +```bash +> sudo podman pull --tls-verify=false localhost:5000/alpine +Trying to pull localhost:5000/alpine... +Error: error pulling image "localhost:5000/alpine": unable to pull localhost:5000/alpine: unable to pull image: Source image rejected: Invalid GPG signature: … +``` + +So in general there are four main things to be taken into consideration when +signing container images with Podman and GPG: + +1. We need a valid private GPG key on the signing machine and corresponding + public keys on every system which would pull the image +2. A web server has to run somewhere which has access to the signature storage +3. The web server has to be configured in any + `/etc/containers/registries.d/*.yaml` file +4. Every image pulling system has to be configured to contain the enforcing + policy configuration via `policy.conf` + +That’s it for image signing and GPG. The cool thing is that this setup works out +of the box with [CRI-O][2] as well and can be used to sign container images in +Kubernetes environments. + +[2]: https://cri-o.io @@ -10,7 +10,7 @@ require ( github.com/containernetworking/cni v0.7.2-0.20200304161608-4fae32b84921 github.com/containernetworking/plugins v0.8.5 github.com/containers/buildah v1.14.3 - github.com/containers/common v0.5.0 + github.com/containers/common v0.6.1 github.com/containers/conmon v2.0.10+incompatible github.com/containers/image/v5 v5.2.1 github.com/containers/psgo v1.4.0 @@ -77,6 +77,8 @@ github.com/containers/common v0.4.2 h1:O5d1gj/xdpQdZi0MEivRQ/7AeRaVeHdbSP/bvShw4 github.com/containers/common v0.4.2/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= github.com/containers/common v0.5.0 h1:ZAef7h3oO46PcbTyfooZf8XLHrYad+GkhSu3EhH6P24= github.com/containers/common v0.5.0/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= +github.com/containers/common v0.6.1 h1:z9VeVXYeOnNV99uNLp7zoE5KO1n0hqz1mdm5a6AiIrA= +github.com/containers/common v0.6.1/go.mod h1:m62kenckrWi5rZx32kaLje2Og0hpf6NsaTBn6+b+Oys= github.com/containers/conmon v2.0.10+incompatible h1:EiwL41r5vx8SxG+dyUmbJ3baV9GUWjijPOdCkzM6gWU= github.com/containers/conmon v2.0.10+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/image/v5 v5.2.1 h1:rQR6QSUneWBoW1bTFpP9EJJTevQFv27YsKYQVJIzg+s= diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 12a13a0ce..7a85c1f04 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -470,9 +470,9 @@ func (c *Container) teardownStorage() error { return nil } -// Reset resets state fields to default values -// It is performed before a refresh and clears the state after a reboot -// It does not save the results - assumes the database will do that for us +// Reset resets state fields to default values. +// It is performed before a refresh and clears the state after a reboot. +// It does not save the results - assumes the database will do that for us. func resetState(state *ContainerState) error { state.PID = 0 state.ConmonPID = 0 @@ -483,7 +483,6 @@ func resetState(state *ContainerState) error { } state.ExecSessions = make(map[string]*ExecSession) state.LegacyExecSessions = nil - state.NetworkStatus = nil state.BindMounts = make(map[string]string) state.StoppedByUser = false state.RestartPolicyMatch = false @@ -539,6 +538,18 @@ func (c *Container) refresh() error { } c.lock = lock + // Try to delete any lingering IP allocations. + // If this fails, just log and ignore. + // I'm a little concerned that this is so far down in refresh() and we + // could fail before getting to it - but the worst that would happen is + // that Inspect() would return info on IPs we no longer own. + if len(c.state.NetworkStatus) > 0 { + if err := c.removeIPv4Allocations(); err != nil { + logrus.Errorf("Error removing IP allocations for container %s: %v", c.ID(), err) + } + } + c.state.NetworkStatus = nil + if err := c.save(); err != nil { return errors.Wrapf(err, "error refreshing state for container %s", c.ID()) } @@ -548,11 +559,58 @@ func (c *Container) refresh() error { return err } - if rootless.IsRootless() { + return nil +} + +// Try and remove IP address allocations. Presently IPv4 only. +// Should be safe as rootless because NetworkStatus should only be populated if +// CNI is running. +func (c *Container) removeIPv4Allocations() error { + cniNetworksDir, err := getCNINetworksDir() + if err != nil { + return err + } + + if len(c.state.NetworkStatus) == 0 { return nil } - return c.refreshCNI() + cniDefaultNetwork := "" + if c.runtime.netPlugin != nil { + cniDefaultNetwork = c.runtime.netPlugin.GetDefaultNetworkName() + } + + switch { + case len(c.config.Networks) > 0 && len(c.config.Networks) != len(c.state.NetworkStatus): + return errors.Wrapf(define.ErrInternal, "network mismatch: asked to join %d CNI networks but got %d CNI results", len(c.config.Networks), len(c.state.NetworkStatus)) + case len(c.config.Networks) == 0 && len(c.state.NetworkStatus) != 1: + return errors.Wrapf(define.ErrInternal, "network mismatch: did not specify CNI networks but joined more than one (%d)", len(c.state.NetworkStatus)) + case len(c.config.Networks) == 0 && cniDefaultNetwork == "": + return errors.Wrapf(define.ErrInternal, "could not retrieve name of CNI default network") + } + + for index, result := range c.state.NetworkStatus { + for _, ctrIP := range result.IPs { + if ctrIP.Version != "4" { + continue + } + candidate := "" + if len(c.config.Networks) > 0 { + // CNI returns networks in order we passed them. + // So our index into results should be our index + // into networks. + candidate = filepath.Join(cniNetworksDir, c.config.Networks[index], ctrIP.Address.IP.String()) + } else { + candidate = filepath.Join(cniNetworksDir, cniDefaultNetwork, ctrIP.Address.IP.String()) + } + logrus.Debugf("Going to try removing IP address reservation file %q for container %s", candidate, c.ID()) + if err := os.Remove(candidate); err != nil && !os.IsNotExist(err) { + return errors.Wrapf(err, "error removing CNI IP reservation file %q for container %s", candidate, c.ID()) + } + } + } + + return nil } // Remove conmon attach socket and terminal resize FIFO diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 63968918c..2f0f59c24 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1436,13 +1436,6 @@ func (c *Container) copyOwnerAndPerms(source, dest string) error { return nil } -// Teardown CNI config on refresh -func (c *Container) refreshCNI() error { - // Let's try and delete any lingering network config... - podNetwork := c.runtime.getPodNetwork(c.ID(), c.config.Name, "", c.config.Networks, c.config.PortMappings, c.config.StaticIP, c.config.StaticMAC) - return c.runtime.netPlugin.TearDownPod(podNetwork) -} - // Get cgroup path in a format suitable for the OCI spec func (c *Container) getOCICgroupPath() (string, error) { unified, err := cgroups.IsCgroup2UnifiedMode() diff --git a/libpod/container_internal_unsupported.go b/libpod/container_internal_unsupported.go index 4abaa6362..395271b2a 100644 --- a/libpod/container_internal_unsupported.go +++ b/libpod/container_internal_unsupported.go @@ -41,10 +41,6 @@ func (c *Container) copyOwnerAndPerms(source, dest string) error { return nil } -func (c *Container) refreshCNI() error { - return define.ErrNotImplemented -} - func (c *Container) getOCICgroupPath() (string, error) { return "", define.ErrNotImplemented } diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 5a27a2abb..f1bf79ce7 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -657,6 +657,13 @@ func resultToBasicNetworkConfig(result *cnitypes.Result) (InspectBasicNetworkCon return config, nil } +// This is a horrible hack, necessary because CNI does not properly clean up +// after itself on an unclean reboot. Return what we're pretty sure is the path +// to CNI's internal files (it's not really exposed to us). +func getCNINetworksDir() (string, error) { + return "/var/lib/cni/networks", nil +} + type logrusDebugWriter struct { prefix string } diff --git a/libpod/networking_unsupported.go b/libpod/networking_unsupported.go index 7f343cf35..32b354a44 100644 --- a/libpod/networking_unsupported.go +++ b/libpod/networking_unsupported.go @@ -23,3 +23,7 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) { func (c *Container) getContainerNetworkInfo() (*InspectNetworkSettings, error) { return nil, define.ErrNotImplemented } + +func getCNINetworksDir() (string, error) { + return "", define.ErrNotImplemented +} diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index a5242270e..0d2ca1a64 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -1057,7 +1057,8 @@ func (r *LocalRuntime) Prune(ctx context.Context, maxWorkers int, filters []stri if c.PodID() != "" { return false } - if state == define.ContainerStateStopped || state == define.ContainerStateExited { + if state == define.ContainerStateStopped || state == define.ContainerStateExited || + state == define.ContainerStateCreated || state == define.ContainerStateConfigured { return true } return false diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index d87de481c..fc396eddb 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -291,7 +291,8 @@ func (r *LocalRuntime) NewImageFromLocal(name string) (*ContainerImage, error) { // LoadFromArchiveReference creates an image from a local archive func (r *LocalRuntime) LoadFromArchiveReference(ctx context.Context, srcRef types.ImageReference, signaturePolicyPath string, writer io.Writer) ([]*ContainerImage, error) { var iid string - reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, srcRef.DockerReference().String()) + creds := iopodman.AuthConfig{} + reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, srcRef.DockerReference().String(), creds) if err != nil { return nil, err } @@ -323,7 +324,12 @@ func (r *LocalRuntime) New(ctx context.Context, name, signaturePolicyPath, authf if label != nil { return nil, errors.New("the remote client function does not support checking a remote image for a label") } - reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, name) + creds := iopodman.AuthConfig{} + if dockeroptions.DockerRegistryCreds != nil { + creds.Username = dockeroptions.DockerRegistryCreds.Username + creds.Password = dockeroptions.DockerRegistryCreds.Password + } + reply, err := iopodman.PullImage().Send(r.Conn, varlink.More, name, creds) if err != nil { return nil, err } diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index cfd3b993e..b6f2f58e8 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -10,12 +10,15 @@ import ( "strconv" "strings" + "github.com/containers/buildah" "github.com/containers/image/v5/docker" "github.com/containers/image/v5/docker/reference" + "github.com/containers/image/v5/manifest" "github.com/containers/image/v5/transports/alltransports" "github.com/containers/image/v5/types" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" + image2 "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/api/handlers" "github.com/containers/libpod/pkg/api/handlers/utils" "github.com/containers/libpod/pkg/util" @@ -416,3 +419,84 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { utils.WriteResponse(w, http.StatusOK, res) } + +func CommitContainer(w http.ResponseWriter, r *http.Request) { + var ( + destImage string + mimeType string + ) + decoder := r.Context().Value("decoder").(*schema.Decoder) + runtime := r.Context().Value("runtime").(*libpod.Runtime) + + query := struct { + Author string `schema:"author"` + Changes []string `schema:"changes"` + Comment string `schema:"comment"` + Container string `schema:"container"` + Format string `schema:"format"` + Pause bool `schema:"pause"` + Repo string `schema:"repo"` + Tag string `schema:"tag"` + }{ + Format: "oci", + } + + if err := decoder.Decode(&query, r.URL.Query()); err != nil { + utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String())) + return + } + rtc, err := runtime.GetConfig() + if err != nil { + utils.Error(w, "failed to get runtime config", http.StatusInternalServerError, errors.Wrap(err, "failed to get runtime config")) + return + } + sc := image2.GetSystemContext(rtc.SignaturePolicyPath, "", false) + tag := "latest" + options := libpod.ContainerCommitOptions{ + Pause: true, + } + switch query.Format { + case "oci": + mimeType = buildah.OCIv1ImageManifest + if len(query.Comment) > 0 { + utils.InternalServerError(w, errors.New("messages are only compatible with the docker image format (-f docker)")) + return + } + case "docker": + mimeType = manifest.DockerV2Schema2MediaType + default: + utils.InternalServerError(w, errors.Errorf("unrecognized image format %q", query.Format)) + return + } + options.CommitOptions = buildah.CommitOptions{ + SignaturePolicyPath: rtc.SignaturePolicyPath, + ReportWriter: os.Stderr, + SystemContext: sc, + PreferredManifestType: mimeType, + } + + if len(query.Tag) > 0 { + tag = query.Tag + } + options.Message = query.Comment + options.Author = query.Author + options.Pause = query.Pause + options.Changes = query.Changes + ctr, err := runtime.LookupContainer(query.Container) + if err != nil { + utils.Error(w, "failed to lookup container", http.StatusNotFound, err) + return + } + + // I know mitr hates this ... but doing for now + if len(query.Repo) > 1 { + destImage = fmt.Sprintf("%s:%s", query.Repo, tag) + } + + commitImage, err := ctr.Commit(r.Context(), destImage, options) + if err != nil && !strings.Contains(err.Error(), "is not running") { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure")) + return + } + utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: commitImage.ID()}) // nolint +} diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index e6ad045a2..87ddf5add 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -978,6 +978,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // name: container // type: string // description: the name or ID of a container + // required: true // - in: query // name: repo // type: string @@ -1000,8 +1001,14 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: pause the container before committing it // - in: query // name: changes + // description: instructions to apply while committing in Dockerfile format (i.e. "CMD=/bin/foo") + // type: array + // items: + // type: string + // - in: query + // name: format // type: string - // description: instructions to apply while committing in Dockerfile format + // description: format of the image manifest and metadata (default "oci") // produces: // - application/json // responses: @@ -1011,6 +1018,6 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // $ref: '#/responses/NoSuchImage' // 500: // $ref: '#/responses/InternalError' - r.Handle(VersionedPath("/commit"), s.APIHandler(compat.CommitContainer)).Methods(http.MethodPost) + r.Handle(VersionedPath("/libpod/commit"), s.APIHandler(libpod.CommitContainer)).Methods(http.MethodPost) return nil } diff --git a/pkg/bindings/containers/commit.go b/pkg/bindings/containers/commit.go new file mode 100644 index 000000000..12c25f842 --- /dev/null +++ b/pkg/bindings/containers/commit.go @@ -0,0 +1,49 @@ +package containers + +import ( + "context" + "net/http" + "net/url" + "strconv" + + "github.com/containers/libpod/pkg/api/handlers" + "github.com/containers/libpod/pkg/bindings" +) + +// Commit creates a container image from a container. The container is defined by nameOrId. Use +// the CommitOptions for finer grain control on characteristics of the resulting image. +func Commit(ctx context.Context, nameOrId string, options CommitOptions) (handlers.IDResponse, error) { + id := handlers.IDResponse{} + conn, err := bindings.GetClient(ctx) + if err != nil { + return id, err + } + params := url.Values{} + params.Set("container", nameOrId) + if options.Author != nil { + params.Set("author", *options.Author) + } + for _, change := range options.Changes { + params.Set("changes", change) + } + if options.Comment != nil { + params.Set("comment", *options.Comment) + } + if options.Format != nil { + params.Set("format", *options.Format) + } + if options.Pause != nil { + params.Set("pause", strconv.FormatBool(*options.Pause)) + } + if options.Repo != nil { + params.Set("repo", *options.Repo) + } + if options.Tag != nil { + params.Set("tag", *options.Tag) + } + response, err := conn.DoRequest(nil, http.MethodPost, "/commit", params) + if err != nil { + return id, err + } + return id, response.Process(&id) +} diff --git a/pkg/bindings/containers/types.go b/pkg/bindings/containers/types.go index 87342f7ea..31daaf565 100644 --- a/pkg/bindings/containers/types.go +++ b/pkg/bindings/containers/types.go @@ -11,3 +11,16 @@ type LogOptions struct { Timestamps *bool Until *string } + +// CommitOptions describe details about the resulting commited +// image as defined by repo and tag. None of these options +// are required. +type CommitOptions struct { + Author *string + Changes []string + Comment *string + Format *string + Pause *bool + Repo *string + Tag *string +} diff --git a/pkg/bindings/test/pods_test.go b/pkg/bindings/test/pods_test.go index bcf8e69b8..e94048a9c 100644 --- a/pkg/bindings/test/pods_test.go +++ b/pkg/bindings/test/pods_test.go @@ -79,7 +79,9 @@ var _ = Describe("Podman pods", func() { // The test validates the list pod endpoint with passing filters as the params. It("List pods with filters", func() { - var newpod2 string = "newpod2" + var ( + newpod2 string = "newpod2" + ) bt.Podcreate(&newpod2) _, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod) Expect(err).To(BeNil()) diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go index febfc2268..6ecd3cf98 100644 --- a/pkg/rootlessport/rootlessport_linux.go +++ b/pkg/rootlessport/rootlessport_linux.go @@ -19,6 +19,7 @@ import ( "io/ioutil" "os" "os/exec" + "os/signal" "syscall" "github.com/containernetworking/plugins/pkg/ns" @@ -101,6 +102,28 @@ func parent() error { return err } + sigC := make(chan os.Signal, 1) + signal.Notify(sigC, syscall.SIGPIPE) + defer func() { + // dummy signal to terminate the goroutine + sigC <- syscall.SIGKILL + }() + go func() { + defer func() { + signal.Stop(sigC) + close(sigC) + }() + + s := <-sigC + if s == syscall.SIGPIPE { + if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil { + syscall.Dup2(int(f.Fd()), 1) // nolint:errcheck + syscall.Dup2(int(f.Fd()), 2) // nolint:errcheck + f.Close() + } + } + }() + // create the parent driver stateDir, err := ioutil.TempDir(cfg.TmpDir, "rootlessport") if err != nil { diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go index c4809f16b..2dfb84e58 100644 --- a/pkg/varlinkapi/images.go +++ b/pkg/varlinkapi/images.go @@ -688,12 +688,18 @@ func (i *LibpodAPI) ExportImage(call iopodman.VarlinkCall, name, destination str } // PullImage pulls an image from a registry to the image store. -func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string) error { +func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string, creds iopodman.AuthConfig) error { var ( imageID string err error ) - dockerRegistryOptions := image.DockerRegistryOptions{} + dockerRegistryOptions := image.DockerRegistryOptions{ + DockerRegistryCreds: &types.DockerAuthConfig{ + Username: creds.Username, + Password: creds.Password, + }, + } + so := image.SigningOptions{} if call.WantsMore() { diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index c9b01ad4a..672b0e103 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -59,6 +59,34 @@ var _ = Describe("Podman prune", func() { Expect(podmanTest.NumberOfContainers()).To(Equal(1)) }) + It("podman container prune after create containers", func() { + create := podmanTest.Podman([]string{"create", "--name", "test", BB}) + create.WaitWithDefaultTimeout() + Expect(create.ExitCode()).To(Equal(0)) + + prune := podmanTest.Podman([]string{"container", "prune", "-f"}) + prune.WaitWithDefaultTimeout() + Expect(prune.ExitCode()).To(Equal(0)) + + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + }) + + It("podman container prune after create & init containers", func() { + create := podmanTest.Podman([]string{"create", "--name", "test", BB}) + create.WaitWithDefaultTimeout() + Expect(create.ExitCode()).To(Equal(0)) + + init := podmanTest.Podman([]string{"init", "test"}) + init.WaitWithDefaultTimeout() + Expect(init.ExitCode()).To(Equal(0)) + + prune := podmanTest.Podman([]string{"container", "prune", "-f"}) + prune.WaitWithDefaultTimeout() + Expect(prune.ExitCode()).To(Equal(0)) + + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + }) + It("podman image prune none images", func() { SkipIfRemote() podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true") diff --git a/test/e2e/volume_prune_test.go b/test/e2e/volume_prune_test.go index ba249278b..3049646b0 100644 --- a/test/e2e/volume_prune_test.go +++ b/test/e2e/volume_prune_test.go @@ -89,7 +89,7 @@ var _ = Describe("Podman volume prune", func() { session = podmanTest.Podman([]string{"volume", "ls"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - Expect(len(session.OutputToStringArray())).To(Equal(2)) + Expect(len(session.OutputToStringArray())).To(Equal(0)) podmanTest.Cleanup() }) diff --git a/test/system/010-images.bats b/test/system/010-images.bats index 3224c9b42..6957d4830 100644 --- a/test/system/010-images.bats +++ b/test/system/010-images.bats @@ -27,11 +27,11 @@ load helpers @test "podman images - json" { # 'created': podman includes fractional seconds, podman-remote does not tests=" -names[0] | $PODMAN_TEST_IMAGE_FQN -id | [0-9a-f]\\\{64\\\} -digest | sha256:[0-9a-f]\\\{64\\\} -created | [0-9-]\\\+T[0-9:.]\\\+Z -size | [0-9]\\\+ +Names[0] | $PODMAN_TEST_IMAGE_FQN +ID | [0-9a-f]\\\{64\\\} +Digest | sha256:[0-9a-f]\\\{64\\\} +CreatedAt | [0-9-]\\\+T[0-9:.]\\\+Z +Size | [0-9]\\\+ " run_podman images -a --format json diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index 0a09d994e..db70e53a4 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -160,11 +160,6 @@ type ContainersConfig struct { // ShmSize holds the size of /dev/shm. ShmSize string `toml:"shm_size"` - // SignaturePolicyPath is the path to a signature policy to use for - // validating images. If left empty, the containers/image default signature - // policy will be used. - SignaturePolicyPath string `toml:"_"` - // UTSNS indicates how to create a UTS namespace for the container UTSNS string `toml:"utsns"` @@ -283,6 +278,11 @@ type EngineConfig struct { // backwards compat with older version of libpod and Podman. SetOptions + // SignaturePolicyPath is the path to a signature policy to use for + // validating images. If left empty, the containers/image default signature + // policy will be used. + SignaturePolicyPath string `toml:"_"` + // SDNotify tells container engine to allow containers to notify the host systemd of // readiness using the SD_NOTIFY mechanism. SDNotify bool @@ -827,6 +827,9 @@ func isDirectory(path string) error { } func rootlessConfigPath() (string, error) { + if configHome := os.Getenv("XDG_CONFIG_HOME"); configHome != "" { + return filepath.Join(configHome, UserOverrideContainersConfig), nil + } home, err := unshare.HomeDir() if err != nil { return "", err diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index dca320d87..04c3f9773 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -123,7 +123,6 @@ func DefaultConfig() (*Config, error) { return nil, err } - var signaturePolicyPath string netns := "bridge" if unshare.IsRootless() { home, err := unshare.HomeDir() @@ -132,7 +131,7 @@ func DefaultConfig() (*Config, error) { } sigPath := filepath.Join(home, DefaultRootlessSignaturePolicyPath) if _, err := os.Stat(sigPath); err == nil { - signaturePolicyPath = sigPath + defaultEngineConfig.SignaturePolicyPath = sigPath } netns = "slirp4netns" } @@ -154,23 +153,22 @@ func DefaultConfig() (*Config, error) { Env: []string{ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", }, - EnvHost: false, - HTTPProxy: false, - Init: false, - InitPath: "", - IPCNS: "private", - LogDriver: DefaultLogDriver, - LogSizeMax: DefaultLogSizeMax, - NetNS: netns, - NoHosts: false, - PidsLimit: DefaultPidsLimit, - PidNS: "private", - SeccompProfile: SeccompDefaultPath, - ShmSize: DefaultShmSize, - SignaturePolicyPath: signaturePolicyPath, - UTSNS: "private", - UserNS: "private", - UserNSSize: DefaultUserNSSize, + EnvHost: false, + HTTPProxy: false, + Init: false, + InitPath: "", + IPCNS: "private", + LogDriver: DefaultLogDriver, + LogSizeMax: DefaultLogSizeMax, + NetNS: netns, + NoHosts: false, + PidsLimit: DefaultPidsLimit, + PidNS: "private", + SeccompProfile: SeccompDefaultPath, + ShmSize: DefaultShmSize, + UTSNS: "private", + UserNS: "private", + UserNSSize: DefaultUserNSSize, }, Network: NetworkConfig{ DefaultNetwork: "podman", diff --git a/vendor/github.com/containers/common/pkg/config/default_linux.go b/vendor/github.com/containers/common/pkg/config/default_linux.go index 43ef5da78..91b73d344 100644 --- a/vendor/github.com/containers/common/pkg/config/default_linux.go +++ b/vendor/github.com/containers/common/pkg/config/default_linux.go @@ -18,7 +18,7 @@ func isCgroup2UnifiedMode() (isUnified bool, isUnifiedErr error) { if err := syscall.Statfs(cgroupRoot, &st); err != nil { isUnified, isUnifiedErr = false, err } else { - isUnified, isUnifiedErr = st.Type == unix.CGROUP2_SUPER_MAGIC, nil + isUnified, isUnifiedErr = int64(st.Type) == int64(unix.CGROUP2_SUPER_MAGIC), nil } return } diff --git a/vendor/github.com/containers/common/pkg/config/libpodConfig.go b/vendor/github.com/containers/common/pkg/config/libpodConfig.go index be168208b..333f43815 100644 --- a/vendor/github.com/containers/common/pkg/config/libpodConfig.go +++ b/vendor/github.com/containers/common/pkg/config/libpodConfig.go @@ -302,10 +302,9 @@ func rootlessLibpodConfigPath() (string, error) { func (c *Config) libpodConfig() *ConfigFromLibpod { return &ConfigFromLibpod{ - SignaturePolicyPath: c.Containers.SignaturePolicyPath, - InitPath: c.Containers.InitPath, - MaxLogSize: c.Containers.LogSizeMax, - EnableLabeling: c.Containers.EnableLabeling, + InitPath: c.Containers.InitPath, + MaxLogSize: c.Containers.LogSizeMax, + EnableLabeling: c.Containers.EnableLabeling, SetOptions: c.Engine.SetOptions, VolumePath: c.Engine.VolumePath, @@ -334,6 +333,7 @@ func (c *Config) libpodConfig() *ConfigFromLibpod { DetachKeys: c.Engine.DetachKeys, SDNotify: c.Engine.SDNotify, CgroupCheck: c.Engine.CgroupCheck, + SignaturePolicyPath: c.Engine.SignaturePolicyPath, CNIConfigDir: c.Network.NetworkConfigDir, CNIPluginDir: c.Network.CNIPluginDirs, @@ -343,11 +343,11 @@ func (c *Config) libpodConfig() *ConfigFromLibpod { func (c *Config) libpodToContainersConfig(libpodConf *ConfigFromLibpod) { - c.Containers.SignaturePolicyPath = libpodConf.SignaturePolicyPath c.Containers.InitPath = libpodConf.InitPath c.Containers.LogSizeMax = libpodConf.MaxLogSize c.Containers.EnableLabeling = libpodConf.EnableLabeling + c.Engine.SignaturePolicyPath = libpodConf.SignaturePolicyPath c.Engine.SetOptions = libpodConf.SetOptions c.Engine.VolumePath = libpodConf.VolumePath c.Engine.ImageDefaultTransport = libpodConf.ImageDefaultTransport diff --git a/vendor/modules.txt b/vendor/modules.txt index 1ad73e1bc..b143eea5a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -82,7 +82,7 @@ github.com/containers/buildah/pkg/secrets github.com/containers/buildah/pkg/supplemented github.com/containers/buildah/pkg/umask github.com/containers/buildah/util -# github.com/containers/common v0.5.0 +# github.com/containers/common v0.6.1 github.com/containers/common/pkg/capabilities github.com/containers/common/pkg/config github.com/containers/common/pkg/unshare |