summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/volumes.go2
-rwxr-xr-xcontrib/cirrus/runner.sh14
-rw-r--r--libpod/container_internal.go17
-rw-r--r--libpod/container_internal_linux.go2
-rw-r--r--pkg/api/handlers/compat/unsupported.go5
-rw-r--r--pkg/api/handlers/utils/errors.go4
-rw-r--r--pkg/api/server/swagger.go29
-rw-r--r--pkg/bindings/errors.go6
-rw-r--r--pkg/domain/entities/types.go24
-rw-r--r--pkg/domain/infra/tunnel/containers.go2
-rw-r--r--pkg/domain/infra/tunnel/images.go9
-rw-r--r--pkg/domain/infra/tunnel/network.go3
-rw-r--r--pkg/domain/infra/tunnel/volumes.go3
-rw-r--r--pkg/errorhandling/errorhandling.go24
-rw-r--r--pkg/specgen/generate/kube/kube.go21
-rw-r--r--pkg/specgen/generate/kube/volume.go2
-rw-r--r--pkg/specgen/volumes.go2
-rw-r--r--test/e2e/play_kube_test.go72
-rw-r--r--test/e2e/restart_test.go29
-rw-r--r--vendor/github.com/containers/common/pkg/parse/parse.go157
-rw-r--r--vendor/github.com/containers/common/pkg/parse/parse_unix.go51
-rw-r--r--vendor/modules.txt1
22 files changed, 373 insertions, 106 deletions
diff --git a/cmd/podman/common/volumes.go b/cmd/podman/common/volumes.go
index dfbb7b1b2..a6e6faeca 100644
--- a/cmd/podman/common/volumes.go
+++ b/cmd/podman/common/volumes.go
@@ -5,7 +5,7 @@ import (
"path/filepath"
"strings"
- "github.com/containers/buildah/pkg/parse"
+ "github.com/containers/common/pkg/parse"
"github.com/containers/podman/v2/pkg/specgen"
"github.com/containers/podman/v2/pkg/util"
spec "github.com/opencontainers/runtime-spec/specs-go"
diff --git a/contrib/cirrus/runner.sh b/contrib/cirrus/runner.sh
index 2f909876a..b0060163e 100755
--- a/contrib/cirrus/runner.sh
+++ b/contrib/cirrus/runner.sh
@@ -203,16 +203,18 @@ function _run_altbuild() {
function _run_release() {
# TODO: These tests should come from code external to the podman repo.
- # to allow test-changes (and re-runs) in the case of a correctible test
+ # to allow test-changes (and re-runs) in the case of a correctable test
# flaw or flake at release tag-push time. For now, the test is here
- # given it's simplicity.
+ # given its simplicity.
+ msg "podman info:"
+ bin/podman info
msg "Checking podman release (or potential release) criteria."
- info_output=$(bin/podman info 2>&1)
- if grep -q -- '-dev'<<<"$info_output"; then
- die "Releases must never contain '-dev' in output of 'podman info':
-$info_output"
+ dev=$(bin/podman info |& grep -- -dev)
+ if [[ -n "$dev" ]]; then
+ die "Releases must never contain '-dev' in output of 'podman info' ($dev)"
fi
+ msg "All OK"
}
logformatter() {
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index c7548e0e5..f4cdb749f 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -1,6 +1,7 @@
package libpod
import (
+ "bufio"
"bytes"
"context"
"fmt"
@@ -1865,16 +1866,26 @@ func (c *Container) writeStringToStaticDir(filename, contents string) (string, e
return destFileName, nil
}
-// appendStringToRundir appends the provided string to the runtimedir file
-func (c *Container) appendStringToRundir(destFile, output string) (string, error) {
+// appendStringToRunDir appends the provided string to the runtimedir file
+func (c *Container) appendStringToRunDir(destFile, output string) (string, error) {
destFileName := filepath.Join(c.state.RunDir, destFile)
- f, err := os.OpenFile(destFileName, os.O_APPEND|os.O_WRONLY, 0600)
+ f, err := os.OpenFile(destFileName, os.O_APPEND|os.O_RDWR, 0600)
if err != nil {
return "", err
}
defer f.Close()
+ compareStr := strings.TrimRight(output, "\n")
+ scanner := bufio.NewScanner(f)
+ scanner.Split(bufio.ScanLines)
+
+ for scanner.Scan() {
+ if strings.Compare(scanner.Text(), compareStr) == 0 {
+ return filepath.Join(c.state.RunDir, destFile), nil
+ }
+ }
+
if _, err := f.WriteString(output); err != nil {
return "", errors.Wrapf(err, "unable to write %s", destFileName)
}
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 575047f95..ce2b52234 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1742,7 +1742,7 @@ func (c *Container) generateHosts(path string) (string, error) {
// FIXME. Path should be used by this function,but I am not sure what is correct; remove //lint
// once this is fixed
func (c *Container) appendHosts(path string, netCtr *Container) (string, error) { //nolint
- return c.appendStringToRundir("hosts", netCtr.getHosts())
+ return c.appendStringToRunDir("hosts", netCtr.getHosts())
}
// getHosts finds the pertinent information for a container's host file in its config and state
diff --git a/pkg/api/handlers/compat/unsupported.go b/pkg/api/handlers/compat/unsupported.go
index e5ff266f9..1c518690f 100644
--- a/pkg/api/handlers/compat/unsupported.go
+++ b/pkg/api/handlers/compat/unsupported.go
@@ -4,9 +4,8 @@ import (
"fmt"
"net/http"
- "github.com/containers/podman/v2/pkg/domain/entities"
-
"github.com/containers/podman/v2/pkg/api/handlers/utils"
+ "github.com/containers/podman/v2/pkg/errorhandling"
log "github.com/sirupsen/logrus"
)
@@ -14,5 +13,5 @@ func UnsupportedHandler(w http.ResponseWriter, r *http.Request) {
msg := fmt.Sprintf("Path %s is not supported", r.URL.Path)
log.Infof("Request Failed: %s", msg)
- utils.WriteJSON(w, http.StatusNotFound, entities.ErrorModel{Message: msg})
+ utils.WriteJSON(w, http.StatusNotFound, errorhandling.ErrorModel{Message: msg})
}
diff --git a/pkg/api/handlers/utils/errors.go b/pkg/api/handlers/utils/errors.go
index fc77b8ec0..e2c287c45 100644
--- a/pkg/api/handlers/utils/errors.go
+++ b/pkg/api/handlers/utils/errors.go
@@ -5,7 +5,7 @@ import (
"net/http"
"github.com/containers/podman/v2/libpod/define"
- "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/errorhandling"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
)
@@ -24,7 +24,7 @@ var (
func Error(w http.ResponseWriter, apiMessage string, code int, err error) {
// Log detailed message of what happened to machine running podman service
log.Infof("Request Failed(%s): %s", http.StatusText(code), err.Error())
- em := entities.ErrorModel{
+ em := errorhandling.ErrorModel{
Because: (errors.Cause(err)).Error(),
Message: err.Error(),
ResponseCode: code,
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 45253e01a..d4fc33442 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/entities/reports"
+ "github.com/containers/podman/v2/pkg/errorhandling"
)
// No such image
@@ -12,7 +13,7 @@ import (
type swagErrNoSuchImage struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -21,7 +22,7 @@ type swagErrNoSuchImage struct {
type swagErrNoSuchContainer struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -30,7 +31,7 @@ type swagErrNoSuchContainer struct {
type swagErrNoSuchNetwork struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -39,7 +40,7 @@ type swagErrNoSuchNetwork struct {
type swagErrNoSuchExecInstance struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -48,7 +49,7 @@ type swagErrNoSuchExecInstance struct {
type swagErrNoSuchVolume struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -57,7 +58,7 @@ type swagErrNoSuchVolume struct {
type swagErrNoSuchPod struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -66,7 +67,7 @@ type swagErrNoSuchPod struct {
type swagErrNoSuchManifest struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -75,7 +76,7 @@ type swagErrNoSuchManifest struct {
type swagInternalError struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -84,7 +85,7 @@ type swagInternalError struct {
type swagConflictError struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -93,7 +94,7 @@ type swagConflictError struct {
type swagBadParamError struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -102,7 +103,7 @@ type swagBadParamError struct {
type swagContainerAlreadyStartedError struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -111,7 +112,7 @@ type swagContainerAlreadyStartedError struct {
type swagContainerAlreadyStopped struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -120,7 +121,7 @@ type swagContainerAlreadyStopped struct {
type swagPodAlreadyStartedError struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
@@ -129,7 +130,7 @@ type swagPodAlreadyStartedError struct {
type swagPodAlreadyStopped struct {
// in:body
Body struct {
- entities.ErrorModel
+ errorhandling.ErrorModel
}
}
diff --git a/pkg/bindings/errors.go b/pkg/bindings/errors.go
index 603299389..e75ce898d 100644
--- a/pkg/bindings/errors.go
+++ b/pkg/bindings/errors.go
@@ -4,7 +4,7 @@ import (
"encoding/json"
"io/ioutil"
- "github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/errorhandling"
"github.com/pkg/errors"
)
@@ -13,7 +13,7 @@ var (
)
func handleError(data []byte) error {
- e := entities.ErrorModel{}
+ e := errorhandling.ErrorModel{}
if err := json.Unmarshal(data, &e); err != nil {
return err
}
@@ -36,7 +36,7 @@ func (a APIResponse) Process(unmarshalInto interface{}) error {
}
func CheckResponseCode(inError error) (int, error) {
- e, ok := inError.(entities.ErrorModel)
+ e, ok := inError.(errorhandling.ErrorModel)
if !ok {
return -1, errors.New("error is not type ErrorModel")
}
diff --git a/pkg/domain/entities/types.go b/pkg/domain/entities/types.go
index 12135c2b1..e5473dc62 100644
--- a/pkg/domain/entities/types.go
+++ b/pkg/domain/entities/types.go
@@ -1,7 +1,6 @@
package entities
import (
- "errors"
"net"
"github.com/containers/buildah/imagebuildah"
@@ -90,29 +89,6 @@ type ContainerCreateResponse struct {
Warnings []string `json:"Warnings"`
}
-type ErrorModel struct {
- // API root cause formatted for automated parsing
- // example: API root cause
- Because string `json:"cause"`
- // human error message, formatted for a human to read
- // example: human error message
- Message string `json:"message"`
- // http response code
- ResponseCode int `json:"response"`
-}
-
-func (e ErrorModel) Error() string {
- return e.Message
-}
-
-func (e ErrorModel) Cause() error {
- return errors.New(e.Because)
-}
-
-func (e ErrorModel) Code() int {
- return e.ResponseCode
-}
-
// BuildOptions describe the options for building container images.
type BuildOptions struct {
imagebuildah.BuildOptions
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 3366cb425..49bcdec98 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -211,7 +211,7 @@ func (ic *ContainerEngine) ContainerInspect(ctx context.Context, namesOrIds []st
for _, name := range namesOrIds {
inspect, err := containers.Inspect(ic.ClientCtx, name, options)
if err != nil {
- errModel, ok := err.(entities.ErrorModel)
+ errModel, ok := err.(errorhandling.ErrorModel)
if !ok {
return nil, nil, err
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 8ab832599..7a4aa1fbc 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -8,16 +8,15 @@ import (
"strings"
"time"
- "github.com/containers/podman/v2/libpod/image"
-
- "github.com/containers/image/v5/types"
-
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/docker/reference"
+ "github.com/containers/image/v5/types"
+ "github.com/containers/podman/v2/libpod/image"
images "github.com/containers/podman/v2/pkg/bindings/images"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/domain/utils"
+ "github.com/containers/podman/v2/pkg/errorhandling"
utils2 "github.com/containers/podman/v2/utils"
"github.com/pkg/errors"
)
@@ -187,7 +186,7 @@ func (ir *ImageEngine) Inspect(ctx context.Context, namesOrIDs []string, opts en
for _, i := range namesOrIDs {
r, err := images.GetImage(ir.ClientCtx, i, options)
if err != nil {
- errModel, ok := err.(entities.ErrorModel)
+ errModel, ok := err.(errorhandling.ErrorModel)
if !ok {
return nil, nil, err
}
diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go
index 9afb8db02..d4e827580 100644
--- a/pkg/domain/infra/tunnel/network.go
+++ b/pkg/domain/infra/tunnel/network.go
@@ -5,6 +5,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings/network"
"github.com/containers/podman/v2/pkg/domain/entities"
+ "github.com/containers/podman/v2/pkg/errorhandling"
"github.com/pkg/errors"
)
@@ -22,7 +23,7 @@ func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []stri
for _, name := range namesOrIds {
report, err := network.Inspect(ic.ClientCtx, name, options)
if err != nil {
- errModel, ok := err.(entities.ErrorModel)
+ errModel, ok := err.(errorhandling.ErrorModel)
if !ok {
return nil, nil, err
}
diff --git a/pkg/domain/infra/tunnel/volumes.go b/pkg/domain/infra/tunnel/volumes.go
index 10e8d7da8..f21336828 100644
--- a/pkg/domain/infra/tunnel/volumes.go
+++ b/pkg/domain/infra/tunnel/volumes.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/podman/v2/pkg/bindings/volumes"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/domain/entities/reports"
+ "github.com/containers/podman/v2/pkg/errorhandling"
"github.com/pkg/errors"
)
@@ -55,7 +56,7 @@ func (ic *ContainerEngine) VolumeInspect(ctx context.Context, namesOrIds []strin
for _, id := range namesOrIds {
data, err := volumes.Inspect(ic.ClientCtx, id, nil)
if err != nil {
- errModel, ok := err.(entities.ErrorModel)
+ errModel, ok := err.(errorhandling.ErrorModel)
if !ok {
return nil, nil, err
}
diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go
index 21df261fb..b1923be98 100644
--- a/pkg/errorhandling/errorhandling.go
+++ b/pkg/errorhandling/errorhandling.go
@@ -70,3 +70,27 @@ func CloseQuiet(f *os.File) {
func Contains(err error, sub error) bool {
return strings.Contains(err.Error(), sub.Error())
}
+
+// ErrorModel is used in remote connections with podman
+type ErrorModel struct {
+ // API root cause formatted for automated parsing
+ // example: API root cause
+ Because string `json:"cause"`
+ // human error message, formatted for a human to read
+ // example: human error message
+ Message string `json:"message"`
+ // http response code
+ ResponseCode int `json:"response"`
+}
+
+func (e ErrorModel) Error() string {
+ return e.Message
+}
+
+func (e ErrorModel) Cause() error {
+ return errors.New(e.Because)
+}
+
+func (e ErrorModel) Code() int {
+ return e.ResponseCode
+}
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index e5b09dcd8..e39a700eb 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -5,7 +5,7 @@ import (
"fmt"
"strings"
- "github.com/containers/buildah/pkg/parse"
+ "github.com/containers/common/pkg/parse"
"github.com/containers/podman/v2/libpod/image"
ann "github.com/containers/podman/v2/pkg/annotations"
"github.com/containers/podman/v2/pkg/specgen"
@@ -129,24 +129,20 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
// TODO: We don't understand why specgen does not take of this, but
// integration tests clearly pointed out that it was required.
- s.Command = []string{}
imageData, err := opts.Image.Inspect(ctx)
if err != nil {
return nil, err
}
s.WorkDir = "/"
- // We will use "Docker field name" internally here to avoid confusion
- // and reference the "Kubernetes field name" when referencing the YAML
- // ref: https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#notes
- entrypoint := []string{}
- cmd := []string{}
+ // Entrypoint/Command handling is based off of
+ // https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#notes
if imageData != nil && imageData.Config != nil {
if imageData.Config.WorkingDir != "" {
s.WorkDir = imageData.Config.WorkingDir
}
// Pull entrypoint and cmd from image
- entrypoint = imageData.Config.Entrypoint
- cmd = imageData.Config.Cmd
+ s.Entrypoint = imageData.Config.Entrypoint
+ s.Command = imageData.Config.Cmd
s.Labels = imageData.Config.Labels
if len(imageData.Config.StopSignal) > 0 {
stopSignal, err := util.ParseSignal(imageData.Config.StopSignal)
@@ -158,16 +154,15 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
}
// If only the yaml.Command is specified, set it as the entrypoint and drop the image Cmd
if len(opts.Container.Command) != 0 {
- entrypoint = opts.Container.Command
- cmd = []string{}
+ s.Entrypoint = opts.Container.Command
+ s.Command = []string{}
}
// Only override the cmd field if yaml.Args is specified
// Keep the image entrypoint, or the yaml.command if specified
if len(opts.Container.Args) != 0 {
- cmd = opts.Container.Args
+ s.Command = opts.Container.Args
}
- s.Command = append(entrypoint, cmd...)
// FIXME,
// we are currently ignoring imageData.Config.ExposedPorts
if opts.Container.WorkingDir != "" {
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index bb8edabb7..f5687f60d 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -3,7 +3,7 @@ package kube
import (
"os"
- "github.com/containers/buildah/pkg/parse"
+ "github.com/containers/common/pkg/parse"
"github.com/containers/podman/v2/libpod"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
diff --git a/pkg/specgen/volumes.go b/pkg/specgen/volumes.go
index a4f42d715..83634b4ef 100644
--- a/pkg/specgen/volumes.go
+++ b/pkg/specgen/volumes.go
@@ -4,7 +4,7 @@ import (
"path/filepath"
"strings"
- "github.com/containers/buildah/pkg/parse"
+ "github.com/containers/common/pkg/parse"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index f009e333e..5930462d5 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -825,9 +825,16 @@ var _ = Describe("Podman play kube", func() {
inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
+ cmd := inspect.OutputToString()
+
+ inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ ep := inspect.OutputToString()
+
// Use the defined command to override the image's command
- correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
- Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
+ Expect(ep).To(ContainSubstring(strings.Join(defaultCtrCmd, " ")))
+ Expect(cmd).To(ContainSubstring(strings.Join(defaultCtrArg, " ")))
})
// If you do not supply command or args for a Container, the defaults defined in the Docker image are used.
@@ -840,12 +847,17 @@ var _ = Describe("Podman play kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
+ // this image's ENTRYPOINT is `/entrypoint.sh`
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`/entrypoint.sh`))
- // this image's ENTRYPOINT is `/entrypoint.sh` and it's COMMAND is `/etc/docker/registry/config.yml`
- Expect(inspect.OutputToString()).To(ContainSubstring(`[/entrypoint.sh /etc/docker/registry/config.yml]`))
+ // and its COMMAND is `/etc/docker/registry/config.yml`
+ inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`[/etc/docker/registry/config.yml]`))
})
// If you supply a command but no args for a Container, only the supplied command is used.
@@ -859,12 +871,18 @@ var _ = Describe("Podman play kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
- inspect.WaitWithDefaultTimeout()
- Expect(inspect.ExitCode()).To(Equal(0))
// Use the defined command to override the image's command, and don't set the args
// so the full command in result should not contains the image's command
- Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello]`))
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`echo hello`))
+
+ inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ // an empty command is reported as '[]'
+ Expect(inspect.OutputToString()).To(ContainSubstring(`[]`))
})
// If you supply only args for a Container, the default Entrypoint defined in the Docker image is run with the args that you supplied.
@@ -877,12 +895,16 @@ var _ = Describe("Podman play kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
+ // this image's ENTRYPOINT is `/entrypoint.sh`
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
- // this image's ENTRYPOINT is `/entrypoint.sh`
- // so result should be `/entrypoint.sh + withArg(...)`
- Expect(inspect.OutputToString()).To(ContainSubstring(`[/entrypoint.sh echo hello]`))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`/entrypoint.sh`))
+
+ inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello]`))
})
// If you supply a command and args,
@@ -897,10 +919,15 @@ var _ = Describe("Podman play kube", func() {
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).To(Equal(0))
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Entrypoint }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
- Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello]`))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`echo`))
+
+ inspect = podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod), "--format", "'{{ .Config.Cmd }}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`[hello]`))
})
It("podman play kube test correct output", func() {
@@ -917,11 +944,6 @@ var _ = Describe("Podman play kube", func() {
logs.WaitWithDefaultTimeout()
Expect(logs.ExitCode()).To(Equal(0))
Expect(logs.OutputToString()).To(ContainSubstring("hello world"))
-
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(p), "--format", "'{{ .Config.Cmd }}'"})
- inspect.WaitWithDefaultTimeout()
- Expect(inspect.ExitCode()).To(Equal(0))
- Expect(inspect.OutputToString()).To(ContainSubstring(`[echo hello world]`))
})
It("podman play kube test restartPolicy", func() {
@@ -1286,12 +1308,11 @@ spec:
Expect(kube.ExitCode()).To(Equal(0))
podNames := getPodNamesInDeployment(deployment)
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[0]), "--format", "'{{ .Config.Cmd }}'"})
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[0]), "--format", "'{{ .Config.Entrypoint }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
// yaml's command should override the image's Entrypoint
- correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
- Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
+ Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " ")))
})
It("podman play kube deployment more than 1 replica test correct command", func() {
@@ -1306,12 +1327,11 @@ spec:
Expect(kube.ExitCode()).To(Equal(0))
podNames := getPodNamesInDeployment(deployment)
- correctCmd := "[" + strings.Join(defaultCtrCmd, " ") + " " + strings.Join(defaultCtrArg, " ")
for i = 0; i < numReplicas; i++ {
- inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "'{{ .Config.Cmd }}'"})
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "'{{ .Config.Entrypoint }}'"})
inspect.WaitWithDefaultTimeout()
Expect(inspect.ExitCode()).To(Equal(0))
- Expect(inspect.OutputToString()).To(ContainSubstring(correctCmd))
+ Expect(inspect.OutputToString()).To(ContainSubstring(strings.Join(defaultCtrCmd, " ")))
}
})
diff --git a/test/e2e/restart_test.go b/test/e2e/restart_test.go
index 114bd481a..584ccd22b 100644
--- a/test/e2e/restart_test.go
+++ b/test/e2e/restart_test.go
@@ -196,4 +196,33 @@ var _ = Describe("Podman restart", func() {
Expect(restartTime.OutputToStringArray()[0]).To(Equal(startTime.OutputToStringArray()[0]))
Expect(restartTime.OutputToStringArray()[1]).To(Not(Equal(startTime.OutputToStringArray()[1])))
})
+
+ It("Podman restart a container in a pod and hosts shouln't duplicated", func() {
+ // Fixes: https://github.com/containers/podman/issues/8921
+
+ _, ec, _ := podmanTest.CreatePod("foobar99")
+ Expect(ec).To(Equal(0))
+
+ session := podmanTest.RunTopContainerInPod("host-restart-test", "foobar99")
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ testCmd := []string{"exec", "host-restart-test", "sh", "-c", "wc -l < /etc/hosts"}
+
+ // before restart
+ beforeRestart := podmanTest.Podman(testCmd)
+ beforeRestart.WaitWithDefaultTimeout()
+ Expect(beforeRestart.ExitCode()).To(Equal(0))
+
+ session = podmanTest.Podman([]string{"restart", "host-restart-test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ afterRestart := podmanTest.Podman(testCmd)
+ afterRestart.WaitWithDefaultTimeout()
+ Expect(afterRestart.ExitCode()).To(Equal(0))
+
+ // line count should be equal
+ Expect(beforeRestart.OutputToString()).To(Equal(afterRestart.OutputToString()))
+ })
})
diff --git a/vendor/github.com/containers/common/pkg/parse/parse.go b/vendor/github.com/containers/common/pkg/parse/parse.go
new file mode 100644
index 000000000..611b2e84b
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/parse/parse.go
@@ -0,0 +1,157 @@
+package parse
+
+// this package contains functions that parse and validate
+// user input and is shared either amongst container engine subcommands
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/pkg/errors"
+)
+
+// ValidateVolumeOpts validates a volume's options
+func ValidateVolumeOpts(options []string) ([]string, error) {
+ var foundRootPropagation, foundRWRO, foundLabelChange, bindType, foundExec, foundDev, foundSuid int
+ finalOpts := make([]string, 0, len(options))
+ for _, opt := range options {
+ switch opt {
+ case "noexec", "exec":
+ foundExec++
+ if foundExec > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'noexec' or 'exec' option", strings.Join(options, ", "))
+ }
+ case "nodev", "dev":
+ foundDev++
+ if foundDev > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'nodev' or 'dev' option", strings.Join(options, ", "))
+ }
+ case "nosuid", "suid":
+ foundSuid++
+ if foundSuid > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'nosuid' or 'suid' option", strings.Join(options, ", "))
+ }
+ case "rw", "ro":
+ foundRWRO++
+ if foundRWRO > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'rw' or 'ro' option", strings.Join(options, ", "))
+ }
+ case "z", "Z", "O":
+ foundLabelChange++
+ if foundLabelChange > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 'z', 'Z', or 'O' option", strings.Join(options, ", "))
+ }
+ case "private", "rprivate", "shared", "rshared", "slave", "rslave", "unbindable", "runbindable":
+ foundRootPropagation++
+ if foundRootPropagation > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]shared', '[r]private', '[r]slave' or '[r]unbindable' option", strings.Join(options, ", "))
+ }
+ case "bind", "rbind":
+ bindType++
+ if bindType > 1 {
+ return nil, errors.Errorf("invalid options %q, can only specify 1 '[r]bind' option", strings.Join(options, ", "))
+ }
+ case "cached", "delegated":
+ // The discarded ops are OS X specific volume options
+ // introduced in a recent Docker version.
+ // They have no meaning on Linux, so here we silently
+ // drop them. This matches Docker's behavior (the options
+ // are intended to be always safe to use, even not on OS
+ // X).
+ continue
+ default:
+ return nil, errors.Errorf("invalid option type %q", opt)
+ }
+ finalOpts = append(finalOpts, opt)
+ }
+ return finalOpts, nil
+}
+
+// Device parses device mapping string to a src, dest & permissions string
+// Valid values for device looklike:
+// '/dev/sdc"
+// '/dev/sdc:/dev/xvdc"
+// '/dev/sdc:/dev/xvdc:rwm"
+// '/dev/sdc:rm"
+func Device(device string) (src, dest, permissions string, err error) {
+ permissions = "rwm"
+ arr := strings.Split(device, ":")
+ switch len(arr) {
+ case 3:
+ if !isValidDeviceMode(arr[2]) {
+ return "", "", "", errors.Errorf("invalid device mode: %s", arr[2])
+ }
+ permissions = arr[2]
+ fallthrough
+ case 2:
+ if isValidDeviceMode(arr[1]) {
+ permissions = arr[1]
+ } else {
+ if arr[1] == "" || arr[1][0] != '/' {
+ return "", "", "", errors.Errorf("invalid device mode: %s", arr[1])
+ }
+ dest = arr[1]
+ }
+ fallthrough
+ case 1:
+ if len(arr[0]) > 0 {
+ src = arr[0]
+ break
+ }
+ fallthrough
+ default:
+ return "", "", "", errors.Errorf("invalid device specification: %s", device)
+ }
+
+ if dest == "" {
+ dest = src
+ }
+ return src, dest, permissions, nil
+}
+
+// isValidDeviceMode checks if the mode for device is valid or not.
+// isValid mode is a composition of r (read), w (write), and m (mknod).
+func isValidDeviceMode(mode string) bool {
+ var legalDeviceMode = map[rune]bool{
+ 'r': true,
+ 'w': true,
+ 'm': true,
+ }
+ if mode == "" {
+ return false
+ }
+ for _, c := range mode {
+ if !legalDeviceMode[c] {
+ return false
+ }
+ legalDeviceMode[c] = false
+ }
+ return true
+}
+
+// ValidateVolumeHostDir validates a volume mount's source directory
+func ValidateVolumeHostDir(hostDir string) error {
+ if hostDir == "" {
+ return errors.Errorf("host directory cannot be empty")
+ }
+ if filepath.IsAbs(hostDir) {
+ if _, err := os.Stat(hostDir); err != nil {
+ return errors.Wrapf(err, "error checking path %q", hostDir)
+ }
+ }
+ // If hostDir is not an absolute path, that means the user wants to create a
+ // named volume. This will be done later on in the code.
+ return nil
+}
+
+// ValidateVolumeCtrDir validates a volume mount's destination directory.
+func ValidateVolumeCtrDir(ctrDir string) error {
+ if ctrDir == "" {
+ return errors.Errorf("container directory cannot be empty")
+ }
+ if !filepath.IsAbs(ctrDir) {
+ return errors.Errorf("invalid container path %q, must be an absolute path", ctrDir)
+ }
+ return nil
+}
diff --git a/vendor/github.com/containers/common/pkg/parse/parse_unix.go b/vendor/github.com/containers/common/pkg/parse/parse_unix.go
new file mode 100644
index 000000000..880fbf674
--- /dev/null
+++ b/vendor/github.com/containers/common/pkg/parse/parse_unix.go
@@ -0,0 +1,51 @@
+// +build linux darwin
+
+package parse
+
+import (
+ "os"
+ "path/filepath"
+
+ "github.com/containers/storage/pkg/unshare"
+ "github.com/opencontainers/runc/libcontainer/configs"
+ "github.com/opencontainers/runc/libcontainer/devices"
+ "github.com/pkg/errors"
+)
+
+func DeviceFromPath(device string) ([]configs.Device, error) {
+ var devs []configs.Device
+ src, dst, permissions, err := Device(device)
+ if err != nil {
+ return nil, err
+ }
+ if unshare.IsRootless() && src != dst {
+ return nil, errors.Errorf("Renaming device %s to %s is not supported in rootless containers", src, dst)
+ }
+ srcInfo, err := os.Stat(src)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting info of source device %s", src)
+ }
+
+ if !srcInfo.IsDir() {
+
+ dev, err := devices.DeviceFromPath(src, permissions)
+ if err != nil {
+ return nil, errors.Wrapf(err, "%s is not a valid device", src)
+ }
+ dev.Path = dst
+ devs = append(devs, *dev)
+ return devs, nil
+ }
+
+ // If source device is a directory
+ srcDevices, err := devices.GetDevices(src)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error getting source devices from directory %s", src)
+ }
+ for _, d := range srcDevices {
+ d.Path = filepath.Join(dst, filepath.Base(d.Path))
+ d.Permissions = configs.DevicePermissions(permissions)
+ devs = append(devs, *d)
+ }
+ return devs, nil
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index e15b16188..a7c3b628a 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -97,6 +97,7 @@ github.com/containers/common/pkg/capabilities
github.com/containers/common/pkg/cgroupv2
github.com/containers/common/pkg/completion
github.com/containers/common/pkg/config
+github.com/containers/common/pkg/parse
github.com/containers/common/pkg/report
github.com/containers/common/pkg/report/camelcase
github.com/containers/common/pkg/retry