summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/check_cirrus_cron.yml9
-rw-r--r--cmd/podman/auto-update.go97
-rw-r--r--cmd/podman/manifest/create.go5
-rw-r--r--docs/source/markdown/podman-auto-update.1.md24
-rw-r--r--docs/source/markdown/podman-create.1.md34
-rw-r--r--docs/source/markdown/podman-pull.1.md2
-rw-r--r--docs/source/markdown/podman-run.1.md37
-rw-r--r--go.mod2
-rw-r--r--go.sum3
-rw-r--r--libpod/oci_conmon_exec_linux.go3
-rw-r--r--nix/default-arm64.nix5
-rw-r--r--nix/default.nix7
-rw-r--r--nix/nixpkgs.json8
-rw-r--r--pkg/autoupdate/autoupdate.go238
-rw-r--r--pkg/bindings/containers/attach.go19
-rw-r--r--pkg/domain/entities/auto-update.go15
-rw-r--r--pkg/domain/entities/engine_container.go2
-rw-r--r--pkg/domain/infra/abi/auto-update.go5
-rw-r--r--pkg/domain/infra/tunnel/auto-update.go2
-rw-r--r--test/apiv2/20-containers.at8
-rw-r--r--test/apiv2/30-volumes.at7
-rw-r--r--test/e2e/manifest_test.go6
-rw-r--r--test/system/075-exec.bats2
-rw-r--r--test/system/250-systemd.bats2
-rw-r--r--test/system/255-auto-update.bats13
-rw-r--r--test/system/500-networking.bats1
-rw-r--r--vendor/github.com/google/uuid/null.go118
-rw-r--r--vendor/github.com/google/uuid/uuid.go45
-rw-r--r--vendor/github.com/google/uuid/version4.go27
-rw-r--r--vendor/modules.txt2
30 files changed, 579 insertions, 169 deletions
diff --git a/.github/workflows/check_cirrus_cron.yml b/.github/workflows/check_cirrus_cron.yml
index d869576fd..65c483c96 100644
--- a/.github/workflows/check_cirrus_cron.yml
+++ b/.github/workflows/check_cirrus_cron.yml
@@ -6,10 +6,12 @@
name: check_cirrus_cron
on:
- # Note: This only applies to the master branch.
+ # Note: This only applies to the main branch.
schedule:
- # Assume cirrus cron jobs runs at least once per day
- - cron: '59 23 * * *'
+ # N/B: This should correspond to a period slightly after
+ # the last job finishes running. See job defs. at:
+ # https://cirrus-ci.com/settings/repository/6707778565701632
+ - cron: '59 23 * * 1-5'
# Debug: Allow triggering job manually in github-actions WebUI
workflow_dispatch: {}
@@ -30,7 +32,6 @@ jobs:
steps:
- uses: actions/checkout@v2
with:
- ref: master
persist-credentials: false
- name: Get failed cron names and Build IDs
diff --git a/cmd/podman/auto-update.go b/cmd/podman/auto-update.go
index 99226790f..6ccf4e167 100644
--- a/cmd/podman/auto-update.go
+++ b/cmd/podman/auto-update.go
@@ -1,10 +1,15 @@
package main
import (
+ "encoding/json"
"fmt"
+ "os"
+ "strings"
"github.com/containers/common/pkg/auth"
"github.com/containers/common/pkg/completion"
+ "github.com/containers/common/pkg/report"
+ "github.com/containers/podman/v3/cmd/podman/common"
"github.com/containers/podman/v3/cmd/podman/registry"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/errorhandling"
@@ -12,8 +17,13 @@ import (
"github.com/spf13/cobra"
)
+type cliAutoUpdateOptions struct {
+ entities.AutoUpdateOptions
+ format string
+}
+
var (
- autoUpdateOptions = entities.AutoUpdateOptions{}
+ autoUpdateOptions = cliAutoUpdateOptions{}
autoUpdateDescription = `Auto update containers according to their auto-update policy.
Auto-update policies are specified with the "io.containers.autoupdate" label.
@@ -42,6 +52,9 @@ func init() {
authfileFlagName := "authfile"
flags.StringVar(&autoUpdateOptions.Authfile, authfileFlagName, auth.GetDefaultAuthFile(), "Path to the authentication file. Use REGISTRY_AUTH_FILE environment variable to override")
_ = autoUpdateCommand.RegisterFlagCompletionFunc(authfileFlagName, completion.AutocompleteDefault)
+
+ flags.StringVar(&autoUpdateOptions.format, "format", "", "Change the output format to JSON or a Go template")
+ _ = autoUpdateCommand.RegisterFlagCompletionFunc("format", common.AutocompleteFormat(autoUpdateOutput{}))
}
func autoUpdate(cmd *cobra.Command, args []string) error {
@@ -49,11 +62,83 @@ func autoUpdate(cmd *cobra.Command, args []string) error {
// Backwards compat. System tests expect this error string.
return errors.Errorf("`%s` takes no arguments", cmd.CommandPath())
}
- report, failures := registry.ContainerEngine().AutoUpdate(registry.GetContext(), autoUpdateOptions)
- if report != nil {
- for _, unit := range report.Units {
- fmt.Println(unit)
- }
+
+ allReports, failures := registry.ContainerEngine().AutoUpdate(registry.GetContext(), autoUpdateOptions.AutoUpdateOptions)
+ if allReports == nil {
+ return errorhandling.JoinErrors(failures)
+ }
+
+ if err := writeTemplate(allReports, autoUpdateOptions.format); err != nil {
+ failures = append(failures, err)
}
+
return errorhandling.JoinErrors(failures)
}
+
+type autoUpdateOutput struct {
+ Unit string
+ Container string
+ ContainerName string
+ ContainerID string
+ Image string
+ Policy string
+ Updated string
+}
+
+func reportsToOutput(allReports []*entities.AutoUpdateReport) []autoUpdateOutput {
+ output := make([]autoUpdateOutput, len(allReports))
+ for i, r := range allReports {
+ output[i] = autoUpdateOutput{
+ Unit: r.SystemdUnit,
+ Container: fmt.Sprintf("%s (%s)", r.ContainerID[:12], r.ContainerName),
+ ContainerName: r.ContainerName,
+ ContainerID: r.ContainerID,
+ Image: r.ImageName,
+ Policy: r.Policy,
+ Updated: r.Updated,
+ }
+ }
+ return output
+}
+
+func writeTemplate(allReports []*entities.AutoUpdateReport, inputFormat string) error {
+ var format string
+ var printHeader bool
+
+ output := reportsToOutput(allReports)
+ switch inputFormat {
+ case "":
+ rows := []string{"{{.Unit}}", "{{.Container}}", "{{.Image}}", "{{.Policy}}", "{{.Updated}}"}
+ format = "{{range . }}" + strings.Join(rows, "\t") + "\n{{end -}}"
+ printHeader = true
+ case "json":
+ prettyJSON, err := json.MarshalIndent(output, "", " ")
+ if err != nil {
+ return err
+ }
+ fmt.Println(string(prettyJSON))
+ return nil
+ default:
+ format = "{{range . }}" + inputFormat + "\n{{end -}}"
+ }
+
+ tmpl, err := report.NewTemplate("auto-update").Parse(format)
+ if err != nil {
+ return err
+ }
+
+ w, err := report.NewWriterDefault(os.Stdout)
+ if err != nil {
+ return err
+ }
+ defer w.Flush()
+
+ if printHeader {
+ headers := report.Headers(autoUpdateOutput{}, nil)
+ if err := tmpl.Execute(w, headers); err != nil {
+ return err
+ }
+ }
+
+ return tmpl.Execute(w, output)
+}
diff --git a/cmd/podman/manifest/create.go b/cmd/podman/manifest/create.go
index 9f7d74d14..95c9f89b0 100644
--- a/cmd/podman/manifest/create.go
+++ b/cmd/podman/manifest/create.go
@@ -13,15 +13,16 @@ import (
var (
manifestCreateOpts = entities.ManifestCreateOptions{}
createCmd = &cobra.Command{
- Use: "create [options] LIST [IMAGE]",
+ Use: "create [options] LIST [IMAGE...]",
Short: "Create manifest list or image index",
Long: "Creates manifest lists or image indexes.",
RunE: create,
ValidArgsFunction: common.AutocompleteImages,
Example: `podman manifest create mylist:v1.11
podman manifest create mylist:v1.11 arch-specific-image-to-add
+ podman manifest create mylist:v1.11 arch-specific-image-to-add another-arch-specific-image-to-add
podman manifest create --all mylist:v1.11 transport:tagged-image-to-add`,
- Args: cobra.RangeArgs(1, 2),
+ Args: cobra.MinimumNArgs(1),
}
)
diff --git a/docs/source/markdown/podman-auto-update.1.md b/docs/source/markdown/podman-auto-update.1.md
index 24b910470..4f2608be4 100644
--- a/docs/source/markdown/podman-auto-update.1.md
+++ b/docs/source/markdown/podman-auto-update.1.md
@@ -41,6 +41,22 @@ If the authorization state is not found there, `$HOME/.docker/config.json` is ch
Note: There is also the option to override the default path of the authentication file by setting the `REGISTRY_AUTH_FILE` environment variable. This can be done with **export REGISTRY_AUTH_FILE=_path_**.
+#### **--format**=*format*
+
+Change the default output format. This can be of a supported type like 'json' or a Go template.
+Valid placeholders for the Go template are listed below:
+
+| **Placeholder** | **Description** |
+| --------------- | -------------------------------------- |
+| .Unit | Name of the systemd unit |
+| .ContainerName | Name of the container |
+| .ContainerID | ID of the container |
+| .Container | ID and name of the container |
+| .Image | Name of the image |
+| .Policy | Auto-update policy of the container |
+| .Updated | Update status: true,false,failed |
+
+
## EXAMPLES
Autoupdate with registry policy
@@ -53,7 +69,7 @@ bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
### Generate a systemd unit for this container
$ podman generate systemd --new --files bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d
-/home/user/containers/libpod/container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
+/home/user/container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
### Load the new systemd unit and start it
$ mv ./container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service ~/.config/systemd/user
@@ -67,7 +83,7 @@ $ systemctl --user start container-bc219740a210455fa27deacc96d50a9e20516492f1417
### Auto-update the container
$ podman auto-update
-container-bc219740a210455fa27deacc96d50a9e20516492f1417507c13ce1533dbdcd9d.service
+[...]
```
Autoupdate with local policy
@@ -80,7 +96,7 @@ be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338
### Generate a systemd unit for this container
$ podman generate systemd --new --files be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338
-/home/user/containers/libpod/container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service
+/home/user/container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service
### Load the new systemd unit and start it
$ mv ./container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service ~/.config/systemd/user
@@ -102,7 +118,7 @@ $ podman commit --change CMD=/bin/bash inspiring_galileo busybox:latest
### Auto-update the container
$ podman auto-update
-container-be0889fd06f252a2e5141b37072c6bada68563026cb2b2649f53394d87ccc338.service
+[...]
```
## SEE ALSO
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index f56b363e0..1720e6eb6 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -858,7 +858,7 @@ Secrets and its storage are managed using the `podman secret` command.
Secret Options
- `type=mount|env` : How the secret will be exposed to the container. Default mount.
-- `target=target` : Target of secret. Defauts to secret name.
+- `target=target` : Target of secret. Defaults to secret name.
- `uid=0` : UID of secret. Defaults to 0. Mount secret type only.
- `gid=0` : GID of secret. Defaults to 0. Mount secret type only.
- `mode=0` : Mode of secret. Defaults to 0444. Mount secret type only.
@@ -1086,14 +1086,28 @@ Set the user namespace mode for the container. It defaults to the **PODMAN_USERN
Valid _mode_ values are:
-- **auto[:**_OPTIONS,..._**]**: automatically create a namespace. It is possible to specify these options to `auto`:
- - **gidmapping=**_HOST_GID:CONTAINER_GID:SIZE_: to force a GID mapping to be present in the user namespace.
- - **size=**_SIZE_: to specify an explicit size for the automatic user namespace. e.g. `--userns=auto:size=8192`. If `size` is not specified, `auto` will estimate a size for the user namespace.
- - **uidmapping=**_HOST_UID:CONTAINER_UID:SIZE_: to force a UID mapping to be present in the user namespace.
-- **container:**_id_: join the user namespace of the specified container.
-- **host**: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).
+**auto**[:_OPTIONS,..._]: automatically create a unique user namespace.
+
+The `--userns=auto` flag, requires that the user name `containers` and a range of subordinate user ids that the Podman container is allowed to use be specified in the /etc/subuid and /etc/subgid files.
+
+Example: `containers:2147483647:2147483648`.
+
+Podman allocates unique ranges of UIDs and GIDs from the `containers` subpordinate user ids. The size of the ranges is based on the number of UIDs required in the image. The number of UIDs and GIDs can be overridden with the `size` option. The `auto` options currently does not work in rootless mode
+
+ Valid `auto`options:
+
+ - *gidmapping*=_HOST_GID:CONTAINER_GID:SIZE_: to force a GID mapping to be present in the user namespace.
+ - *size*=_SIZE_: to specify an explicit size for the automatic user namespace. e.g. `--userns=auto:size=8192`. If `size` is not specified, `auto` will estimate a size for the user namespace.
+ - *uidmapping*=_HOST_UID:CONTAINER_UID:SIZE_: to force a UID mapping to be present in the user namespace.
+
+**container:**_id_: join the user namespace of the specified container.
+
+**host**: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).
+
- **keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user.
+
- **ns:**_namespace_: run the container in the given existing user namespace.
+
- **private**: create a new namespace for the container.
This option is incompatible with **--gidmap**, **--uidmap**, **--subuidname** and **--subgidname**.
@@ -1353,6 +1367,12 @@ the uids and gids from the host.
$ podman create --uidmap 0:30000:7000 --gidmap 0:30000:7000 fedora echo hello
```
+### Setting automatic user namespace separated containers
+
+```
+# podman create --userns=auto:size=65536 ubi8-init
+```
+
### Configure timezone in a container
```
diff --git a/docs/source/markdown/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md
index 10661e16e..189464d17 100644
--- a/docs/source/markdown/podman-pull.1.md
+++ b/docs/source/markdown/podman-pull.1.md
@@ -182,7 +182,7 @@ Storing signatures
d6e46aa2470df1d32034c6707c8041158b652f38d2a9ae3d7ad7e7532d22ebe0
```
-Pull an image by specifiying an authentication file.
+Pull an image by specifying an authentication file.
```
$ podman pull --authfile temp-auths/myauths.json docker://docker.io/umohnani/finaltest
Trying to pull docker.io/umohnani/finaltest:latest...Getting image source signatures
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 1c3efa0c3..ce0cf1a2f 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -908,7 +908,7 @@ Secrets and its storage are managed using the `podman secret` command.
Secret Options
- `type=mount|env` : How the secret will be exposed to the container. Default mount.
-- `target=target` : Target of secret. Defauts to secret name.
+- `target=target` : Target of secret. Defaults to secret name.
- `uid=0` : UID of secret. Defaults to 0. Mount secret type only.
- `gid=0` : GID of secret. Defaults to 0. Mount secret type only.
- `mode=0` : Mode of secret. Defaults to 0444. Mount secret type only.
@@ -1159,14 +1159,28 @@ Set the user namespace mode for the container. It defaults to the **PODMAN_USERN
Valid _mode_ values are:
-- **auto[:**_OPTIONS,..._**]**: automatically create a namespace. It is possible to specify these options to `auto`:
- - **gidmapping=**_HOST_GID:CONTAINER_GID:SIZE_: to force a GID mapping to be present in the user namespace.
- - **size=**_SIZE_: to specify an explicit size for the automatic user namespace. e.g. `--userns=auto:size=8192`. If `size` is not specified, `auto` will estimate a size for the user namespace.
- - **uidmapping=**_HOST_UID:CONTAINER_UID:SIZE_: to force a UID mapping to be present in the user namespace.
-- **container:**_id_: join the user namespace of the specified container.
-- **host**: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).
+**auto**[:_OPTIONS,..._]: automatically create a unique user namespace.
+
+The `--userns=auto` flag, requires that the user name `containers` and a range of subordinate user ids that the Podman container is allowed to use be specified in the /etc/subuid and /etc/subgid files.
+
+Example: `containers:2147483647:2147483648`.
+
+Podman allocates unique ranges of UIDs and GIDs from the `containers` subpordinate user ids. The size of the ranges is based on the number of UIDs required in the image. The number of UIDs and GIDs can be overridden with the `size` option. The `auto` options currently does not work in rootless mode
+
+ Valid `auto`options:
+
+ - *gidmapping*=_HOST_GID:CONTAINER_GID:SIZE_: to force a GID mapping to be present in the user namespace.
+ - *size*=_SIZE_: to specify an explicit size for the automatic user namespace. e.g. `--userns=auto:size=8192`. If `size` is not specified, `auto` will estimate a size for the user namespace.
+ - *uidmapping*=_HOST_UID:CONTAINER_UID:SIZE_: to force a UID mapping to be present in the user namespace.
+
+**container:**_id_: join the user namespace of the specified container.
+
+**host**: run in the user namespace of the caller. The processes running in the container will have the same privileges on the host as any other process launched by the calling user (default).
+
- **keep-id**: creates a user namespace where the current rootless user's UID:GID are mapped to the same values in the container. This option is ignored for containers created by the root user.
+
- **ns:**_namespace_: run the container in the given existing user namespace.
+
- **private**: create a new namespace for the container.
This option is incompatible with **--gidmap**, **--uidmap**, **--subuidname** and **--subgidname**.
@@ -1676,6 +1690,15 @@ $ echo "asdf" | podman run --rm -i --entrypoint /bin/cat someimage
asdf
```
+### Setting automatic user namespace separated containers
+
+```
+# podman run --userns=auto:size=65536 ubi8-micro cat /proc/self/uid_map
+0 2147483647 65536
+# podman run --userns=auto:size=65536 ubi8-micro cat /proc/self/uid_map
+0 2147549183 65536
+```
+
### Setting Namespaced Kernel Parameters (Sysctls)
The **--sysctl** sets namespaced kernel parameters (sysctls) in the
diff --git a/go.mod b/go.mod
index 2b519adc2..2dd760cee 100644
--- a/go.mod
+++ b/go.mod
@@ -33,7 +33,7 @@ require (
github.com/ghodss/yaml v1.0.0
github.com/godbus/dbus/v5 v5.0.4
github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
- github.com/google/uuid v1.2.0
+ github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/gorilla/schema v1.2.0
github.com/hashicorp/go-multierror v1.1.1
diff --git a/go.sum b/go.sum
index 321008809..fb0690b39 100644
--- a/go.sum
+++ b/go.sum
@@ -482,8 +482,9 @@ github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIE
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go
index 09d3d1833..05a4e19b0 100644
--- a/libpod/oci_conmon_exec_linux.go
+++ b/libpod/oci_conmon_exec_linux.go
@@ -610,6 +610,9 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp
_, err := utils.CopyDetachable(conn, httpBuf, detachKeys)
logrus.Debugf("STDIN copy completed")
stdinChan <- err
+ if connErr := conn.CloseWrite(); connErr != nil {
+ logrus.Errorf("Unable to close conn: %v", connErr)
+ }
}()
}
diff --git a/nix/default-arm64.nix b/nix/default-arm64.nix
index d29f75520..8868788ae 100644
--- a/nix/default-arm64.nix
+++ b/nix/default-arm64.nix
@@ -30,8 +30,10 @@ let
"--enable-confdir=/etc"
"--enable-usbdropdir=/var/lib/pcsc/drivers"
"--disable-libsystemd"
+ "--disable-libudev"
+ "--disable-libusb"
];
- buildInputs = [ pkgs.python3 pkgs.udev pkgs.dbus pkgs.systemd ];
+ buildInputs = [ pkgs.python3 pkgs.dbus ];
});
systemd = (static pkg.systemd).overrideAttrs (x: {
outputs = [ "out" "dev" ];
@@ -69,6 +71,7 @@ let
export LDFLAGS='-s -w -static-libgcc -static'
export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"'
export BUILDTAGS='static netgo osusergo exclude_graphdriver_btrfs exclude_graphdriver_devicemapper seccomp apparmor selinux'
+ export CGO_ENABLED=1
'';
buildPhase = ''
patchShebangs .
diff --git a/nix/default.nix b/nix/default.nix
index f6194e3d9..4d15532c2 100644
--- a/nix/default.nix
+++ b/nix/default.nix
@@ -27,9 +27,11 @@ let
configureFlags = [
"--enable-confdir=/etc"
"--enable-usbdropdir=/var/lib/pcsc/drivers"
- "--with-systemdsystemunitdir=${placeholder "bin"}/lib/systemd/system"
+ "--disable-libsystemd"
+ "--disable-libudev"
+ "--disable-libusb"
];
- buildInputs = [ pkgs.python3 pkgs.udev pkgs.dbus pkgs.systemd ];
+ buildInputs = [ pkgs.python3 pkgs.dbus ];
});
systemd = (static pkg.systemd).overrideAttrs (x: {
outputs = [ "out" "dev" ];
@@ -67,6 +69,7 @@ let
export LDFLAGS='-s -w -static-libgcc -static'
export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"'
export BUILDTAGS='static netgo osusergo exclude_graphdriver_btrfs exclude_graphdriver_devicemapper seccomp apparmor selinux'
+ export CGO_ENABLED=1
'';
buildPhase = ''
patchShebangs .
diff --git a/nix/nixpkgs.json b/nix/nixpkgs.json
index a9771eade..efcfe202e 100644
--- a/nix/nixpkgs.json
+++ b/nix/nixpkgs.json
@@ -1,9 +1,9 @@
{
"url": "https://github.com/nixos/nixpkgs",
- "rev": "60cce7e5e1fdf62421ef6d4184ee399b46209366",
- "date": "2021-06-09T01:18:50-04:00",
- "path": "/nix/store/fixgn194626rb7gf99l9jaqm0hbqn2ix-nixpkgs",
- "sha256": "100xrb925cana1kfd0c7gwkjjalq891vfgr0rn1gl9j8gp3l3gx6",
+ "rev": "2a96414d7e350160a33ed0978449c9ff5b5a6eb3",
+ "date": "2021-07-13T18:21:47+02:00",
+ "path": "/nix/store/2ai9q8ac6vxb2rrngdz82y8jxnk15cvm-nixpkgs",
+ "sha256": "1dzrfqdjq3yq5jjskiqflzy58l2xx6059gay9p1k07zrlm1wigy5",
"fetchSubmodules": false,
"deepClone": false,
"leaveDotGit": false
diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go
index 0a13e7e74..fd95c319c 100644
--- a/pkg/autoupdate/autoupdate.go
+++ b/pkg/autoupdate/autoupdate.go
@@ -9,12 +9,13 @@ import (
"github.com/containers/common/pkg/config"
"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/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
+ "github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/systemd"
systemdDefine "github.com/containers/podman/v3/pkg/systemd/define"
+ "github.com/coreos/go-systemd/v22/dbus"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -119,7 +120,7 @@ func ValidateImageReference(imageName string) error {
//
// It returns a slice of successfully restarted systemd units and a slice of
// errors encountered during auto update.
-func AutoUpdate(runtime *libpod.Runtime, options Options) ([]string, []error) {
+func AutoUpdate(ctx context.Context, runtime *libpod.Runtime, options Options) ([]*entities.AutoUpdateReport, []error) {
// Create a map from `image ID -> []*Container`.
containerMap, errs := imageContainersMap(runtime)
if len(containerMap) == 0 {
@@ -130,7 +131,7 @@ func AutoUpdate(runtime *libpod.Runtime, options Options) ([]string, []error) {
listOptions := &libimage.ListImagesOptions{
Filters: []string{"readonly=false"},
}
- imagesSlice, err := runtime.LibimageRuntime().ListImages(context.Background(), nil, listOptions)
+ imagesSlice, err := runtime.LibimageRuntime().ListImages(ctx, nil, listOptions)
if err != nil {
return nil, []error{err}
}
@@ -147,8 +148,8 @@ func AutoUpdate(runtime *libpod.Runtime, options Options) ([]string, []error) {
}
defer conn.Close()
- // Update images.
- containersToRestart := []*libpod.Container{}
+ // Update all images/container according to their auto-update policy.
+ var allReports []*entities.AutoUpdateReport
updatedRawImages := make(map[string]bool)
for imageID, policyMapper := range containerMap {
image, exists := imageMap[imageID]
@@ -156,76 +157,139 @@ func AutoUpdate(runtime *libpod.Runtime, options Options) ([]string, []error) {
errs = append(errs, errors.Errorf("container image ID %q not found in local storage", imageID))
return nil, errs
}
- // Now we have to check if the image of any containers must be updated.
- // Note that the image ID is NOT enough for this check as a given image
- // may have multiple tags.
- for _, registryCtr := range policyMapper[PolicyRegistryImage] {
- cid := registryCtr.ID()
- rawImageName := registryCtr.RawImageName()
- if rawImageName == "" {
- errs = append(errs, errors.Errorf("error registry auto-updating container %q: raw-image name is empty", cid))
- }
- readAuthenticationPath(registryCtr, options)
- needsUpdate, err := newerRemoteImageAvailable(runtime, image, rawImageName, options)
+
+ for _, ctr := range policyMapper[PolicyRegistryImage] {
+ report, err := autoUpdateRegistry(ctx, image, ctr, updatedRawImages, &options, conn, runtime)
if err != nil {
- errs = append(errs, errors.Wrapf(err, "error registry auto-updating container %q: image check for %q failed", cid, rawImageName))
- continue
+ errs = append(errs, err)
}
-
- if needsUpdate {
- logrus.Infof("Auto-updating container %q using registry image %q", cid, rawImageName)
- if _, updated := updatedRawImages[rawImageName]; !updated {
- _, err = updateImage(runtime, rawImageName, options)
- if err != nil {
- errs = append(errs, errors.Wrapf(err, "error registry auto-updating container %q: image update for %q failed", cid, rawImageName))
- continue
- }
- updatedRawImages[rawImageName] = true
- }
- containersToRestart = append(containersToRestart, registryCtr)
+ if report != nil {
+ allReports = append(allReports, report)
}
}
- for _, localCtr := range policyMapper[PolicyLocalImage] {
- cid := localCtr.ID()
- rawImageName := localCtr.RawImageName()
- if rawImageName == "" {
- errs = append(errs, errors.Errorf("error locally auto-updating container %q: raw-image name is empty", cid))
- }
- // This avoids restarting containers unnecessarily.
- needsUpdate, err := newerLocalImageAvailable(runtime, image, rawImageName)
+ for _, ctr := range policyMapper[PolicyLocalImage] {
+ report, err := autoUpdateLocally(ctx, image, ctr, &options, conn, runtime)
if err != nil {
- errs = append(errs, errors.Wrapf(err, "error locally auto-updating container %q: image check for %q failed", cid, rawImageName))
- continue
+ errs = append(errs, err)
}
-
- if needsUpdate {
- logrus.Infof("Auto-updating container %q using local image %q", cid, rawImageName)
- containersToRestart = append(containersToRestart, localCtr)
+ if report != nil {
+ allReports = append(allReports, report)
}
}
}
- // Restart containers.
- updatedUnits := []string{}
- for _, ctr := range containersToRestart {
- labels := ctr.Labels()
- unit, exists := labels[systemdDefine.EnvVariable]
- if !exists {
- // Shouldn't happen but let's be sure of it.
- errs = append(errs, errors.Errorf("error auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable))
- continue
- }
- _, err := conn.RestartUnit(unit, "replace", nil)
- if err != nil {
- errs = append(errs, errors.Wrapf(err, "error auto-updating container %q: restarting systemd unit %q failed", ctr.ID(), unit))
- continue
+ return allReports, errs
+}
+
+// autoUpdateRegistry updates the image/container according to the "registry" policy.
+func autoUpdateRegistry(ctx context.Context, image *libimage.Image, ctr *libpod.Container, updatedRawImages map[string]bool, options *Options, conn *dbus.Conn, runtime *libpod.Runtime) (*entities.AutoUpdateReport, error) {
+ cid := ctr.ID()
+ rawImageName := ctr.RawImageName()
+ if rawImageName == "" {
+ return nil, errors.Errorf("error registry auto-updating container %q: raw-image name is empty", cid)
+ }
+
+ labels := ctr.Labels()
+ unit, exists := labels[systemdDefine.EnvVariable]
+ if !exists {
+ return nil, errors.Errorf("error auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable)
+ }
+
+ report := &entities.AutoUpdateReport{
+ ContainerID: cid,
+ ContainerName: ctr.Name(),
+ ImageName: rawImageName,
+ Policy: PolicyRegistryImage,
+ SystemdUnit: unit,
+ Updated: "failed",
+ }
+
+ if _, updated := updatedRawImages[rawImageName]; updated {
+ logrus.Infof("Auto-updating container %q using registry image %q", cid, rawImageName)
+ if err := restartSystemdUnit(ctr, unit, conn); err != nil {
+ return report, err
}
- logrus.Infof("Successfully restarted systemd unit %q", unit)
- updatedUnits = append(updatedUnits, unit)
+ report.Updated = "true"
+ return report, nil
+ }
+
+ authfile := getAuthfilePath(ctr, options)
+ needsUpdate, err := newerRemoteImageAvailable(ctx, runtime, image, rawImageName, authfile)
+ if err != nil {
+ return report, errors.Wrapf(err, "error registry auto-updating container %q: image check for %q failed", cid, rawImageName)
+ }
+
+ if !needsUpdate {
+ report.Updated = "false"
+ return report, nil
+ }
+
+ if _, err := updateImage(ctx, runtime, rawImageName, options); err != nil {
+ return report, errors.Wrapf(err, "error registry auto-updating container %q: image update for %q failed", cid, rawImageName)
+ }
+ updatedRawImages[rawImageName] = true
+
+ logrus.Infof("Auto-updating container %q using registry image %q", cid, rawImageName)
+ if err := restartSystemdUnit(ctr, unit, conn); err != nil {
+ return report, err
}
- return updatedUnits, errs
+ report.Updated = "true"
+ return report, nil
+}
+
+// autoUpdateRegistry updates the image/container according to the "local" policy.
+func autoUpdateLocally(ctx context.Context, image *libimage.Image, ctr *libpod.Container, options *Options, conn *dbus.Conn, runtime *libpod.Runtime) (*entities.AutoUpdateReport, error) {
+ cid := ctr.ID()
+ rawImageName := ctr.RawImageName()
+ if rawImageName == "" {
+ return nil, errors.Errorf("error locally auto-updating container %q: raw-image name is empty", cid)
+ }
+
+ labels := ctr.Labels()
+ unit, exists := labels[systemdDefine.EnvVariable]
+ if !exists {
+ return nil, errors.Errorf("error auto-updating container %q: no %s label found", ctr.ID(), systemdDefine.EnvVariable)
+ }
+
+ report := &entities.AutoUpdateReport{
+ ContainerID: cid,
+ ContainerName: ctr.Name(),
+ ImageName: rawImageName,
+ Policy: PolicyLocalImage,
+ SystemdUnit: unit,
+ Updated: "failed",
+ }
+
+ needsUpdate, err := newerLocalImageAvailable(runtime, image, rawImageName)
+ if err != nil {
+ return report, errors.Wrapf(err, "error locally auto-updating container %q: image check for %q failed", cid, rawImageName)
+ }
+
+ if !needsUpdate {
+ report.Updated = "false"
+ return report, nil
+ }
+
+ logrus.Infof("Auto-updating container %q using local image %q", cid, rawImageName)
+ if err := restartSystemdUnit(ctr, unit, conn); err != nil {
+ return report, err
+ }
+
+ report.Updated = "true"
+ return report, nil
+}
+
+// restartSystemdUnit restarts the systemd unit the container is running in.
+func restartSystemdUnit(ctr *libpod.Container, unit string, conn *dbus.Conn) error {
+ _, err := conn.RestartUnit(unit, "replace", nil)
+ if err != nil {
+ return errors.Wrapf(err, "error auto-updating container %q: restarting systemd unit %q failed", ctr.ID(), unit)
+ }
+
+ logrus.Infof("Successfully restarted systemd unit %q of container %q", unit, ctr.ID())
+ return nil
}
// imageContainersMap generates a map[image ID] -> [containers using the image]
@@ -280,52 +344,25 @@ func imageContainersMap(runtime *libpod.Runtime) (map[string]policyMapper, []err
return containerMap, errors
}
-// readAuthenticationPath reads a container's labels and reads authentication path into options
-func readAuthenticationPath(ctr *libpod.Container, options Options) {
+// getAuthfilePath returns an authfile path, if set. The authfile label in the
+// container, if set, as precedence over the one set in the options.
+func getAuthfilePath(ctr *libpod.Container, options *Options) string {
labels := ctr.Labels()
authFilePath, exists := labels[AuthfileLabel]
if exists {
- options.Authfile = authFilePath
+ return authFilePath
}
+ return options.Authfile
}
// newerRemoteImageAvailable returns true if there corresponding image on the remote
// registry is newer.
-func newerRemoteImageAvailable(runtime *libpod.Runtime, img *libimage.Image, origName string, options Options) (bool, error) {
+func newerRemoteImageAvailable(ctx context.Context, runtime *libpod.Runtime, img *libimage.Image, origName string, authfile string) (bool, error) {
remoteRef, err := docker.ParseReference("//" + origName)
if err != nil {
return false, err
}
-
- data, err := img.Inspect(context.Background(), false)
- if err != nil {
- return false, err
- }
-
- sys := runtime.SystemContext()
- sys.AuthFilePath = options.Authfile
-
- // We need to account for the arch that the image uses. It seems
- // common on ARM to tweak this option to pull the correct image. See
- // github.com/containers/podman/issues/6613.
- sys.ArchitectureChoice = data.Architecture
-
- remoteImg, err := remoteRef.NewImage(context.Background(), sys)
- if err != nil {
- return false, err
- }
-
- rawManifest, _, err := remoteImg.Manifest(context.Background())
- if err != nil {
- return false, err
- }
-
- remoteDigest, err := manifest.Digest(rawManifest)
- if err != nil {
- return false, err
- }
-
- return img.Digest().String() != remoteDigest.String(), nil
+ return img.HasDifferentDigest(ctx, remoteRef)
}
// newerLocalImageAvailable returns true if the container and local image have different digests
@@ -334,21 +371,16 @@ func newerLocalImageAvailable(runtime *libpod.Runtime, img *libimage.Image, rawI
if err != nil {
return false, err
}
-
- localDigest := localImg.Digest().String()
-
- ctrDigest := img.Digest().String()
-
- return localDigest != ctrDigest, nil
+ return localImg.Digest().String() != img.Digest().String(), nil
}
// updateImage pulls the specified image.
-func updateImage(runtime *libpod.Runtime, name string, options Options) (*libimage.Image, error) {
+func updateImage(ctx context.Context, runtime *libpod.Runtime, name string, options *Options) (*libimage.Image, error) {
pullOptions := &libimage.PullOptions{}
pullOptions.AuthFilePath = options.Authfile
pullOptions.Writer = os.Stderr
- pulledImages, err := runtime.LibimageRuntime().Pull(context.Background(), name, config.PullPolicyAlways, pullOptions)
+ pulledImages, err := runtime.LibimageRuntime().Pull(ctx, name, config.PullPolicyAlways, pullOptions)
if err != nil {
return nil, err
}
diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go
index cc12c8ab7..01c14d350 100644
--- a/pkg/bindings/containers/attach.go
+++ b/pkg/bindings/containers/attach.go
@@ -25,6 +25,12 @@ import (
"golang.org/x/crypto/ssh/terminal"
)
+// The CloseWriter interface is used to determine whether we can do a one-sided
+// close of a hijacked connection.
+type CloseWriter interface {
+ CloseWrite() error
+}
+
// Attach attaches to a running container
func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Writer, stderr io.Writer, attachReady chan bool, options *AttachOptions) error {
if options == nil {
@@ -161,6 +167,12 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri
logrus.Error("failed to write input to service: " + err.Error())
}
stdinChan <- err
+
+ if closeWrite, ok := socket.(CloseWriter); ok {
+ if err := closeWrite.CloseWrite(); err != nil {
+ logrus.Warnf("Failed to close STDIN for writing: %v", err)
+ }
+ }
}()
}
@@ -485,6 +497,13 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar
if err != nil {
logrus.Error("failed to write input to service: " + err.Error())
}
+
+ if closeWrite, ok := socket.(CloseWriter); ok {
+ logrus.Debugf("Closing STDIN")
+ if err := closeWrite.CloseWrite(); err != nil {
+ logrus.Warnf("Failed to close STDIN for writing: %v", err)
+ }
+ }
}()
}
diff --git a/pkg/domain/entities/auto-update.go b/pkg/domain/entities/auto-update.go
index c51158816..d74462b86 100644
--- a/pkg/domain/entities/auto-update.go
+++ b/pkg/domain/entities/auto-update.go
@@ -8,6 +8,17 @@ type AutoUpdateOptions struct {
// AutoUpdateReport contains the results from running auto-update.
type AutoUpdateReport struct {
- // Units - the restarted systemd units during auto-update.
- Units []string
+ // ID of the container *before* an update.
+ ContainerID string
+ // Name of the container *before* an update.
+ ContainerName string
+ // Name of the image.
+ ImageName string
+ // The configured auto-update policy.
+ Policy string
+ // SystemdUnit running a container configured for auto updates.
+ SystemdUnit string
+ // Indicates whether the image was updated and the container (and
+ // systemd unit) restarted.
+ Updated string
}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 28e5160db..62e83fab3 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -14,7 +14,7 @@ import (
type ContainerCopyFunc func() error
type ContainerEngine interface {
- AutoUpdate(ctx context.Context, options AutoUpdateOptions) (*AutoUpdateReport, []error)
+ AutoUpdate(ctx context.Context, options AutoUpdateOptions) ([]*AutoUpdateReport, []error)
Config(ctx context.Context) (*config.Config, error)
ContainerAttach(ctx context.Context, nameOrID string, options AttachOptions) error
ContainerCheckpoint(ctx context.Context, namesOrIds []string, options CheckpointOptions) ([]*CheckpointReport, error)
diff --git a/pkg/domain/infra/abi/auto-update.go b/pkg/domain/infra/abi/auto-update.go
index c9d7f2130..daa882ecf 100644
--- a/pkg/domain/infra/abi/auto-update.go
+++ b/pkg/domain/infra/abi/auto-update.go
@@ -7,11 +7,10 @@ import (
"github.com/containers/podman/v3/pkg/domain/entities"
)
-func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) (*entities.AutoUpdateReport, []error) {
+func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) ([]*entities.AutoUpdateReport, []error) {
// Convert the entities options to the autoupdate ones. We can't use
// them in the entities package as low-level packages must not leak
// into the remote client.
autoOpts := autoupdate.Options{Authfile: options.Authfile}
- units, failures := autoupdate.AutoUpdate(ic.Libpod, autoOpts)
- return &entities.AutoUpdateReport{Units: units}, failures
+ return autoupdate.AutoUpdate(ctx, ic.Libpod, autoOpts)
}
diff --git a/pkg/domain/infra/tunnel/auto-update.go b/pkg/domain/infra/tunnel/auto-update.go
index 41165cc74..038c60537 100644
--- a/pkg/domain/infra/tunnel/auto-update.go
+++ b/pkg/domain/infra/tunnel/auto-update.go
@@ -7,6 +7,6 @@ import (
"github.com/pkg/errors"
)
-func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) (*entities.AutoUpdateReport, []error) {
+func (ic *ContainerEngine) AutoUpdate(ctx context.Context, options entities.AutoUpdateOptions) ([]*entities.AutoUpdateReport, []error) {
return nil, []error{errors.New("not implemented")}
}
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index ef51757c9..c5b2f5ec1 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -211,15 +211,11 @@ t GET containers/$cid/json 200 \
t POST containers/create Image=$IMAGE Entrypoint='["top"]' 201 \
.Id~[0-9a-f]\\{64\\}
cid_top=$(jq -r '.Id' <<<"$output")
-network_expect="{}"
-if root; then
- network_expect='.podman.NetworkID=podman'
-fi
t GET containers/${cid_top}/json 200 \
.Config.Entrypoint[0]="top" \
.Config.Cmd='[]' \
- .Path="top"
- .NetworkSettings.Networks="$network_expect"
+ .Path="top" \
+ .NetworkSettings.Networks.podman.NetworkID=podman
t POST containers/${cid_top}/start 204
# make sure the container is running
t GET containers/${cid_top}/json 200 \
diff --git a/test/apiv2/30-volumes.at b/test/apiv2/30-volumes.at
index 5feceea7b..b639e05f9 100644
--- a/test/apiv2/30-volumes.at
+++ b/test/apiv2/30-volumes.at
@@ -13,13 +13,14 @@ t POST libpod/volumes/create name=foo1 201 \
.CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \
.Labels={} \
.Options={}
+# TODO(mwhahaha): there might be a bug here since options is null and not {}
t POST volumes/create 201 \
- .Name~[0-9a-f]\\{64\\}
+ .Name~[0-9a-f]\\{64\\} \
.Driver=local \
- .Mountpoint=$volumepath/~[0-9a-f]\\{64\\}/_data \
+ .Mountpoint~$volumepath/[0-9a-f]\\{64\\}/_data \
.CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \
.Labels={} \
- .Options={}
+ .Options=null
t POST libpod/volumes/create 201
t POST libpod/volumes/create \
Name=foo2 \
diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go
index b2dc4f734..8c1ea4134 100644
--- a/test/e2e/manifest_test.go
+++ b/test/e2e/manifest_test.go
@@ -50,6 +50,12 @@ var _ = Describe("Podman manifest", func() {
Expect(session.ExitCode()).To(Equal(0))
})
+ It("podman manifest create", func() {
+ session := podmanTest.Podman([]string{"manifest", "create", "foo", imageList})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ })
+
It("podman manifest inspect", func() {
session := podmanTest.Podman([]string{"manifest", "inspect", BB})
session.WaitWithDefaultTimeout()
diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats
index badf44c49..3e8c3c1ea 100644
--- a/test/system/075-exec.bats
+++ b/test/system/075-exec.bats
@@ -59,8 +59,6 @@ load helpers
# Issue #4785 - piping to exec statement - fixed in #4818
# Issue #5046 - piping to exec truncates results (actually a conmon issue)
@test "podman exec - cat from stdin" {
- skip_if_remote "FIXME: pending #7360"
-
run_podman run -d $IMAGE sh -c 'while [ ! -e /stop ]; do sleep 0.1;done'
cid="$output"
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index 4ea192009..aafe385c8 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -119,7 +119,7 @@ function service_cleanup() {
# Run auto-update and check that it restarted the container
run_podman commit --change "CMD=/bin/bash" $cname $IMAGE
run_podman auto-update
- is $output $SERVICE_NAME "autoupdate local restarted container"
+ is "$output" ".*$SERVICE_NAME.*" "autoupdate local restarted container"
# All good. Stop service, clean up.
service_cleanup
diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats
index 3713243d5..4959bb6aa 100644
--- a/test/system/255-auto-update.bats
+++ b/test/system/255-auto-update.bats
@@ -121,8 +121,10 @@ function _confirm_update() {
generate_service alpine image
_wait_service_ready container-$cname.service
- run_podman auto-update
+ run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
is "$output" "Trying to pull.*" "Image is updated."
+ is "$output" ".*container-$cname.service,quay.io/libpod/alpine:latest,true,registry.*" "Image is updated."
+
_confirm_update $cname $ori_image
}
@@ -151,10 +153,15 @@ function _confirm_update() {
@test "podman auto-update - label io.containers.autoupdate=local" {
generate_service localtest local
- podman commit --change CMD=/bin/bash $cname quay.io/libpod/localtest:latest
+ image=quay.io/libpod/localtest:latest
+ podman commit --change CMD=/bin/bash $cname $image
+ podman image inspect --format "{{.ID}}" $image
+ imageID="$output"
_wait_service_ready container-$cname.service
- run_podman auto-update
+ run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
+ is "$output" ".*container-$cname.service,quay.io/libpod/localtest:latest,true,local.*" "Image is updated."
+
_confirm_update $cname $ori_image
}
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index d55a786f7..4feb57807 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -20,7 +20,6 @@ load helpers
# Copied from tsweeney's https://github.com/containers/podman/issues/4827
@test "podman networking: port on localhost" {
- skip_if_remote "FIXME: reevaluate this one after #7360 is fixed"
random_1=$(random_string 30)
random_2=$(random_string 30)
diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go
new file mode 100644
index 000000000..d7fcbf286
--- /dev/null
+++ b/vendor/github.com/google/uuid/null.go
@@ -0,0 +1,118 @@
+// Copyright 2021 Google Inc. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+ "bytes"
+ "database/sql/driver"
+ "encoding/json"
+ "fmt"
+)
+
+var jsonNull = []byte("null")
+
+// NullUUID represents a UUID that may be null.
+// NullUUID implements the SQL driver.Scanner interface so
+// it can be used as a scan destination:
+//
+// var u uuid.NullUUID
+// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u)
+// ...
+// if u.Valid {
+// // use u.UUID
+// } else {
+// // NULL value
+// }
+//
+type NullUUID struct {
+ UUID UUID
+ Valid bool // Valid is true if UUID is not NULL
+}
+
+// Scan implements the SQL driver.Scanner interface.
+func (nu *NullUUID) Scan(value interface{}) error {
+ if value == nil {
+ nu.UUID, nu.Valid = Nil, false
+ return nil
+ }
+
+ err := nu.UUID.Scan(value)
+ if err != nil {
+ nu.Valid = false
+ return err
+ }
+
+ nu.Valid = true
+ return nil
+}
+
+// Value implements the driver Valuer interface.
+func (nu NullUUID) Value() (driver.Value, error) {
+ if !nu.Valid {
+ return nil, nil
+ }
+ // Delegate to UUID Value function
+ return nu.UUID.Value()
+}
+
+// MarshalBinary implements encoding.BinaryMarshaler.
+func (nu NullUUID) MarshalBinary() ([]byte, error) {
+ if nu.Valid {
+ return nu.UUID[:], nil
+ }
+
+ return []byte(nil), nil
+}
+
+// UnmarshalBinary implements encoding.BinaryUnmarshaler.
+func (nu *NullUUID) UnmarshalBinary(data []byte) error {
+ if len(data) != 16 {
+ return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
+ }
+ copy(nu.UUID[:], data)
+ nu.Valid = true
+ return nil
+}
+
+// MarshalText implements encoding.TextMarshaler.
+func (nu NullUUID) MarshalText() ([]byte, error) {
+ if nu.Valid {
+ return nu.UUID.MarshalText()
+ }
+
+ return jsonNull, nil
+}
+
+// UnmarshalText implements encoding.TextUnmarshaler.
+func (nu *NullUUID) UnmarshalText(data []byte) error {
+ id, err := ParseBytes(data)
+ if err != nil {
+ nu.Valid = false
+ return err
+ }
+ nu.UUID = id
+ nu.Valid = true
+ return nil
+}
+
+// MarshalJSON implements json.Marshaler.
+func (nu NullUUID) MarshalJSON() ([]byte, error) {
+ if nu.Valid {
+ return json.Marshal(nu.UUID)
+ }
+
+ return jsonNull, nil
+}
+
+// UnmarshalJSON implements json.Unmarshaler.
+func (nu *NullUUID) UnmarshalJSON(data []byte) error {
+ if bytes.Equal(data, jsonNull) {
+ *nu = NullUUID{}
+ return nil // valid null UUID
+ }
+ err := json.Unmarshal(data, &nu.UUID)
+ nu.Valid = err == nil
+ return err
+}
diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go
index 60d26bb50..a57207aeb 100644
--- a/vendor/github.com/google/uuid/uuid.go
+++ b/vendor/github.com/google/uuid/uuid.go
@@ -12,6 +12,7 @@ import (
"fmt"
"io"
"strings"
+ "sync"
)
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
@@ -33,7 +34,15 @@ const (
Future // Reserved for future definition.
)
-var rander = rand.Reader // random function
+const randPoolSize = 16 * 16
+
+var (
+ rander = rand.Reader // random function
+ poolEnabled = false
+ poolMu sync.Mutex
+ poolPos = randPoolSize // protected with poolMu
+ pool [randPoolSize]byte // protected with poolMu
+)
type invalidLengthError struct{ len int }
@@ -41,6 +50,12 @@ func (err invalidLengthError) Error() string {
return fmt.Sprintf("invalid UUID length: %d", err.len)
}
+// IsInvalidLengthError is matcher function for custom error invalidLengthError
+func IsInvalidLengthError(err error) bool {
+ _, ok := err.(invalidLengthError)
+ return ok
+}
+
// Parse decodes s into a UUID or returns an error. Both the standard UUID
// forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the
@@ -249,3 +264,31 @@ func SetRand(r io.Reader) {
}
rander = r
}
+
+// EnableRandPool enables internal randomness pool used for Random
+// (Version 4) UUID generation. The pool contains random bytes read from
+// the random number generator on demand in batches. Enabling the pool
+// may improve the UUID generation throughput significantly.
+//
+// Since the pool is stored on the Go heap, this feature may be a bad fit
+// for security sensitive applications.
+//
+// Both EnableRandPool and DisableRandPool are not thread-safe and should
+// only be called when there is no possibility that New or any other
+// UUID Version 4 generation function will be called concurrently.
+func EnableRandPool() {
+ poolEnabled = true
+}
+
+// DisableRandPool disables the randomness pool if it was previously
+// enabled with EnableRandPool.
+//
+// Both EnableRandPool and DisableRandPool are not thread-safe and should
+// only be called when there is no possibility that New or any other
+// UUID Version 4 generation function will be called concurrently.
+func DisableRandPool() {
+ poolEnabled = false
+ defer poolMu.Unlock()
+ poolMu.Lock()
+ poolPos = randPoolSize
+}
diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go
index 86160fbd0..7697802e4 100644
--- a/vendor/github.com/google/uuid/version4.go
+++ b/vendor/github.com/google/uuid/version4.go
@@ -27,6 +27,8 @@ func NewString() string {
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
+// Uses the randomness pool if it was enabled with EnableRandPool.
+//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
@@ -35,7 +37,10 @@ func NewString() string {
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() (UUID, error) {
- return NewRandomFromReader(rander)
+ if !poolEnabled {
+ return NewRandomFromReader(rander)
+ }
+ return newRandomFromPool()
}
// NewRandomFromReader returns a UUID based on bytes read from a given io.Reader.
@@ -49,3 +54,23 @@ func NewRandomFromReader(r io.Reader) (UUID, error) {
uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
return uuid, nil
}
+
+func newRandomFromPool() (UUID, error) {
+ var uuid UUID
+ poolMu.Lock()
+ if poolPos == randPoolSize {
+ _, err := io.ReadFull(rander, pool[:])
+ if err != nil {
+ poolMu.Unlock()
+ return Nil, err
+ }
+ poolPos = 0
+ }
+ copy(uuid[:], pool[poolPos:(poolPos+16)])
+ poolPos += 16
+ poolMu.Unlock()
+
+ uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4
+ uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10
+ return uuid, nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 19b8d0a47..c29cfe8cc 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -370,7 +370,7 @@ github.com/google/go-intervals/intervalset
github.com/google/gofuzz
# github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf
github.com/google/shlex
-# github.com/google/uuid v1.2.0
+# github.com/google/uuid v1.3.0
github.com/google/uuid
# github.com/gorilla/mux v1.8.0
github.com/gorilla/mux