summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/netflags.go9
-rw-r--r--cmd/podman/containers/create.go2
-rw-r--r--cmd/podman/containers/run.go2
-rw-r--r--cmd/podman/pods/create.go3
-rw-r--r--docs/source/Commands.rst4
-rw-r--r--docs/source/markdown/containers-mounts.conf.5.md16
-rw-r--r--go.mod4
-rw-r--r--go.sum7
-rw-r--r--libpod/networking_linux.go24
-rw-r--r--pkg/api/handlers/compat/containers_create.go5
-rw-r--r--pkg/api/handlers/compat/containers_stats.go30
-rw-r--r--pkg/api/handlers/compat/images.go76
-rw-r--r--pkg/api/handlers/compat/images_push.go112
-rw-r--r--pkg/api/handlers/libpod/images.go2
-rw-r--r--pkg/api/handlers/libpod/images_pull.go2
-rw-r--r--pkg/api/handlers/libpod/manifests.go2
-rw-r--r--pkg/api/handlers/utils/images.go25
-rw-r--r--pkg/api/server/register_containers.go5
-rw-r--r--pkg/domain/infra/abi/network.go2
-rw-r--r--pkg/machine/config.go1
-rw-r--r--pkg/machine/ignition.go17
-rw-r--r--pkg/machine/qemu/machine.go118
-rw-r--r--pkg/machine/qemu/options_darwin.go2
-rw-r--r--pkg/machine/qemu/options_darwin_amd64.go2
-rw-r--r--pkg/machine/qemu/options_linux.go10
-rw-r--r--rootless.md2
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_container.py4
-rw-r--r--test/e2e/play_kube_test.go2
-rw-r--r--test/system/001-basic.bats8
-rw-r--r--test/system/030-run.bats6
-rw-r--r--test/system/500-networking.bats4
-rw-r--r--vendor/github.com/containers/common/libimage/normalize.go51
-rw-r--r--vendor/github.com/containers/common/libimage/pull.go23
-rw-r--r--vendor/github.com/containers/common/libimage/runtime.go9
-rw-r--r--vendor/github.com/containers/common/pkg/config/default.go2
-rw-r--r--vendor/github.com/containers/common/pkg/config/nosystemd.go10
-rw-r--r--vendor/github.com/containers/common/pkg/config/systemd.go40
-rw-r--r--vendor/github.com/containers/common/version/version.go2
-rw-r--r--vendor/github.com/onsi/ginkgo/config/config.go2
-rw-r--r--vendor/github.com/onsi/ginkgo/ginkgo_dsl.go4
-rw-r--r--vendor/github.com/onsi/ginkgo/types/deprecation_support.go4
-rw-r--r--vendor/modules.txt4
42 files changed, 466 insertions, 193 deletions
diff --git a/cmd/podman/common/netflags.go b/cmd/podman/common/netflags.go
index 9941bc716..4f634f355 100644
--- a/cmd/podman/common/netflags.go
+++ b/cmd/podman/common/netflags.go
@@ -85,7 +85,10 @@ func DefineNetFlags(cmd *cobra.Command) {
)
}
-func NetFlagsToNetOptions(cmd *cobra.Command) (*entities.NetOptions, error) {
+// NetFlagsToNetOptions parses the network flags for the given cmd.
+// The netnsFromConfig bool is used to indicate if the --network flag
+// should always be parsed regardless if it was set on the cli.
+func NetFlagsToNetOptions(cmd *cobra.Command, netnsFromConfig bool) (*entities.NetOptions, error) {
var (
err error
)
@@ -193,7 +196,9 @@ func NetFlagsToNetOptions(cmd *cobra.Command) (*entities.NetOptions, error) {
return nil, err
}
- if cmd.Flags().Changed("network") {
+ // parse the --network value only when the flag is set or we need to use
+ // the netns config value, e.g. when --pod is not used
+ if netnsFromConfig || cmd.Flag("network").Changed {
network, err := cmd.Flags().GetString("network")
if err != nil {
return nil, err
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index 07a859983..68a17abd0 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -87,7 +87,7 @@ func create(cmd *cobra.Command, args []string) error {
var (
err error
)
- cliVals.Net, err = common.NetFlagsToNetOptions(cmd)
+ cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "")
if err != nil {
return err
}
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index 2611c5b6e..579af4eb1 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -106,7 +106,7 @@ func init() {
func run(cmd *cobra.Command, args []string) error {
var err error
- cliVals.Net, err = common.NetFlagsToNetOptions(cmd)
+ cliVals.Net, err = common.NetFlagsToNetOptions(cmd, cliVals.Pod == "")
if err != nil {
return err
}
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 3c2c8a3bc..735dfa78c 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -166,10 +166,11 @@ func create(cmd *cobra.Command, args []string) error {
defer errorhandling.SyncQuiet(podIDFD)
}
- createOptions.Net, err = common.NetFlagsToNetOptions(cmd)
+ createOptions.Net, err = common.NetFlagsToNetOptions(cmd, createOptions.Infra)
if err != nil {
return err
}
+
if len(createOptions.Net.PublishPorts) > 0 {
if !createOptions.Infra {
return errors.Errorf("you must have an infra container to publish port bindings to the host")
diff --git a/docs/source/Commands.rst b/docs/source/Commands.rst
index 766b6a02e..767b09c08 100644
--- a/docs/source/Commands.rst
+++ b/docs/source/Commands.rst
@@ -55,7 +55,7 @@ Commands
:doc:`logs <markdown/podman-logs.1>` Fetch the logs of a container
-:doc:`machine <markdown/podman-machine.1>` Manage podman's virtual machine
+:doc:`machine <machine>` Manage podman's virtual machine
:doc:`manifest <manifest>` Create and manipulate manifest lists and image indexes
@@ -91,7 +91,7 @@ Commands
:doc:`search <markdown/podman-search.1>` Search registry for image
-:doc:`secret <markdown/podman-secret.1>` Manage podman secrets
+:doc:`secret <secret>` Manage podman secrets
:doc:`start <markdown/podman-start.1>` Start one or more containers
diff --git a/docs/source/markdown/containers-mounts.conf.5.md b/docs/source/markdown/containers-mounts.conf.5.md
deleted file mode 100644
index 74492c831..000000000
--- a/docs/source/markdown/containers-mounts.conf.5.md
+++ /dev/null
@@ -1,16 +0,0 @@
-% containers-mounts.conf(5)
-
-## NAME
-containers-mounts.conf - configuration file for default mounts in containers
-
-## DESCRIPTION
-The mounts.conf file specifies volume mount directories that are automatically mounted inside containers. Container processes can then use this content. Usually these directories are used for passing secrets or credentials required by the package software to access remote package repositories. Note that for security reasons, tools adhering to the mounts.conf are expected to copy the contents instead of bind mounting the paths from the host.
-
-## FORMAT
-The format of the mounts.conf is the volume format `/SRC:/DEST`, one mount per line. For example, a mounts.conf with the line `/usr/share/secrets:/run/secrets` would cause the contents of the `/usr/share/secrets` directory on the host to be mounted on the `/run/secrets` directory inside the container. Setting mountpoints allows containers to use the files of the host, for instance, to use the host's subscription to some enterprise Linux distribution.
-
-## FILES
-Some distributions may provide a `/usr/share/containers/mounts.conf` file to provide default mounts, but users can create a `/etc/containers/mounts.conf`, to specify their own special volumes to mount in the container. When Podman runs in rootless mode, the file `$HOME/.config/containers/mounts.conf` will override the default if it exists.
-
-## HISTORY
-Aug 2018, Originally compiled by Valentin Rothberg <vrothberg@suse.com>
diff --git a/go.mod b/go.mod
index 148817291..93687fb90 100644
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
github.com/containernetworking/cni v0.8.1
github.com/containernetworking/plugins v0.9.1
github.com/containers/buildah v1.21.0
- github.com/containers/common v0.39.0
+ github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.12.0
github.com/containers/ocicrypt v1.1.1
@@ -42,7 +42,7 @@ require (
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635
github.com/mrunalp/fileutils v0.5.0
- github.com/onsi/ginkgo v1.16.2
+ github.com/onsi/ginkgo v1.16.3
github.com/onsi/gomega v1.13.0
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6
diff --git a/go.sum b/go.sum
index ae16c613b..cba584a94 100644
--- a/go.sum
+++ b/go.sum
@@ -219,8 +219,8 @@ github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRD
github.com/containers/buildah v1.21.0 h1:LuwuqRPjan3X3AIdGwfkEkqMgmrDMNpQznFqNdHgCz8=
github.com/containers/buildah v1.21.0/go.mod h1:yPdlpVd93T+i91yGxrJbW1YOWrqN64j5ZhHOZmHUejs=
github.com/containers/common v0.38.4/go.mod h1:egfpX/Y3+19Dz4Wa1eRZDdgzoEOeneieF9CQppKzLBg=
-github.com/containers/common v0.39.0 h1:MrvpFa/bM4UmUILACv2IhOif4oLmWAiD4C+CpOc/MUo=
-github.com/containers/common v0.39.0/go.mod h1:vPUHCg/dHoiyqIyLN+EdbjUaGrVEhs/hAvsqsxuYepk=
+github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a h1:XzYOUf7qjgVJ59YGqAzehlbT63EgjUJhMnfhsPSSJV0=
+github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a/go.mod h1:CxHAf4iQOZZ8nASIjMdYHHRyA8dMR4tINSS7WQWlv90=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.12.0 h1:1hNS2QkzFQ4lH3GYQLyAXB0acRMhS1Ubm6oV++8vw4w=
@@ -648,8 +648,9 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
-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.3 h1:3s86PZkI1ApJh6HFIzC1gXby/mIyZqfE5zxSvtoBSsM=
+github.com/onsi/ginkgo v1.16.3/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 0e8a4f768..c928e02a6 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -273,7 +273,6 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) {
if err != nil {
return nil, errors.Wrap(err, "error creating rootless cni network namespace")
}
-
// setup slirp4netns here
path := r.config.Engine.NetworkCmdPath
if path == "" {
@@ -437,9 +436,32 @@ func (r *Runtime) GetRootlessCNINetNs(new bool) (*RootlessCNI, error) {
return rootlessCNINS, nil
}
+// setPrimaryMachineIP is used for podman-machine and it sets
+// and environment variable with the IP address of the podman-machine
+// host.
+func setPrimaryMachineIP() error {
+ // no connection is actually made here
+ conn, err := net.Dial("udp", "8.8.8.8:80")
+ if err != nil {
+ return err
+ }
+ defer func() {
+ if err := conn.Close(); err != nil {
+ logrus.Error(err)
+ }
+ }()
+ addr := conn.LocalAddr().(*net.UDPAddr)
+ return os.Setenv("PODMAN_MACHINE_HOST", addr.IP.String())
+}
+
// setUpOCICNIPod will set up the cni networks, on error it will also tear down the cni
// networks. If rootless it will join/create the rootless cni namespace.
func (r *Runtime) setUpOCICNIPod(podNetwork ocicni.PodNetwork) ([]ocicni.NetResult, error) {
+ if r.config.MachineEnabled() {
+ if err := setPrimaryMachineIP(); err != nil {
+ return nil, err
+ }
+ }
rootlessCNINS, err := r.GetRootlessCNINetNs(true)
if err != nil {
return nil, err
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 8e9e1fb39..0b5cbd343 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -71,13 +71,12 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
imgNameOrID := newImage.ID()
// if the img had multi names with the same sha256 ID, should use the InputName, not the ID
if len(newImage.Names()) > 1 {
- imageRef, err := utils.ParseDockerReference(resolvedName)
- if err != nil {
+ if err := utils.IsRegistryReference(resolvedName); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
}
// maybe the InputName has no tag, so use full name to display
- imgNameOrID = imageRef.DockerReference().String()
+ imgNameOrID = resolvedName
}
sg := specgen.NewSpecGenerator(imgNameOrID, cliOpts.RootFS)
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go
index 694b57bb1..851955207 100644
--- a/pkg/api/handlers/compat/containers_stats.go
+++ b/pkg/api/handlers/compat/containers_stats.go
@@ -22,7 +22,8 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
- Stream bool `schema:"stream"`
+ Stream bool `schema:"stream"`
+ OneShot bool `schema:"one-shot"` //added schema for one shot
}{
Stream: true,
}
@@ -30,6 +31,10 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
+ if query.Stream && query.OneShot { // mismatch. one-shot can only be passed with stream=false
+ utils.Error(w, "invalid combination of stream and one-shot", http.StatusBadRequest, define.ErrInvalidArg)
+ return
+ }
name := utils.GetName(r)
ctnr, err := runtime.LookupContainer(name)
@@ -56,6 +61,16 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
return
}
+ coder := json.NewEncoder(w)
+ // Write header and content type.
+ w.WriteHeader(http.StatusOK)
+ w.Header().Add("Content-Type", "application/json")
+ if flusher, ok := w.(http.Flusher); ok {
+ flusher.Flush()
+ }
+
+ // Setup JSON encoder for streaming.
+ coder.SetEscapeHTML(true)
var preRead time.Time
var preCPUStats CPUStats
if query.Stream {
@@ -75,17 +90,6 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {
}
}
- // Write header and content type.
- w.WriteHeader(http.StatusOK)
- w.Header().Add("Content-Type", "application/json")
- if flusher, ok := w.(http.Flusher); ok {
- flusher.Flush()
- }
-
- // Setup JSON encoder for streaming.
- coder := json.NewEncoder(w)
- coder.SetEscapeHTML(true)
-
streamLabel: // A label to flatten the scope
select {
case <-r.Context().Done():
@@ -199,7 +203,7 @@ streamLabel: // A label to flatten the scope
flusher.Flush()
}
- if !query.Stream {
+ if !query.Stream || query.OneShot {
return
}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 3f4320efa..7b336c470 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -1,7 +1,6 @@
package compat
import (
- "context"
"encoding/json"
"fmt"
"io/ioutil"
@@ -13,12 +12,12 @@ import (
"github.com/containers/common/libimage"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/manifest"
+ "github.com/containers/image/v5/pkg/shortnames"
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/auth"
- "github.com/containers/podman/v3/pkg/channel"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/storage"
@@ -210,6 +209,11 @@ func CreateImageFromSrc(w http.ResponseWriter, r *http.Request) {
})
}
+type pullResult struct {
+ images []*libimage.Image
+ err error
+}
+
func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
// 200 no error
// 404 repo does not exist or no read access
@@ -231,6 +235,14 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
fromImage := mergeNameAndTagOrDigest(query.FromImage, query.Tag)
+ // without this early check this function would return 200 but reported error via body stream soon after
+ // it's better to let caller know early via HTTP status code that request cannot be processed
+ _, err := shortnames.Resolve(runtime.SystemContext(), fromImage)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrap(err, "failed to resolve image name"))
+ return
+ }
+
authConf, authfile, key, err := auth.GetCredentials(r)
if err != nil {
utils.Error(w, "failed to retrieve repository credentials", http.StatusBadRequest, errors.Wrapf(err, "failed to parse %q header for %s", key, r.URL.String()))
@@ -247,26 +259,14 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
}
pullOptions.Writer = os.Stderr // allows for debugging on the server
- stderr := channel.NewWriter(make(chan []byte))
- defer stderr.Close()
-
progress := make(chan types.ProgressProperties)
+
pullOptions.Progress = progress
- var img string
- runCtx, cancel := context.WithCancel(context.Background())
+ pullResChan := make(chan pullResult)
go func() {
- defer cancel()
- pulledImages, err := runtime.LibimageRuntime().Pull(runCtx, fromImage, config.PullPolicyAlways, pullOptions)
- if err != nil {
- stderr.Write([]byte(err.Error() + "\n"))
- } else {
- if len(pulledImages) == 0 {
- utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.New("internal error: no images pulled"))
- return
- }
- img = pulledImages[0].ID()
- }
+ pulledImages, err := runtime.LibimageRuntime().Pull(r.Context(), fromImage, config.PullPolicyAlways, pullOptions)
+ pullResChan <- pullResult{images: pulledImages, err: err}
}()
flush := func() {
@@ -281,7 +281,6 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
enc.SetEscapeHTML(true)
- var failed bool
loop: // break out of for/select infinite loop
for {
@@ -312,32 +311,31 @@ loop: // break out of for/select infinite loop
}
report.Id = e.Artifact.Digest.Encoded()[0:12]
if err := enc.Encode(report); err != nil {
- stderr.Write([]byte(err.Error()))
- }
- flush()
- case e := <-stderr.Chan():
- failed = true
- report.Error = string(e)
- if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
flush()
- case <-runCtx.Done():
- if !failed {
- if utils.IsLibpodRequest(r) {
- report.Status = "Pull complete"
+ case pullRes := <-pullResChan:
+ err := pullRes.err
+ pulledImages := pullRes.images
+ if err != nil {
+ report.Error = err.Error()
+ } else {
+ if len(pulledImages) > 0 {
+ img := pulledImages[0].ID()
+ if utils.IsLibpodRequest(r) {
+ report.Status = "Pull complete"
+ } else {
+ report.Status = "Download complete"
+ }
+ report.Id = img[0:12]
} else {
- report.Status = "Download complete"
- }
- report.Id = img[0:12]
- if err := enc.Encode(report); err != nil {
- logrus.Warnf("Failed to json encode error %q", err.Error())
+ report.Error = "internal error: no images pulled"
}
- flush()
}
- break loop // break out of for/select infinite loop
- case <-r.Context().Done():
- // Client has closed connection
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to json encode error %q", err.Error())
+ }
+ flush()
break loop // break out of for/select infinite loop
}
}
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
index db02af445..62f8cdc77 100644
--- a/pkg/api/handlers/compat/images_push.go
+++ b/pkg/api/handlers/compat/images_push.go
@@ -1,7 +1,6 @@
package compat
import (
- "context"
"encoding/json"
"fmt"
"io/ioutil"
@@ -12,7 +11,6 @@ import (
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/auth"
- "github.com/containers/podman/v3/pkg/channel"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/domain/infra/abi"
"github.com/containers/storage"
@@ -101,46 +99,33 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
destination = imageName
}
- errorWriter := channel.NewWriter(make(chan []byte))
- defer errorWriter.Close()
-
- statusWriter := channel.NewWriter(make(chan []byte))
- defer statusWriter.Close()
-
- runCtx, cancel := context.WithCancel(context.Background())
- var failed bool
-
- go func() {
- defer cancel()
-
- statusWriter.Write([]byte(fmt.Sprintf("The push refers to repository [%s]", imageName)))
-
- err := imageEngine.Push(runCtx, imageName, destination, options)
- if err != nil {
- if errors.Cause(err) != storage.ErrImageUnknown {
- errorWriter.Write([]byte("An image does not exist locally with the tag: " + imageName))
- } else {
- errorWriter.Write([]byte(err.Error()))
- }
- }
- }()
-
- flush := func() {
- if flusher, ok := w.(http.Flusher); ok {
- flusher.Flush()
- }
+ flush := func() {}
+ if flusher, ok := w.(http.Flusher); ok {
+ flush = flusher.Flush
}
w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json")
flush()
+ var report jsonmessage.JSONMessage
enc := json.NewEncoder(w)
enc.SetEscapeHTML(true)
+ report.Status = fmt.Sprintf("The push refers to repository [%s]", imageName)
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to json encode error %q", err.Error())
+ }
+ flush()
+
+ pushErrChan := make(chan error)
+ go func() {
+ pushErrChan <- imageEngine.Push(r.Context(), imageName, destination, options)
+ }()
+
loop: // break out of for/select infinite loop
for {
- var report jsonmessage.JSONMessage
+ report = jsonmessage.JSONMessage{}
select {
case e := <-options.Progress:
@@ -160,43 +145,50 @@ loop: // break out of for/select infinite loop
}
report.ID = e.Artifact.Digest.Encoded()[0:12]
if err := enc.Encode(report); err != nil {
- errorWriter.Write([]byte(err.Error()))
+ logrus.Warnf("Failed to json encode error %q", err.Error())
}
flush()
- case e := <-statusWriter.Chan():
- report.Status = string(e)
- if err := enc.Encode(report); err != nil {
- errorWriter.Write([]byte(err.Error()))
+ case err := <-pushErrChan:
+ if err != nil {
+ var msg string
+ if errors.Cause(err) != storage.ErrImageUnknown {
+ msg = "An image does not exist locally with the tag: " + imageName
+ } else {
+ msg = err.Error()
+ }
+ report.Error = &jsonmessage.JSONError{
+ Message: msg,
+ }
+ report.ErrorMessage = msg
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to json encode error %q", err.Error())
+ }
+ flush()
+ break loop
}
- flush()
- case e := <-errorWriter.Chan():
- failed = true
- report.Error = &jsonmessage.JSONError{
- Message: string(e),
+
+ digestBytes, err := ioutil.ReadAll(digestFile)
+ if err != nil {
+ report.Error = &jsonmessage.JSONError{
+ Message: err.Error(),
+ }
+ report.ErrorMessage = err.Error()
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to json encode error %q", err.Error())
+ }
+ flush()
+ break loop
}
- report.ErrorMessage = string(e)
+ tag := query.Tag
+ if tag == "" {
+ tag = "latest"
+ }
+ report.Status = fmt.Sprintf("%s: digest: %s", tag, string(digestBytes))
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
+
flush()
- case <-runCtx.Done():
- if !failed {
- digestBytes, err := ioutil.ReadAll(digestFile)
- if err == nil {
- tag := query.Tag
- if tag == "" {
- tag = "latest"
- }
- report.Status = fmt.Sprintf("%s: digest: %s", tag, string(digestBytes))
- if err := enc.Encode(report); err != nil {
- logrus.Warnf("Failed to json encode error %q", err.Error())
- }
- flush()
- }
- }
- break loop // break out of for/select infinite loop
- case <-r.Context().Done():
- // Client has closed connection
break loop // break out of for/select infinite loop
}
}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index a90408bfd..fc6ab4b4c 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -482,7 +482,7 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
destination = source
}
- if _, err := utils.ParseDockerReference(destination); err != nil {
+ if err := utils.IsRegistryReference(destination); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
}
diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go
index 7545ba235..fe56aa31d 100644
--- a/pkg/api/handlers/libpod/images_pull.go
+++ b/pkg/api/handlers/libpod/images_pull.go
@@ -48,7 +48,7 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
}
// Make sure that the reference has no transport or the docker one.
- if _, err := utils.ParseDockerReference(query.Reference); err != nil {
+ if err := utils.IsRegistryReference(query.Reference); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
}
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index f21eb2e80..2f36db583 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -169,7 +169,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
- if _, err := utils.ParseDockerReference(query.Destination); err != nil {
+ if err := utils.IsRegistryReference(query.Destination); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
}
diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go
index 2662cd368..2a1908d63 100644
--- a/pkg/api/handlers/utils/images.go
+++ b/pkg/api/handlers/utils/images.go
@@ -15,22 +15,19 @@ import (
"github.com/pkg/errors"
)
-// ParseDockerReference parses the specified image name to a
-// `types.ImageReference` and enforces it to refer to a docker-transport
-// reference.
-func ParseDockerReference(name string) (types.ImageReference, error) {
- dockerPrefix := fmt.Sprintf("%s://", docker.Transport.Name())
+// IsRegistryReference checks if the specified name points to the "docker://"
+// transport. If it points to no supported transport, we'll assume a
+// non-transport reference pointing to an image (e.g., "fedora:latest").
+func IsRegistryReference(name string) error {
imageRef, err := alltransports.ParseImageName(name)
- if err == nil && imageRef.Transport().Name() != docker.Transport.Name() {
- return nil, errors.Errorf("reference %q must be a docker reference", name)
- } else if err != nil {
- origErr := err
- imageRef, err = alltransports.ParseImageName(fmt.Sprintf("%s%s", dockerPrefix, name))
- if err != nil {
- return nil, errors.Wrapf(origErr, "reference %q must be a docker reference", name)
- }
+ if err != nil {
+ // No supported transport -> assume a docker-stype reference.
+ return nil
}
- return imageRef, nil
+ if imageRef.Transport().Name() == docker.Transport.Name() {
+ return nil
+ }
+ return errors.Errorf("unsupport transport %s in %q: only docker transport is supported", imageRef.Transport().Name(), name)
}
// ParseStorageReference parses the specified image name to a
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index 536c4707a..aa999905e 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -375,6 +375,11 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// type: boolean
// default: true
// description: Stream the output
+ // - in: query
+ // name: one-shot
+ // type: boolean
+ // default: false
+ // description: Provide a one-shot response in which preCPU stats are blank, resulting in a single cycle return.
// produces:
// - application/json
// responses:
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index 33ab280e5..7900caaa6 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -11,7 +11,7 @@ import (
)
func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.NetworkListOptions) ([]*entities.NetworkListReport, error) {
- var reports []*entities.NetworkListReport
+ reports := make([]*entities.NetworkListReport, 0)
config, err := ic.Libpod.GetConfig()
if err != nil {
diff --git a/pkg/machine/config.go b/pkg/machine/config.go
index 652229963..58794ce42 100644
--- a/pkg/machine/config.go
+++ b/pkg/machine/config.go
@@ -32,6 +32,7 @@ var (
ErrVMAlreadyExists = errors.New("VM already exists")
ErrVMAlreadyRunning = errors.New("VM already running")
ErrMultipleActiveVM = errors.New("only one VM can be active at a time")
+ ForwarderBinaryName = "gvproxy"
)
type Download struct {
diff --git a/pkg/machine/ignition.go b/pkg/machine/ignition.go
index 00068a136..a5c7210af 100644
--- a/pkg/machine/ignition.go
+++ b/pkg/machine/ignition.go
@@ -118,6 +118,7 @@ func getDirs(usrName string) []Directory {
// in one swoop, then the leading dirs are creates as root.
newDirs := []string{
"/home/" + usrName + "/.config",
+ "/home/" + usrName + "/.config/containers",
"/home/" + usrName + "/.config/systemd",
"/home/" + usrName + "/.config/systemd/user",
"/home/" + usrName + "/.config/systemd/user/default.target.wants",
@@ -159,6 +160,22 @@ func getFiles(usrName string) []File {
},
})
+ // Set containers.conf up for core user to use cni networks
+ // by default
+ files = append(files, File{
+ Node: Node{
+ Group: getNodeGrp(usrName),
+ Path: "/home/" + usrName + "/.config/containers/containers.conf",
+ User: getNodeUsr(usrName),
+ },
+ FileEmbedded1: FileEmbedded1{
+ Append: nil,
+ Contents: Resource{
+ Source: strToPtr("data:,%5Bcontainers%5D%0D%0Anetns%3D%22bridge%22%0D%0Arootless_networking%3D%22cni%22"),
+ },
+ Mode: intToPtr(484),
+ },
+ })
// Add a file into linger
files = append(files, File{
Node: Node{
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 0bd711c90..31c355d4a 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -13,6 +13,8 @@ import (
"strings"
"time"
+ "github.com/containers/podman/v3/pkg/rootless"
+
"github.com/containers/podman/v3/pkg/machine"
"github.com/containers/podman/v3/utils"
"github.com/containers/storage/pkg/homedir"
@@ -82,9 +84,10 @@ func NewMachine(opts machine.InitOptions) (machine.VM, error) {
cmd = append(cmd, []string{"-qmp", monitor.Network + ":/" + monitor.Address + ",server=on,wait=off"}...)
// Add network
- cmd = append(cmd, "-nic", "user,model=virtio,hostfwd=tcp::"+strconv.Itoa(vm.Port)+"-:22")
-
- socketPath, err := getSocketDir()
+ // Right now the mac address is hardcoded so that the host networking gives it a specific IP address. This is
+ // why we can only run one vm at a time right now
+ cmd = append(cmd, []string{"-netdev", "socket,id=vlan,fd=3", "-device", "virtio-net-pci,netdev=vlan,mac=5a:94:ef:e4:0c:ee"}...)
+ socketPath, err := getRuntimeDir()
if err != nil {
return nil, err
}
@@ -235,12 +238,35 @@ func (v *MachineVM) Init(opts machine.InitOptions) error {
// Start executes the qemu command line and forks it
func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
var (
- conn net.Conn
- err error
- wait time.Duration = time.Millisecond * 500
+ conn net.Conn
+ err error
+ qemuSocketConn net.Conn
+ wait time.Duration = time.Millisecond * 500
)
+ if err := v.startHostNetworking(); err != nil {
+ return errors.Errorf("unable to start host networking: %q", err)
+ }
+ qemuSocketPath, _, err := v.getSocketandPid()
+
+ for i := 0; i < 6; i++ {
+ qemuSocketConn, err = net.Dial("unix", qemuSocketPath)
+ if err == nil {
+ break
+ }
+ time.Sleep(wait)
+ wait++
+ }
+ if err != nil {
+ return err
+ }
+
+ fd, err := qemuSocketConn.(*net.UnixConn).File()
+ if err != nil {
+ return err
+ }
+
attr := new(os.ProcAttr)
- files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
+ files := []*os.File{os.Stdin, os.Stdout, os.Stderr, fd}
attr.Files = files
logrus.Debug(v.CmdLine)
cmd := v.CmdLine
@@ -256,7 +282,7 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
return err
}
fmt.Println("Waiting for VM ...")
- socketPath, err := getSocketDir()
+ socketPath, err := getRuntimeDir()
if err != nil {
return err
}
@@ -309,16 +335,42 @@ func (v *MachineVM) Stop(name string, _ machine.StopOptions) error {
logrus.Error(err)
}
}()
- _, err = qmpMonitor.Run(input)
- return err
+ if _, err = qmpMonitor.Run(input); err != nil {
+ return err
+ }
+ _, pidFile, err := v.getSocketandPid()
+ if err != nil {
+ return err
+ }
+ if _, err := os.Stat(pidFile); os.IsNotExist(err) {
+ logrus.Infof("pid file %s does not exist", pidFile)
+ return nil
+ }
+ pidString, err := ioutil.ReadFile(pidFile)
+ if err != nil {
+ return err
+ }
+ pidNum, err := strconv.Atoi(string(pidString))
+ if err != nil {
+ return err
+ }
+
+ p, err := os.FindProcess(pidNum)
+ if p == nil && err != nil {
+ return err
+ }
+ return p.Kill()
}
// NewQMPMonitor creates the monitor subsection of our vm
func NewQMPMonitor(network, name string, timeout time.Duration) (Monitor, error) {
- rtDir, err := getSocketDir()
+ rtDir, err := getRuntimeDir()
if err != nil {
return Monitor{}, err
}
+ if !rootless.IsRootless() {
+ rtDir = "/run"
+ }
rtDir = filepath.Join(rtDir, "podman")
if _, err := os.Stat(filepath.Join(rtDir)); os.IsNotExist(err) {
// TODO 0644 is fine on linux but macos is weird
@@ -533,3 +585,47 @@ func CheckActiveVM() (bool, string, error) {
}
return false, "", nil
}
+
+// startHostNetworking runs a binary on the host system that allows users
+// to setup port forwarding to the podman virtual machine
+func (v *MachineVM) startHostNetworking() error {
+ binary, err := exec.LookPath(machine.ForwarderBinaryName)
+ if err != nil {
+ return err
+ }
+ // Listen on all at port 7777 for setting up and tearing
+ // down forwarding
+ listenSocket := "tcp://0.0.0.0:7777"
+ qemuSocket, pidFile, err := v.getSocketandPid()
+ if err != nil {
+ return err
+ }
+ attr := new(os.ProcAttr)
+ // Pass on stdin, stdout, stderr
+ files := []*os.File{os.Stdin, os.Stdout, os.Stderr}
+ attr.Files = files
+ cmd := []string{binary}
+ cmd = append(cmd, []string{"-listen", listenSocket, "-listen-qemu", fmt.Sprintf("unix://%s", qemuSocket), "-pid-file", pidFile}...)
+ // Add the ssh port
+ cmd = append(cmd, []string{"-ssh-port", fmt.Sprintf("%d", v.Port)}...)
+ if logrus.GetLevel() == logrus.DebugLevel {
+ cmd = append(cmd, "--debug")
+ fmt.Println(cmd)
+ }
+ _, err = os.StartProcess(cmd[0], cmd, attr)
+ return err
+}
+
+func (v *MachineVM) getSocketandPid() (string, string, error) {
+ rtPath, err := getRuntimeDir()
+ if err != nil {
+ return "", "", err
+ }
+ if !rootless.IsRootless() {
+ rtPath = "/run"
+ }
+ socketDir := filepath.Join(rtPath, "podman")
+ pidFile := filepath.Join(socketDir, fmt.Sprintf("%s.pid", v.Name))
+ qemuSocket := filepath.Join(socketDir, fmt.Sprintf("qemu_%s.sock", v.Name))
+ return qemuSocket, pidFile, nil
+}
diff --git a/pkg/machine/qemu/options_darwin.go b/pkg/machine/qemu/options_darwin.go
index 46ccf24cb..440937131 100644
--- a/pkg/machine/qemu/options_darwin.go
+++ b/pkg/machine/qemu/options_darwin.go
@@ -6,7 +6,7 @@ import (
"github.com/pkg/errors"
)
-func getSocketDir() (string, error) {
+func getRuntimeDir() (string, error) {
tmpDir, ok := os.LookupEnv("TMPDIR")
if !ok {
return "", errors.New("unable to resolve TMPDIR")
diff --git a/pkg/machine/qemu/options_darwin_amd64.go b/pkg/machine/qemu/options_darwin_amd64.go
index 69f7982b2..ee1036291 100644
--- a/pkg/machine/qemu/options_darwin_amd64.go
+++ b/pkg/machine/qemu/options_darwin_amd64.go
@@ -5,7 +5,7 @@ var (
)
func (v *MachineVM) addArchOptions() []string {
- opts := []string{"-cpu", "host"}
+ opts := []string{"-machine", "q35,accel=hvf:tcg"}
return opts
}
diff --git a/pkg/machine/qemu/options_linux.go b/pkg/machine/qemu/options_linux.go
index 0a2e40d8f..c73a68cc6 100644
--- a/pkg/machine/qemu/options_linux.go
+++ b/pkg/machine/qemu/options_linux.go
@@ -1,7 +1,13 @@
package qemu
-import "github.com/containers/podman/v3/pkg/util"
+import (
+ "github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/util"
+)
-func getSocketDir() (string, error) {
+func getRuntimeDir() (string, error) {
+ if !rootless.IsRootless() {
+ return "/run", nil
+ }
return util.GetRuntimeDir()
}
diff --git a/rootless.md b/rootless.md
index 9edd5a437..bee5d337b 100644
--- a/rootless.md
+++ b/rootless.md
@@ -29,7 +29,7 @@ can easily fail
* Ubuntu supports non root overlay, but no other Linux distros do.
* Only other supported driver is VFS.
* Cannot use ping out of the box.
- * [(Can be fixed by setting sysctl on host)](https://github.com/containers/podman/blob/master/troubleshooting.md#6-rootless-containers-cannot-ping-hosts)
+ * [(Can be fixed by setting sysctl on host)](https://github.com/containers/podman/blob/master/troubleshooting.md#5-rootless-containers-cannot-ping-hosts)
* Requires new shadow-utils (not found in older (RHEL7/Centos7 distros) Should be fixed in RHEL7.7 release)
* A few commands do not work.
* mount/unmount (on fuse-overlay)
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 ad096ed38..f67013117 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
@@ -30,6 +30,10 @@ class ContainerTestCase(APITestCase):
self.assertIn(r.status_code, (200, 409), r.text)
if r.status_code == 200:
self.assertId(r.content)
+ r = requests.get(self.uri(self.resolve_container("/containers/{}/stats?stream=false&one-shot=true")))
+ self.assertIn(r.status_code, (200, 409), r.text)
+ if r.status_code == 200:
+ self.assertId(r.content)
def test_delete(self):
r = requests.delete(self.uri(self.resolve_container("/containers/{}")))
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index e0af27f7a..833991452 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -2119,7 +2119,7 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(125))
- Expect(kube.ErrorToString()).To(ContainSubstring(invalidImageName))
+ Expect(kube.ErrorToString()).To(ContainSubstring("invalid reference format"))
})
It("podman play kube applies log driver to containers", func() {
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index 97ef61511..963c89281 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -49,6 +49,14 @@ function setup() {
@test "podman can pull an image" {
run_podman pull $IMAGE
+
+ # Also make sure that the tag@digest syntax is supported.
+ run_podman inspect --format "{{ .Digest }}" $IMAGE
+ digest=$output
+ run_podman pull $IMAGE@$digest
+
+ # Now untag the digest reference again.
+ run_podman untag $IMAGE $IMAGE@$digest
}
# PR #7212: allow --remote anywhere before subcommand, not just as 1st flag
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 2ea981a85..32fc85c4e 100644
--- a/test/system/030-run.bats
+++ b/test/system/030-run.bats
@@ -600,12 +600,12 @@ json-file | f
echo "$randomcontent" > $testdir/content
# Workdir does not exist on the image but is volume mounted.
- run_podman run --rm --workdir /IamNotOnTheImage -v $testdir:/IamNotOnTheImage $IMAGE cat content
+ run_podman run --rm --workdir /IamNotOnTheImage -v $testdir:/IamNotOnTheImage:Z $IMAGE cat content
is "$output" "$randomcontent" "cat random content"
# Workdir does not exist on the image but is created by the runtime as it's
# a subdir of a volume.
- run_podman run --rm --workdir /IamNotOntheImage -v $testdir/content:/IamNotOntheImage/foo $IMAGE cat foo
+ run_podman run --rm --workdir /IamNotOntheImage -v $testdir/content:/IamNotOntheImage/foo:Z $IMAGE cat foo
is "$output" "$randomcontent" "cat random content"
# Make sure that running on a read-only rootfs works (#9230).
@@ -702,6 +702,8 @@ EOF
run_podman build -t nomtab $tmpdir
run_podman run --rm nomtab stat -c %N /etc/mtab
is "$output" "$expected" "/etc/mtab should be created"
+
+ run_podman rmi nomtab
}
# vim: filetype=sh
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 1cec50827..63b9a7c14 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -34,7 +34,7 @@ load helpers
# Bind-mount this file with a different name to a container running httpd
run_podman run -d --name myweb -p "$HOST_PORT:80" \
--restart always \
- -v $INDEX1:/var/www/index.txt \
+ -v $INDEX1:/var/www/index.txt:Z \
-w /var/www \
$IMAGE /bin/busybox-extras httpd -f -p 80
cid=$output
@@ -257,7 +257,7 @@ load helpers
# Bind-mount this file with a different name to a container running httpd
run_podman run -d --name myweb -p "$HOST_PORT:80" \
--network $netname \
- -v $INDEX1:/var/www/index.txt \
+ -v $INDEX1:/var/www/index.txt:Z \
-w /var/www \
$IMAGE /bin/busybox-extras httpd -f -p 80
cid=$output
diff --git a/vendor/github.com/containers/common/libimage/normalize.go b/vendor/github.com/containers/common/libimage/normalize.go
index 03d2456de..bfea807c8 100644
--- a/vendor/github.com/containers/common/libimage/normalize.go
+++ b/vendor/github.com/containers/common/libimage/normalize.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/image/v5/docker/reference"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
// NormalizeName normalizes the provided name according to the conventions by
@@ -40,6 +41,11 @@ func NormalizeName(name string) (reference.Named, error) {
}
if _, hasTag := named.(reference.NamedTagged); hasTag {
+ // Strip off the tag of a tagged and digested reference.
+ named, err = normalizeTaggedDigestedNamed(named)
+ if err != nil {
+ return nil, err
+ }
return named, nil
}
if _, hasDigest := named.(reference.Digested); hasDigest {
@@ -90,3 +96,48 @@ func ToNameTagPairs(repoTags []reference.Named) ([]NameTagPair, error) {
}
return pairs, nil
}
+
+// normalizeTaggedDigestedString strips the tag off the specified string iff it
+// is tagged and digested. Note that the tag is entirely ignored to match
+// Docker behavior.
+func normalizeTaggedDigestedString(s string) (string, error) {
+ // Note that the input string is not expected to be parseable, so we
+ // return it verbatim in error cases.
+ ref, err := reference.Parse(s)
+ if err != nil {
+ return "", err
+ }
+ named, ok := ref.(reference.Named)
+ if !ok {
+ return s, nil
+ }
+ named, err = normalizeTaggedDigestedNamed(named)
+ if err != nil {
+ return "", err
+ }
+ return named.String(), nil
+}
+
+// normalizeTaggedDigestedNamed strips the tag off the specified named
+// reference iff it is tagged and digested. Note that the tag is entirely
+// ignored to match Docker behavior.
+func normalizeTaggedDigestedNamed(named reference.Named) (reference.Named, error) {
+ _, isTagged := named.(reference.NamedTagged)
+ if !isTagged {
+ return named, nil
+ }
+ digested, isDigested := named.(reference.Digested)
+ if !isDigested {
+ return named, nil
+ }
+
+ // Now strip off the tag.
+ newNamed := reference.TrimNamed(named)
+ // And re-add the digest.
+ newNamed, err := reference.WithDigest(newNamed, digested.Digest())
+ if err != nil {
+ return named, err
+ }
+ logrus.Debugf("Stripped off tag from tagged and digested reference %q", named.String())
+ return newNamed, nil
+}
diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go
index 5fa888251..acf5c818f 100644
--- a/vendor/github.com/containers/common/libimage/pull.go
+++ b/vendor/github.com/containers/common/libimage/pull.go
@@ -52,6 +52,7 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP
options = &PullOptions{}
}
+ var possiblyUnqualifiedName string // used for short-name resolution
ref, err := alltransports.ParseImageName(name)
if err != nil {
// If the image clearly refers to a local one, we can look it up directly.
@@ -67,6 +68,15 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP
return []*Image{local}, err
}
+ // Docker compat: strip off the tag iff name is tagged and digested
+ // (e.g., fedora:latest@sha256...). In that case, the tag is stripped
+ // off and entirely ignored. The digest is the sole source of truth.
+ normalizedName, normalizeError := normalizeTaggedDigestedString(name)
+ if normalizeError != nil {
+ return nil, normalizeError
+ }
+ name = normalizedName
+
// If the input does not include a transport assume it refers
// to a registry.
dockerRef, dockerErr := alltransports.ParseImageName("docker://" + name)
@@ -74,6 +84,17 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP
return nil, err
}
ref = dockerRef
+ possiblyUnqualifiedName = name
+ } else if ref.Transport().Name() == registryTransport.Transport.Name() {
+ // Normalize the input if we're referring to the docker
+ // transport directly. That makes sure that a `docker://fedora`
+ // will resolve directly to `docker.io/library/fedora:latest`
+ // and not be subject to short-name resolution.
+ named := ref.DockerReference()
+ if named == nil {
+ return nil, errors.New("internal error: unexpected nil reference")
+ }
+ possiblyUnqualifiedName = named.String()
}
if options.AllTags && ref.Transport().Name() != registryTransport.Transport.Name() {
@@ -94,7 +115,7 @@ func (r *Runtime) Pull(ctx context.Context, name string, pullPolicy config.PullP
// DOCKER REGISTRY
case registryTransport.Transport.Name():
- pulledImages, pullError = r.copyFromRegistry(ctx, ref, strings.TrimPrefix(name, "docker://"), pullPolicy, options)
+ pulledImages, pullError = r.copyFromRegistry(ctx, ref, possiblyUnqualifiedName, pullPolicy, options)
// DOCKER ARCHIVE
case dockerArchiveTransport.Transport.Name():
diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go
index aa798d008..bbf1c2a61 100644
--- a/vendor/github.com/containers/common/libimage/runtime.go
+++ b/vendor/github.com/containers/common/libimage/runtime.go
@@ -180,6 +180,15 @@ func (r *Runtime) LookupImage(name string, options *LookupImageOptions) (*Image,
}
logrus.Debugf("Found image %q in local containers storage (%s)", name, storageRef.StringWithinTransport())
return r.storageToImage(img, storageRef), "", nil
+ } else {
+ // Docker compat: strip off the tag iff name is tagged and digested
+ // (e.g., fedora:latest@sha256...). In that case, the tag is stripped
+ // off and entirely ignored. The digest is the sole source of truth.
+ normalizedName, err := normalizeTaggedDigestedString(name)
+ if err != nil {
+ return nil, "", err
+ }
+ name = normalizedName
}
originalName := name
diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go
index 2b660d1ab..d5a7d5b84 100644
--- a/vendor/github.com/containers/common/pkg/config/default.go
+++ b/vendor/github.com/containers/common/pkg/config/default.go
@@ -195,7 +195,7 @@ func DefaultConfig() (*Config, error) {
Init: false,
InitPath: "",
IPCNS: "private",
- LogDriver: DefaultLogDriver,
+ LogDriver: defaultLogDriver(),
LogSizeMax: DefaultLogSizeMax,
NetNS: netns,
NoHosts: false,
diff --git a/vendor/github.com/containers/common/pkg/config/nosystemd.go b/vendor/github.com/containers/common/pkg/config/nosystemd.go
index 5b82b1389..6e39a6ccd 100644
--- a/vendor/github.com/containers/common/pkg/config/nosystemd.go
+++ b/vendor/github.com/containers/common/pkg/config/nosystemd.go
@@ -3,9 +3,17 @@
package config
func defaultCgroupManager() string {
- return "cgroupfs"
+ return CgroupfsCgroupsManager
}
func defaultEventsLogger() string {
return "file"
}
+
+func defaultLogDriver() string {
+ return DefaultLogDriver
+}
+
+func useSystemd() bool {
+ return false
+}
diff --git a/vendor/github.com/containers/common/pkg/config/systemd.go b/vendor/github.com/containers/common/pkg/config/systemd.go
index 02e5c4ac2..ed014126b 100644
--- a/vendor/github.com/containers/common/pkg/config/systemd.go
+++ b/vendor/github.com/containers/common/pkg/config/systemd.go
@@ -3,11 +3,23 @@
package config
import (
+ "io/ioutil"
+ "strings"
+ "sync"
+
"github.com/containers/common/pkg/cgroupv2"
"github.com/containers/storage/pkg/unshare"
)
+var (
+ systemdOnce sync.Once
+ usesSystemd bool
+)
+
func defaultCgroupManager() string {
+ if !useSystemd() {
+ return CgroupfsCgroupsManager
+ }
enabled, err := cgroupv2.Enabled()
if err == nil && !enabled && unshare.IsRootless() {
return CgroupfsCgroupsManager
@@ -15,6 +27,32 @@ func defaultCgroupManager() string {
return SystemdCgroupsManager
}
+
func defaultEventsLogger() string {
- return "journald"
+ if useSystemd() {
+ return "journald"
+ }
+ return "file"
+}
+
+func defaultLogDriver() string {
+ // If we decide to change the default for logdriver, it should be done here.
+ if useSystemd() {
+ return DefaultLogDriver
+ }
+
+ return DefaultLogDriver
+
+}
+
+func useSystemd() bool {
+ systemdOnce.Do(func() {
+ dat, err := ioutil.ReadFile("/proc/1/comm")
+ if err == nil {
+ val := strings.TrimSuffix(string(dat), "\n")
+ usesSystemd = (val == "systemd")
+ }
+ return
+ })
+ return usesSystemd
}
diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go
index 54661f433..ff3bf9a32 100644
--- a/vendor/github.com/containers/common/version/version.go
+++ b/vendor/github.com/containers/common/version/version.go
@@ -1,4 +1,4 @@
package version
// Version is the version of the build.
-const Version = "0.39.0"
+const Version = "0.39.1-dev"
diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go
index ab8863d75..88ac2b2c9 100644
--- a/vendor/github.com/onsi/ginkgo/config/config.go
+++ b/vendor/github.com/onsi/ginkgo/config/config.go
@@ -20,7 +20,7 @@ import (
"fmt"
)
-const VERSION = "1.16.2"
+const VERSION = "1.16.3"
type GinkgoConfigType struct {
RandomSeed int64
diff --git a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
index 998c2c2ca..4a6e1e1ee 100644
--- a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
+++ b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go
@@ -473,24 +473,28 @@ func By(text string, callbacks ...func()) {
//The body function must have the signature:
// func(b Benchmarker)
func Measure(text string, body interface{}, samples int) bool {
+ deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
global.Suite.PushMeasureNode(text, body, types.FlagTypeNone, codelocation.New(1), samples)
return true
}
//You can focus individual Measures using FMeasure
func FMeasure(text string, body interface{}, samples int) bool {
+ deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
global.Suite.PushMeasureNode(text, body, types.FlagTypeFocused, codelocation.New(1), samples)
return true
}
//You can mark Measurements as pending using PMeasure
func PMeasure(text string, _ ...interface{}) bool {
+ deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
//You can mark Measurements as pending using XMeasure
func XMeasure(text string, _ ...interface{}) bool {
+ deprecationTracker.TrackDeprecation(types.Deprecations.Measure(), codelocation.New(1))
global.Suite.PushMeasureNode(text, func(b Benchmarker) {}, types.FlagTypePending, codelocation.New(1), 0)
return true
}
diff --git a/vendor/github.com/onsi/ginkgo/types/deprecation_support.go b/vendor/github.com/onsi/ginkgo/types/deprecation_support.go
index 71420f597..305c134b7 100644
--- a/vendor/github.com/onsi/ginkgo/types/deprecation_support.go
+++ b/vendor/github.com/onsi/ginkgo/types/deprecation_support.go
@@ -46,9 +46,9 @@ func (d deprecations) Async() Deprecation {
func (d deprecations) Measure() Deprecation {
return Deprecation{
- Message: "Measure is deprecated in Ginkgo V2",
+ Message: "Measure is deprecated and will be removed in Ginkgo V2. Please migrate to gomega/gmeasure.",
DocLink: "removed-measure",
- Version: "1.16.0",
+ Version: "1.16.3",
}
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 9eb01adfe..83cd57794 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -91,7 +91,7 @@ github.com/containers/buildah/pkg/overlay
github.com/containers/buildah/pkg/parse
github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/util
-# github.com/containers/common v0.39.0
+# github.com/containers/common v0.39.1-0.20210527140106-e5800a20386a
github.com/containers/common/libimage
github.com/containers/common/libimage/manifests
github.com/containers/common/pkg/apparmor
@@ -446,7 +446,7 @@ github.com/nxadm/tail/ratelimiter
github.com/nxadm/tail/util
github.com/nxadm/tail/watch
github.com/nxadm/tail/winfile
-# github.com/onsi/ginkgo v1.16.2
+# github.com/onsi/ginkgo v1.16.3
github.com/onsi/ginkgo
github.com/onsi/ginkgo/config
github.com/onsi/ginkgo/extensions/table