summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/libpod/manifests.go70
-rw-r--r--pkg/api/server/register_containers.go5
-rw-r--r--pkg/api/server/register_manifest.go5
-rw-r--r--pkg/bindings/manifests/manifests.go43
-rw-r--r--pkg/domain/entities/manifest.go12
-rw-r--r--pkg/domain/infra/abi/manifest.go3
-rw-r--r--pkg/domain/infra/abi/terminal/terminal_unsupported.go25
-rw-r--r--pkg/domain/infra/tunnel/manifest.go2
-rw-r--r--pkg/machine/ignition_freebsd.go8
-rw-r--r--pkg/machine/qemu/options_freebsd.go13
-rw-r--r--pkg/machine/qemu/options_freebsd_amd64.go18
-rw-r--r--pkg/rootless/rootless_linux.go26
-rw-r--r--pkg/specgen/generate/config_unsupported.go29
-rw-r--r--pkg/specgen/generate/oci.go28
-rw-r--r--pkg/specgen/generate/rlimit_int64.go6
-rw-r--r--pkg/specgen/generate/rlimit_uint64.go6
-rw-r--r--pkg/specgen/specgen.go3
-rw-r--r--pkg/util/utils_freebsd.go12
-rw-r--r--pkg/util/utils_unsupported.go4
19 files changed, 279 insertions, 39 deletions
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index 2d6223e4e..b0c93f3b9 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -19,12 +19,14 @@ import (
"github.com/containers/podman/v4/pkg/api/handlers/utils"
api "github.com/containers/podman/v4/pkg/api/types"
"github.com/containers/podman/v4/pkg/auth"
+ "github.com/containers/podman/v4/pkg/channel"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/infra/abi"
"github.com/containers/podman/v4/pkg/errorhandling"
"github.com/gorilla/mux"
"github.com/gorilla/schema"
"github.com/opencontainers/go-digest"
+ "github.com/sirupsen/logrus"
)
func ManifestCreate(w http.ResponseWriter, r *http.Request) {
@@ -311,9 +313,13 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
Format string `schema:"format"`
RemoveSignatures bool `schema:"removeSignatures"`
TLSVerify bool `schema:"tlsVerify"`
+ Quiet bool `schema:"quiet"`
}{
// Add defaults here once needed.
TLSVerify: true,
+ // #15210: older versions did not sent *any* data, so we need
+ // to be quiet by default to remain backwards compatible
+ Quiet: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusBadRequest,
@@ -344,6 +350,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
CompressionFormat: query.CompressionFormat,
Format: query.Format,
Password: password,
+ Quiet: true,
RemoveSignatures: query.RemoveSignatures,
Username: username,
}
@@ -356,12 +363,67 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
imageEngine := abi.ImageEngine{Libpod: runtime}
source := utils.GetName(r)
- digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options)
- if err != nil {
- utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err))
+
+ // Let's keep thing simple when running in quiet mode and push directly.
+ if query.Quiet {
+ digest, err := imageEngine.ManifestPush(context.Background(), source, destination, options)
+ if err != nil {
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err))
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, entities.ManifestPushReport{ID: digest})
return
}
- utils.WriteResponse(w, http.StatusOK, entities.IDResponse{ID: digest})
+
+ writer := channel.NewWriter(make(chan []byte))
+ defer writer.Close()
+ options.Writer = writer
+
+ pushCtx, pushCancel := context.WithCancel(r.Context())
+ var digest string
+ var pushError error
+ go func() {
+ defer pushCancel()
+ digest, pushError = imageEngine.ManifestPush(pushCtx, source, destination, options)
+ }()
+
+ flush := func() {
+ if flusher, ok := w.(http.Flusher); ok {
+ flusher.Flush()
+ }
+ }
+
+ w.WriteHeader(http.StatusOK)
+ w.Header().Set("Content-Type", "application/json")
+ flush()
+
+ enc := json.NewEncoder(w)
+ enc.SetEscapeHTML(true)
+ for {
+ var report entities.ManifestPushReport
+ select {
+ case s := <-writer.Chan():
+ report.Stream = string(s)
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to encode json: %v", err)
+ }
+ flush()
+ case <-pushCtx.Done():
+ if pushError != nil {
+ report.Error = pushError.Error()
+ } else {
+ report.ID = digest
+ }
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to encode json: %v", err)
+ }
+ flush()
+ return
+ case <-r.Context().Done():
+ // Client has closed connection
+ return
+ }
+ }
}
// ManifestModify efficiently updates the named manifest list
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index b319fc14a..8aba4ea05 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -11,9 +11,9 @@ import (
func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// swagger:operation POST /containers/create compat ContainerCreate
// ---
- // summary: Create a container
// tags:
// - containers (compat)
+ // summary: Create a container
// produces:
// - application/json
// parameters:
@@ -678,9 +678,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// swagger:operation POST /libpod/containers/create libpod ContainerCreateLibpod
// ---
- // summary: Create a container
// tags:
// - containers
+ // summary: Create a container
// produces:
// - application/json
// parameters:
@@ -689,6 +689,7 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// description: attributes for creating a container
// schema:
// $ref: "#/definitions/SpecGenerator"
+ // required: true
// responses:
// 201:
// $ref: "#/responses/containerCreateResponse"
diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go
index 19b507047..c22479cf9 100644
--- a/pkg/api/server/register_manifest.go
+++ b/pkg/api/server/register_manifest.go
@@ -75,6 +75,11 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// type: boolean
// default: true
// description: Require HTTPS and verify signatures when contacting registries.
+ // - in: query
+ // name: quiet
+ // description: "silences extra stream data on push"
+ // type: boolean
+ // default: true
// responses:
// 200:
// schema:
diff --git a/pkg/bindings/manifests/manifests.go b/pkg/bindings/manifests/manifests.go
index 80153c4b4..49e4089f5 100644
--- a/pkg/bindings/manifests/manifests.go
+++ b/pkg/bindings/manifests/manifests.go
@@ -2,10 +2,13 @@ package manifests
import (
"context"
+ "encoding/json"
"errors"
"fmt"
+ "io"
"io/ioutil"
"net/http"
+ "os"
"strconv"
"strings"
@@ -142,7 +145,6 @@ func Delete(ctx context.Context, name string) (*entities.ManifestRemoveReport, e
// the name will be used instead. If the optional all boolean is specified, all images specified
// in the list will be pushed as well.
func Push(ctx context.Context, name, destination string, options *images.PushOptions) (string, error) {
- var idr entities.IDResponse
if options == nil {
options = new(images.PushOptions)
}
@@ -176,7 +178,44 @@ func Push(ctx context.Context, name, destination string, options *images.PushOpt
}
defer response.Body.Close()
- return idr.ID, response.Process(&idr)
+ if !response.IsSuccess() {
+ return "", response.Process(err)
+ }
+
+ // Historically push writes status to stderr
+ writer := io.Writer(os.Stderr)
+ if options.GetQuiet() {
+ writer = io.Discard
+ } else if progressWriter := options.GetProgressWriter(); progressWriter != nil {
+ writer = progressWriter
+ }
+
+ dec := json.NewDecoder(response.Body)
+ for {
+ var report entities.ManifestPushReport
+ if err := dec.Decode(&report); err != nil {
+ return "", err
+ }
+
+ select {
+ case <-response.Request.Context().Done():
+ break
+ default:
+ // non-blocking select
+ }
+
+ switch {
+ case report.ID != "":
+ return report.ID, nil
+ case report.Stream != "":
+ fmt.Fprint(writer, report.Stream)
+ case report.Error != "":
+ // There can only be one error.
+ return "", errors.New(report.Error)
+ default:
+ return "", fmt.Errorf("failed to parse push results stream, unexpected input: %v", report)
+ }
+ }
}
// Modify modifies the given manifest list using options and the optional list of images
diff --git a/pkg/domain/entities/manifest.go b/pkg/domain/entities/manifest.go
index e88c5f854..126b76c62 100644
--- a/pkg/domain/entities/manifest.go
+++ b/pkg/domain/entities/manifest.go
@@ -61,6 +61,18 @@ type ManifestModifyOptions struct {
ManifestRemoveOptions
}
+// ManifestPushReport provides the model for the pushed manifest
+//
+// swagger:model
+type ManifestPushReport struct {
+ // ID of the pushed manifest
+ ID string `json:"Id"`
+ // Stream used to provide push progress
+ Stream string `json:"stream,omitempty"`
+ // Error contains text of errors from pushing
+ Error string `json:"error,omitempty"`
+}
+
// ManifestRemoveOptions provides the model for removing digests from a manifest
//
// swagger:model
diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go
index 4b10d9b18..e0c11267e 100644
--- a/pkg/domain/infra/abi/manifest.go
+++ b/pkg/domain/infra/abi/manifest.go
@@ -321,6 +321,7 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin
pushOptions.SignBySigstorePrivateKeyFile = opts.SignBySigstorePrivateKeyFile
pushOptions.SignSigstorePrivateKeyPassphrase = opts.SignSigstorePrivateKeyPassphrase
pushOptions.InsecureSkipTLSVerify = opts.SkipTLSVerify
+ pushOptions.Writer = opts.Writer
compressionFormat := opts.CompressionFormat
if compressionFormat == "" {
@@ -341,7 +342,7 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin
if opts.All {
pushOptions.ImageListSelection = cp.CopyAllImages
}
- if !opts.Quiet {
+ if !opts.Quiet && pushOptions.Writer == nil {
pushOptions.Writer = os.Stderr
}
diff --git a/pkg/domain/infra/abi/terminal/terminal_unsupported.go b/pkg/domain/infra/abi/terminal/terminal_unsupported.go
new file mode 100644
index 000000000..8fe325736
--- /dev/null
+++ b/pkg/domain/infra/abi/terminal/terminal_unsupported.go
@@ -0,0 +1,25 @@
+//go:build !linux
+// +build !linux
+
+package terminal
+
+import (
+ "context"
+ "errors"
+ "os"
+
+ "github.com/containers/podman/v4/libpod"
+ "github.com/containers/podman/v4/libpod/define"
+)
+
+// ExecAttachCtr execs and attaches to a container
+func ExecAttachCtr(ctx context.Context, ctr *libpod.Container, execConfig *libpod.ExecConfig, streams *define.AttachStreams) (int, error) {
+ return -1, errors.New("not implemented ExecAttachCtr")
+}
+
+// StartAttachCtr starts and (if required) attaches to a container
+// if you change the signature of this function from os.File to io.Writer, it will trigger a downstream
+// error. we may need to just lint disable this one.
+func StartAttachCtr(ctx context.Context, ctr *libpod.Container, stdout, stderr, stdin *os.File, detachKeys string, sigProxy bool, startContainer bool) error { //nolint: interfacer
+ return errors.New("not implemented StartAttachCtr")
+}
diff --git a/pkg/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go
index 00ecb3b59..2a514861d 100644
--- a/pkg/domain/infra/tunnel/manifest.go
+++ b/pkg/domain/infra/tunnel/manifest.go
@@ -99,7 +99,7 @@ func (ir *ImageEngine) ManifestRm(ctx context.Context, names []string) (*entitie
// ManifestPush pushes a manifest list or image index to the destination
func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination string, opts entities.ImagePushOptions) (string, error) {
options := new(images.PushOptions)
- options.WithUsername(opts.Username).WithPassword(opts.Password).WithAuthfile(opts.Authfile).WithRemoveSignatures(opts.RemoveSignatures).WithAll(opts.All).WithFormat(opts.Format).WithCompressionFormat(opts.CompressionFormat)
+ options.WithUsername(opts.Username).WithPassword(opts.Password).WithAuthfile(opts.Authfile).WithRemoveSignatures(opts.RemoveSignatures).WithAll(opts.All).WithFormat(opts.Format).WithCompressionFormat(opts.CompressionFormat).WithQuiet(opts.Quiet).WithProgressWriter(opts.Writer)
if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
if s == types.OptionalBoolTrue {
diff --git a/pkg/machine/ignition_freebsd.go b/pkg/machine/ignition_freebsd.go
new file mode 100644
index 000000000..ddea40782
--- /dev/null
+++ b/pkg/machine/ignition_freebsd.go
@@ -0,0 +1,8 @@
+//go:build freebsd
+// +build freebsd
+
+package machine
+
+func getLocalTimeZone() (string, error) {
+ return "", nil
+}
diff --git a/pkg/machine/qemu/options_freebsd.go b/pkg/machine/qemu/options_freebsd.go
new file mode 100644
index 000000000..124358db8
--- /dev/null
+++ b/pkg/machine/qemu/options_freebsd.go
@@ -0,0 +1,13 @@
+package qemu
+
+import (
+ "os"
+)
+
+func getRuntimeDir() (string, error) {
+ tmpDir, ok := os.LookupEnv("TMPDIR")
+ if !ok {
+ tmpDir = "/tmp"
+ }
+ return tmpDir, nil
+}
diff --git a/pkg/machine/qemu/options_freebsd_amd64.go b/pkg/machine/qemu/options_freebsd_amd64.go
new file mode 100644
index 000000000..ff8d10db1
--- /dev/null
+++ b/pkg/machine/qemu/options_freebsd_amd64.go
@@ -0,0 +1,18 @@
+package qemu
+
+var (
+ QemuCommand = "qemu-system-x86_64"
+)
+
+func (v *MachineVM) addArchOptions() []string {
+ opts := []string{"-machine", "q35,accel=hvf:tcg", "-cpu", "host"}
+ return opts
+}
+
+func (v *MachineVM) prepare() error {
+ return nil
+}
+
+func (v *MachineVM) archRemovalFiles() []string {
+ return []string{}
+}
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index b0012b32b..8c4316dbb 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -251,20 +251,22 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (_ boo
return false, 0, nil
}
- if mounts, err := pmount.GetMounts(); err == nil {
- for _, m := range mounts {
- if m.Mountpoint == "/" {
- isShared := false
- for _, o := range strings.Split(m.Optional, ",") {
- if strings.HasPrefix(o, "shared:") {
- isShared = true
- break
+ if _, inContainer := os.LookupEnv("container"); !inContainer {
+ if mounts, err := pmount.GetMounts(); err == nil {
+ for _, m := range mounts {
+ if m.Mountpoint == "/" {
+ isShared := false
+ for _, o := range strings.Split(m.Optional, ",") {
+ if strings.HasPrefix(o, "shared:") {
+ isShared = true
+ break
+ }
}
+ if !isShared {
+ logrus.Warningf("%q is not a shared mount, this could cause issues or missing mounts with rootless containers", m.Mountpoint)
+ }
+ break
}
- if !isShared {
- logrus.Warningf("%q is not a shared mount, this could cause issues or missing mounts with rootless containers", m.Mountpoint)
- }
- break
}
}
}
diff --git a/pkg/specgen/generate/config_unsupported.go b/pkg/specgen/generate/config_unsupported.go
new file mode 100644
index 000000000..a97ae0709
--- /dev/null
+++ b/pkg/specgen/generate/config_unsupported.go
@@ -0,0 +1,29 @@
+//go:build !linux
+// +build !linux
+
+package generate
+
+import (
+ "errors"
+
+ "github.com/containers/common/libimage"
+ "github.com/containers/podman/v4/pkg/specgen"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+)
+
+// DevicesFromPath computes a list of devices
+func DevicesFromPath(g *generate.Generator, devicePath string) error {
+ return errors.New("unsupported DevicesFromPath")
+}
+
+func BlockAccessToKernelFilesystems(privileged, pidModeIsHost bool, mask, unmask []string, g *generate.Generator) {
+}
+
+func supportAmbientCapabilities() bool {
+ return false
+}
+
+func getSeccompConfig(s *specgen.SpecGenerator, configSpec *spec.Spec, img *libimage.Image) (*spec.LinuxSeccomp, error) {
+ return nil, errors.New("not implemented getSeccompConfig")
+}
diff --git a/pkg/specgen/generate/oci.go b/pkg/specgen/generate/oci.go
index f59fe1011..a531494c9 100644
--- a/pkg/specgen/generate/oci.go
+++ b/pkg/specgen/generate/oci.go
@@ -58,38 +58,38 @@ func addRlimits(s *specgen.SpecGenerator, g *generate.Generator) {
// files and number of processes to the maximum they can be set to
// (without overriding a sysctl)
if !nofileSet {
- max := define.RLimitDefaultValue
- current := define.RLimitDefaultValue
+ max := rlimT(define.RLimitDefaultValue)
+ current := rlimT(define.RLimitDefaultValue)
if isRootless {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &rlimit); err != nil {
logrus.Warnf("Failed to return RLIMIT_NOFILE ulimit %q", err)
}
- if rlimit.Cur < current {
- current = rlimit.Cur
+ if rlimT(rlimit.Cur) < current {
+ current = rlimT(rlimit.Cur)
}
- if rlimit.Max < max {
- max = rlimit.Max
+ if rlimT(rlimit.Max) < max {
+ max = rlimT(rlimit.Max)
}
}
- g.AddProcessRlimits("RLIMIT_NOFILE", max, current)
+ g.AddProcessRlimits("RLIMIT_NOFILE", uint64(max), uint64(current))
}
if !nprocSet {
- max := define.RLimitDefaultValue
- current := define.RLimitDefaultValue
+ max := rlimT(define.RLimitDefaultValue)
+ current := rlimT(define.RLimitDefaultValue)
if isRootless {
var rlimit unix.Rlimit
if err := unix.Getrlimit(unix.RLIMIT_NPROC, &rlimit); err != nil {
logrus.Warnf("Failed to return RLIMIT_NPROC ulimit %q", err)
}
- if rlimit.Cur < current {
- current = rlimit.Cur
+ if rlimT(rlimit.Cur) < current {
+ current = rlimT(rlimit.Cur)
}
- if rlimit.Max < max {
- max = rlimit.Max
+ if rlimT(rlimit.Max) < max {
+ max = rlimT(rlimit.Max)
}
}
- g.AddProcessRlimits("RLIMIT_NPROC", max, current)
+ g.AddProcessRlimits("RLIMIT_NPROC", uint64(max), uint64(current))
}
}
diff --git a/pkg/specgen/generate/rlimit_int64.go b/pkg/specgen/generate/rlimit_int64.go
new file mode 100644
index 000000000..b4cce3453
--- /dev/null
+++ b/pkg/specgen/generate/rlimit_int64.go
@@ -0,0 +1,6 @@
+//go:build freebsd
+// +build freebsd
+
+package generate
+
+type rlimT int64
diff --git a/pkg/specgen/generate/rlimit_uint64.go b/pkg/specgen/generate/rlimit_uint64.go
new file mode 100644
index 000000000..d85f8dd2c
--- /dev/null
+++ b/pkg/specgen/generate/rlimit_uint64.go
@@ -0,0 +1,6 @@
+//go:build linux || darwin
+// +build linux darwin
+
+package generate
+
+type rlimT uint64
diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go
index c31c3f035..b90f07ef8 100644
--- a/pkg/specgen/specgen.go
+++ b/pkg/specgen/specgen.go
@@ -13,7 +13,8 @@ import (
spec "github.com/opencontainers/runtime-spec/specs-go"
)
-// LogConfig describes the logging characteristics for a container
+// LogConfig describes the logging characteristics for a container
+// swagger:model LogConfigLibpod
type LogConfig struct {
// LogDriver is the container's log driver.
// Optional.
diff --git a/pkg/util/utils_freebsd.go b/pkg/util/utils_freebsd.go
new file mode 100644
index 000000000..17436ae81
--- /dev/null
+++ b/pkg/util/utils_freebsd.go
@@ -0,0 +1,12 @@
+//go:build freebsd
+// +build freebsd
+
+package util
+
+import (
+ "errors"
+)
+
+func GetContainerPidInformationDescriptors() ([]string, error) {
+ return []string{}, errors.New("this function is not supported on freebsd")
+}
diff --git a/pkg/util/utils_unsupported.go b/pkg/util/utils_unsupported.go
index 3a0f8646b..26fb7adf9 100644
--- a/pkg/util/utils_unsupported.go
+++ b/pkg/util/utils_unsupported.go
@@ -1,5 +1,5 @@
-//go:build darwin || windows
-// +build darwin windows
+//go:build darwin || windows || freebsd
+// +build darwin windows freebsd
package util