diff options
-rw-r--r-- | cmd/podman/manifest/create.go | 5 | ||||
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 3 | ||||
-rw-r--r-- | libpod/oci_conmon_exec_linux.go | 3 | ||||
-rw-r--r-- | pkg/bindings/containers/attach.go | 19 | ||||
-rw-r--r-- | test/apiv2/20-containers.at | 8 | ||||
-rw-r--r-- | test/apiv2/30-volumes.at | 7 | ||||
-rw-r--r-- | test/e2e/manifest_test.go | 6 | ||||
-rw-r--r-- | test/system/075-exec.bats | 2 | ||||
-rw-r--r-- | test/system/500-networking.bats | 1 | ||||
-rw-r--r-- | vendor/github.com/google/uuid/null.go | 118 | ||||
-rw-r--r-- | vendor/github.com/google/uuid/uuid.go | 45 | ||||
-rw-r--r-- | vendor/github.com/google/uuid/version4.go | 27 | ||||
-rw-r--r-- | vendor/modules.txt | 2 |
14 files changed, 229 insertions, 19 deletions
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), } ) @@ -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 @@ -482,8 +482,9 @@ github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIE github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= diff --git a/libpod/oci_conmon_exec_linux.go b/libpod/oci_conmon_exec_linux.go index 09d3d1833..05a4e19b0 100644 --- a/libpod/oci_conmon_exec_linux.go +++ b/libpod/oci_conmon_exec_linux.go @@ -610,6 +610,9 @@ func attachExecHTTP(c *Container, sessionID string, r *http.Request, w http.Resp _, err := utils.CopyDetachable(conn, httpBuf, detachKeys) logrus.Debugf("STDIN copy completed") stdinChan <- err + if connErr := conn.CloseWrite(); connErr != nil { + logrus.Errorf("Unable to close conn: %v", connErr) + } }() } diff --git a/pkg/bindings/containers/attach.go b/pkg/bindings/containers/attach.go index cc12c8ab7..01c14d350 100644 --- a/pkg/bindings/containers/attach.go +++ b/pkg/bindings/containers/attach.go @@ -25,6 +25,12 @@ import ( "golang.org/x/crypto/ssh/terminal" ) +// The CloseWriter interface is used to determine whether we can do a one-sided +// close of a hijacked connection. +type CloseWriter interface { + CloseWrite() error +} + // Attach attaches to a running container func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Writer, stderr io.Writer, attachReady chan bool, options *AttachOptions) error { if options == nil { @@ -161,6 +167,12 @@ func Attach(ctx context.Context, nameOrID string, stdin io.Reader, stdout io.Wri logrus.Error("failed to write input to service: " + err.Error()) } stdinChan <- err + + if closeWrite, ok := socket.(CloseWriter); ok { + if err := closeWrite.CloseWrite(); err != nil { + logrus.Warnf("Failed to close STDIN for writing: %v", err) + } + } }() } @@ -485,6 +497,13 @@ func ExecStartAndAttach(ctx context.Context, sessionID string, options *ExecStar if err != nil { logrus.Error("failed to write input to service: " + err.Error()) } + + if closeWrite, ok := socket.(CloseWriter); ok { + logrus.Debugf("Closing STDIN") + if err := closeWrite.CloseWrite(); err != nil { + logrus.Warnf("Failed to close STDIN for writing: %v", err) + } + } }() } diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index ef51757c9..c5b2f5ec1 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -211,15 +211,11 @@ t GET containers/$cid/json 200 \ t POST containers/create Image=$IMAGE Entrypoint='["top"]' 201 \ .Id~[0-9a-f]\\{64\\} cid_top=$(jq -r '.Id' <<<"$output") -network_expect="{}" -if root; then - network_expect='.podman.NetworkID=podman' -fi t GET containers/${cid_top}/json 200 \ .Config.Entrypoint[0]="top" \ .Config.Cmd='[]' \ - .Path="top" - .NetworkSettings.Networks="$network_expect" + .Path="top" \ + .NetworkSettings.Networks.podman.NetworkID=podman t POST containers/${cid_top}/start 204 # make sure the container is running t GET containers/${cid_top}/json 200 \ diff --git a/test/apiv2/30-volumes.at b/test/apiv2/30-volumes.at index 5feceea7b..b639e05f9 100644 --- a/test/apiv2/30-volumes.at +++ b/test/apiv2/30-volumes.at @@ -13,13 +13,14 @@ t POST libpod/volumes/create name=foo1 201 \ .CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \ .Labels={} \ .Options={} +# TODO(mwhahaha): there might be a bug here since options is null and not {} t POST volumes/create 201 \ - .Name~[0-9a-f]\\{64\\} + .Name~[0-9a-f]\\{64\\} \ .Driver=local \ - .Mountpoint=$volumepath/~[0-9a-f]\\{64\\}/_data \ + .Mountpoint~$volumepath/[0-9a-f]\\{64\\}/_data \ .CreatedAt~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \ .Labels={} \ - .Options={} + .Options=null t POST libpod/volumes/create 201 t POST libpod/volumes/create \ Name=foo2 \ diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index b2dc4f734..8c1ea4134 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -50,6 +50,12 @@ var _ = Describe("Podman manifest", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman manifest create", func() { + session := podmanTest.Podman([]string{"manifest", "create", "foo", imageList}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + It("podman manifest inspect", func() { session := podmanTest.Podman([]string{"manifest", "inspect", BB}) session.WaitWithDefaultTimeout() diff --git a/test/system/075-exec.bats b/test/system/075-exec.bats index badf44c49..3e8c3c1ea 100644 --- a/test/system/075-exec.bats +++ b/test/system/075-exec.bats @@ -59,8 +59,6 @@ load helpers # Issue #4785 - piping to exec statement - fixed in #4818 # Issue #5046 - piping to exec truncates results (actually a conmon issue) @test "podman exec - cat from stdin" { - skip_if_remote "FIXME: pending #7360" - run_podman run -d $IMAGE sh -c 'while [ ! -e /stop ]; do sleep 0.1;done' cid="$output" diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index d55a786f7..4feb57807 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -20,7 +20,6 @@ load helpers # Copied from tsweeney's https://github.com/containers/podman/issues/4827 @test "podman networking: port on localhost" { - skip_if_remote "FIXME: reevaluate this one after #7360 is fixed" random_1=$(random_string 30) random_2=$(random_string 30) diff --git a/vendor/github.com/google/uuid/null.go b/vendor/github.com/google/uuid/null.go new file mode 100644 index 000000000..d7fcbf286 --- /dev/null +++ b/vendor/github.com/google/uuid/null.go @@ -0,0 +1,118 @@ +// Copyright 2021 Google Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package uuid + +import ( + "bytes" + "database/sql/driver" + "encoding/json" + "fmt" +) + +var jsonNull = []byte("null") + +// NullUUID represents a UUID that may be null. +// NullUUID implements the SQL driver.Scanner interface so +// it can be used as a scan destination: +// +// var u uuid.NullUUID +// err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&u) +// ... +// if u.Valid { +// // use u.UUID +// } else { +// // NULL value +// } +// +type NullUUID struct { + UUID UUID + Valid bool // Valid is true if UUID is not NULL +} + +// Scan implements the SQL driver.Scanner interface. +func (nu *NullUUID) Scan(value interface{}) error { + if value == nil { + nu.UUID, nu.Valid = Nil, false + return nil + } + + err := nu.UUID.Scan(value) + if err != nil { + nu.Valid = false + return err + } + + nu.Valid = true + return nil +} + +// Value implements the driver Valuer interface. +func (nu NullUUID) Value() (driver.Value, error) { + if !nu.Valid { + return nil, nil + } + // Delegate to UUID Value function + return nu.UUID.Value() +} + +// MarshalBinary implements encoding.BinaryMarshaler. +func (nu NullUUID) MarshalBinary() ([]byte, error) { + if nu.Valid { + return nu.UUID[:], nil + } + + return []byte(nil), nil +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler. +func (nu *NullUUID) UnmarshalBinary(data []byte) error { + if len(data) != 16 { + return fmt.Errorf("invalid UUID (got %d bytes)", len(data)) + } + copy(nu.UUID[:], data) + nu.Valid = true + return nil +} + +// MarshalText implements encoding.TextMarshaler. +func (nu NullUUID) MarshalText() ([]byte, error) { + if nu.Valid { + return nu.UUID.MarshalText() + } + + return jsonNull, nil +} + +// UnmarshalText implements encoding.TextUnmarshaler. +func (nu *NullUUID) UnmarshalText(data []byte) error { + id, err := ParseBytes(data) + if err != nil { + nu.Valid = false + return err + } + nu.UUID = id + nu.Valid = true + return nil +} + +// MarshalJSON implements json.Marshaler. +func (nu NullUUID) MarshalJSON() ([]byte, error) { + if nu.Valid { + return json.Marshal(nu.UUID) + } + + return jsonNull, nil +} + +// UnmarshalJSON implements json.Unmarshaler. +func (nu *NullUUID) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, jsonNull) { + *nu = NullUUID{} + return nil // valid null UUID + } + err := json.Unmarshal(data, &nu.UUID) + nu.Valid = err == nil + return err +} diff --git a/vendor/github.com/google/uuid/uuid.go b/vendor/github.com/google/uuid/uuid.go index 60d26bb50..a57207aeb 100644 --- a/vendor/github.com/google/uuid/uuid.go +++ b/vendor/github.com/google/uuid/uuid.go @@ -12,6 +12,7 @@ import ( "fmt" "io" "strings" + "sync" ) // A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC @@ -33,7 +34,15 @@ const ( Future // Reserved for future definition. ) -var rander = rand.Reader // random function +const randPoolSize = 16 * 16 + +var ( + rander = rand.Reader // random function + poolEnabled = false + poolMu sync.Mutex + poolPos = randPoolSize // protected with poolMu + pool [randPoolSize]byte // protected with poolMu +) type invalidLengthError struct{ len int } @@ -41,6 +50,12 @@ func (err invalidLengthError) Error() string { return fmt.Sprintf("invalid UUID length: %d", err.len) } +// IsInvalidLengthError is matcher function for custom error invalidLengthError +func IsInvalidLengthError(err error) bool { + _, ok := err.(invalidLengthError) + return ok +} + // Parse decodes s into a UUID or returns an error. Both the standard UUID // forms of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx and // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the @@ -249,3 +264,31 @@ func SetRand(r io.Reader) { } rander = r } + +// EnableRandPool enables internal randomness pool used for Random +// (Version 4) UUID generation. The pool contains random bytes read from +// the random number generator on demand in batches. Enabling the pool +// may improve the UUID generation throughput significantly. +// +// Since the pool is stored on the Go heap, this feature may be a bad fit +// for security sensitive applications. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func EnableRandPool() { + poolEnabled = true +} + +// DisableRandPool disables the randomness pool if it was previously +// enabled with EnableRandPool. +// +// Both EnableRandPool and DisableRandPool are not thread-safe and should +// only be called when there is no possibility that New or any other +// UUID Version 4 generation function will be called concurrently. +func DisableRandPool() { + poolEnabled = false + defer poolMu.Unlock() + poolMu.Lock() + poolPos = randPoolSize +} diff --git a/vendor/github.com/google/uuid/version4.go b/vendor/github.com/google/uuid/version4.go index 86160fbd0..7697802e4 100644 --- a/vendor/github.com/google/uuid/version4.go +++ b/vendor/github.com/google/uuid/version4.go @@ -27,6 +27,8 @@ func NewString() string { // The strength of the UUIDs is based on the strength of the crypto/rand // package. // +// Uses the randomness pool if it was enabled with EnableRandPool. +// // A note about uniqueness derived from the UUID Wikipedia entry: // // Randomly generated UUIDs have 122 random bits. One's annual risk of being @@ -35,7 +37,10 @@ func NewString() string { // equivalent to the odds of creating a few tens of trillions of UUIDs in a // year and having one duplicate. func NewRandom() (UUID, error) { - return NewRandomFromReader(rander) + if !poolEnabled { + return NewRandomFromReader(rander) + } + return newRandomFromPool() } // NewRandomFromReader returns a UUID based on bytes read from a given io.Reader. @@ -49,3 +54,23 @@ func NewRandomFromReader(r io.Reader) (UUID, error) { uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 return uuid, nil } + +func newRandomFromPool() (UUID, error) { + var uuid UUID + poolMu.Lock() + if poolPos == randPoolSize { + _, err := io.ReadFull(rander, pool[:]) + if err != nil { + poolMu.Unlock() + return Nil, err + } + poolPos = 0 + } + copy(uuid[:], pool[poolPos:(poolPos+16)]) + poolPos += 16 + poolMu.Unlock() + + uuid[6] = (uuid[6] & 0x0f) | 0x40 // Version 4 + uuid[8] = (uuid[8] & 0x3f) | 0x80 // Variant is 10 + return uuid, nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 19b8d0a47..c29cfe8cc 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -370,7 +370,7 @@ github.com/google/go-intervals/intervalset github.com/google/gofuzz # github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/google/shlex -# github.com/google/uuid v1.2.0 +# github.com/google/uuid v1.3.0 github.com/google/uuid # github.com/gorilla/mux v1.8.0 github.com/gorilla/mux |