summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/images.go32
-rw-r--r--pkg/api/handlers/compat/images_build.go1
-rw-r--r--pkg/api/handlers/compat/images_push.go1
-rw-r--r--pkg/api/handlers/compat/images_search.go1
-rw-r--r--pkg/api/handlers/compat/networks.go54
-rw-r--r--pkg/api/handlers/libpod/containers_create.go3
-rw-r--r--pkg/api/handlers/libpod/images.go71
-rw-r--r--pkg/api/handlers/libpod/images_push.go145
-rw-r--r--pkg/api/handlers/libpod/manifests.go1
-rw-r--r--pkg/api/server/register_images.go13
-rw-r--r--pkg/api/server/register_manifest.go10
-rw-r--r--pkg/bindings/images/images.go40
-rw-r--r--pkg/bindings/images/push.go96
-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/entities/containers.go9
-rw-r--r--pkg/domain/entities/images.go15
-rw-r--r--pkg/domain/entities/machine.go22
-rw-r--r--pkg/domain/entities/play.go5
-rw-r--r--pkg/domain/infra/abi/containers.go41
-rw-r--r--pkg/domain/infra/abi/images.go3
-rw-r--r--pkg/domain/infra/abi/play.go80
-rw-r--r--pkg/domain/infra/abi/secrets.go2
-rw-r--r--pkg/domain/infra/tunnel/containers.go26
-rw-r--r--pkg/domain/infra/tunnel/images.go2
-rw-r--r--pkg/k8s.io/api/core/v1/types.go1
-rw-r--r--pkg/machine/e2e/basic_test.go4
-rw-r--r--pkg/machine/e2e/config_basic_test.go (renamed from pkg/machine/e2e/config_basic.go)3
-rw-r--r--pkg/machine/e2e/config_info_test.go (renamed from pkg/machine/e2e/config_info.go)2
-rw-r--r--pkg/machine/e2e/config_init_test.go (renamed from pkg/machine/e2e/config_init.go)6
-rw-r--r--pkg/machine/e2e/config_inspect_test.go (renamed from pkg/machine/e2e/config_inspect.go)2
-rw-r--r--pkg/machine/e2e/config_list_test.go (renamed from pkg/machine/e2e/config_list.go)2
-rw-r--r--pkg/machine/e2e/config_rm_test.go (renamed from pkg/machine/e2e/config_rm.go)8
-rw-r--r--pkg/machine/e2e/config_set_test.go (renamed from pkg/machine/e2e/config_set.go)2
-rw-r--r--pkg/machine/e2e/config_ssh_test.go (renamed from pkg/machine/e2e/config_ssh.go)8
-rw-r--r--pkg/machine/e2e/config_start_test.go (renamed from pkg/machine/e2e/config_start.go)3
-rw-r--r--pkg/machine/e2e/config_stop_test.go (renamed from pkg/machine/e2e/config_stop.go)3
-rw-r--r--pkg/machine/e2e/config_test.go (renamed from pkg/machine/e2e/config.go)26
-rw-r--r--pkg/machine/e2e/info_test.go6
-rw-r--r--pkg/machine/e2e/init_test.go8
-rw-r--r--pkg/machine/e2e/inspect_test.go8
-rw-r--r--pkg/machine/e2e/list_test.go8
-rw-r--r--pkg/machine/e2e/machine_test.go2
-rw-r--r--pkg/machine/e2e/rm_test.go2
-rw-r--r--pkg/machine/e2e/set_test.go8
-rw-r--r--pkg/machine/e2e/ssh_test.go14
-rw-r--r--pkg/machine/e2e/start_test.go2
-rw-r--r--pkg/machine/e2e/stop_test.go2
-rw-r--r--pkg/machine/qemu/machine.go4
-rw-r--r--pkg/specgen/generate/container.go15
-rw-r--r--pkg/specgen/generate/container_create.go4
-rw-r--r--pkg/specgen/generate/kube/kube.go10
-rw-r--r--pkg/specgen/generate/kube/play_test.go2
-rw-r--r--pkg/specgen/generate/kube/volume.go56
-rw-r--r--pkg/specgenutil/specgen.go9
56 files changed, 646 insertions, 276 deletions
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 2f8d151d8..39bd165d6 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -23,6 +23,7 @@ import (
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/domain/infra/abi"
"github.com/containers/storage"
+ "github.com/docker/docker/pkg/jsonmessage"
"github.com/gorilla/schema"
"github.com/opencontainers/go-digest"
"github.com/sirupsen/logrus"
@@ -325,16 +326,8 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
loop: // break out of for/select infinite loop
for {
- var report struct {
- Stream string `json:"stream,omitempty"`
- Status string `json:"status,omitempty"`
- Progress struct {
- Current uint64 `json:"current,omitempty"`
- Total int64 `json:"total,omitempty"`
- } `json:"progressDetail,omitempty"`
- Error string `json:"error,omitempty"`
- Id string `json:"id,omitempty"` //nolint:revive,stylecheck
- }
+ report := jsonmessage.JSONMessage{}
+ report.Progress = &jsonmessage.JSONProgress{}
select {
case e := <-progress:
switch e.Event {
@@ -342,14 +335,15 @@ loop: // break out of for/select infinite loop
report.Status = "Pulling fs layer"
case types.ProgressEventRead:
report.Status = "Downloading"
- report.Progress.Current = e.Offset
+ report.Progress.Current = int64(e.Offset)
report.Progress.Total = e.Artifact.Size
+ report.ProgressMessage = report.Progress.String()
case types.ProgressEventSkipped:
report.Status = "Already exists"
case types.ProgressEventDone:
report.Status = "Download complete"
}
- report.Id = e.Artifact.Digest.Encoded()[0:12]
+ report.ID = e.Artifact.Digest.Encoded()[0:12]
if err := enc.Encode(report); err != nil {
logrus.Warnf("Failed to json encode error %q", err.Error())
}
@@ -358,7 +352,11 @@ loop: // break out of for/select infinite loop
err := pullRes.err
pulledImages := pullRes.images
if err != nil {
- report.Error = err.Error()
+ msg := err.Error()
+ report.Error = &jsonmessage.JSONError{
+ Message: msg,
+ }
+ report.ErrorMessage = msg
} else {
if len(pulledImages) > 0 {
img := pulledImages[0].ID()
@@ -367,9 +365,13 @@ loop: // break out of for/select infinite loop
} else {
report.Status = "Download complete"
}
- report.Id = img[0:12]
+ report.ID = img[0:12]
} else {
- report.Error = "internal error: no images pulled"
+ msg := "internal error: no images pulled"
+ report.Error = &jsonmessage.JSONError{
+ Message: msg,
+ }
+ report.ErrorMessage = msg
}
}
if err := enc.Encode(report); err != nil {
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_push.go b/pkg/api/handlers/compat/images_push.go
index bb82ef10d..f29808124 100644
--- a/pkg/api/handlers/compat/images_push.go
+++ b/pkg/api/handlers/compat/images_push.go
@@ -156,6 +156,7 @@ loop: // break out of for/select infinite loop
Current: int64(e.Offset),
Total: e.Artifact.Size,
}
+ report.ProgressMessage = report.Progress.String()
case types.ProgressEventSkipped:
report.Status = "Layer already exists"
case types.ProgressEventDone:
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/compat/networks.go b/pkg/api/handlers/compat/networks.go
index 65177218a..29d1398cf 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -23,6 +23,13 @@ import (
"github.com/sirupsen/logrus"
)
+func normalizeNetworkName(rt *libpod.Runtime, name string) (string, bool) {
+ if name == nettypes.BridgeNetworkDriver {
+ return rt.Network().DefaultNetworkName(), true
+ }
+ return name, false
+}
+
func InspectNetwork(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
@@ -44,13 +51,13 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.Error(w, http.StatusBadRequest, define.ErrInvalidArg)
return
}
- name := utils.GetName(r)
+ name, changed := normalizeNetworkName(runtime, utils.GetName(r))
net, err := runtime.Network().NetworkInspect(name)
if err != nil {
utils.NetworkNotFound(w, name, err)
return
}
- report, err := convertLibpodNetworktoDockerNetwork(runtime, net)
+ report, err := convertLibpodNetworktoDockerNetwork(runtime, &net, changed)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -58,7 +65,7 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, report)
}
-func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, network nettypes.Network) (*types.NetworkResource, error) {
+func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, network *nettypes.Network, changeDefaultName bool) (*types.NetworkResource, error) {
cons, err := runtime.GetAllContainers()
if err != nil {
return nil, err
@@ -107,11 +114,15 @@ func convertLibpodNetworktoDockerNetwork(runtime *libpod.Runtime, network nettyp
Config: ipamConfigs,
}
+ name := network.Name
+ if changeDefaultName && name == runtime.Network().DefaultNetworkName() {
+ name = nettypes.BridgeNetworkDriver
+ }
report := types.NetworkResource{
- Name: network.Name,
- ID: network.ID,
- Driver: network.Driver,
- // TODO add Created: ,
+ Name: name,
+ ID: network.ID,
+ Driver: network.Driver,
+ Created: network.Created,
Internal: network.Internal,
EnableIPv6: network.IPv6Enabled,
Labels: network.Labels,
@@ -149,7 +160,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
}
reports := make([]*types.NetworkResource, 0, len(nets))
for _, net := range nets {
- report, err := convertLibpodNetworktoDockerNetwork(runtime, net)
+ report, err := convertLibpodNetworktoDockerNetwork(runtime, &net, true)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -182,27 +193,22 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
network.Options = make(map[string]string)
- // TODO: we should consider making this constants in c/common/libnetwork/types
+ // dockers bridge networks are always isolated from each other
+ if network.Driver == nettypes.BridgeNetworkDriver {
+ network.Options[nettypes.IsolateOption] = "true"
+ }
+
for opt, optVal := range networkCreate.Options {
switch opt {
- case "mtu":
+ case nettypes.MTUOption:
fallthrough
case "com.docker.network.driver.mtu":
- if network.Driver == nettypes.BridgeNetworkDriver {
- network.Options["mtu"] = optVal
- }
- case "icc":
- fallthrough
- case "com.docker.network.bridge.enable_icc":
- // TODO: needs to be implemented
- if network.Driver == nettypes.BridgeNetworkDriver {
- responseWarning = "com.docker.network.bridge.enable_icc is not currently implemented"
- }
+ network.Options[nettypes.MTUOption] = optVal
case "com.docker.network.bridge.name":
if network.Driver == nettypes.BridgeNetworkDriver {
network.NetworkInterface = optVal
}
- case "mode":
+ case nettypes.ModeOption:
if network.Driver == nettypes.MacVLANNetworkDriver || network.Driver == nettypes.IPVLANNetworkDriver {
network.Options[opt] = optVal
}
@@ -305,7 +311,7 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
Timeout: query.Timeout,
}
- name := utils.GetName(r)
+ name, _ := normalizeNetworkName(runtime, utils.GetName(r))
reports, err := ic.NetworkRm(r.Context(), []string{name}, options)
if err != nil {
utils.Error(w, http.StatusInternalServerError, err)
@@ -340,7 +346,7 @@ func Connect(w http.ResponseWriter, r *http.Request) {
netOpts := nettypes.PerNetworkOptions{}
- name := utils.GetName(r)
+ name, _ := normalizeNetworkName(runtime, utils.GetName(r))
if netConnect.EndpointConfig != nil {
if netConnect.EndpointConfig.Aliases != nil {
netOpts.Aliases = netConnect.EndpointConfig.Aliases
@@ -416,7 +422,7 @@ func Disconnect(w http.ResponseWriter, r *http.Request) {
return
}
- name := utils.GetName(r)
+ name, _ := normalizeNetworkName(runtime, utils.GetName(r))
err := runtime.DisconnectContainerFromNetwork(netDisconnect.Container, name, netDisconnect.Force)
if err != nil {
if errors.Is(err, define.ErrNoSuchCtr) {
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index e4964d602..1307c267a 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -31,6 +31,9 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
ContainerNetworkConfig: specgen.ContainerNetworkConfig{
UseImageHosts: conf.Containers.NoHosts,
},
+ ContainerSecurityConfig: specgen.ContainerSecurityConfig{
+ Umask: conf.Containers.Umask,
+ },
}
if err := json.NewDecoder(r.Body).Decode(&sg); err != nil {
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index ed1c65f8e..67943ecf1 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -1,7 +1,6 @@
package libpod
import (
- "context"
"errors"
"fmt"
"io"
@@ -14,13 +13,11 @@ import (
"github.com/containers/buildah"
"github.com/containers/common/libimage"
"github.com/containers/image/v5/manifest"
- "github.com/containers/image/v5/types"
"github.com/containers/podman/v4/libpod"
"github.com/containers/podman/v4/libpod/define"
"github.com/containers/podman/v4/pkg/api/handlers"
"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/domain/entities"
"github.com/containers/podman/v4/pkg/domain/entities/reports"
"github.com/containers/podman/v4/pkg/domain/infra/abi"
@@ -416,74 +413,6 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, report)
}
-// PushImage is the handler for the compat http endpoint for pushing images.
-func PushImage(w http.ResponseWriter, r *http.Request) {
- decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
- 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"`
- }{
- // This is where you can override the golang default value for one of fields
- }
- if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
- return
- }
-
- source := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
- if _, err := utils.ParseStorageReference(source); err != nil {
- utils.Error(w, http.StatusBadRequest, err)
- return
- }
-
- destination := query.Destination
- if destination == "" {
- destination = source
- }
-
- if err := utils.IsRegistryReference(destination); err != nil {
- utils.Error(w, http.StatusBadRequest, err)
- return
- }
-
- authconf, authfile, err := auth.GetCredentials(r)
- if err != nil {
- utils.Error(w, http.StatusBadRequest, err)
- return
- }
- defer auth.RemoveAuthfile(authfile)
- var username, password string
- if authconf != nil {
- username = authconf.Username
- password = authconf.Password
- }
- options := entities.ImagePushOptions{
- All: query.All,
- Authfile: authfile,
- Format: query.Format,
- Password: password,
- Quiet: true,
- RemoveSignatures: query.RemoveSignatures,
- Username: username,
- }
- if _, found := r.URL.Query()["tlsVerify"]; found {
- options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
- }
-
- imageEngine := abi.ImageEngine{Libpod: runtime}
- if err := imageEngine.Push(context.Background(), source, destination, options); err != nil {
- utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err))
- return
- }
-
- utils.WriteResponse(w, http.StatusOK, "")
-}
-
func CommitContainer(w http.ResponseWriter, r *http.Request) {
var (
destImage string
diff --git a/pkg/api/handlers/libpod/images_push.go b/pkg/api/handlers/libpod/images_push.go
new file mode 100644
index 000000000..9ee651f5b
--- /dev/null
+++ b/pkg/api/handlers/libpod/images_push.go
@@ -0,0 +1,145 @@
+package libpod
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/containers/image/v5/types"
+ "github.com/containers/podman/v4/libpod"
+ "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/gorilla/schema"
+ "github.com/sirupsen/logrus"
+)
+
+// PushImage is the handler for the compat http endpoint for pushing images.
+func PushImage(w http.ResponseWriter, r *http.Request) {
+ decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder)
+ 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"`
+ }{
+ TLSVerify: true,
+ // #14971: 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, fmt.Errorf("failed to parse parameters for %s: %w", r.URL.String(), err))
+ return
+ }
+
+ source := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
+ if _, err := utils.ParseStorageReference(source); err != nil {
+ utils.Error(w, http.StatusBadRequest, err)
+ return
+ }
+
+ destination := query.Destination
+ if destination == "" {
+ destination = source
+ }
+
+ if err := utils.IsRegistryReference(destination); err != nil {
+ utils.Error(w, http.StatusBadRequest, err)
+ return
+ }
+
+ authconf, authfile, err := auth.GetCredentials(r)
+ if err != nil {
+ utils.Error(w, http.StatusBadRequest, err)
+ return
+ }
+ defer auth.RemoveAuthfile(authfile)
+
+ var username, password string
+ if authconf != nil {
+ username = authconf.Username
+ password = authconf.Password
+ }
+ options := entities.ImagePushOptions{
+ All: query.All,
+ Authfile: authfile,
+ Format: query.Format,
+ Password: password,
+ Quiet: true,
+ RemoveSignatures: query.RemoveSignatures,
+ Username: username,
+ }
+
+ if _, found := r.URL.Query()["tlsVerify"]; found {
+ options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify)
+ }
+
+ imageEngine := abi.ImageEngine{Libpod: runtime}
+
+ // Let's keep thing simple when running in quiet mode and push directly.
+ if query.Quiet {
+ if err := imageEngine.Push(context.Background(), source, destination, options); err != nil {
+ utils.Error(w, http.StatusBadRequest, fmt.Errorf("error pushing image %q: %w", destination, err))
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, "")
+ return
+ }
+
+ writer := channel.NewWriter(make(chan []byte))
+ defer writer.Close()
+ options.Writer = writer
+
+ pushCtx, pushCancel := context.WithCancel(r.Context())
+ var pushError error
+ go func() {
+ defer pushCancel()
+ pushError = imageEngine.Push(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.ImagePushReport
+ 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()
+ 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
+ }
+ }
+}
diff --git a/pkg/api/handlers/libpod/manifests.go b/pkg/api/handlers/libpod/manifests.go
index 3235a2972..43c7139d3 100644
--- a/pkg/api/handlers/libpod/manifests.go
+++ b/pkg/api/handlers/libpod/manifests.go
@@ -310,6 +310,7 @@ func ManifestPush(w http.ResponseWriter, r *http.Request) {
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,
diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go
index a2f46cb35..1bfedd77e 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
@@ -730,6 +730,11 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// description: Require TLS verification.
// type: boolean
// default: true
+ // - in: query
+ // name: quiet
+ // description: "silences extra stream data on push"
+ // type: boolean
+ // default: true
// - in: header
// name: X-Registry-Auth
// type: string
@@ -1115,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/images.go b/pkg/bindings/images/images.go
index cd5147629..bb7867c4e 100644
--- a/pkg/bindings/images/images.go
+++ b/pkg/bindings/images/images.go
@@ -267,46 +267,6 @@ func Import(ctx context.Context, r io.Reader, options *ImportOptions) (*entities
return &report, response.Process(&report)
}
-// Push is the binding for libpod's v2 endpoints for push images. Note that
-// `source` must be a referring to an image in the remote's container storage.
-// The destination must be a reference to a registry (i.e., of docker transport
-// or be normalized to one). Other transports are rejected as they do not make
-// sense in a remote context.
-func Push(ctx context.Context, source string, destination string, options *PushOptions) error {
- if options == nil {
- options = new(PushOptions)
- }
- conn, err := bindings.GetClient(ctx)
- if err != nil {
- return err
- }
- header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
- if err != nil {
- return err
- }
-
- params, err := options.ToParams()
- if err != nil {
- return err
- }
- // SkipTLSVerify is special. We need to delete the param added by
- // toparams and change the key and flip the bool
- if options.SkipTLSVerify != nil {
- params.Del("SkipTLSVerify")
- params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
- }
- params.Set("destination", destination)
-
- path := fmt.Sprintf("/images/%s/push", source)
- response, err := conn.DoRequest(ctx, nil, http.MethodPost, path, params, header)
- if err != nil {
- return err
- }
- defer response.Body.Close()
-
- return response.Process(err)
-}
-
// Search is the binding for libpod's v2 endpoints for Search images.
func Search(ctx context.Context, term string, options *SearchOptions) ([]entities.ImageSearchReport, error) {
if options == nil {
diff --git a/pkg/bindings/images/push.go b/pkg/bindings/images/push.go
new file mode 100644
index 000000000..8db3726e6
--- /dev/null
+++ b/pkg/bindings/images/push.go
@@ -0,0 +1,96 @@
+package images
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "strconv"
+
+ imageTypes "github.com/containers/image/v5/types"
+ "github.com/containers/podman/v4/pkg/auth"
+ "github.com/containers/podman/v4/pkg/bindings"
+ "github.com/containers/podman/v4/pkg/domain/entities"
+)
+
+// Push is the binding for libpod's endpoints for push images. Note that
+// `source` must be a referring to an image in the remote's container storage.
+// The destination must be a reference to a registry (i.e., of docker transport
+// or be normalized to one). Other transports are rejected as they do not make
+// sense in a remote context.
+func Push(ctx context.Context, source string, destination string, options *PushOptions) error {
+ if options == nil {
+ options = new(PushOptions)
+ }
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return err
+ }
+ header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
+ if err != nil {
+ return err
+ }
+
+ params, err := options.ToParams()
+ if err != nil {
+ return err
+ }
+ // SkipTLSVerify is special. We need to delete the param added by
+ // toparams and change the key and flip the bool
+ if options.SkipTLSVerify != nil {
+ params.Del("SkipTLSVerify")
+ params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
+ }
+ params.Set("destination", destination)
+
+ path := fmt.Sprintf("/images/%s/push", source)
+ response, err := conn.DoRequest(ctx, nil, http.MethodPost, path, params, header)
+ if err != nil {
+ return err
+ }
+ defer response.Body.Close()
+
+ if !response.IsSuccess() {
+ return response.Process(err)
+ }
+
+ // Historically push writes status to stderr
+ writer := io.Writer(os.Stderr)
+ if options.GetQuiet() {
+ writer = ioutil.Discard
+ }
+
+ dec := json.NewDecoder(response.Body)
+ for {
+ var report entities.ImagePushReport
+ if err := dec.Decode(&report); err != nil {
+ if errors.Is(err, io.EOF) {
+ break
+ }
+ return err
+ }
+
+ select {
+ case <-response.Request.Context().Done():
+ break
+ default:
+ // non-blocking select
+ }
+
+ switch {
+ 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)
+ }
+ }
+
+ return nil
+}
diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go
index 3728ae5c0..0e672cdea 100644
--- a/pkg/bindings/images/types.go
+++ b/pkg/bindings/images/types.go
@@ -133,6 +133,8 @@ type PushOptions struct {
RemoveSignatures *bool
// Username for authenticating against the registry.
Username *string
+ // Quiet can be specified to suppress progress when pushing.
+ Quiet *bool
}
//go:generate go run ../generator/generator.go SearchOptions
diff --git a/pkg/bindings/images/types_push_options.go b/pkg/bindings/images/types_push_options.go
index 25f6c5546..63a19fb81 100644
--- a/pkg/bindings/images/types_push_options.go
+++ b/pkg/bindings/images/types_push_options.go
@@ -136,3 +136,18 @@ func (o *PushOptions) GetUsername() string {
}
return *o.Username
}
+
+// WithQuiet set field Quiet to given value
+func (o *PushOptions) WithQuiet(value bool) *PushOptions {
+ o.Quiet = &value
+ return o
+}
+
+// GetQuiet returns value of field Quiet
+func (o *PushOptions) GetQuiet() bool {
+ if o.Quiet == nil {
+ var z bool
+ return z
+ }
+ return *o.Quiet
+}
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/entities/containers.go b/pkg/domain/entities/containers.go
index 934a7cbdc..df793034b 100644
--- a/pkg/domain/entities/containers.go
+++ b/pkg/domain/entities/containers.go
@@ -71,12 +71,15 @@ type StringSliceReport struct {
}
type PauseUnPauseOptions struct {
- All bool
+ Filters map[string][]string
+ All bool
+ Latest bool
}
type PauseUnpauseReport struct {
- Err error
- Id string //nolint:revive,stylecheck
+ Err error
+ Id string //nolint:revive,stylecheck
+ RawInput string
}
type StopOptions struct {
diff --git a/pkg/domain/entities/images.go b/pkg/domain/entities/images.go
index da317cfad..b8b346005 100644
--- a/pkg/domain/entities/images.go
+++ b/pkg/domain/entities/images.go
@@ -1,6 +1,7 @@
package entities
import (
+ "io"
"net/url"
"time"
@@ -192,8 +193,7 @@ type ImagePushOptions struct {
// image. Default is manifest type of source, with fallbacks.
// Ignored for remote calls.
Format string
- // Quiet can be specified to suppress pull progress when pulling. Ignored
- // for remote calls.
+ // Quiet can be specified to suppress push progress when pushing.
Quiet bool
// Rm indicates whether to remove the manifest list if push succeeds
Rm bool
@@ -211,6 +211,17 @@ type ImagePushOptions struct {
Progress chan types.ProgressProperties
// CompressionFormat is the format to use for the compression of the blobs
CompressionFormat string
+ // Writer is used to display copy information including progress bars.
+ Writer io.Writer
+}
+
+// ImagePushReport is the response from pushing an image.
+// Currently only used in the remote API.
+type ImagePushReport struct {
+ // Stream used to provide push progress
+ Stream string `json:"stream,omitempty"`
+ // Error contains text of errors from pushing
+ Error string `json:"error,omitempty"`
}
// ImageSearchOptions are the arguments for searching images.
diff --git a/pkg/domain/entities/machine.go b/pkg/domain/entities/machine.go
index 6ba53dbd1..4fd0413c9 100644
--- a/pkg/domain/entities/machine.go
+++ b/pkg/domain/entities/machine.go
@@ -1,5 +1,7 @@
package entities
+import "github.com/containers/podman/v4/libpod/define"
+
type ListReporter struct {
Name string
Default bool
@@ -16,3 +18,23 @@ type ListReporter struct {
RemoteUsername string
IdentityPath string
}
+
+// MachineInfo contains info on the machine host and version info
+type MachineInfo struct {
+ Host *MachineHostInfo `json:"Host"`
+ Version define.Version `json:"Version"`
+}
+
+// MachineHostInfo contains info on the machine host
+type MachineHostInfo struct {
+ Arch string `json:"Arch"`
+ CurrentMachine string `json:"CurrentMachine"`
+ DefaultMachine string `json:"DefaultMachine"`
+ EventsDir string `json:"EventsDir"`
+ MachineConfigDir string `json:"MachineConfigDir"`
+ MachineImageDir string `json:"MachineImageDir"`
+ MachineState string `json:"MachineState"`
+ NumberOfMachines int `json:"NumberOfMachines"`
+ OS string `json:"OS"`
+ VMType string `json:"VMType"`
+}
diff --git a/pkg/domain/entities/play.go b/pkg/domain/entities/play.go
index 35a5d8a4a..5bb438d7d 100644
--- a/pkg/domain/entities/play.go
+++ b/pkg/domain/entities/play.go
@@ -88,6 +88,7 @@ type PlayKubeReport struct {
// Volumes - volumes created by play kube.
Volumes []PlayKubeVolume
PlayKubeTeardown
+ Secrets []PlaySecret
}
type KubePlayReport = PlayKubeReport
@@ -100,3 +101,7 @@ type PlayKubeTeardown struct {
StopReport []*PodStopReport
RmReport []*PodRmReport
}
+
+type PlaySecret struct {
+ CreateReport *SecretCreateReport
+}
diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go
index 04eb85504..dd7053a23 100644
--- a/pkg/domain/infra/abi/containers.go
+++ b/pkg/domain/infra/abi/containers.go
@@ -62,6 +62,11 @@ func getContainersAndInputByContext(all, latest bool, names []string, filters ma
}
case all:
ctrs, err = runtime.GetAllContainers()
+ if err == nil {
+ for _, ctr := range ctrs {
+ rawInput = append(rawInput, ctr.ID())
+ }
+ }
case latest:
ctr, err = runtime.GetLatestContainer()
if err == nil {
@@ -133,37 +138,57 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- ctrs, err := getContainersByContext(options.All, false, namesOrIds, ic.Libpod)
+ ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, options.Filters, ic.Libpod)
if err != nil {
return nil, err
}
- report := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
+ ctrMap := map[string]string{}
+ if len(rawInputs) == len(ctrs) {
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID()] = rawInputs[i]
+ }
+ }
+ reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := c.Pause()
if err != nil && options.All && errors.Is(err, define.ErrCtrStateInvalid) {
logrus.Debugf("Container %s is not running", c.ID())
continue
}
- report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
+ reports = append(reports, &entities.PauseUnpauseReport{
+ Id: c.ID(),
+ Err: err,
+ RawInput: ctrMap[c.ID()],
+ })
}
- return report, nil
+ return reports, nil
}
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- ctrs, err := getContainersByContext(options.All, false, namesOrIds, ic.Libpod)
+ ctrs, rawInputs, err := getContainersAndInputByContext(options.All, options.Latest, namesOrIds, options.Filters, ic.Libpod)
if err != nil {
return nil, err
}
- report := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
+ ctrMap := map[string]string{}
+ if len(rawInputs) == len(ctrs) {
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID()] = rawInputs[i]
+ }
+ }
+ reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := c.Unpause()
if err != nil && options.All && errors.Is(err, define.ErrCtrStateInvalid) {
logrus.Debugf("Container %s is not paused", c.ID())
continue
}
- report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
+ reports = append(reports, &entities.PauseUnpauseReport{
+ Id: c.ID(),
+ Err: err,
+ RawInput: ctrMap[c.ID()],
+ })
}
- return report, nil
+ return reports, nil
}
func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) {
names := namesOrIds
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 38008c7b9..ff42b0367 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -305,6 +305,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
pushOptions.RemoveSignatures = options.RemoveSignatures
pushOptions.SignBy = options.SignBy
pushOptions.InsecureSkipTLSVerify = options.SkipTLSVerify
+ pushOptions.Writer = options.Writer
compressionFormat := options.CompressionFormat
if compressionFormat == "" {
@@ -322,7 +323,7 @@ func (ir *ImageEngine) Push(ctx context.Context, source string, destination stri
pushOptions.CompressionFormat = &algo
}
- if !options.Quiet {
+ if !options.Quiet && pushOptions.Writer == nil {
pushOptions.Writer = os.Stderr
}
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index 8b47eff53..3f2fd5f92 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -84,15 +84,15 @@ func (ic *ContainerEngine) createServiceContainer(ctx context.Context, name stri
return ctr, nil
}
-// Creates the name for a service container based on the provided content of a
-// K8s yaml file.
-func serviceContainerName(content []byte) string {
+// Creates the name for a k8s entity based on the provided content of a
+// K8s yaml file and a given suffix.
+func k8sName(content []byte, suffix string) string {
// The name of the service container is the first 12
// characters of the yaml file's hash followed by the
// '-service' suffix to guarantee a predictable and
// discoverable name.
hash := digest.FromBytes(content).Encoded()
- return hash[0:12] + "-service"
+ return hash[0:12] + "-" + suffix
}
func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options entities.PlayKubeOptions) (_ *entities.PlayKubeReport, finalErr error) {
@@ -132,7 +132,7 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
// TODO: create constants for the various "kinds" of yaml files.
var serviceContainer *libpod.Container
if options.ServiceContainer && (kind == "Pod" || kind == "Deployment") {
- ctr, err := ic.createServiceContainer(ctx, serviceContainerName(content), options)
+ ctr, err := ic.createServiceContainer(ctx, k8sName(content, "service"), options)
if err != nil {
return nil, err
}
@@ -213,6 +213,19 @@ func (ic *ContainerEngine) PlayKube(ctx context.Context, body io.Reader, options
return nil, fmt.Errorf("unable to read YAML as Kube ConfigMap: %w", err)
}
configMaps = append(configMaps, configMap)
+ case "Secret":
+ var secret v1.Secret
+
+ if err := yaml.Unmarshal(document, &secret); err != nil {
+ return nil, fmt.Errorf("unable to read YAML as kube secret: %w", err)
+ }
+
+ r, err := ic.playKubeSecret(&secret)
+ if err != nil {
+ return nil, err
+ }
+ report.Secrets = append(report.Secrets, entities.PlaySecret{CreateReport: r})
+ validKinds++
default:
logrus.Infof("Kube kind %s not supported", kind)
continue
@@ -380,7 +393,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
configMaps = append(configMaps, cm)
}
- volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes, configMaps)
+ volumes, err := kube.InitializeVolumes(podYAML.Spec.Volumes, configMaps, secretsManager)
if err != nil {
return nil, err
}
@@ -388,7 +401,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
// Go through the volumes and create a podman volume for all volumes that have been
// defined by a configmap
for _, v := range volumes {
- if v.Type == kube.KubeVolumeTypeConfigMap && !v.Optional {
+ if (v.Type == kube.KubeVolumeTypeConfigMap || v.Type == kube.KubeVolumeTypeSecret) && !v.Optional {
vol, err := ic.Libpod.NewVolume(ctx, libpod.WithVolumeName(v.Source))
if err != nil {
if errors.Is(err, define.ErrVolumeExists) {
@@ -583,6 +596,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
UserNSIsHost: p.Userns.IsHost(),
Volumes: volumes,
}
+
specGen, err := kube.ToSpecGen(ctx, &specgenOpts)
if err != nil {
return nil, err
@@ -968,3 +982,55 @@ func (ic *ContainerEngine) PlayKubeDown(ctx context.Context, body io.Reader, _ e
return reports, nil
}
+
+// playKubeSecret allows users to create and store a kubernetes secret as a podman secret
+func (ic *ContainerEngine) playKubeSecret(secret *v1.Secret) (*entities.SecretCreateReport, error) {
+ r := &entities.SecretCreateReport{}
+
+ // Create the secret manager before hand
+ secretsManager, err := ic.Libpod.SecretsManager()
+ if err != nil {
+ return nil, err
+ }
+
+ data, err := yaml.Marshal(secret)
+ if err != nil {
+ return nil, err
+ }
+
+ secretsPath := ic.Libpod.GetSecretsStorageDir()
+ opts := make(map[string]string)
+ opts["path"] = filepath.Join(secretsPath, "filedriver")
+ // maybe k8sName(data)...
+ // using this does not allow the user to use the name given to the secret
+ // but keeping secret.Name as the ID can lead to a collision.
+
+ s, err := secretsManager.Lookup(secret.Name)
+ if err == nil {
+ if val, ok := s.Metadata["immutable"]; ok {
+ if val == "true" {
+ return nil, fmt.Errorf("cannot remove colliding secret as it is set to immutable")
+ }
+ }
+ _, err = secretsManager.Delete(s.Name)
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ // now we have either removed the old secret w/ the same name or
+ // the name was not taken. Either way, we can now store.
+
+ meta := make(map[string]string)
+ if secret.Immutable != nil && *secret.Immutable {
+ meta["immutable"] = "true"
+ }
+ secretID, err := secretsManager.Store(secret.Name, data, "file", opts, meta)
+ if err != nil {
+ return nil, err
+ }
+
+ r.ID = secretID
+
+ return r, nil
+}
diff --git a/pkg/domain/infra/abi/secrets.go b/pkg/domain/infra/abi/secrets.go
index 7321ef715..e82fa4fdd 100644
--- a/pkg/domain/infra/abi/secrets.go
+++ b/pkg/domain/infra/abi/secrets.go
@@ -42,7 +42,7 @@ func (ic *ContainerEngine) SecretCreate(ctx context.Context, name string, reader
}
}
- secretID, err := manager.Store(name, data, options.Driver, options.DriverOpts)
+ secretID, err := manager.Store(name, data, options.Driver, options.DriverOpts, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go
index fcabff7c4..272c23268 100644
--- a/pkg/domain/infra/tunnel/containers.go
+++ b/pkg/domain/infra/tunnel/containers.go
@@ -57,10 +57,14 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin
}
func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, namesOrIds)
+ ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, options.All, false, namesOrIds, options.Filters)
if err != nil {
return nil, err
}
+ ctrMap := map[string]string{}
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID] = rawInputs[i]
+ }
reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := containers.Pause(ic.ClientCtx, c.ID, nil)
@@ -68,24 +72,36 @@ func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []stri
logrus.Debugf("Container %s is not running", c.ID)
continue
}
- reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
+ reports = append(reports, &entities.PauseUnpauseReport{
+ Id: c.ID,
+ Err: err,
+ RawInput: ctrMap[c.ID],
+ })
}
return reports, nil
}
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
- reports := []*entities.PauseUnpauseReport{}
- ctrs, err := getContainersByContext(ic.ClientCtx, options.All, false, namesOrIds)
+ ctrs, rawInputs, err := getContainersAndInputByContext(ic.ClientCtx, options.All, false, namesOrIds, options.Filters)
if err != nil {
return nil, err
}
+ ctrMap := map[string]string{}
+ for i := range ctrs {
+ ctrMap[ctrs[i].ID] = rawInputs[i]
+ }
+ reports := make([]*entities.PauseUnpauseReport, 0, len(ctrs))
for _, c := range ctrs {
err := containers.Unpause(ic.ClientCtx, c.ID, nil)
if err != nil && options.All && strings.Contains(err.Error(), define.ErrCtrStateInvalid.Error()) {
logrus.Debugf("Container %s is not paused", c.ID)
continue
}
- reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
+ reports = append(reports, &entities.PauseUnpauseReport{
+ Id: c.ID,
+ Err: err,
+ RawInput: ctrMap[c.ID],
+ })
}
return reports, nil
}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index 18f750dcc..9ad408850 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)
+ 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)
if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined {
if s == types.OptionalBoolTrue {
diff --git a/pkg/k8s.io/api/core/v1/types.go b/pkg/k8s.io/api/core/v1/types.go
index 48f353cc6..39a675dae 100644
--- a/pkg/k8s.io/api/core/v1/types.go
+++ b/pkg/k8s.io/api/core/v1/types.go
@@ -56,6 +56,7 @@ type VolumeSource struct {
// ConfigMap represents a configMap that should populate this volume
// +optional
ConfigMap *ConfigMapVolumeSource `json:"configMap,omitempty"`
+ Secret *SecretVolumeSource
}
// PersistentVolumeClaimVolumeSource references the user's PVC in the same namespace.
diff --git a/pkg/machine/e2e/basic_test.go b/pkg/machine/e2e/basic_test.go
index f67fb4c67..da0310485 100644
--- a/pkg/machine/e2e/basic_test.go
+++ b/pkg/machine/e2e/basic_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
@@ -20,7 +20,7 @@ var _ = Describe("run basic podman commands", func() {
})
It("Basic ops", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/config_basic.go b/pkg/machine/e2e/config_basic_test.go
index be0896156..d1cb24174 100644
--- a/pkg/machine/e2e/config_basic.go
+++ b/pkg/machine/e2e/config_basic_test.go
@@ -1,8 +1,7 @@
-package e2e
+package e2e_test
type basicMachine struct {
args []string
- cmd []string
}
func (s basicMachine) buildCmd(m *machineTestBuilder) []string {
diff --git a/pkg/machine/e2e/config_info.go b/pkg/machine/e2e/config_info_test.go
index 410c7e518..4da40ab99 100644
--- a/pkg/machine/e2e/config_info.go
+++ b/pkg/machine/e2e/config_info_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type infoMachine struct {
format string
diff --git a/pkg/machine/e2e/config_init.go b/pkg/machine/e2e/config_init_test.go
index 7f18cce7d..d6c7990b0 100644
--- a/pkg/machine/e2e/config_init.go
+++ b/pkg/machine/e2e/config_init_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strconv"
@@ -25,7 +25,7 @@ type initMachine struct {
memory *uint
now bool
timezone string
- rootful bool
+ rootful bool //nolint:unused,structcheck
volumes []string
cmd []string
@@ -71,7 +71,7 @@ func (i *initMachine) withDiskSize(size uint) *initMachine {
return i
}
-func (i *initMachine) withIgnitionPath(path string) *initMachine {
+func (i *initMachine) withIgnitionPath(path string) *initMachine { //nolint:unused
i.ignitionPath = path
return i
}
diff --git a/pkg/machine/e2e/config_inspect.go b/pkg/machine/e2e/config_inspect_test.go
index 74c9a5d9c..ffd74220f 100644
--- a/pkg/machine/e2e/config_inspect.go
+++ b/pkg/machine/e2e/config_inspect_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type inspectMachine struct {
/*
diff --git a/pkg/machine/e2e/config_list.go b/pkg/machine/e2e/config_list_test.go
index 150f984bc..78f9edc62 100644
--- a/pkg/machine/e2e/config_list.go
+++ b/pkg/machine/e2e/config_list_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type listMachine struct {
/*
diff --git a/pkg/machine/e2e/config_rm.go b/pkg/machine/e2e/config_rm_test.go
index 6cf262a22..1f9c9b4ec 100644
--- a/pkg/machine/e2e/config_rm.go
+++ b/pkg/machine/e2e/config_rm_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
type rmMachine struct {
/*
@@ -40,17 +40,17 @@ func (i *rmMachine) withForce() *rmMachine {
return i
}
-func (i *rmMachine) withSaveIgnition() *rmMachine {
+func (i *rmMachine) withSaveIgnition() *rmMachine { //nolint:unused
i.saveIgnition = true
return i
}
-func (i *rmMachine) withSaveImage() *rmMachine {
+func (i *rmMachine) withSaveImage() *rmMachine { //nolint:unused
i.saveImage = true
return i
}
-func (i *rmMachine) withSaveKeys() *rmMachine {
+func (i *rmMachine) withSaveKeys() *rmMachine { //nolint:unused
i.saveKeys = true
return i
}
diff --git a/pkg/machine/e2e/config_set.go b/pkg/machine/e2e/config_set_test.go
index b310ab1b9..3c773b970 100644
--- a/pkg/machine/e2e/config_set.go
+++ b/pkg/machine/e2e/config_set_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strconv"
diff --git a/pkg/machine/e2e/config_ssh.go b/pkg/machine/e2e/config_ssh_test.go
index b09eed47d..f062625fa 100644
--- a/pkg/machine/e2e/config_ssh.go
+++ b/pkg/machine/e2e/config_ssh_test.go
@@ -1,14 +1,12 @@
-package e2e
+package e2e_test
type sshMachine struct {
/*
--username string Username to use when ssh-ing into the VM.
*/
- username string
+ username string //nolint:unused
sshCommand []string
-
- cmd []string
}
func (s sshMachine) buildCmd(m *machineTestBuilder) []string {
@@ -22,7 +20,7 @@ func (s sshMachine) buildCmd(m *machineTestBuilder) []string {
return cmd
}
-func (s *sshMachine) withUsername(name string) *sshMachine {
+func (s *sshMachine) withUsername(name string) *sshMachine { //nolint:unused
s.username = name
return s
}
diff --git a/pkg/machine/e2e/config_start.go b/pkg/machine/e2e/config_start_test.go
index 86b1721f8..d9efbf489 100644
--- a/pkg/machine/e2e/config_start.go
+++ b/pkg/machine/e2e/config_start_test.go
@@ -1,10 +1,9 @@
-package e2e
+package e2e_test
type startMachine struct {
/*
No command line args other than a machine vm name (also not required)
*/
- cmd []string
}
func (s startMachine) buildCmd(m *machineTestBuilder) []string {
diff --git a/pkg/machine/e2e/config_stop.go b/pkg/machine/e2e/config_stop_test.go
index 04dcfb524..41142ec7e 100644
--- a/pkg/machine/e2e/config_stop.go
+++ b/pkg/machine/e2e/config_stop_test.go
@@ -1,10 +1,9 @@
-package e2e
+package e2e_test
type stopMachine struct {
/*
No command line args other than a machine vm name (also not required)
*/
- cmd []string
}
func (s stopMachine) buildCmd(m *machineTestBuilder) []string {
diff --git a/pkg/machine/e2e/config.go b/pkg/machine/e2e/config_test.go
index b3fe74b0c..9940e711b 100644
--- a/pkg/machine/e2e/config.go
+++ b/pkg/machine/e2e/config_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"encoding/json"
@@ -10,13 +10,11 @@ import (
"time"
"github.com/containers/podman/v4/pkg/machine"
- "github.com/containers/podman/v4/pkg/machine/qemu"
"github.com/containers/podman/v4/pkg/util"
"github.com/containers/storage/pkg/stringid"
- . "github.com/onsi/ginkgo" //nolint:golint,stylecheck
+ . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
- "github.com/onsi/gomega/gexec"
- . "github.com/onsi/gomega/gexec" //nolint:golint,stylecheck
+ . "github.com/onsi/gomega/gexec"
)
var originalHomeDir = os.Getenv("HOME")
@@ -36,7 +34,7 @@ type MachineTestBuilder interface {
run() (*machineSession, error)
}
type machineSession struct {
- *gexec.Session
+ *Session
}
type machineTestBuilder struct {
@@ -47,10 +45,6 @@ type machineTestBuilder struct {
podmanBinary string
timeout time.Duration
}
-type qemuMachineInspectInfo struct {
- State machine.Status
- VM qemu.MachineVM
-}
// waitWithTimeout waits for a command to complete for a given
// number of seconds
@@ -121,7 +115,7 @@ func (m *machineTestBuilder) setCmd(mc machineCommand) *machineTestBuilder {
// If no name for the machine exists, we set a random name.
if !util.StringInSlice(m.name, m.names) {
if len(m.name) < 1 {
- m.name = randomString(12)
+ m.name = randomString()
}
m.names = append(m.names, m.name)
}
@@ -136,10 +130,10 @@ func (m *machineTestBuilder) setTimeout(timeout time.Duration) *machineTestBuild
// toQemuInspectInfo is only for inspecting qemu machines. Other providers will need
// to make their own.
-func (mb *machineTestBuilder) toQemuInspectInfo() ([]machine.InspectInfo, int, error) {
+func (m *machineTestBuilder) toQemuInspectInfo() ([]machine.InspectInfo, int, error) {
args := []string{"machine", "inspect"}
- args = append(args, mb.names...)
- session, err := runWrapper(mb.podmanBinary, args, defaultTimeout, true)
+ args = append(args, m.names...)
+ session, err := runWrapper(m.podmanBinary, args, defaultTimeout, true)
if err != nil {
return nil, -1, err
}
@@ -175,9 +169,7 @@ func runWrapper(podmanBinary string, cmdArgs []string, timeout time.Duration, wa
return &ms, nil
}
-func (m *machineTestBuilder) init() {}
-
// randomString returns a string of given length composed of random characters
-func randomString(n int) string {
+func randomString() string {
return stringid.GenerateRandomID()[0:12]
}
diff --git a/pkg/machine/e2e/info_test.go b/pkg/machine/e2e/info_test.go
index eeabb78af..fe0cfba32 100644
--- a/pkg/machine/e2e/info_test.go
+++ b/pkg/machine/e2e/info_test.go
@@ -1,7 +1,7 @@
-package e2e
+package e2e_test
import (
- "github.com/containers/podman/v4/cmd/podman/machine"
+ "github.com/containers/podman/v4/pkg/domain/entities"
jsoniter "github.com/json-iterator/go"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -51,7 +51,7 @@ var _ = Describe("podman machine info", func() {
Expect(err).NotTo(HaveOccurred())
Expect(infoSession).Should(Exit(0))
- infoReport := &machine.Info{}
+ infoReport := &entities.MachineInfo{}
err = jsoniter.Unmarshal(infoSession.Bytes(), infoReport)
Expect(err).To(BeNil())
})
diff --git a/pkg/machine/e2e/init_test.go b/pkg/machine/e2e/init_test.go
index 40f140cae..b246dc4da 100644
--- a/pkg/machine/e2e/init_test.go
+++ b/pkg/machine/e2e/init_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"io/ioutil"
@@ -78,7 +78,7 @@ var _ = Describe("podman machine init", func() {
})
It("machine init with cpus, disk size, memory, timezone", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withCPUs(2).withDiskSize(102).withMemory(4000).withTimezone("Pacific/Honolulu")).run()
Expect(err).To(BeNil())
@@ -108,7 +108,7 @@ var _ = Describe("podman machine init", func() {
switch runtime.GOOS {
// os's handle memory differently
case "linux":
- Expect(memorySession.outputToString()).To(ContainSubstring("3821"))
+ Expect(memorySession.outputToString()).To(ContainSubstring("3822"))
case "darwin":
Expect(memorySession.outputToString()).To(ContainSubstring("3824"))
default:
@@ -130,7 +130,7 @@ var _ = Describe("podman machine init", func() {
mount := tmpDir + ":/testmountdir"
defer os.RemoveAll(tmpDir)
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withVolume(mount)).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/inspect_test.go b/pkg/machine/e2e/inspect_test.go
index 93fb8cc2b..0ab928205 100644
--- a/pkg/machine/e2e/inspect_test.go
+++ b/pkg/machine/e2e/inspect_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strings"
@@ -52,15 +52,15 @@ var _ = Describe("podman machine stop", func() {
})
It("inspect with go format", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
Expect(session).To(Exit(0))
// regular inspect should
- inspectJson := new(inspectMachine)
- inspectSession, err := mb.setName(name).setCmd(inspectJson).run()
+ inspectJSON := new(inspectMachine)
+ inspectSession, err := mb.setName(name).setCmd(inspectJSON).run()
Expect(err).To(BeNil())
Expect(inspectSession).To(Exit(0))
diff --git a/pkg/machine/e2e/list_test.go b/pkg/machine/e2e/list_test.go
index 8b7443d47..5c7ae6c5e 100644
--- a/pkg/machine/e2e/list_test.go
+++ b/pkg/machine/e2e/list_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"strings"
@@ -45,8 +45,8 @@ var _ = Describe("podman machine list", func() {
It("list machines with quiet or noheading", func() {
// Random names for machines to test list
- name1 := randomString(12)
- name2 := randomString(12)
+ name1 := randomString()
+ name2 := randomString()
list := new(listMachine)
firstList, err := mb.setCmd(list.withQuiet()).run()
@@ -109,7 +109,7 @@ var _ = Describe("podman machine list", func() {
It("list with --format", func() {
// Random names for machines to test list
- name1 := randomString(12)
+ name1 := randomString()
i := new(initMachine)
session, err := mb.setName(name1).setCmd(i.withImagePath(mb.imagePath)).run()
diff --git a/pkg/machine/e2e/machine_test.go b/pkg/machine/e2e/machine_test.go
index 93eabdad3..5de04b9f7 100644
--- a/pkg/machine/e2e/machine_test.go
+++ b/pkg/machine/e2e/machine_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"fmt"
diff --git a/pkg/machine/e2e/rm_test.go b/pkg/machine/e2e/rm_test.go
index 43b8c594c..e33eaf702 100644
--- a/pkg/machine/e2e/rm_test.go
+++ b/pkg/machine/e2e/rm_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
diff --git a/pkg/machine/e2e/set_test.go b/pkg/machine/e2e/set_test.go
index 80cb89488..4839e33da 100644
--- a/pkg/machine/e2e/set_test.go
+++ b/pkg/machine/e2e/set_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"runtime"
@@ -22,7 +22,7 @@ var _ = Describe("podman machine set", func() {
})
It("set machine cpus, disk, memory", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
@@ -62,7 +62,7 @@ var _ = Describe("podman machine set", func() {
switch runtime.GOOS {
// it seems macos and linux handle memory differently
case "linux":
- Expect(memorySession.outputToString()).To(ContainSubstring("3821"))
+ Expect(memorySession.outputToString()).To(ContainSubstring("3822"))
case "darwin":
Expect(memorySession.outputToString()).To(ContainSubstring("3824"))
default:
@@ -75,7 +75,7 @@ var _ = Describe("podman machine set", func() {
})
It("no settings should change if no flags", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/ssh_test.go b/pkg/machine/e2e/ssh_test.go
index 9ee31ac26..52d714c91 100644
--- a/pkg/machine/e2e/ssh_test.go
+++ b/pkg/machine/e2e/ssh_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
@@ -20,17 +20,16 @@ var _ = Describe("podman machine ssh", func() {
})
It("bad machine name", func() {
- name := randomString(12)
+ name := randomString()
ssh := sshMachine{}
session, err := mb.setName(name).setCmd(ssh).run()
Expect(err).To(BeNil())
Expect(session).To(Exit(125))
- // TODO seems like stderr is not being returned; re-enabled when fixed
- //Expect(session.outputToString()).To(ContainSubstring("not exist"))
+ Expect(session.errorToString()).To(ContainSubstring("not exist"))
})
It("ssh to non-running machine", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).To(BeNil())
@@ -39,13 +38,12 @@ var _ = Describe("podman machine ssh", func() {
ssh := sshMachine{}
sshSession, err := mb.setName(name).setCmd(ssh).run()
Expect(err).To(BeNil())
- // TODO seems like stderr is not being returned; re-enabled when fixed
- //Expect(sshSession.outputToString()).To(ContainSubstring("is not running"))
+ Expect(sshSession.errorToString()).To(ContainSubstring("is not running"))
Expect(sshSession).To(Exit(125))
})
It("ssh to running machine and check os-type", func() {
- name := randomString(12)
+ name := randomString()
i := new(initMachine)
session, err := mb.setName(name).setCmd(i.withImagePath(mb.imagePath).withNow()).run()
Expect(err).To(BeNil())
diff --git a/pkg/machine/e2e/start_test.go b/pkg/machine/e2e/start_test.go
index 1de66eb9a..1f9405569 100644
--- a/pkg/machine/e2e/start_test.go
+++ b/pkg/machine/e2e/start_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
"github.com/containers/podman/v4/pkg/machine"
diff --git a/pkg/machine/e2e/stop_test.go b/pkg/machine/e2e/stop_test.go
index 0c27045a6..621bbdb16 100644
--- a/pkg/machine/e2e/stop_test.go
+++ b/pkg/machine/e2e/stop_test.go
@@ -1,4 +1,4 @@
-package e2e
+package e2e_test
import (
. "github.com/onsi/ginkgo"
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/specgen/generate/container.go b/pkg/specgen/generate/container.go
index 9bb7caace..8cfac924b 100644
--- a/pkg/specgen/generate/container.go
+++ b/pkg/specgen/generate/container.go
@@ -494,10 +494,10 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
if s.ResourceLimits == nil {
s.ResourceLimits = &spec.LinuxResources{}
}
- if s.ResourceLimits.BlockIO == nil {
- s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
- }
if bps := s.ThrottleReadBpsDevice; len(bps) > 0 {
+ if s.ResourceLimits.BlockIO == nil {
+ s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
+ }
for k, v := range bps {
statT := unix.Stat_t{}
if err := unix.Stat(k, &statT); err != nil {
@@ -512,6 +512,9 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
}
}
if bps := s.ThrottleWriteBpsDevice; len(bps) > 0 {
+ if s.ResourceLimits.BlockIO == nil {
+ s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
+ }
for k, v := range bps {
statT := unix.Stat_t{}
if err := unix.Stat(k, &statT); err != nil {
@@ -523,6 +526,9 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
}
}
if iops := s.ThrottleReadIOPSDevice; len(iops) > 0 {
+ if s.ResourceLimits.BlockIO == nil {
+ s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
+ }
for k, v := range iops {
statT := unix.Stat_t{}
if err := unix.Stat(k, &statT); err != nil {
@@ -534,6 +540,9 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error {
}
}
if iops := s.ThrottleWriteIOPSDevice; len(iops) > 0 {
+ if s.ResourceLimits.BlockIO == nil {
+ s.ResourceLimits.BlockIO = &spec.LinuxBlockIO{}
+ }
for k, v := range iops {
statT := unix.Stat_t{}
if err := unix.Stat(k, &statT); err != nil {
diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go
index 389900820..8334d386f 100644
--- a/pkg/specgen/generate/container_create.go
+++ b/pkg/specgen/generate/container_create.go
@@ -55,6 +55,10 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener
}
}
+ if err := FinishThrottleDevices(s); err != nil {
+ return nil, nil, nil, err
+ }
+
// Set defaults for unset namespaces
if s.PidNS.IsDefault() {
defaultNS, err := GetDefaultNamespaceMode("pid", rtc, pod)
diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go
index 454a1e1d0..e9abf419b 100644
--- a/pkg/specgen/generate/kube/kube.go
+++ b/pkg/specgen/generate/kube/kube.go
@@ -398,6 +398,16 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener
Type: "b",
}
s.Devices = append(s.Devices, device)
+ case KubeVolumeTypeSecret:
+ // in podman play kube we need to add these secrets as volumes rather than as
+ // specgen.Secrets. Adding them as volumes allows for all key: value pairs to be mounted
+ secretVolume := specgen.NamedVolume{
+ Dest: volume.MountPath,
+ Name: volumeSource.Source,
+ Options: options,
+ }
+
+ s.Volumes = append(s.Volumes, &secretVolume)
default:
return nil, errors.New("unsupported volume source type")
}
diff --git a/pkg/specgen/generate/kube/play_test.go b/pkg/specgen/generate/kube/play_test.go
index 466dab610..470c0c39c 100644
--- a/pkg/specgen/generate/kube/play_test.go
+++ b/pkg/specgen/generate/kube/play_test.go
@@ -28,7 +28,7 @@ func createSecrets(t *testing.T, d string) *secrets.SecretsManager {
data, err := json.Marshal(s.Data)
assert.NoError(t, err)
- _, err = secretsManager.Store(s.ObjectMeta.Name, data, driver, driverOpts)
+ _, err = secretsManager.Store(s.ObjectMeta.Name, data, driver, driverOpts, nil)
assert.NoError(t, err)
}
diff --git a/pkg/specgen/generate/kube/volume.go b/pkg/specgen/generate/kube/volume.go
index f5c0c241d..c12adadd8 100644
--- a/pkg/specgen/generate/kube/volume.go
+++ b/pkg/specgen/generate/kube/volume.go
@@ -6,9 +6,13 @@ import (
"os"
"github.com/containers/common/pkg/parse"
+ "github.com/containers/common/pkg/secrets"
"github.com/containers/podman/v4/libpod"
v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
+ metav1 "github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/apis/meta/v1"
+
"github.com/sirupsen/logrus"
+ "gopkg.in/yaml.v3"
)
const (
@@ -27,6 +31,7 @@ const (
KubeVolumeTypeConfigMap
KubeVolumeTypeBlockDevice
KubeVolumeTypeCharDevice
+ KubeVolumeTypeSecret
)
//nolint:revive
@@ -125,6 +130,49 @@ func VolumeFromHostPath(hostPath *v1.HostPathVolumeSource) (*KubeVolume, error)
}, nil
}
+// VolumeFromSecret creates a new kube volume from a kube secret.
+func VolumeFromSecret(secretSource *v1.SecretVolumeSource, secretsManager *secrets.SecretsManager) (*KubeVolume, error) {
+ // returns a byte array of a kube secret data, meaning this needs to go into a string map
+ _, secretByte, err := secretsManager.LookupSecretData(secretSource.SecretName)
+ if err != nil {
+ return nil, err
+ }
+
+ // unmarshaling directly into a v1.secret creates type mismatch errors
+ // use a more friendly, string only secret struct.
+ type KubeSecret struct {
+ metav1.TypeMeta `json:",inline"`
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+ // +optional
+ Immutable *bool `json:"immutable,omitempty"`
+ Data map[string]string `json:"data,omitempty"`
+ // +optional
+ StringData map[string]string `json:"stringData,omitempty"`
+ // +optional
+ Type string `json:"type,omitempty"`
+ }
+
+ data := &KubeSecret{}
+
+ err = yaml.Unmarshal(secretByte, data)
+ if err != nil {
+ return nil, err
+ }
+
+ kv := &KubeVolume{}
+ kv.Type = KubeVolumeTypeSecret
+ kv.Source = secretSource.SecretName
+ kv.Optional = *secretSource.Optional
+ kv.Items = make(map[string]string)
+
+ // add key: value pairs to the items array
+ for key, entry := range data.Data {
+ kv.Items[key] = entry
+ }
+ return kv, nil
+}
+
// Create a KubeVolume from a PersistentVolumeClaimVolumeSource
func VolumeFromPersistentVolumeClaim(claim *v1.PersistentVolumeClaimVolumeSource) (*KubeVolume, error) {
return &KubeVolume{
@@ -172,7 +220,7 @@ func VolumeFromConfigMap(configMapVolumeSource *v1.ConfigMapVolumeSource, config
}
// Create a KubeVolume from one of the supported VolumeSource
-func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap) (*KubeVolume, error) {
+func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap, secretsManager *secrets.SecretsManager) (*KubeVolume, error) {
switch {
case volumeSource.HostPath != nil:
return VolumeFromHostPath(volumeSource.HostPath)
@@ -180,17 +228,19 @@ func VolumeFromSource(volumeSource v1.VolumeSource, configMaps []v1.ConfigMap) (
return VolumeFromPersistentVolumeClaim(volumeSource.PersistentVolumeClaim)
case volumeSource.ConfigMap != nil:
return VolumeFromConfigMap(volumeSource.ConfigMap, configMaps)
+ case volumeSource.Secret != nil:
+ return VolumeFromSecret(volumeSource.Secret, secretsManager)
default:
return nil, errors.New("HostPath, ConfigMap, and PersistentVolumeClaim are currently the only supported VolumeSource")
}
}
// Create a map of volume name to KubeVolume
-func InitializeVolumes(specVolumes []v1.Volume, configMaps []v1.ConfigMap) (map[string]*KubeVolume, error) {
+func InitializeVolumes(specVolumes []v1.Volume, configMaps []v1.ConfigMap, secretsManager *secrets.SecretsManager) (map[string]*KubeVolume, error) {
volumes := make(map[string]*KubeVolume)
for _, specVolume := range specVolumes {
- volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps)
+ volume, err := VolumeFromSource(specVolume.VolumeSource, configMaps, secretsManager)
if err != nil {
return nil, fmt.Errorf("failed to create volume %q: %w", specVolume.Name, err)
}
diff --git a/pkg/specgenutil/specgen.go b/pkg/specgenutil/specgen.go
index 4ab019b5b..7392e7b44 100644
--- a/pkg/specgenutil/specgen.go
+++ b/pkg/specgenutil/specgen.go
@@ -77,11 +77,11 @@ func getIOLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (
if s.ResourceLimits == nil {
s.ResourceLimits = &specs.LinuxResources{}
}
- if s.ResourceLimits.BlockIO == nil {
- s.ResourceLimits.BlockIO = &specs.LinuxBlockIO{}
- }
hasLimits := false
if b := c.BlkIOWeight; len(b) > 0 {
+ if s.ResourceLimits.BlockIO == nil {
+ s.ResourceLimits.BlockIO = &specs.LinuxBlockIO{}
+ }
u, err := strconv.ParseUint(b, 10, 16)
if err != nil {
return nil, fmt.Errorf("invalid value for blkio-weight: %w", err)
@@ -103,7 +103,6 @@ func getIOLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (
if s.ThrottleReadBpsDevice, err = parseThrottleBPSDevices(bps); err != nil {
return nil, err
}
-
hasLimits = true
}
@@ -131,8 +130,6 @@ func getIOLimits(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions) (
if !hasLimits {
return nil, nil
}
- io = s.ResourceLimits.BlockIO
-
return io, nil
}