aboutsummaryrefslogtreecommitdiff
path: root/pkg/domain
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/domain')
-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/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.go66
-rw-r--r--pkg/domain/infra/abi/images.go3
-rw-r--r--pkg/domain/infra/abi/manifest.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.go48
-rw-r--r--pkg/domain/infra/tunnel/images.go2
-rw-r--r--pkg/domain/infra/tunnel/manifest.go10
15 files changed, 236 insertions, 46 deletions
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/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 04eb85504..783224e9c 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
@@ -235,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)
@@ -1035,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
@@ -1055,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
}
}
@@ -1072,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
}
@@ -1088,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)
@@ -1103,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/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/manifest.go b/pkg/domain/infra/abi/manifest.go
index d20744d76..bdc3d9513 100644
--- a/pkg/domain/infra/abi/manifest.go
+++ b/pkg/domain/infra/abi/manifest.go
@@ -331,7 +331,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/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..98c73c51a 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
}
@@ -771,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
}
}
@@ -784,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
}
@@ -796,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
}
@@ -815,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 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/domain/infra/tunnel/manifest.go b/pkg/domain/infra/tunnel/manifest.go
index d2554f198..4a3148fac 100644
--- a/pkg/domain/infra/tunnel/manifest.go
+++ b/pkg/domain/infra/tunnel/manifest.go
@@ -110,5 +110,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
}