summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/images_build.go1
-rw-r--r--pkg/api/handlers/compat/images_search.go1
-rw-r--r--pkg/api/handlers/libpod/images_push.go29
-rw-r--r--pkg/api/handlers/libpod/manifests.go19
-rw-r--r--pkg/api/server/handler_api.go95
-rw-r--r--pkg/api/server/register_containers.go8
-rw-r--r--pkg/api/server/register_events.go4
-rw-r--r--pkg/api/server/register_images.go12
-rw-r--r--pkg/api/server/register_manifest.go10
-rw-r--r--pkg/bindings/images/types.go2
-rw-r--r--pkg/bindings/images/types_push_options.go15
-rw-r--r--pkg/bindings/test/images_test.go2
-rw-r--r--pkg/domain/filters/containers.go9
-rw-r--r--pkg/domain/filters/pods.go3
-rw-r--r--pkg/domain/filters/volumes.go5
-rw-r--r--pkg/domain/infra/abi/containers.go25
-rw-r--r--pkg/domain/infra/abi/manifest.go20
-rw-r--r--pkg/domain/infra/tunnel/containers.go22
-rw-r--r--pkg/domain/infra/tunnel/images.go2
-rw-r--r--pkg/domain/infra/tunnel/manifest.go13
-rw-r--r--pkg/machine/qemu/machine.go4
-rw-r--r--pkg/util/filters.go33
-rw-r--r--pkg/util/filters_test.go4
23 files changed, 224 insertions, 114 deletions
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index a9185c3d3..15cfc824e 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -140,6 +140,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Registry: "docker.io",
Rm: true,
ShmSize: 64 * 1024 * 1024,
+ TLSVerify: true,
}
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
diff --git a/pkg/api/handlers/compat/images_search.go b/pkg/api/handlers/compat/images_search.go
index a6fd3a3a1..2fc95e84e 100644
--- a/pkg/api/handlers/compat/images_search.go
+++ b/pkg/api/handlers/compat/images_search.go
@@ -26,6 +26,7 @@ func SearchImages(w http.ResponseWriter, r *http.Request) {
ListTags bool `json:"listTags"`
}{
// This is where you can override the golang default value for one of fields
+ TLSVerify: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
diff --git a/pkg/api/handlers/libpod/images_push.go b/pkg/api/handlers/libpod/images_push.go
index f427dc01b..e931fd2f9 100644
--- a/pkg/api/handlers/libpod/images_push.go
+++ b/pkg/api/handlers/libpod/images_push.go
@@ -25,13 +25,15 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
query := struct {
- All bool `schema:"all"`
- Destination string `schema:"destination"`
- Format string `schema:"format"`
- RemoveSignatures bool `schema:"removeSignatures"`
- TLSVerify bool `schema:"tlsVerify"`
- Quiet bool `schema:"quiet"`
+ All bool `schema:"all"`
+ CompressionFormat string `schema:"compressionFormat"`
+ Destination string `schema:"destination"`
+ Format string `schema:"format"`
+ RemoveSignatures bool `schema:"removeSignatures"`
+ TLSVerify bool `schema:"tlsVerify"`
+ Quiet bool `schema:"quiet"`
}{
+ TLSVerify: true,
// #14971: older versions did not sent *any* data, so we need
// to be quiet by default to remain backwards compatible
Quiet: true,
@@ -70,13 +72,14 @@ func PushImage(w http.ResponseWriter, r *http.Request) {
password = authconf.Password
}
options := entities.ImagePushOptions{
- All: query.All,
- Authfile: authfile,
- Format: query.Format,
- Password: password,
- Quiet: true,
- RemoveSignatures: query.RemoveSignatures,
- Username: username,
+ All: query.All,
+ Authfile: authfile,
+ CompressionFormat: query.CompressionFormat,
+ Format: query.Format,
+ Password: password,
+ Quiet: true,
+ RemoveSignatures: query.RemoveSignatures,
+ Username: username,
}
if _, found := r.URL.Query()["tlsVerify"]; found {
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index 3235a2972..2d6223e4e 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -306,10 +306,14 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
query := struct {
- All bool `schema:"all"`
- TLSVerify bool `schema:"tlsVerify"`
+ All bool `schema:"all"`
+ CompressionFormat string `schema:"compressionFormat"`
+ Format string `schema:"format"`
+ RemoveSignatures bool `schema:"removeSignatures"`
+ TLSVerify bool `schema:"tlsVerify"`
}{
// Add defaults here once needed.
+ TLSVerify: true,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusBadRequest,
@@ -335,10 +339,13 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
password = authconf.Password
}
options := entities.ImagePushOptions{
- Authfile: authfile,
- Username: username,
- Password: password,
- All: query.All,
+ All: query.All,
+ Authfile: authfile,
+ CompressionFormat: query.CompressionFormat,
+ Format: query.Format,
+ Password: password,
+ RemoveSignatures: query.RemoveSignatures,
+ Username: username,
}
if sys := runtime.SystemContext(); sys != nil {
options.CertDir = sys.DockerCertPath
diff --git a/pkg/api/server/handler_api.go b/pkg/api/server/handler_api.go
index a3aa681d0..57cafa5f6 100644
--- a/pkg/api/server/handler_api.go
+++ b/pkg/api/server/handler_api.go
@@ -1,7 +1,10 @@
package server
import (
+ "bufio"
+ "errors"
"fmt"
+ "net"
"net/http"
"runtime"
@@ -9,34 +12,54 @@ import (
"github.com/sirupsen/logrus"
)
+type BufferedResponseWriter struct {
+ b *bufio.Writer
+ w http.ResponseWriter
+}
+
// APIHandler is a wrapper to enhance HandlerFunc's and remove redundant code
func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Wrapper to hide some boilerplate
- fn := func(w http.ResponseWriter, r *http.Request) {
- if err := r.ParseForm(); err != nil {
- logrus.WithFields(logrus.Fields{
- "X-Reference-Id": r.Header.Get("X-Reference-Id"),
- }).Info("Failed Request: unable to parse form: " + err.Error())
- }
+ s.apiWrapper(h, w, r, false)
+ }
+}
+
+// An API Handler to help historical clients with broken parsing that expect
+// streaming JSON payloads to be reliably messaged framed (full JSON record
+// always fits in each read())
+func (s *APIServer) StreamBufferedAPIHandler(h http.HandlerFunc) http.HandlerFunc {
+ return func(w http.ResponseWriter, r *http.Request) {
+ // Wrapper to hide some boilerplate
+ s.apiWrapper(h, w, r, true)
+ }
+}
- cv := version.APIVersion[version.Compat][version.CurrentAPI]
- w.Header().Set("API-Version", fmt.Sprintf("%d.%d", cv.Major, cv.Minor))
+func (s *APIServer) apiWrapper(h http.HandlerFunc, w http.ResponseWriter, r *http.Request, buffer bool) {
+ if err := r.ParseForm(); err != nil {
+ logrus.WithFields(logrus.Fields{
+ "X-Reference-Id": r.Header.Get("X-Reference-Id"),
+ }).Info("Failed Request: unable to parse form: " + err.Error())
+ }
- lv := version.APIVersion[version.Libpod][version.CurrentAPI].String()
- w.Header().Set("Libpod-API-Version", lv)
- w.Header().Set("Server", "Libpod/"+lv+" ("+runtime.GOOS+")")
+ cv := version.APIVersion[version.Compat][version.CurrentAPI]
+ w.Header().Set("API-Version", fmt.Sprintf("%d.%d", cv.Major, cv.Minor))
- if s.CorsHeaders != "" {
- w.Header().Set("Access-Control-Allow-Origin", s.CorsHeaders)
- w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth, Connection, Upgrade, X-Registry-Config")
- w.Header().Set("Access-Control-Allow-Methods", "HEAD, GET, POST, DELETE, PUT, OPTIONS")
- }
+ lv := version.APIVersion[version.Libpod][version.CurrentAPI].String()
+ w.Header().Set("Libpod-API-Version", lv)
+ w.Header().Set("Server", "Libpod/"+lv+" ("+runtime.GOOS+")")
- h(w, r)
- }
- fn(w, r)
+ if s.CorsHeaders != "" {
+ w.Header().Set("Access-Control-Allow-Origin", s.CorsHeaders)
+ w.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Registry-Auth, Connection, Upgrade, X-Registry-Config")
+ w.Header().Set("Access-Control-Allow-Methods", "HEAD, GET, POST, DELETE, PUT, OPTIONS")
}
+
+ if buffer {
+ w = newBufferedResponseWriter(w)
+ }
+
+ h(w, r)
}
// VersionedPath prepends the version parsing code
@@ -44,3 +67,37 @@ func (s *APIServer) APIHandler(h http.HandlerFunc) http.HandlerFunc {
func VersionedPath(p string) string {
return "/v{version:[0-9][0-9A-Za-z.-]*}" + p
}
+
+func (w *BufferedResponseWriter) Header() http.Header {
+ return w.w.Header()
+}
+
+func (w *BufferedResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ _ = w.b.Flush()
+ if wrapped, ok := w.w.(http.Hijacker); ok {
+ return wrapped.Hijack()
+ }
+
+ return nil, nil, errors.New("ResponseWriter does not support hijacking")
+}
+
+func (w *BufferedResponseWriter) Write(b []byte) (int, error) {
+ return w.b.Write(b)
+}
+
+func (w *BufferedResponseWriter) WriteHeader(statusCode int) {
+ w.w.WriteHeader(statusCode)
+}
+
+func (w *BufferedResponseWriter) Flush() {
+ _ = w.b.Flush()
+ if wrapped, ok := w.w.(http.Flusher); ok {
+ wrapped.Flush()
+ }
+}
+func newBufferedResponseWriter(rw http.ResponseWriter) *BufferedResponseWriter {
+ return &BufferedResponseWriter{
+ bufio.NewWriterSize(rw, 8192),
+ rw,
+ }
+}
diff --git a/pkg/api/server/register_containers.go b/pkg/api/server/register_containers.go
index e2ecdb6af..b319fc14a 100644
--- a/pkg/api/server/register_containers.go
+++ b/pkg/api/server/register_containers.go
@@ -397,9 +397,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/containerNotFound"
// 500:
// $ref: "#/responses/internalError"
- r.HandleFunc(VersionedPath("/containers/{name}/stats"), s.APIHandler(compat.StatsContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/containers/{name}/stats"), s.StreamBufferedAPIHandler(compat.StatsContainer)).Methods(http.MethodGet)
// Added non version path to URI to support docker non versioned paths
- r.HandleFunc("/containers/{name}/stats", s.APIHandler(compat.StatsContainer)).Methods(http.MethodGet)
+ r.HandleFunc("/containers/{name}/stats", s.StreamBufferedAPIHandler(compat.StatsContainer)).Methods(http.MethodGet)
// swagger:operation POST /containers/{name}/stop compat ContainerStop
// ---
// tags:
@@ -455,9 +455,9 @@ func (s *APIServer) registerContainersHandlers(r *mux.Router) error {
// $ref: "#/responses/containerNotFound"
// 500:
// $ref: "#/responses/internalError"
- r.HandleFunc(VersionedPath("/containers/{name}/top"), s.APIHandler(compat.TopContainer)).Methods(http.MethodGet)
+ r.HandleFunc(VersionedPath("/containers/{name}/top"), s.StreamBufferedAPIHandler(compat.TopContainer)).Methods(http.MethodGet)
// Added non version path to URI to support docker non versioned paths
- r.HandleFunc("/containers/{name}/top", s.APIHandler(compat.TopContainer)).Methods(http.MethodGet)
+ r.HandleFunc("/containers/{name}/top", s.StreamBufferedAPIHandler(compat.TopContainer)).Methods(http.MethodGet)
// swagger:operation POST /containers/{name}/unpause compat ContainerUnpause
// ---
// tags:
diff --git a/pkg/api/server/register_events.go b/pkg/api/server/register_events.go
index 76f9ec619..3442b3eab 100644
--- a/pkg/api/server/register_events.go
+++ b/pkg/api/server/register_events.go
@@ -34,9 +34,9 @@ func (s *APIServer) registerEventsHandlers(r *mux.Router) error {
// description: returns a string of json data describing an event
// 500:
// "$ref": "#/responses/internalError"
- r.Handle(VersionedPath("/events"), s.APIHandler(compat.GetEvents)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/events"), s.StreamBufferedAPIHandler(compat.GetEvents)).Methods(http.MethodGet)
// Added non version path to URI to support docker non versioned paths
- r.Handle("/events", s.APIHandler(compat.GetEvents)).Methods(http.MethodGet)
+ r.Handle("/events", s.StreamBufferedAPIHandler(compat.GetEvents)).Methods(http.MethodGet)
// swagger:operation GET /libpod/events system SystemEventsLibpod
// ---
// tags:
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index 11ab8cae0..d71e0d470 100644
--- a/pkg/api/server/register_images.go
+++ b/pkg/api/server/register_images.go
@@ -192,8 +192,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - in: query
// name: tlsVerify
// type: boolean
- // default: false
- // description: skip TLS verification for registries
+ // default: true
+ // description: Require HTTPS and verify signatures when contacting registries.
// - in: query
// name: listTags
// type: boolean
@@ -702,9 +702,9 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// $ref: "#/responses/badParamError"
// 500:
// $ref: "#/responses/internalError"
- r.Handle(VersionedPath("/build"), s.APIHandler(compat.BuildImage)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/build"), s.StreamBufferedAPIHandler(compat.BuildImage)).Methods(http.MethodPost)
// Added non version path to URI to support docker non versioned paths
- r.Handle("/build", s.APIHandler(compat.BuildImage)).Methods(http.MethodPost)
+ r.Handle("/build", s.StreamBufferedAPIHandler(compat.BuildImage)).Methods(http.MethodPost)
/*
libpod endpoints
*/
@@ -1120,8 +1120,8 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// - in: query
// name: tlsVerify
// type: boolean
- // default: false
- // description: skip TLS verification for registries
+ // default: true
+ // description: Require HTTPS and verify signatures when contacting registries.
// - in: query
// name: listTags
// type: boolean
diff --git a/pkg/api/server/register_manifest.go b/pkg/api/server/register_manifest.go
index 4fadb92fd..19b507047 100644
--- a/pkg/api/server/register_manifest.go
+++ b/pkg/api/server/register_manifest.go
@@ -69,12 +69,12 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// name: all
// description: push all images
// type: boolean
- // default: false
+ // default: true
// - in: query
// name: tlsVerify
// type: boolean
- // default: false
- // description: skip TLS verification for registries
+ // default: true
+ // description: Require HTTPS and verify signatures when contacting registries.
// responses:
// 200:
// schema:
@@ -195,8 +195,8 @@ func (s *APIServer) registerManifestHandlers(r *mux.Router) error {
// - in: query
// name: tlsVerify
// type: boolean
- // default: false
- // description: skip TLS verification for registries
+ // default: true
+ // description: Require HTTPS and verify signatures when contacting registries.
// - in: body
// name: options
// description: options for mutating a manifest
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index 0e672cdea..0664afc1b 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -123,6 +123,8 @@ type PushOptions struct {
Authfile *string
// Compress tarball image layers when pushing to a directory using the 'dir' transport.
Compress *bool
+ // CompressionFormat is the format to use for the compression of the blobs
+ CompressionFormat *string
// Manifest type of the pushed image
Format *string
// Password for authenticating against the registry.
diff --git a/pkg/bindings/images/types_push_options.go b/pkg/bindings/images/types_push_options.go
index 63a19fb81..1ae031824 100644
--- a/pkg/bindings/images/types_push_options.go
+++ b/pkg/bindings/images/types_push_options.go
@@ -62,6 +62,21 @@ func (o *PushOptions) GetCompress() bool {
return *o.Compress
}
+// WithCompressionFormat set field CompressionFormat to given value
+func (o *PushOptions) WithCompressionFormat(value string) *PushOptions {
+ o.CompressionFormat = &value
+ return o
+}
+
+// GetCompressionFormat returns value of field CompressionFormat
+func (o *PushOptions) GetCompressionFormat() string {
+ if o.CompressionFormat == nil {
+ var z string
+ return z
+ }
+ return *o.CompressionFormat
+}
+
// WithFormat set field Format to given value
func (o *PushOptions) WithFormat(value string) *PushOptions {
o.Format = &value
diff --git a/pkg/bindings/test/images_test.go b/pkg/bindings/test/images_test.go
index a005be6ac..8f76ce456 100644
--- a/pkg/bindings/test/images_test.go
+++ b/pkg/bindings/test/images_test.go
@@ -120,8 +120,6 @@ var _ = Describe("Podman images", func() {
// deleting hence image cannot be deleted until the container is deleted.
_, errs = images.Remove(bt.conn, []string{alpine.shortName}, nil)
code, _ = bindings.CheckResponseCode(errs[0])
- // FIXME FIXME FIXME: #12441: another invalid error
- // FIXME FIXME FIXME: this time msg="Image used by SHA: ..."
Expect(code).To(BeNumerically("==", -1))
// Removing the image "alpine" where force = true
diff --git a/pkg/domain/filters/containers.go b/pkg/domain/filters/containers.go
index f88a165e7..de62b6582 100644
--- a/pkg/domain/filters/containers.go
+++ b/pkg/domain/filters/containers.go
@@ -7,6 +7,7 @@ import (
"strings"
"time"
+ "github.com/containers/common/pkg/filters"
cutil "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
@@ -24,7 +25,7 @@ func GenerateContainerFilterFuncs(filter string, filterValues []string, r *libpo
case "label":
// we have to match that all given labels exits on that container
return func(c *libpod.Container) bool {
- return util.MatchLabelFilters(filterValues, c.Labels())
+ return filters.MatchLabelFilters(filterValues, c.Labels())
}, nil
case "name":
// we only have to match one name
@@ -299,7 +300,11 @@ func GeneratePruneContainerFilterFuncs(filter string, filterValues []string, r *
switch filter {
case "label":
return func(c *libpod.Container) bool {
- return util.MatchLabelFilters(filterValues, c.Labels())
+ return filters.MatchLabelFilters(filterValues, c.Labels())
+ }, nil
+ case "label!":
+ return func(c *libpod.Container) bool {
+ return !filters.MatchLabelFilters(filterValues, c.Labels())
}, nil
case "until":
return prepareUntilFilterFunc(filterValues)
diff --git a/pkg/domain/filters/pods.go b/pkg/domain/filters/pods.go
index 78b97db64..7b0944292 100644
--- a/pkg/domain/filters/pods.go
+++ b/pkg/domain/filters/pods.go
@@ -6,6 +6,7 @@ import (
"strconv"
"strings"
+ "github.com/containers/common/pkg/filters"
cutil "github.com/containers/common/pkg/util"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
@@ -115,7 +116,7 @@ func GeneratePodFilterFunc(filter string, filterValues []string, r *libpod.Runti
case "label":
return func(p *libpod.Pod) bool {
labels := p.Labels()
- return util.MatchLabelFilters(filterValues, labels)
+ return filters.MatchLabelFilters(filterValues, labels)
}, nil
case "until":
return func(p *libpod.Pod) bool {
diff --git a/pkg/domain/filters/volumes.go b/pkg/domain/filters/volumes.go
index 7c5047225..9cec39fbb 100644
--- a/pkg/domain/filters/volumes.go
+++ b/pkg/domain/filters/volumes.go
@@ -6,6 +6,7 @@ import (
"regexp"
"strings"
+ pruneFilters "github.com/containers/common/pkg/filters"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/pkg/util"
)
@@ -36,7 +37,7 @@ func GenerateVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, error) {
case "label":
filter := val
vf = append(vf, func(v *libpod.Volume) bool {
- return util.MatchLabelFilters([]string{filter}, v.Labels())
+ return pruneFilters.MatchLabelFilters([]string{filter}, v.Labels())
})
case "opt":
filterArray := strings.SplitN(val, "=", 2)
@@ -100,7 +101,7 @@ func GeneratePruneVolumeFilters(filters url.Values) ([]libpod.VolumeFilter, erro
switch filter {
case "label":
vf = append(vf, func(v *libpod.Volume) bool {
- return util.MatchLabelFilters([]string{filterVal}, v.Labels())
+ return pruneFilters.MatchLabelFilters([]string{filterVal}, v.Labels())
})
case "until":
f, err := createUntilFilterVolumeFunction(filterVal)
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index dd7053a23..783224e9c 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -260,6 +260,7 @@ func (ic *ContainerEngine) ContainerPrune(ctx context.Context, options entities.
if err != nil {
return nil, err
}
+
filterFuncs = append(filterFuncs, generatedFunc)
}
return ic.Libpod.PruneContainers(filterFuncs)
@@ -1060,6 +1061,15 @@ func (ic *ContainerEngine) Diff(ctx context.Context, namesOrIDs []string, opts e
}
func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.ContainerRunOptions) (*entities.ContainerRunReport, error) {
+ removeContainer := func(ctr *libpod.Container, force bool) error {
+ var timeout *uint
+ if err := ic.Libpod.RemoveContainer(ctx, ctr, force, true, timeout); err != nil {
+ logrus.Debugf("unable to remove container %s after failing to start and attach to it: %v", ctr.ID(), err)
+ return err
+ }
+ return nil
+ }
+
warn, err := generate.CompleteSpec(ctx, ic.Libpod, opts.Spec)
if err != nil {
return nil, err
@@ -1080,6 +1090,8 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
if opts.CIDFile != "" {
if err := util.CreateCidFile(opts.CIDFile, ctr.ID()); err != nil {
+ // If you fail to create CIDFile then remove the container
+ _ = removeContainer(ctr, true)
return nil, err
}
}
@@ -1097,6 +1109,11 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
if err := ctr.Start(ctx, true); err != nil {
// This means the command did not exist
report.ExitCode = define.ExitCode(err)
+ if opts.Rm {
+ if rmErr := removeContainer(ctr, true); rmErr != nil && !errors.Is(rmErr, define.ErrNoSuchCtr) {
+ logrus.Errorf("Container %s failed to be removed", ctr.ID())
+ }
+ }
return &report, err
}
@@ -1113,10 +1130,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
return &report, nil
}
if opts.Rm {
- var timeout *uint
- if deleteError := ic.Libpod.RemoveContainer(ctx, ctr, true, false, timeout); deleteError != nil {
- logrus.Debugf("unable to remove container %s after failing to start and attach to it", ctr.ID())
- }
+ _ = removeContainer(ctr, true)
}
if errors.Is(err, define.ErrWillDeadlock) {
logrus.Debugf("Deadlock error on %q: %v", ctr.ID(), err)
@@ -1128,8 +1142,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
}
report.ExitCode = ic.GetContainerExitCode(ctx, ctr)
if opts.Rm && !ctr.ShouldRestart(ctx) {
- var timeout *uint
- if err := ic.Libpod.RemoveContainer(ctx, ctr, false, true, timeout); err != nil {
+ if err := removeContainer(ctr, false); err != nil {
if errors.Is(err, define.ErrNoSuchCtr) ||
errors.Is(err, define.ErrCtrRemoved) {
logrus.Infof("Container %s was already removed, skipping --rm", ctr.ID())
diff --git a/pkg/domain/infra/abi/manifest.go b/pkg/domain/infra/abi/manifest.go
index d20744d76..b135b05ba 100644
--- a/pkg/domain/infra/abi/manifest.go
+++ b/pkg/domain/infra/abi/manifest.go
@@ -13,6 +13,7 @@ import (
"github.com/containers/common/libimage"
cp "github.com/containers/image/v5/copy"
"github.com/containers/image/v5/manifest"
+ "github.com/containers/image/v5/pkg/compression"
"github.com/containers/image/v5/pkg/shortnames"
"github.com/containers/image/v5/transports"
"github.com/containers/image/v5/transports/alltransports"
@@ -318,6 +319,22 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin
pushOptions.SignBy = opts.SignBy
pushOptions.InsecureSkipTLSVerify = opts.SkipTLSVerify
+ compressionFormat := opts.CompressionFormat
+ if compressionFormat == "" {
+ config, err := ir.Libpod.GetConfigNoCopy()
+ if err != nil {
+ return "", err
+ }
+ compressionFormat = config.Engine.CompressionFormat
+ }
+ if compressionFormat != "" {
+ algo, err := compression.AlgorithmByName(compressionFormat)
+ if err != nil {
+ return "", err
+ }
+ pushOptions.CompressionFormat = &algo
+ }
+
if opts.All {
pushOptions.ImageListSelection = cp.CopyAllImages
}
@@ -331,7 +348,8 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin
}
if opts.Rm {
- if _, rmErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, []string{manifestList.ID()}, nil); len(rmErrors) > 0 {
+ rmOpts := &libimage.RemoveImagesOptions{LookupManifest: true}
+ if _, rmErrors := ir.Libpod.LibimageRuntime().RemoveImages(ctx, []string{manifestList.ID()}, rmOpts); len(rmErrors) > 0 {
return "", fmt.Errorf("error removing manifest after push: %w", rmErrors[0])
}
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index 272c23268..98c73c51a 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -787,8 +787,17 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
for _, w := range con.Warnings {
fmt.Fprintf(os.Stderr, "%s\n", w)
}
+ removeContainer := func(id string, force bool) error {
+ removeOptions := new(containers.RemoveOptions).WithVolumes(true).WithForce(force)
+ reports, err := containers.Remove(ic.ClientCtx, id, removeOptions)
+ logIfRmError(id, err, reports)
+ return err
+ }
+
if opts.CIDFile != "" {
if err := util.CreateCidFile(opts.CIDFile, con.ID); err != nil {
+ // If you fail to create CIDFile then remove the container
+ _ = removeContainer(con.ID, true)
return nil, err
}
}
@@ -800,6 +809,11 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
err := containers.Start(ic.ClientCtx, con.ID, new(containers.StartOptions).WithRecursive(true))
if err != nil {
report.ExitCode = define.ExitCode(err)
+ if opts.Rm {
+ if rmErr := removeContainer(con.ID, true); rmErr != nil && !errors.Is(rmErr, define.ErrNoSuchCtr) {
+ logrus.Errorf("Container %s failed to be removed", con.ID)
+ }
+ }
}
return &report, err
}
@@ -812,10 +826,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
report.ExitCode = define.ExitCode(err)
if opts.Rm {
- reports, rmErr := containers.Remove(ic.ClientCtx, con.ID, new(containers.RemoveOptions).WithForce(false).WithVolumes(true))
- if rmErr != nil || reports[0].Err != nil {
- logrus.Debugf("unable to remove container %s after failing to start and attach to it", con.ID)
- }
+ _ = removeContainer(con.ID, false)
}
return &report, err
}
@@ -831,8 +842,7 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta
}
if !shouldRestart {
- reports, err := containers.Remove(ic.ClientCtx, con.ID, new(containers.RemoveOptions).WithForce(false).WithVolumes(true))
- logIfRmError(con.ID, err, reports)
+ _ = removeContainer(con.ID, false)
}
}()
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 9ad408850..4f79325fd 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -240,7 +240,7 @@ func (ir *ImageEngine) Import(ctx context.Context, opts entities.ImageImportOpti
func (ir *ImageEngine) Push(ctx context.Context, source string, destination string, opts entities.ImagePushOptions) error {
options := new(images.PushOptions)
- options.WithAll(opts.All).WithCompress(opts.Compress).WithUsername(opts.Username).WithPassword(opts.Password).WithAuthfile(opts.Authfile).WithFormat(opts.Format).WithRemoveSignatures(opts.RemoveSignatures).WithQuiet(opts.Quiet)
+ options.WithAll(opts.All).WithCompress(opts.Compress).WithUsername(opts.Username).WithPassword(opts.Password).WithAuthfile(opts.Authfile).WithFormat(opts.Format).WithRemoveSignatures(opts.RemoveSignatures).WithQuiet(opts.Quiet).WithCompressionFormat(opts.CompressionFormat)
if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
if s == types.OptionalBoolTrue {
diff --git a/pkg/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go
index d2554f198..00ecb3b59 100644
--- a/pkg/domain/infra/tunnel/manifest.go
+++ b/pkg/domain/infra/tunnel/manifest.go
@@ -99,8 +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)
- options.WithAll(opts.All)
+ options.WithUsername(opts.Username).WithPassword(opts.Password).WithAuthfile(opts.Authfile).WithRemoveSignatures(opts.RemoveSignatures).WithAll(opts.All).WithFormat(opts.Format).WithCompressionFormat(opts.CompressionFormat)
if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
if s == types.OptionalBoolTrue {
@@ -110,5 +109,15 @@ func (ir *ImageEngine) ManifestPush(ctx context.Context, name, destination strin
}
}
digest, err := manifests.Push(ir.ClientCtx, name, destination, options)
+ if err != nil {
+ return "", fmt.Errorf("error adding to manifest list %s: %w", name, err)
+ }
+
+ if opts.Rm {
+ if _, rmErrors := ir.Remove(ctx, []string{name}, entities.ImageRemoveOptions{LookupManifest: true}); len(rmErrors) > 0 {
+ return "", fmt.Errorf("error removing manifest after push: %w", rmErrors[0])
+ }
+ }
+
return digest, err
}
diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go
index 3b57455c4..7974c261e 100644
--- a/pkg/machine/qemu/machine.go
+++ b/pkg/machine/qemu/machine.go
@@ -670,11 +670,11 @@ func (v *MachineVM) Start(name string, _ machine.StartOptions) error {
// because / is immutable, we have to monkey around with permissions
// if we dont mount in /home or /mnt
args := []string{"-q", "--"}
- if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ if !strings.HasPrefix(mount.Target, "/home") && !strings.HasPrefix(mount.Target, "/mnt") {
args = append(args, "sudo", "chattr", "-i", "/", ";")
}
args = append(args, "sudo", "mkdir", "-p", mount.Target)
- if !strings.HasPrefix(mount.Target, "/home") || !strings.HasPrefix(mount.Target, "/mnt") {
+ if !strings.HasPrefix(mount.Target, "/home") && !strings.HasPrefix(mount.Target, "/mnt") {
args = append(args, ";", "sudo", "chattr", "+i", "/", ";")
}
err = v.SSH(name, machine.SSHOptions{Args: args})
diff --git a/pkg/util/filters.go b/pkg/util/filters.go
index 08148806f..104b9c3c2 100644
--- a/pkg/util/filters.go
+++ b/pkg/util/filters.go
@@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"net/http"
- "path/filepath"
"strings"
"time"
@@ -94,35 +93,3 @@ func PrepareFilters(r *http.Request) (*map[string][]string, error) {
}
return &filterMap, nil
}
-
-func matchPattern(pattern string, value string) bool {
- if strings.Contains(pattern, "*") {
- filter := fmt.Sprintf("*%s*", pattern)
- filter = strings.ReplaceAll(filter, string(filepath.Separator), "|")
- newName := strings.ReplaceAll(value, string(filepath.Separator), "|")
- match, _ := filepath.Match(filter, newName)
- return match
- }
- return false
-}
-
-// MatchLabelFilters matches labels and returns true if they are valid
-func MatchLabelFilters(filterValues []string, labels map[string]string) bool {
-outer:
- for _, filterValue := range filterValues {
- filterArray := strings.SplitN(filterValue, "=", 2)
- filterKey := filterArray[0]
- if len(filterArray) > 1 {
- filterValue = filterArray[1]
- } else {
- filterValue = ""
- }
- for labelKey, labelValue := range labels {
- if ((labelKey == filterKey) || matchPattern(filterKey, labelKey)) && (filterValue == "" || labelValue == filterValue) {
- continue outer
- }
- }
- return false
- }
- return true
-}
diff --git a/pkg/util/filters_test.go b/pkg/util/filters_test.go
index 47259013e..8e45ea61c 100644
--- a/pkg/util/filters_test.go
+++ b/pkg/util/filters_test.go
@@ -2,6 +2,8 @@ package util
import (
"testing"
+
+ "github.com/containers/common/pkg/filters"
)
func TestMatchLabelFilters(t *testing.T) {
@@ -71,7 +73,7 @@ func TestMatchLabelFilters(t *testing.T) {
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
- if got := MatchLabelFilters(tt.args.filterValues, tt.args.labels); got != tt.want {
+ if got := filters.MatchLabelFilters(tt.args.filterValues, tt.args.labels); got != tt.want {
t.Errorf("MatchLabelFilters() = %v, want %v", got, tt.want)
}
})