summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/check_cirrus_cron.yml9
-rw-r--r--cmd/podman/manifest/create.go5
-rw-r--r--cmd/podman/pods/ps.go5
-rw-r--r--docs/source/includes.rst2
-rw-r--r--docs/source/markdown/podman-create.1.md2
-rw-r--r--docs/source/markdown/podman-pod-ps.1.md59
-rw-r--r--docs/source/markdown/podman-run.1.md2
-rw-r--r--docs/tutorials/rootless_tutorial.md54
-rw-r--r--go.mod6
-rw-r--r--go.sum12
-rw-r--r--libpod/container_internal_linux.go5
-rw-r--r--libpod/container_log.go4
-rw-r--r--libpod/container_log_linux.go8
-rw-r--r--libpod/logs/log.go8
-rw-r--r--libpod/runtime.go9
-rw-r--r--pkg/api/handlers/compat/containers_logs.go14
-rw-r--r--pkg/api/handlers/types.go43
-rw-r--r--pkg/bindings/images/build.go6
-rw-r--r--pkg/systemd/generate/containers.go7
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_container.py13
-rw-r--r--test/compose/uptwice/Dockerfile2
-rw-r--r--test/compose/uptwice/docker-compose.yml5
-rw-r--r--test/compose/uptwice/tests.sh4
-rw-r--r--test/e2e/manifest_test.go6
-rw-r--r--test/e2e/pod_ps_test.go8
-rw-r--r--test/python/docker/compat/test_containers.py14
-rw-r--r--test/system/070-build.bats34
-rw-r--r--vendor/github.com/Microsoft/hcsshim/errors.go6
-rw-r--r--vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go12
-rw-r--r--vendor/github.com/containers/storage/VERSION2
-rw-r--r--vendor/github.com/containers/storage/go.mod2
-rw-r--r--vendor/github.com/containers/storage/go.sum4
-rw-r--r--vendor/github.com/containers/storage/pkg/fileutils/fileutils.go2
-rw-r--r--vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go26
-rw-r--r--vendor/github.com/containers/storage/types/options.go19
-rw-r--r--vendor/github.com/containers/storage/types/storage_broken.conf18
-rw-r--r--vendor/github.com/containers/storage/types/utils.go10
-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/github.com/onsi/gomega/CHANGELOG.md17
-rw-r--r--vendor/github.com/onsi/gomega/README.md2
-rw-r--r--vendor/github.com/onsi/gomega/gexec/build.go6
-rw-r--r--vendor/github.com/onsi/gomega/go.mod2
-rw-r--r--vendor/github.com/onsi/gomega/go.sum6
-rw-r--r--vendor/github.com/onsi/gomega/gomega_dsl.go88
-rw-r--r--vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go49
-rw-r--r--vendor/modules.txt8
48 files changed, 631 insertions, 184 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/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/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go
index 3e5ab86f4..14e3e2ea9 100644
--- a/cmd/podman/pods/ps.go
+++ b/cmd/podman/pods/ps.go
@@ -124,6 +124,11 @@ func pods(cmd *cobra.Command, _ []string) error {
"NumberOfContainers": "# OF CONTAINERS",
"Created": "CREATED",
"InfraID": "INFRA ID",
+ "ContainerIds": "IDS",
+ "ContainerNames": "NAMES",
+ "ContainerStatuses": "STATUS",
+ "Cgroup": "CGROUP",
+ "Namespace": "NAMESPACES",
})
renderHeaders := true
row := podPsFormat()
diff --git a/docs/source/includes.rst b/docs/source/includes.rst
index 8d3b6e2db..6e04d77f4 100644
--- a/docs/source/includes.rst
+++ b/docs/source/includes.rst
@@ -16,4 +16,4 @@
.. _podman run: http://docs.podman.io/en/latest/markdown/podman-run.1.html
.. _podman build: http://docs.podman.io/en/latest/markdown/podman-build.1.html
.. _podman push: http://docs.podman.io/en/latest/markdown/podman-push.1.html
-.. image:: https://github.com/containers/podman/blob/master/logo/podman-logo.png?raw=true
+.. image:: https://github.com/containers/podman/blob/main/logo/podman-logo.png?raw=true
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index 2c51b312d..f56b363e0 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -646,7 +646,7 @@ Valid _mode_ values are:
- **ns:**_path_: path to a network namespace to join;
- **private**: create a new namespace for the container (default)
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
- - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default is false.
+ - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`, which is added to `/etc/hosts` as `host.containers.internal` for your convenience). Default is false.
- **mtu=MTU**: Specify the MTU to use for this network. (Default is `65520`).
- **cidr=CIDR**: Specify ip range to use for this network. (Default is `10.0.2.0/24`).
- **enable_ipv6=true|false**: Enable IPv6. Default is false. (Required for `outbound_addr6`).
diff --git a/docs/source/markdown/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md
index c1f5fd5e3..156adccaa 100644
--- a/docs/source/markdown/podman-pod-ps.1.md
+++ b/docs/source/markdown/podman-pod-ps.1.md
@@ -12,7 +12,9 @@ By default it lists:
* pod id
* pod name
+ * the time the pod was created
* number of containers attached to pod
+ * container id of the pod infra container
* status of pod as defined by the following table
| **Status** | **Description** |
@@ -28,15 +30,15 @@ By default it lists:
#### **--ctr-names**
-Includes the container names in the container info field
+Display the container names
#### **--ctr-ids**
-Includes the container IDs in the container info field
+Display the container IDs
#### **--ctr-status**
-Includes the container statuses in the container info field
+Display the container statuses
#### **--latest**, **-l**
@@ -111,62 +113,55 @@ Print usage statement
```
$ podman pod ps
-POD ID NAME STATUS NUMBER OF CONTAINERS
-00dfd6fa02c0 jolly_goldstine Running 1
-f4df8692e116 nifty_torvalds Created 2
+POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
+00dfd6fa02c0 jolly_goldstine Running 31 hours ago ba465ab0a3a4 1
+f4df8692e116 nifty_torvalds Created 10 minutes ago 331693bff40a 2
```
```
$ podman pod ps --ctr-names
-POD ID NAME STATUS CONTAINER INFO
-00dfd6fa02c0 jolly_goldstine Running [ loving_archimedes ]
-f4df8692e116 nifty_torvalds Created [ thirsty_hawking ] [ wizardly_golick ]
+POD ID NAME STATUS CREATED INFRA ID NAMES
+00dfd6fa02c0 jolly_goldstine Running 31 hours ago ba465ab0a3a4 loving_archimedes
+f4df8692e116 nifty_torvalds Created 10 minutes ago 331693bff40a thirsty_hawking,wizardly_golick
```
```
$ podman pod ps --ctr-status --ctr-names --ctr-ids
-POD ID NAME STATUS CONTAINER INFO
-00dfd6fa02c0 jolly_goldstine Running [ ba465ab0a3a4 loving_archimedes Running ]
-f4df8692e116 nifty_torvalds Created [ 331693bff40a thirsty_hawking Created ] [ 8e428daeb89e wizardly_golick Created ]
+POD ID NAME STATUS CREATED INFRA ID IDS NAMES STATUS
+00dfd6fa02c0 jolly_goldstine Running 31 hours ago ba465ab0a3a4 ba465ab0a3a4 loving_archimedes running
+f4df8692e116 nifty_torvalds Created 10 minutes ago 331693bff40a 331693bff40a,8e428daeb89e thirsty_hawking,wizardly_golick configured,configured
```
```
-$ podman pod ps --format "{{.ID}} {{.ContainerInfo}} {{.Cgroup}}" --ctr-names
-00dfd6fa02c0 [ loving_archimedes ] /libpod_parent
-f4df8692e116 [ thirsty_hawking ] [ wizardly_golick ] /libpod_parent
-```
-
-```
-$ podman pod ps --cgroup
-POD ID NAME STATUS NUMBER OF CONTAINERS CGROUP USE POD CGROUP
-00dfd6fa02c0 jolly_goldstine Running 1 /libpod_parent true
-f4df8692e116 nifty_torvalds Created 2 /libpod_parent true
+$ podman pod ps --format "{{.ID}} {{.ContainerNames}} {{.Cgroup}}"
+00dfd6fa02c0 loving_archimedes /libpod_parent
+f4df8692e116 thirsty_hawking,wizardly_golick /libpod_parent
```
```
$ podman pod ps --sort id --filter ctr-number=2
-POD ID NAME STATUS NUMBER OF CONTAINERS
-f4df8692e116 nifty_torvalds Created 2
+POD ID NAME STATUS CREATED INFRA ID # OF CONTAINERS
+f4df8692e116 nifty_torvalds Created 10 minutes ago 331693bff40a 2
```
```
$ podman pod ps --ctr-ids
-POD ID NAME STATUS CONTAINER INFO
-00dfd6fa02c0 jolly_goldstine Running [ ba465ab0a3a4 ]
-f4df8692e116 nifty_torvalds Created [ 331693bff40a ] [ 8e428daeb89e ]
+POD ID NAME STATUS CREATED INFRA ID IDS
+00dfd6fa02c0 jolly_goldstine Running 31 hours ago ba465ab0a3a4 ba465ab0a3a4
+f4df8692e116 nifty_torvalds Created 10 minutes ago 331693bff40a 331693bff40a,8e428daeb89e
```
```
$ podman pod ps --no-trunc --ctr-ids
-POD ID NAME STATUS CONTAINER INFO
-00dfd6fa02c0a2daaedfdf8fcecd06f22ad114d46d167d71777224735f701866 jolly_goldstine Running [ ba465ab0a3a4e15e3539a1e79c32d1213a02b0989371e274f98e0f1ae9de7050 ]
-f4df8692e116a3e6d1d62572644ed36ca475d933808cc3c93435c45aa139314b nifty_torvalds Created [ 331693bff40a0ef2f05a3aba73ce49e3243108911927fff04d1f7fc44dda8022 ] [ 8e428daeb89e69b71e7916a13accfb87d122889442b5c05c2d99cf94a3230e9d ]
+POD ID NAME STATUS CREATED INFRA ID IDS
+00dfd6fa02c0a2daaedfdf8fcecd06f22ad114d46d167d71777224735f701866 jolly_goldstine Running 31 hours ago ba465ab0a3a4e15e3539a1e79c32d1213a02b0989371e274f98e0f1ae9de7050 ba465ab0a3a4e15e3539a1e79c32d1213a02b0989371e274f98e0f1ae9de7050
+f4df8692e116a3e6d1d62572644ed36ca475d933808cc3c93435c45aa139314b nifty_torvalds Created 10 minutes ago 331693bff40a926b6d52b184e116afd15497610c378d5d4c42945dd6e33b75b0 331693bff40a926b6d52b184e116afd15497610c378d5d4c42945dd6e33b75b0,8e428daeb89e69b71e7916a13accfb87d122889442b5c05c2d99cf94a3230e9d
```
```
$ podman pod ps --ctr-names
-POD ID NAME STATUS CONTAINER INFO
-314f4da82d74 hi Created [ jovial_jackson ] [ hopeful_archimedes ] [ vibrant_ptolemy ] [ heuristic_jennings ] [ keen_raman ] [ hopeful_newton ] [ mystifying_bose ] [ silly_lalande ] [ serene_lichterman ] ...
+POD ID NAME STATUS CREATED INFRA ID NAMES
+314f4da82d74 hi Created 17 hours ago a9f2d2165675 jovial_jackson,hopeful_archimedes,vibrant_ptolemy,heuristic_jennings,keen_raman,hopeful_newton,mystifying_bose,silly_lalande,serene_lichterman ...
```
## pod ps
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 6027a14a5..1c3efa0c3 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -680,7 +680,7 @@ Valid _mode_ values are:
- **ns:**_path_: path to a network namespace to join;
- **private**: create a new namespace for the container (default)
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) to create a user network stack. This is the default for rootless containers. It is possible to specify these additional options:
- - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default is false.
+ - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`, which is added to `/etc/hosts` as `host.containers.internal` for your convenience). Default is false.
- **mtu=MTU**: Specify the MTU to use for this network. (Default is `65520`).
- **cidr=CIDR**: Specify ip range to use for this network. (Default is `10.0.2.0/24`).
- **enable_ipv6=true|false**: Enable IPv6. Default is false. (Required for `outbound_addr6`).
diff --git a/docs/tutorials/rootless_tutorial.md b/docs/tutorials/rootless_tutorial.md
index 18f60ea00..5d20f2cc0 100644
--- a/docs/tutorials/rootless_tutorial.md
+++ b/docs/tutorials/rootless_tutorial.md
@@ -13,31 +13,31 @@ The alternative OCI runtime support for cgroup V2 can also be turned on at the c
```
podman --runtime crun
```
-or for all commands by changing the value for the "Default OCI runtime" in the containers.conf file either at the system level or at the [user level](#user-configuration-files) from `runtime = "runc"` to `runtime = "crun"`.
+or for all commands by changing the value for the "Default OCI runtime" in the `containers.conf` file either at the system level or at the [user level](#user-configuration-files) from `runtime = "runc"` to `runtime = "crun"`.
## Administrator Actions
### Installing Podman
-For installing Podman, please see the [installation instructions](https://github.com/containers/podman/blob/master/install.md).
+For installing Podman, please see the [installation instructions](https://github.com/containers/podman/blob/main/install.md).
### Building Podman
-For building Podman, please see the [installation instructions](https://github.com/containers/podman/blob/master/install.md#building-from-scratch).
+For building Podman, please see the [installation instructions](https://github.com/containers/podman/blob/main/install.md#building-from-scratch).
-### Install slirp4netns
+### Install `slirp4netns`
-The [slirp4netns](https://github.com/rootless-containers/slirp4netns) package provides user-mode networking for unprivileged network namespaces and must be installed on the machine in order for Podman to run in a rootless environment. The package is available on most Linux distributions via their package distribution software such as yum, dnf, apt, zypper, etc. If the package is not available, you can build and install slirp4netns from [GitHub](https://github.com/rootless-containers/slirp4netns).
+The [slirp4netns](https://github.com/rootless-containers/slirp4netns) package provides user-mode networking for unprivileged network namespaces and must be installed on the machine in order for Podman to run in a rootless environment. The package is available on most Linux distributions via their package distribution software such as `yum`, `dnf`, `apt`, `zypper`, etc. If the package is not available, you can build and install `slirp4netns` from [GitHub](https://github.com/rootless-containers/slirp4netns).
-### Ensure fuse-overlayfs is installed
+### Ensure `fuse-overlayfs` is installed
-When using Podman in a rootless environment, it is recommended to use fuse-overlayfs rather than the VFS file system. For that you need the `fuse-overlayfs` executable available in `$PATH`.
+When using Podman in a rootless environment, it is recommended to use `fuse-overlayfs` rather than the VFS file system. For that you need the `fuse-overlayfs` executable available in `$PATH`.
Your distribution might already provide it in the `fuse-overlayfs` package, but be aware that you need at least version **0.7.6**. This especially needs to be checked on Ubuntu distributions as `fuse-overlayfs` is not generally installed by default and the 0.7.6 version is not available natively on Ubuntu releases prior to **20.04**.
-The fuse-overlayfs project is available from [GitHub](https://github.com/containers/fuse-overlayfs), and provides instructions for easily building a static `fuse-overlayfs` executable.
+The `fuse-overlayfs` project is available from [GitHub](https://github.com/containers/fuse-overlayfs), and provides instructions for easily building a static `fuse-overlayfs` executable.
-If Podman is used before fuse-overlayfs is installed, it may be necessary to adjust the `storage.conf` file (see "User Configuration Files" below) to change the `driver` option under `[storage]` to `"overlay"` and point the `mount_program` option in `[storage.options]` to the path of the `fuse-overlayfs` executable:
+If Podman is used before `fuse-overlayfs` is installed, it may be necessary to adjust the `storage.conf` file (see "User Configuration Files" below) to change the `driver` option under `[storage]` to `"overlay"` and point the `mount_program` option in `[storage.options]` to the path of the `fuse-overlayfs` executable:
```
[storage]
@@ -54,13 +54,13 @@ If Podman is used before fuse-overlayfs is installed, it may be necessary to adj
### Enable user namespaces (on RHEL7 machines)
-The number of user namespaces that are allowed on the system is specified in the file `/proc/sys/user/max_user_namespaces`. On most Linux platforms this is preset by default and no adjustment is necessary. However on RHEL7 machines a user with root privileges may need to set that to a reasonable value by using this command: `sysctl user.max_user_namespaces=15000`.
+The number of user namespaces that are allowed on the system is specified in the file `/proc/sys/user/max_user_namespaces`. On most Linux platforms this is preset by default and no adjustment is necessary. However, on RHEL7 machines, a user with root privileges may need to set that to a reasonable value by using this command: `sysctl user.max_user_namespaces=15000`.
-### /etc/subuid and /etc/subgid configuration
+### `/etc/subuid` and `/etc/subgid` configuration
-Rootless Podman requires the user running it to have a range of UIDs listed in /etc/subuid and /etc/subgid files. The `shadow-utils` or `newuid` package provides these files on different distributions and they must be installed on the system. These files will need someone with root privileges on the system to add or update the entries within them. The following is a summarization from the [How does rootless Podman work?](https://opensource.com/article/19/2/how-does-rootless-podman-work) article by Dan Walsh on [opensource.com](https://opensource.com)
+Rootless Podman requires the user running it to have a range of UIDs listed in the files `/etc/subuid` and `/etc/subgid`. The `shadow-utils` or `newuid` package provides these files on different distributions and they must be installed on the system. Root privileges are required to add or update entries within these files. The following is a summary from the [How does rootless Podman work?](https://opensource.com/article/19/2/how-does-rootless-podman-work) article by Dan Walsh on [opensource.com](https://opensource.com)
-Update the /etc/subuid and /etc/subgid with fields for each user that will be allowed to create containers that look like the following. Note that the values for each user must be unique and without any overlap. If there is an overlap, there is a potential for a user to use another’s namespace and they could corrupt it.
+For each user that will be allowed to create containers, update `/etc/subuid` and `/etc/subgid` for the user with fields that look like the following. Note that the values for each user must be unique. If there is overlap, there is a potential for a user to use another user's namespace and they could corrupt it.
```
cat /etc/subuid
@@ -68,17 +68,17 @@ johndoe:100000:65536
test:165536:65536
```
-The format of this file is USERNAME:UID:RANGE
+The format of this file is `USERNAME:UID:RANGE`
-* username as listed in /etc/passwd or getpwent.
-* The initial uid allocated for the user.
+* username as listed in `/etc/passwd` or in the output of [`getpwent`](https://man7.org/linux/man-pages/man3/getpwent.3.html).
+* The initial UID allocated for the user.
* The size of the range of UIDs allocated for the user.
-This means the user johndoe is allocated UIDS 100000-165535 as well as their standard UID in the /etc/passwd file. NOTE: this is not currently supported with network installs. These files must be available locally to the host machine. It is not possible to configure this with LDAP or Active Directory.
+This means the user `johndoe` is allocated UIDs 100000-165535 as well as their standard UID in the `/etc/passwd` file. NOTE: this is not currently supported with network installs; these files must be available locally to the host machine. It is not possible to configure this with LDAP or Active Directory.
-If you update either the /etc/subuid or the /etc/subgid file, you need to stop all the running containers owned by the user and kill the pause process that is running on the system for that user. This can be done automatically by using the [`podman system migrate`](https://github.com/containers/podman/blob/master/docs/podman-system-migrate.1.md) command which will stop all the containers for the user and will kill the pause process.
+If you update either `/etc/subuid` or `/etc/subgid`, you need to stop all the running containers owned by the user and kill the pause process that is running on the system for that user. This can be done automatically by using the [`podman system migrate`](https://github.com/containers/podman/blob/main/docs/source/markdown/podman-system-migrate.1.md) command which will stop all the containers for the user and will kill the pause process.
-Rather than updating the files directly, the usermod program can be used to assign UIDs and GIDs to a user.
+Rather than updating the files directly, the `usermod` program can be used to assign UIDs and GIDs to a user.
```
usermod --add-subuids 200000-201000 --add-subgids 200000-201000 johndoe
@@ -102,13 +102,13 @@ To make the change persist, the administrator will need to add a file with the `
The majority of the work necessary to run Podman in a rootless environment is on the shoulders of the machine’s administrator.
-Once the Administrator has completed the setup on the machine and then the configurations for the user in /etc/subuid and /etc/subgid, the user can just start using any Podman command that they wish.
+Once the Administrator has completed the setup on the machine and then the configurations for the user in `/etc/subuid` and `/etc/subgid`, the user can just start using any Podman command that they wish.
### User Configuration Files
The Podman configuration files for root reside in `/usr/share/containers` with overrides in `/etc/containers`. In the rootless environment they reside in `${XDG_CONFIG_HOME}/containers` (usually `~/.config/containers`) and are owned by each individual user.
-The three main configuration files are [containers.conf](https://github.com/containers/common/blob/master/docs/containers.conf.5.md), [storage.conf](https://github.com/containers/storage/blob/master/docs/containers-storage.conf.5.md) and [registries.conf](https://github.com/containers/image/blob/master/docs/containers-registries.conf.5.md). The user can modify these files as they wish.
+The three main configuration files are [containers.conf](https://github.com/containers/common/blob/main/docs/containers.conf.5.md), [storage.conf](https://github.com/containers/storage/blob/main/docs/containers-storage.conf.5.md) and [registries.conf](https://github.com/containers/image/blob/main/docs/containers-registries.conf.5.md). The user can modify these files as they wish.
#### containers.conf
Podman reads
@@ -123,7 +123,7 @@ For `storage.conf` the order is
1. `/etc/containers/storage.conf`
2. `$HOME/.config/containers/storage.conf`
-In rootless podman certain fields in `/etc/containers/storage.conf` are ignored. These fields are:
+In rootless Podman certain fields in `/etc/containers/storage.conf` are ignored. These fields are:
```
graphroot=""
container storage graph dir (default: "/var/lib/containers/storage")
@@ -133,7 +133,7 @@ runroot=""
container storage run dir (default: "/run/containers/storage")
Default directory to store all temporary writable content created by container storage programs.
```
-In rootless podman these fields default to
+In rootless Podman these fields default to
```
graphroot="$HOME/.local/share/containers/storage"
runroot="$XDG_RUNTIME_DIR/containers"
@@ -146,14 +146,14 @@ Registry configuration is read in by this order
2. `/etc/containers/registries.d/*`
3. `HOME/.config/containers/registries.conf`
-The files in the home directory should be used to configure rootless podman for personal needs. These files are not created by default. Users can copy the files from `/usr/share/containers` or `/etc/containers` and modify them.
+The files in the home directory should be used to configure rootless Podman for personal needs. These files are not created by default. Users can copy the files from `/usr/share/containers` or `/etc/containers` and modify them.
#### Authorization files
The default authorization file used by the `podman login` and `podman logout` commands reside in `${XDG_RUNTIME_DIR}/containers/auth.json`.
### Using volumes
-Rootless Podman is not, and will never be, root; it's not a setuid binary, and gains no privileges when it runs. Instead, Podman makes use of a user namespace to shift the UIDs and GIDs of a block of users it is given access to on the host (via the newuidmap and newgidmap executables) and your own user within the containers that Podman creates.
+Rootless Podman is not, and will never be, root; it's not a `setuid` binary, and gains no privileges when it runs. Instead, Podman makes use of a user namespace to shift the UIDs and GIDs of a block of users it is given access to on the host (via the `newuidmap` and `newgidmap` executables) and your own user within the containers that Podman creates.
If your container runs with the root user, then `root` in the container is actually your user on the host. UID/GID 1 is the first UID/GID specified in your user's mapping in `/etc/subuid` and `/etc/subgid`, etc. If you mount a directory from the host into a container as a rootless user, and create a file in that directory as root in the container, you'll see it's actually owned by your user on the host.
@@ -193,6 +193,6 @@ Other considerations in regards to volumes:
## More information
-If you are still experiencing problems running Podman in a rootless environment, please refer to the [Shortcomings of Rootless Podman](https://github.com/containers/podman/blob/master/rootless.md) page which lists known issues and solutions to known issues in this environment.
+If you are still experiencing problems running Podman in a rootless environment, please refer to the [Shortcomings of Rootless Podman](https://github.com/containers/podman/blob/main/rootless.md) page which lists known issues and solutions to known issues in this environment.
-For more information on Podman and its subcommands, checkout the asciiart demos on the [README.md](../../README.md#commands) page or the [podman.io](https://podman.io) web site.
+For more information on Podman and its subcommands, follow the links on the main [README.md](../../README.md#podman-information-for-developers) page or the [podman.io](https://podman.io) web site.
diff --git a/go.mod b/go.mod
index 7d007afa6..2dd760cee 100644
--- a/go.mod
+++ b/go.mod
@@ -17,7 +17,7 @@ require (
github.com/containers/image/v5 v5.13.2
github.com/containers/ocicrypt v1.1.2
github.com/containers/psgo v1.5.2
- github.com/containers/storage v1.32.5
+ github.com/containers/storage v1.32.6
github.com/coreos/go-systemd/v22 v22.3.2
github.com/coreos/stream-metadata-go v0.0.0-20210225230131-70edb9eb47b3
github.com/cri-o/ocicni v0.2.1-0.20210621164014-d0acc7862283
@@ -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
@@ -43,7 +43,7 @@ require (
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635
github.com/mrunalp/fileutils v0.5.0
github.com/onsi/ginkgo v1.16.4
- github.com/onsi/gomega v1.13.0
+ github.com/onsi/gomega v1.14.0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
github.com/opencontainers/runc v1.0.0
diff --git a/go.sum b/go.sum
index daec65293..fb0690b39 100644
--- a/go.sum
+++ b/go.sum
@@ -73,8 +73,9 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
-github.com/Microsoft/hcsshim v0.8.17 h1:yFHH5bghP9ij5Y34PPaMOE8g//oXZ0uJQeMENVo2zcI=
github.com/Microsoft/hcsshim v0.8.17/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
+github.com/Microsoft/hcsshim v0.8.20 h1:ZTwcx3NS8n07kPf/JZ1qwU6vnjhVPMUWlXBF8r9UxrE=
+github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@@ -257,8 +258,9 @@ github.com/containers/psgo v1.5.2 h1:3aoozst/GIwsrr/5jnFy3FrJay98uujPCu9lTuSZ/Cw
github.com/containers/psgo v1.5.2/go.mod h1:2ubh0SsreMZjSXW1Hif58JrEcFudQyIy9EzPUWfawVU=
github.com/containers/storage v1.23.5/go.mod h1:ha26Q6ngehFNhf3AWoXldvAvwI4jFe3ETQAf/CeZPyM=
github.com/containers/storage v1.32.2/go.mod h1:YIBxxjfXZTi04Ah49sh1uSGfmT1V89+I5i3deRobzQo=
-github.com/containers/storage v1.32.5 h1:DXgmyA+oOs7YAzKkEqgC5O8l2UuDGJcwEFbdt49qiak=
github.com/containers/storage v1.32.5/go.mod h1:8/DVVDqniaUlUV0D0q7cEnXK6Bs2uU3FPqNZVPumwEs=
+github.com/containers/storage v1.32.6 h1:NqdFRewXO/PYPjgCAScoigZc5QUA21yapSEj6kqD8cw=
+github.com/containers/storage v1.32.6/go.mod h1:mdB+b89p+jU8zpzLTVXA0gWMmIo0WrkfGMh1R8O2IQw=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
@@ -480,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=
@@ -705,8 +708,9 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
-github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
+github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI=
+github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 850af235f..b69ad4105 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -2490,6 +2490,11 @@ func (c *Container) fixVolumePermissions(v *ContainerNamedVolume) error {
// https://github.com/containers/podman/issues/10188
st, err := os.Lstat(filepath.Join(c.state.Mountpoint, v.Dest))
if err == nil {
+ if stat, ok := st.Sys().(*syscall.Stat_t); ok {
+ if err := os.Lchown(mountPoint, int(stat.Uid), int(stat.Gid)); err != nil {
+ return err
+ }
+ }
if err := os.Chmod(mountPoint, st.Mode()|0111); err != nil {
return err
}
diff --git a/libpod/container_log.go b/libpod/container_log.go
index 43b3f7736..743c9c61b 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -56,7 +56,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
for _, nll := range tailLog {
nll.CID = c.ID()
nll.CName = c.Name()
- if nll.Since(options.Since) {
+ if nll.Since(options.Since) && nll.Until(options.Until) {
logChannel <- nll
}
}
@@ -88,7 +88,7 @@ func (c *Container) readFromLogFile(ctx context.Context, options *logs.LogOption
}
nll.CID = c.ID()
nll.CName = c.Name()
- if nll.Since(options.Since) {
+ if nll.Since(options.Since) && nll.Until(options.Until) {
logChannel <- nll
}
}
diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go
index 892ee34e3..9f9dd3b0d 100644
--- a/libpod/container_log_linux.go
+++ b/libpod/container_log_linux.go
@@ -97,6 +97,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
}
}()
+ beforeTimeStamp := true
afterTimeStamp := false // needed for options.Since
tailQueue := []*logs.LogLine{} // needed for options.Tail
doTail := options.Tail > 0
@@ -156,6 +157,13 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption
}
afterTimeStamp = true
}
+ if beforeTimeStamp {
+ entryTime := time.Unix(0, int64(entry.RealtimeTimestamp)*int64(time.Microsecond))
+ if entryTime.Before(options.Until) || !options.Until.IsZero() {
+ continue
+ }
+ beforeTimeStamp = false
+ }
// If we're reading an event and the container exited/died,
// then we're done and can return.
diff --git a/libpod/logs/log.go b/libpod/logs/log.go
index 308053b47..1a0223edc 100644
--- a/libpod/logs/log.go
+++ b/libpod/logs/log.go
@@ -34,6 +34,7 @@ type LogOptions struct {
Details bool
Follow bool
Since time.Time
+ Until time.Time
Tail int64
Timestamps bool
Multi bool
@@ -184,7 +185,12 @@ func (l *LogLine) String(options *LogOptions) string {
// Since returns a bool as to whether a log line occurred after a given time
func (l *LogLine) Since(since time.Time) bool {
- return l.Time.After(since)
+ return l.Time.After(since) || since.IsZero()
+}
+
+// Until returns a bool as to whether a log line occurred before a given time
+func (l *LogLine) Until(until time.Time) bool {
+ return l.Time.Before(until) || until.IsZero()
}
// NewLogLine creates a logLine struct from a container log string
diff --git a/libpod/runtime.go b/libpod/runtime.go
index d31d00ae4..30659a3d4 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -946,9 +946,12 @@ func (r *Runtime) StorageConfig() storage.StoreOptions {
return r.storageConfig
}
-// GetStore returns the runtime stores
-func (r *Runtime) GetStore() storage.Store {
- return r.store
+// RunRoot retrieves the current c/storage temporary directory in use by Libpod.
+func (r *Runtime) RunRoot() string {
+ if r.store == nil {
+ return ""
+ }
+ return r.store.RunRoot()
}
// GetName retrieves the name associated with a given full ID.
diff --git a/pkg/api/handlers/compat/containers_logs.go b/pkg/api/handlers/compat/containers_logs.go
index cb4dee4d2..656e2c627 100644
--- a/pkg/api/handlers/compat/containers_logs.go
+++ b/pkg/api/handlers/compat/containers_logs.go
@@ -72,11 +72,12 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
var until time.Time
if _, found := r.URL.Query()["until"]; found {
- // FIXME: until != since but the logs backend does not yet support until.
- since, err = util.ParseInputTime(query.Until)
- if err != nil {
- utils.BadRequest(w, "until", query.Until, err)
- return
+ if query.Until != "0" {
+ until, err = util.ParseInputTime(query.Until)
+ if err != nil {
+ utils.BadRequest(w, "until", query.Until, err)
+ return
+ }
}
}
@@ -84,6 +85,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
Details: true,
Follow: query.Follow,
Since: since,
+ Until: until,
Tail: tail,
Timestamps: query.Timestamps,
}
@@ -119,7 +121,7 @@ func LogsFromContainer(w http.ResponseWriter, r *http.Request) {
for line := range logChannel {
if _, found := r.URL.Query()["until"]; found {
- if line.Time.After(until) {
+ if line.Time.After(until) && !until.IsZero() {
break
}
}
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index ee157cb56..59f948567 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -232,27 +232,32 @@ func ImageDataToImageInspect(ctx context.Context, l *libimage.Image) (*ImageInsp
Name: info.GraphDriver.Name,
Data: info.GraphDriver.Data,
}
+ // Add in basic ContainerConfig to satisfy docker-compose
+ cc := new(dockerContainer.Config)
+ cc.Hostname = info.ID[0:11] // short ID is the hostname
+ cc.Volumes = info.Config.Volumes
+
dockerImageInspect := docker.ImageInspect{
- Architecture: info.Architecture,
- Author: info.Author,
- Comment: info.Comment,
- Config: &config,
- Created: l.Created().Format(time.RFC3339Nano),
- DockerVersion: info.Version,
- GraphDriver: graphDriver,
- ID: "sha256:" + l.ID(),
- Metadata: docker.ImageMetadata{},
- Os: info.Os,
- OsVersion: info.Version,
- Parent: info.Parent,
- RepoDigests: info.RepoDigests,
- RepoTags: info.RepoTags,
- RootFS: rootfs,
- Size: info.Size,
- Variant: "",
- VirtualSize: info.VirtualSize,
+ Architecture: info.Architecture,
+ Author: info.Author,
+ Comment: info.Comment,
+ Config: &config,
+ ContainerConfig: cc,
+ Created: l.Created().Format(time.RFC3339Nano),
+ DockerVersion: info.Version,
+ GraphDriver: graphDriver,
+ ID: "sha256:" + l.ID(),
+ Metadata: docker.ImageMetadata{},
+ Os: info.Os,
+ OsVersion: info.Version,
+ Parent: info.Parent,
+ RepoDigests: info.RepoDigests,
+ RepoTags: info.RepoTags,
+ RootFS: rootfs,
+ Size: info.Size,
+ Variant: "",
+ VirtualSize: info.VirtualSize,
}
- // TODO: consider filling the container config.
return &ImageInspect{dockerImageInspect}, nil
}
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index 95d9d4df7..3fbc41f99 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -301,6 +301,8 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
tarContent := []string{options.ContextDirectory}
newContainerFiles := []string{}
+
+ dontexcludes := []string{"!Dockerfile", "!Containerfile"}
for _, c := range containerFiles {
if c == "/dev/stdin" {
content, err := ioutil.ReadAll(os.Stdin)
@@ -328,6 +330,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
// Do NOT add to tarfile
if strings.HasPrefix(containerfile, contextDir+string(filepath.Separator)) {
containerfile = strings.TrimPrefix(containerfile, contextDir+string(filepath.Separator))
+ dontexcludes = append(dontexcludes, "!"+containerfile)
} else {
// If Containerfile does not exists assume it is in context directory, do Not add to tarfile
if _, err := os.Lstat(containerfile); err != nil {
@@ -349,8 +352,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
params.Set("dockerfile", string(cFileJSON))
}
-
- tarfile, err := nTar(excludes, tarContent...)
+ tarfile, err := nTar(append(excludes, dontexcludes...), tarContent...)
if err != nil {
logrus.Errorf("cannot tar container entries %v error: %v", tarContent, err)
return nil, err
diff --git a/pkg/systemd/generate/containers.go b/pkg/systemd/generate/containers.go
index 0e6e1b4df..083520316 100644
--- a/pkg/systemd/generate/containers.go
+++ b/pkg/systemd/generate/containers.go
@@ -160,16 +160,11 @@ func generateContainerInfo(ctr *libpod.Container, options entities.GenerateSyste
nameOrID, serviceName := containerServiceName(ctr, options)
- store := ctr.Runtime().GetStore()
- if store == nil {
- return nil, errors.Errorf("could not determine storage store for container")
- }
-
var runRoot string
if options.New {
runRoot = "%t/containers"
} else {
- runRoot = store.RunRoot()
+ runRoot = ctr.Runtime().RunRoot()
if runRoot == "" {
return nil, errors.Errorf("could not lookup container's runroot: got empty string")
}
diff --git a/test/apiv2/python/rest_api/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py
index 2fab4aeb9..f252bd401 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_container.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py
@@ -1,5 +1,6 @@
import random
import unittest
+import json
import requests
from dateutil.parser import parse
@@ -97,6 +98,18 @@ class ContainerTestCase(APITestCase):
def test_logs(self):
r = requests.get(self.uri(self.resolve_container("/containers/{}/logs?stdout=true")))
self.assertEqual(r.status_code, 200, r.text)
+ r = requests.post(
+ self.podman_url + "/v1.40/containers/create?name=topcontainer",
+ json={"Cmd": ["top", "ls"], "Image": "alpine:latest"},
+ )
+ self.assertEqual(r.status_code, 201, r.text)
+ payload = r.json()
+ container_id = payload["Id"]
+ self.assertIsNotNone(container_id)
+ r = requests.get(self.podman_url + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=0")
+ self.assertEqual(r.status_code, 200, r.text)
+ r = requests.get(self.podman_url + f"/v1.40/containers/{payload['Id']}/logs?follow=false&stdout=true&until=1")
+ self.assertEqual(r.status_code, 200, r.text)
def test_commit(self):
r = requests.post(self.uri(self.resolve_container("/commit?container={}")))
diff --git a/test/compose/uptwice/Dockerfile b/test/compose/uptwice/Dockerfile
new file mode 100644
index 000000000..b993af04d
--- /dev/null
+++ b/test/compose/uptwice/Dockerfile
@@ -0,0 +1,2 @@
+FROM alpine
+WORKDIR /app
diff --git a/test/compose/uptwice/docker-compose.yml b/test/compose/uptwice/docker-compose.yml
new file mode 100644
index 000000000..e06f9e554
--- /dev/null
+++ b/test/compose/uptwice/docker-compose.yml
@@ -0,0 +1,5 @@
+version: '3'
+services:
+ app:
+ build: .
+ command: sleep 10002
diff --git a/test/compose/uptwice/tests.sh b/test/compose/uptwice/tests.sh
new file mode 100644
index 000000000..291694d83
--- /dev/null
+++ b/test/compose/uptwice/tests.sh
@@ -0,0 +1,4 @@
+# -*- bash -*-
+
+sed -i -e 's/10001/10002/' docker-compose.yml
+docker-compose up -d
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/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index c5c0827bc..28477d886 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -370,4 +370,12 @@ var _ = Describe("Podman ps", func() {
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(ContainSubstring("value1"))
})
+
+ It("podman pod ps headers", func() {
+ session := podmanTest.Podman([]string{"pod", "ps", "--ctr-ids", "--ctr-names", "--ctr-status", "--ns"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(MatchRegexp(`^POD ID\s+NAME\s+STATUS\s+CREATED\s+INFRA ID\s+IDS\s+NAMES\s+STATUS\s+CGROUP\s+NAMESPACES$`))
+ })
+
})
diff --git a/test/python/docker/compat/test_containers.py b/test/python/docker/compat/test_containers.py
index 511ab1451..38ac5b59f 100644
--- a/test/python/docker/compat/test_containers.py
+++ b/test/python/docker/compat/test_containers.py
@@ -7,6 +7,7 @@ from typing import IO, Optional
from docker import DockerClient, errors
from docker.models.containers import Container
+from docker.models.images import Image
from test.python.docker import Podman
from test.python.docker.compat import common, constant
@@ -237,3 +238,16 @@ class TestContainers(unittest.TestCase):
if ctr is not None:
ctr.stop()
ctr.remove()
+
+ def test_mount_preexisting_dir(self):
+ dockerfile = (B'FROM quay.io/libpod/alpine:latest\n'
+ B'USER root\n'
+ B'RUN mkdir -p /workspace\n'
+ B'RUN chown 1042:1043 /workspace')
+ img: Image
+ img, out = self.client.images.build(fileobj=io.BytesIO(dockerfile))
+ ctr: Container = self.client.containers.create(image=img.id, detach=True, command="top",
+ volumes=["test_mount_preexisting_dir_vol:/workspace"])
+ ctr.start()
+ ret, out = ctr.exec_run(["stat", "-c", "%u:%g", "/workspace"])
+ self.assertTrue(out.startswith(b'1042:1043'), "assert correct uid/gid")
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index c45a661fe..7046625c6 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -509,6 +509,40 @@ EOF
done
}
+# Regression test for #9867
+# Make sure that if you exclude everything in context dir, that
+# the Containerfile/Dockerfile in the context dir are used
+@test "podman build with ignore '*'" {
+ local tmpdir=$PODMAN_TMPDIR/build-test-$(random_string 10)
+ mkdir -p $tmpdir
+
+ cat >$tmpdir/Containerfile <<EOF
+FROM scratch
+EOF
+
+cat >$tmpdir/.dockerignore <<EOF
+*
+EOF
+
+ run_podman build -t build_test $tmpdir
+
+ # Rename Containerfile to Dockerfile
+ mv $tmpdir/Containerfile $tmpdir/Dockerfile
+
+ run_podman build -t build_test $tmpdir
+
+ # Rename Dockerfile to foofile
+ mv $tmpdir/Dockerfile $tmpdir/foofile
+
+ run_podman 125 build -t build_test $tmpdir
+ is "$output" ".*Dockerfile: no such file or directory"
+
+ run_podman build -t build_test -f $tmpdir/foofile $tmpdir
+
+ # Clean up
+ run_podman rmi -f build_test
+}
+
@test "podman build - stdin test" {
# Random workdir, and random string to verify build output
workdir=/$(random_string 10)
diff --git a/vendor/github.com/Microsoft/hcsshim/errors.go b/vendor/github.com/Microsoft/hcsshim/errors.go
index 794308673..f367022e7 100644
--- a/vendor/github.com/Microsoft/hcsshim/errors.go
+++ b/vendor/github.com/Microsoft/hcsshim/errors.go
@@ -59,7 +59,7 @@ var (
// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
ErrVmcomputeOperationInvalidState = hcs.ErrVmcomputeOperationInvalidState
- // ErrProcNotFound is an error encountered when the the process cannot be found
+ // ErrProcNotFound is an error encountered when a procedure look up fails.
ErrProcNotFound = hcs.ErrProcNotFound
// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
@@ -159,7 +159,7 @@ func (e *ProcessError) Error() string {
// IsNotExist checks if an error is caused by the Container or Process not existing.
// Note: Currently, ErrElementNotFound can mean that a Process has either
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
-// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
+// will currently return true when the error is ErrElementNotFound.
func IsNotExist(err error) bool {
if _, ok := err.(EndpointNotFoundError); ok {
return true
@@ -192,7 +192,7 @@ func IsTimeout(err error) bool {
// a Container or Process being already stopped.
// Note: Currently, ErrElementNotFound can mean that a Process has either
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
-// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
+// will currently return true when the error is ErrElementNotFound.
func IsAlreadyStopped(err error) bool {
return hcs.IsAlreadyStopped(getInnerError(err))
}
diff --git a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
index 7696e4b48..644f0ab71 100644
--- a/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
+++ b/vendor/github.com/Microsoft/hcsshim/internal/hcs/errors.go
@@ -60,7 +60,7 @@ var (
// ErrVmcomputeOperationInvalidState is an error encountered when the compute system is not in a valid state for the requested operation
ErrVmcomputeOperationInvalidState = syscall.Errno(0xc0370105)
- // ErrProcNotFound is an error encountered when the the process cannot be found
+ // ErrProcNotFound is an error encountered when a procedure look up fails.
ErrProcNotFound = syscall.Errno(0x7f)
// ErrVmcomputeOperationAccessIsDenied is an error which can be encountered when enumerating compute systems in RS1/RS2
@@ -242,12 +242,11 @@ func makeProcessError(process *Process, op string, err error, events []ErrorEven
// IsNotExist checks if an error is caused by the Container or Process not existing.
// Note: Currently, ErrElementNotFound can mean that a Process has either
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
-// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
+// will currently return true when the error is ErrElementNotFound.
func IsNotExist(err error) bool {
err = getInnerError(err)
return err == ErrComputeSystemDoesNotExist ||
- err == ErrElementNotFound ||
- err == ErrProcNotFound
+ err == ErrElementNotFound
}
// IsAlreadyClosed checks if an error is caused by the Container or Process having been
@@ -278,12 +277,11 @@ func IsTimeout(err error) bool {
// a Container or Process being already stopped.
// Note: Currently, ErrElementNotFound can mean that a Process has either
// already exited, or does not exist. Both IsAlreadyStopped and IsNotExist
-// will currently return true when the error is ErrElementNotFound or ErrProcNotFound.
+// will currently return true when the error is ErrElementNotFound.
func IsAlreadyStopped(err error) bool {
err = getInnerError(err)
return err == ErrVmcomputeAlreadyStopped ||
- err == ErrElementNotFound ||
- err == ErrProcNotFound
+ err == ErrElementNotFound
}
// IsNotSupported returns a boolean indicating whether the error is caused by
diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION
index 949ff3202..5d245052c 100644
--- a/vendor/github.com/containers/storage/VERSION
+++ b/vendor/github.com/containers/storage/VERSION
@@ -1 +1 @@
-1.32.5
+1.32.6
diff --git a/vendor/github.com/containers/storage/go.mod b/vendor/github.com/containers/storage/go.mod
index 93b6b337c..d46000ace 100644
--- a/vendor/github.com/containers/storage/go.mod
+++ b/vendor/github.com/containers/storage/go.mod
@@ -5,7 +5,7 @@ module github.com/containers/storage
require (
github.com/BurntSushi/toml v0.3.1
github.com/Microsoft/go-winio v0.5.0
- github.com/Microsoft/hcsshim v0.8.17
+ github.com/Microsoft/hcsshim v0.8.20
github.com/docker/go-units v0.4.0
github.com/google/go-intervals v0.0.2
github.com/hashicorp/go-multierror v1.1.1
diff --git a/vendor/github.com/containers/storage/go.sum b/vendor/github.com/containers/storage/go.sum
index e826328ef..081da00e4 100644
--- a/vendor/github.com/containers/storage/go.sum
+++ b/vendor/github.com/containers/storage/go.sum
@@ -54,8 +54,8 @@ github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg3
github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg=
github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00=
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
-github.com/Microsoft/hcsshim v0.8.17 h1:yFHH5bghP9ij5Y34PPaMOE8g//oXZ0uJQeMENVo2zcI=
-github.com/Microsoft/hcsshim v0.8.17/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
+github.com/Microsoft/hcsshim v0.8.20 h1:ZTwcx3NS8n07kPf/JZ1qwU6vnjhVPMUWlXBF8r9UxrE=
+github.com/Microsoft/hcsshim v0.8.20/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
diff --git a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go
index b3998fb35..5be98165e 100644
--- a/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go
+++ b/vendor/github.com/containers/storage/pkg/fileutils/fileutils.go
@@ -38,7 +38,7 @@ func NewPatternMatcher(patterns []string) (*PatternMatcher, error) {
return nil, errors.New("illegal exclusion pattern: \"!\"")
}
newp.exclusion = true
- p = p[1:]
+ p = strings.TrimPrefix(filepath.Clean(p[1:]), "/")
pm.exclusions = true
}
// Do some syntax checking on the pattern.
diff --git a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
index f0e46b6b6..b224e7b5c 100644
--- a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
+++ b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go
@@ -5,6 +5,7 @@ package lockfile
import (
"fmt"
"os"
+ "path/filepath"
"sync"
"time"
@@ -33,11 +34,30 @@ type lockfile struct {
// descriptor. Note that the path is opened read-only when ro is set. If ro
// is unset, openLock will open the path read-write and create the file if
// necessary.
-func openLock(path string, ro bool) (int, error) {
+func openLock(path string, ro bool) (fd int, err error) {
if ro {
- return unix.Open(path, os.O_RDONLY|unix.O_CLOEXEC, 0)
+ fd, err = unix.Open(path, os.O_RDONLY|unix.O_CLOEXEC, 0)
+ } else {
+ fd, err = unix.Open(path,
+ os.O_RDWR|unix.O_CLOEXEC|os.O_CREATE,
+ unix.S_IRUSR|unix.S_IWUSR|unix.S_IRGRP|unix.S_IROTH,
+ )
+ }
+
+ if err == nil {
+ return
+ }
+
+ // the directory of the lockfile seems to be removed, try to create it
+ if os.IsNotExist(err) {
+ if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil {
+ return fd, errors.Wrap(err, "creating locker directory")
+ }
+
+ return openLock(path, ro)
}
- return unix.Open(path, os.O_RDWR|unix.O_CLOEXEC|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR|unix.S_IRGRP|unix.S_IROTH)
+
+ return
}
// createLockerForPath returns a Locker object, possibly (depending on the platform)
diff --git a/vendor/github.com/containers/storage/types/options.go b/vendor/github.com/containers/storage/types/options.go
index c0e3ea637..f9bf7e6b6 100644
--- a/vendor/github.com/containers/storage/types/options.go
+++ b/vendor/github.com/containers/storage/types/options.go
@@ -2,7 +2,6 @@ package types
import (
"fmt"
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -272,21 +271,21 @@ func ReloadConfigurationFileIfNeeded(configFile string, storeOptions *StoreOptio
// ReloadConfigurationFile parses the specified configuration file and overrides
// the configuration in storeOptions.
func ReloadConfigurationFile(configFile string, storeOptions *StoreOptions) {
- data, err := ioutil.ReadFile(configFile)
- if err != nil {
+ config := new(tomlConfig)
+
+ meta, err := toml.DecodeFile(configFile, &config)
+ if err == nil {
+ keys := meta.Undecoded()
+ if len(keys) > 0 {
+ logrus.Warningf("Failed to decode the keys %q from %q.", keys, configFile)
+ }
+ } else {
if !os.IsNotExist(err) {
fmt.Printf("Failed to read %s %v\n", configFile, err.Error())
return
}
}
- config := new(tomlConfig)
-
- if _, err := toml.Decode(string(data), config); err != nil {
- fmt.Printf("Failed to parse %s %v\n", configFile, err.Error())
- return
- }
-
// Clear storeOptions of previos settings
*storeOptions = StoreOptions{}
if config.Storage.Driver != "" {
diff --git a/vendor/github.com/containers/storage/types/storage_broken.conf b/vendor/github.com/containers/storage/types/storage_broken.conf
new file mode 100644
index 000000000..3bca1d978
--- /dev/null
+++ b/vendor/github.com/containers/storage/types/storage_broken.conf
@@ -0,0 +1,18 @@
+# This file is is a TEST configuration file for all tools
+# that use the containers/storage library.
+# See man 5 containers-storage.conf for more information
+# The "container storage" table contains all of the server options.
+foo = "bar"
+
+[storage]
+
+# Default Storage Driver
+driver = ""
+
+# Temporary storage location
+runroot = "/run/containers/test"
+
+[storage.options]
+# Primary Read/Write location of container storage
+graphroot = "/var/lib/containers/storage"
+
diff --git a/vendor/github.com/containers/storage/types/utils.go b/vendor/github.com/containers/storage/types/utils.go
index 4d62b151a..03ddd5ad9 100644
--- a/vendor/github.com/containers/storage/types/utils.go
+++ b/vendor/github.com/containers/storage/types/utils.go
@@ -2,7 +2,6 @@ package types
import (
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -75,12 +74,9 @@ func getRootlessRuntimeDirIsolated(env rootlessRuntimeDirEnvironment) (string, e
return runtimeDir, nil
}
- initCommand, err := ioutil.ReadFile(env.getProcCommandFile())
- if err != nil || string(initCommand) == "systemd" {
- runUserDir := env.getRunUserDir()
- if isRootlessRuntimeDirOwner(runUserDir, env) {
- return runUserDir, nil
- }
+ runUserDir := env.getRunUserDir()
+ if isRootlessRuntimeDirOwner(runUserDir, env) {
+ return runUserDir, nil
}
tmpPerUserDir := env.getTmpPerUserDir()
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/github.com/onsi/gomega/CHANGELOG.md b/vendor/github.com/onsi/gomega/CHANGELOG.md
index 4783c0d43..f2181a8cc 100644
--- a/vendor/github.com/onsi/gomega/CHANGELOG.md
+++ b/vendor/github.com/onsi/gomega/CHANGELOG.md
@@ -1,3 +1,20 @@
+## 1.14.0
+
+### Features
+- gmeasure.SamplingConfig now suppers a MinSamplingInterval [e94dbca]
+- Eventually and Consistently support functions that make assertions [2f04e6e]
+ - Eventually and Consistently now allow their passed-in functions to make assertions.
+ These assertions must pass or the function is considered to have failed and is retried.
+ - Eventually and Consistently can now take functions with no return values. These implicitly return nil
+ if they contain no failed assertion. Otherwise they return an error wrapping the first assertion failure. This allows
+ these functions to be used with the Succeed() matcher.
+ - Introduce InterceptGomegaFailure - an analogue to InterceptGomegaFailures - that captures the first assertion failure
+ and halts execution in its passed-in callback.
+
+### Fixes
+- Call Verify GHTTPWithGomega receiver funcs (#454) [496e6fd]
+- Build a binary with an expected name (#446) [7356360]
+
## 1.13.0
### Features
diff --git a/vendor/github.com/onsi/gomega/README.md b/vendor/github.com/onsi/gomega/README.md
index 76aa6b558..d45a8c4e5 100644
--- a/vendor/github.com/onsi/gomega/README.md
+++ b/vendor/github.com/onsi/gomega/README.md
@@ -1,6 +1,6 @@
![Gomega: Ginkgo's Preferred Matcher Library](http://onsi.github.io/gomega/images/gomega.png)
-[![Build Status](https://travis-ci.org/onsi/gomega.svg?branch=master)](https://travis-ci.org/onsi/gomega)
+[![test](https://github.com/onsi/gomega/actions/workflows/test.yml/badge.svg)](https://github.com/onsi/gomega/actions/workflows/test.yml)
Jump straight to the [docs](http://onsi.github.io/gomega/) to learn about Gomega, including a list of [all available matchers](http://onsi.github.io/gomega/#provided-matchers).
diff --git a/vendor/github.com/onsi/gomega/gexec/build.go b/vendor/github.com/onsi/gomega/gexec/build.go
index c7aba62b7..576fc8ee4 100644
--- a/vendor/github.com/onsi/gomega/gexec/build.go
+++ b/vendor/github.com/onsi/gomega/gexec/build.go
@@ -3,8 +3,6 @@
package gexec
import (
- "crypto/md5"
- "encoding/hex"
"errors"
"fmt"
"go/build"
@@ -197,9 +195,7 @@ func newExecutablePath(gopath, packagePath string, suffixes ...string) (string,
return "", errors.New("$GOPATH not provided when building " + packagePath)
}
- hash := md5.Sum([]byte(packagePath))
- filename := fmt.Sprintf("%s-%x%s", path.Base(packagePath), hex.EncodeToString(hash[:]), strings.Join(suffixes, ""))
- executable := filepath.Join(tmpDir, filename)
+ executable := filepath.Join(tmpDir, path.Base(packagePath))
if runtime.GOOS == "windows" {
executable += ".exe"
diff --git a/vendor/github.com/onsi/gomega/go.mod b/vendor/github.com/onsi/gomega/go.mod
index f74d9ea10..62b8f396c 100644
--- a/vendor/github.com/onsi/gomega/go.mod
+++ b/vendor/github.com/onsi/gomega/go.mod
@@ -4,7 +4,7 @@ go 1.14
require (
github.com/golang/protobuf v1.5.2
- github.com/onsi/ginkgo v1.16.2
+ github.com/onsi/ginkgo v1.16.4
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781
gopkg.in/yaml.v2 v2.4.0
)
diff --git a/vendor/github.com/onsi/gomega/go.sum b/vendor/github.com/onsi/gomega/go.sum
index 1ae731a5c..177d5e876 100644
--- a/vendor/github.com/onsi/gomega/go.sum
+++ b/vendor/github.com/onsi/gomega/go.sum
@@ -3,6 +3,7 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
@@ -25,8 +26,8 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.16.2 h1:HFB2fbVIlhIfCfOW81bZFbiC/RvnpXSdhbF2/DJr134=
-github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
+github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -66,6 +67,7 @@ golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e h1:4nW4NLDYnU28ojHaHO8OVxFHk/aQ33U01a9cjED+pzE=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/vendor/github.com/onsi/gomega/gomega_dsl.go b/vendor/github.com/onsi/gomega/gomega_dsl.go
index a05b34b27..67f6e45c1 100644
--- a/vendor/github.com/onsi/gomega/gomega_dsl.go
+++ b/vendor/github.com/onsi/gomega/gomega_dsl.go
@@ -14,6 +14,7 @@ Gomega is MIT-Licensed
package gomega
import (
+ "errors"
"fmt"
"reflect"
"time"
@@ -24,7 +25,7 @@ import (
"github.com/onsi/gomega/types"
)
-const GOMEGA_VERSION = "1.13.0"
+const GOMEGA_VERSION = "1.14.0"
const nilFailHandlerPanic = `You are trying to make an assertion, but Gomega's fail handler is nil.
If you're using Ginkgo then you probably forgot to put your assertion in an It().
@@ -91,10 +92,8 @@ func RegisterTestingT(t types.GomegaTestingT) {
// InterceptGomegaFailures runs a given callback and returns an array of
// failure messages generated by any Gomega assertions within the callback.
-//
-// This is accomplished by temporarily replacing the *global* fail handler
-// with a fail handler that simply annotates failures. The original fail handler
-// is reset when InterceptGomegaFailures returns.
+// Exeuction continues after the first failure allowing users to collect all failures
+// in the callback.
//
// This is most useful when testing custom matchers, but can also be used to check
// on a value using a Gomega assertion without causing a test failure.
@@ -104,11 +103,39 @@ func InterceptGomegaFailures(f func()) []string {
RegisterFailHandler(func(message string, callerSkip ...int) {
failures = append(failures, message)
})
+ defer func() {
+ RegisterFailHandler(originalHandler)
+ }()
f()
- RegisterFailHandler(originalHandler)
return failures
}
+// InterceptGomegaFailure runs a given callback and returns the first
+// failure message generated by any Gomega assertions within the callback, wrapped in an error.
+//
+// The callback ceases execution as soon as the first failed assertion occurs, however Gomega
+// does not register a failure with the FailHandler registered via RegisterFailHandler - it is up
+// to the user to decide what to do with the returned error
+func InterceptGomegaFailure(f func()) (err error) {
+ originalHandler := globalFailWrapper.Fail
+ RegisterFailHandler(func(message string, callerSkip ...int) {
+ err = errors.New(message)
+ panic("stop execution")
+ })
+
+ defer func() {
+ RegisterFailHandler(originalHandler)
+ if e := recover(); e != nil {
+ if err == nil {
+ panic(e)
+ }
+ }
+ }()
+
+ f()
+ return err
+}
+
// Ω wraps an actual value allowing assertions to be made on it:
// Ω("foo").Should(Equal("foo"))
//
@@ -177,7 +204,7 @@ func ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Asse
// Both intervals can either be specified as time.Duration, parsable duration strings or as floats/integers. In the
// last case they are interpreted as seconds.
//
-// If Eventually is passed an actual that is a function taking no arguments and returning at least one value,
+// If Eventually is passed an actual that is a function taking no arguments,
// then Eventually will call the function periodically and try the matcher against the function's first return value.
//
// Example:
@@ -202,6 +229,34 @@ func ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Asse
//
// Will pass only if the the returned error is nil and the returned string passes the matcher.
//
+// Eventually allows you to make assertions in the pased-in function. The function is assumed to have failed and will be retried if any assertion in the function fails.
+// For example:
+//
+// Eventually(func() Widget {
+// resp, err := http.Get(url)
+// Expect(err).NotTo(HaveOccurred())
+// defer resp.Body.Close()
+// Expect(resp.SatusCode).To(Equal(http.StatusOK))
+// var widget Widget
+// Expect(json.NewDecoder(resp.Body).Decode(&widget)).To(Succeed())
+// return widget
+// }).Should(Equal(expectedWidget))
+//
+// will keep trying the passed-in function until all its assertsions pass (i.e. the http request succeeds) _and_ the returned object satisfies the passed-in matcher.
+//
+// Functions passed to Eventually typically have a return value. However you are allowed to pass in a function with no return value. Eventually assumes such a function
+// is making assertions and will turn it into a function that returns an error if any assertion fails, or nil if no assertion fails. This allows you to use the Succeed() matcher
+// to express that a complex operation should eventually succeed. For example:
+//
+// Eventually(func() {
+// model, err := db.Find("foo")
+// Expect(err).NotTo(HaveOccurred())
+// Expect(model.Reticulated()).To(BeTrue())
+// Expect(model.Save()).To(Succeed())
+// }).Should(Succeed())
+//
+// will rerun the function until all its assertions pass.
+//
// Eventually's default timeout is 1 second, and its default polling interval is 10ms
func Eventually(actual interface{}, intervals ...interface{}) AsyncAssertion {
return EventuallyWithOffset(0, actual, intervals...)
@@ -235,13 +290,18 @@ func EventuallyWithOffset(offset int, actual interface{}, intervals ...interface
// Both intervals can either be specified as time.Duration, parsable duration strings or as floats/integers. In the
// last case they are interpreted as seconds.
//
-// If Consistently is passed an actual that is a function taking no arguments and returning at least one value,
-// then Consistently will call the function periodically and try the matcher against the function's first return value.
+// If Consistently is passed an actual that is a function taking no arguments.
+//
+// If the function returns one value, then Consistently will call the function periodically and try the matcher against the function's first return value.
//
// If the function returns more than one value, then Consistently will pass the first value to the matcher and
// assert that all other values are nil/zero.
// This allows you to pass Consistently a function that returns a value and an error - a common pattern in Go.
//
+// Like Eventually, Consistently allows you to make assertions in the function. If any assertion fails Consistently will fail. In addition,
+// Consistently also allows you to pass in a function with no return value. In this case Consistently can be paired with the Succeed() matcher to assert
+// that no assertions in the function fail.
+//
// Consistently is useful in cases where you want to assert that something *does not happen* over a period of time.
// For example, you want to assert that a goroutine does *not* send data down a channel. In this case, you could:
//
@@ -350,7 +410,7 @@ type OmegaMatcher types.GomegaMatcher
//
// Use `NewWithT` to instantiate a `WithT`
type WithT struct {
- t types.GomegaTestingT
+ failWrapper *types.GomegaFailWrapper
}
// GomegaWithT is deprecated in favor of gomega.WithT, which does not stutter.
@@ -367,7 +427,7 @@ type GomegaWithT = WithT
// }
func NewWithT(t types.GomegaTestingT) *WithT {
return &WithT{
- t: t,
+ failWrapper: testingtsupport.BuildTestingTGomegaFailWrapper(t),
}
}
@@ -378,7 +438,7 @@ func NewGomegaWithT(t types.GomegaTestingT) *GomegaWithT {
// ExpectWithOffset is used to make assertions. See documentation for ExpectWithOffset.
func (g *WithT) ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Assertion {
- return assertion.New(actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), offset, extra...)
+ return assertion.New(actual, g.failWrapper, offset, extra...)
}
// EventuallyWithOffset is used to make asynchronous assertions. See documentation for EventuallyWithOffset.
@@ -391,7 +451,7 @@ func (g *WithT) EventuallyWithOffset(offset int, actual interface{}, intervals .
if len(intervals) > 1 {
pollingInterval = toDuration(intervals[1])
}
- return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, offset)
+ return asyncassertion.New(asyncassertion.AsyncAssertionTypeEventually, actual, g.failWrapper, timeoutInterval, pollingInterval, offset)
}
// ConsistentlyWithOffset is used to make asynchronous assertions. See documentation for ConsistentlyWithOffset.
@@ -404,7 +464,7 @@ func (g *WithT) ConsistentlyWithOffset(offset int, actual interface{}, intervals
if len(intervals) > 1 {
pollingInterval = toDuration(intervals[1])
}
- return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, testingtsupport.BuildTestingTGomegaFailWrapper(g.t), timeoutInterval, pollingInterval, offset)
+ return asyncassertion.New(asyncassertion.AsyncAssertionTypeConsistently, actual, g.failWrapper, timeoutInterval, pollingInterval, offset)
}
// Expect is used to make assertions. See documentation for Expect.
diff --git a/vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go b/vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go
index 5204836bf..6aa02bc5d 100644
--- a/vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go
+++ b/vendor/github.com/onsi/gomega/internal/asyncassertion/async_assertion.go
@@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"reflect"
+ "runtime"
"time"
"github.com/onsi/gomega/internal/oraclematcher"
@@ -31,8 +32,8 @@ type AsyncAssertion struct {
func New(asyncType AsyncAssertionType, actualInput interface{}, failWrapper *types.GomegaFailWrapper, timeoutInterval time.Duration, pollingInterval time.Duration, offset int) *AsyncAssertion {
actualType := reflect.TypeOf(actualInput)
if actualType.Kind() == reflect.Func {
- if actualType.NumIn() != 0 || actualType.NumOut() == 0 {
- panic("Expected a function with no arguments and one or more return values.")
+ if actualType.NumIn() != 0 {
+ panic("Expected a function with no arguments and zero or more return values.")
}
}
@@ -70,13 +71,49 @@ func (assertion *AsyncAssertion) buildDescription(optionalDescription ...interfa
func (assertion *AsyncAssertion) actualInputIsAFunction() bool {
actualType := reflect.TypeOf(assertion.actualInput)
- return actualType.Kind() == reflect.Func && actualType.NumIn() == 0 && actualType.NumOut() > 0
+ return actualType.Kind() == reflect.Func && actualType.NumIn() == 0
}
func (assertion *AsyncAssertion) pollActual() (interface{}, error) {
- if assertion.actualInputIsAFunction() {
- values := reflect.ValueOf(assertion.actualInput).Call([]reflect.Value{})
+ if !assertion.actualInputIsAFunction() {
+ return assertion.actualInput, nil
+ }
+ var capturedAssertionFailure string
+ var values []reflect.Value
+
+ numOut := reflect.TypeOf(assertion.actualInput).NumOut()
+
+ func() {
+ originalHandler := assertion.failWrapper.Fail
+ assertion.failWrapper.Fail = func(message string, callerSkip ...int) {
+ skip := 0
+ if len(callerSkip) > 0 {
+ skip = callerSkip[0]
+ }
+ _, file, line, _ := runtime.Caller(skip + 1)
+ capturedAssertionFailure = fmt.Sprintf("Assertion in callback at %s:%d failed:\n%s", file, line, message)
+ panic("stop execution")
+ }
+
+ defer func() {
+ assertion.failWrapper.Fail = originalHandler
+ if e := recover(); e != nil && capturedAssertionFailure == "" {
+ panic(e)
+ }
+ }()
+
+ values = reflect.ValueOf(assertion.actualInput).Call([]reflect.Value{})
+ }()
+
+ if capturedAssertionFailure != "" {
+ if numOut == 0 {
+ return errors.New(capturedAssertionFailure), nil
+ } else {
+ return nil, errors.New(capturedAssertionFailure)
+ }
+ }
+ if numOut > 0 {
extras := []interface{}{}
for _, value := range values[1:] {
extras = append(extras, value.Interface())
@@ -91,7 +128,7 @@ func (assertion *AsyncAssertion) pollActual() (interface{}, error) {
return values[0].Interface(), nil
}
- return assertion.actualInput, nil
+ return nil, nil
}
func (assertion *AsyncAssertion) matcherMayChange(matcher types.GomegaMatcher, value interface{}) bool {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 6c0f001a9..c29cfe8cc 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -9,7 +9,7 @@ github.com/Microsoft/go-winio/backuptar
github.com/Microsoft/go-winio/pkg/guid
github.com/Microsoft/go-winio/pkg/security
github.com/Microsoft/go-winio/vhd
-# github.com/Microsoft/hcsshim v0.8.17
+# github.com/Microsoft/hcsshim v0.8.20
github.com/Microsoft/hcsshim
github.com/Microsoft/hcsshim/computestorage
github.com/Microsoft/hcsshim/internal/cow
@@ -197,7 +197,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process
-# github.com/containers/storage v1.32.5
+# github.com/containers/storage v1.32.6
github.com/containers/storage
github.com/containers/storage/drivers
github.com/containers/storage/drivers/aufs
@@ -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
@@ -482,7 +482,7 @@ github.com/onsi/ginkgo/reporters/stenographer
github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable
github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty
github.com/onsi/ginkgo/types
-# github.com/onsi/gomega v1.13.0
+# github.com/onsi/gomega v1.14.0
github.com/onsi/gomega
github.com/onsi/gomega/format
github.com/onsi/gomega/gbytes