summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/containers.go32
-rw-r--r--pkg/api/handlers/compat/images.go123
-rw-r--r--pkg/api/handlers/compat/images_build.go6
-rw-r--r--pkg/api/handlers/compat/networks.go18
-rw-r--r--pkg/api/handlers/compat/secrets.go32
-rw-r--r--pkg/api/handlers/libpod/images_pull.go3
-rw-r--r--pkg/api/server/register_archive.go2
-rw-r--r--pkg/api/server/register_secrets.go4
-rw-r--r--pkg/autoupdate/autoupdate.go1
-rw-r--r--pkg/bindings/images/build.go6
-rw-r--r--pkg/checkpoint/checkpoint_restore.go36
-rw-r--r--pkg/checkpoint/crutils/checkpoint_restore_utils.go191
-rw-r--r--pkg/domain/entities/secrets.go23
-rw-r--r--pkg/domain/infra/abi/images.go4
-rw-r--r--pkg/domain/infra/abi/play.go2
15 files changed, 413 insertions, 70 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go
index 971b6aa50..d26bb50f4 100644
--- a/pkg/api/handlers/compat/containers.go
+++ b/pkg/api/handlers/compat/containers.go
@@ -307,6 +307,34 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
}
}
+ portMappings, err := l.PortMappings()
+ if err != nil {
+ return nil, err
+ }
+
+ ports := make([]types.Port, len(portMappings))
+ for idx, portMapping := range portMappings {
+ ports[idx] = types.Port{
+ IP: portMapping.HostIP,
+ PrivatePort: uint16(portMapping.ContainerPort),
+ PublicPort: uint16(portMapping.HostPort),
+ Type: portMapping.Protocol,
+ }
+ }
+ inspect, err := l.Inspect(false)
+ if err != nil {
+ return nil, err
+ }
+
+ n, err := json.Marshal(inspect.NetworkSettings)
+ if err != nil {
+ return nil, err
+ }
+ networkSettings := types.SummaryNetworkSettings{}
+ if err := json.Unmarshal(n, &networkSettings); err != nil {
+ return nil, err
+ }
+
return &handlers.Container{Container: types.Container{
ID: l.ID(),
Names: []string{fmt.Sprintf("/%s", l.Name())},
@@ -314,7 +342,7 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
ImageID: imageID,
Command: strings.Join(l.Command(), " "),
Created: l.CreatedTime().Unix(),
- Ports: nil,
+ Ports: ports,
SizeRw: sizeRW,
SizeRootFs: sizeRootFs,
Labels: l.Labels(),
@@ -324,7 +352,7 @@ func LibpodToContainer(l *libpod.Container, sz bool) (*handlers.Container, error
NetworkMode string `json:",omitempty"`
}{
"host"},
- NetworkSettings: nil,
+ NetworkSettings: &networkSettings,
Mounts: nil,
},
ContainerCreateConfig: types.ContainerCreateConfig{},
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index 1a4dd939e..e5caa9ea5 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -1,6 +1,7 @@
package compat
import (
+ "context"
"encoding/json"
"fmt"
"io"
@@ -11,11 +12,13 @@ import (
"github.com/containers/buildah"
"github.com/containers/image/v5/manifest"
+ "github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod"
image2 "github.com/containers/podman/v3/libpod/image"
"github.com/containers/podman/v3/pkg/api/handlers"
"github.com/containers/podman/v3/pkg/api/handlers/utils"
"github.com/containers/podman/v3/pkg/auth"
+ "github.com/containers/podman/v3/pkg/channel"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/util"
"github.com/gorilla/schema"
@@ -236,33 +239,103 @@ func CreateImageFromImage(w http.ResponseWriter, r *http.Request) {
if sys := runtime.SystemContext(); sys != nil {
registryOpts.DockerCertPath = sys.DockerCertPath
}
- img, err := runtime.ImageRuntime().New(r.Context(),
- fromImage,
- "", // signature policy
- authfile,
- nil, // writer
- &registryOpts,
- image2.SigningOptions{},
- nil, // label
- util.PullImageAlways,
- )
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
- return
+
+ stderr := channel.NewWriter(make(chan []byte))
+ defer stderr.Close()
+
+ progress := make(chan types.ProgressProperties)
+
+ var img string
+ runCtx, cancel := context.WithCancel(context.Background())
+ go func() {
+ defer cancel()
+
+ newImage, err := runtime.ImageRuntime().New(
+ runCtx,
+ fromImage,
+ "", // signature policy
+ authfile,
+ nil, // writer
+ &registryOpts,
+ image2.SigningOptions{},
+ nil, // label
+ util.PullImageAlways,
+ progress)
+ if err != nil {
+ stderr.Write([]byte(err.Error() + "\n"))
+ } else {
+ img = newImage.ID()
+ }
+ }()
+
+ flush := func() {
+ if flusher, ok := w.(http.Flusher); ok {
+ flusher.Flush()
+ }
}
- // Success
- utils.WriteResponse(w, http.StatusOK, struct {
- Status string `json:"status"`
- Error string `json:"error,omitempty"`
- Progress string `json:"progress"`
- ProgressDetail map[string]string `json:"progressDetail"`
- Id string `json:"id"` // nolint
- }{
- Status: fmt.Sprintf("pulling image (%s) from %s (Download complete)", img.Tag, strings.Join(img.Names(), ", ")),
- ProgressDetail: map[string]string{},
- Id: img.ID(),
- })
+ w.WriteHeader(http.StatusOK)
+ w.Header().Add("Content-Type", "application/json")
+ flush()
+
+ enc := json.NewEncoder(w)
+ enc.SetEscapeHTML(true)
+ var failed bool
+
+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
+ }
+
+ select {
+ case e := <-progress:
+ switch e.Event {
+ case types.ProgressEventNewArtifact:
+ report.Status = "Pulling fs layer"
+ case types.ProgressEventRead:
+ report.Status = "Downloading"
+ report.Progress.Current = e.Offset
+ report.Progress.Total = e.Artifact.Size
+ case types.ProgressEventSkipped:
+ report.Status = "Already exists"
+ case types.ProgressEventDone:
+ report.Status = "Download complete"
+ }
+ report.Id = e.Artifact.Digest.Encoded()[0:12]
+ if err := enc.Encode(report); err != nil {
+ stderr.Write([]byte(err.Error()))
+ }
+ flush()
+ case e := <-stderr.Chan():
+ failed = true
+ report.Error = string(e)
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to json encode error %q", err.Error())
+ }
+ flush()
+ case <-runCtx.Done():
+ if !failed {
+ report.Status = "Pull complete"
+ report.Id = img[0:12]
+ if err := enc.Encode(report); err != nil {
+ logrus.Warnf("Failed to json encode error %q", err.Error())
+ }
+ flush()
+ }
+ break loop // break out of for/select infinite loop
+ case <-r.Context().Done():
+ // Client has closed connection
+ break loop // break out of for/select infinite loop
+ }
+ }
}
func GetImage(w http.ResponseWriter, r *http.Request) {
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index d79b100e8..009fcf7e8 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -104,6 +104,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Squash bool `schema:"squash"`
Tag []string `schema:"t"`
Target string `schema:"target"`
+ Timestamp int64 `schema:"timestamp"`
}{
Dockerfile: "Dockerfile",
Registry: "docker.io",
@@ -318,6 +319,11 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
Target: query.Target,
}
+ if _, found := r.URL.Query()["timestamp"]; found {
+ ts := time.Unix(query.Timestamp, 0)
+ buildOptions.Timestamp = &ts
+ }
+
runCtx, cancel := context.WithCancel(context.Background())
var imageID string
go func() {
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index 1a04b4289..28e90ac28 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -180,16 +180,18 @@ func findPluginByName(plugins []*libcni.NetworkConfig, pluginType string) ([]byt
func ListNetworks(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- decoder := r.Context().Value("decoder").(*schema.Decoder)
- query := struct {
- Filters map[string][]string `schema:"filters"`
- }{
- // override any golang type defaults
- }
- if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ filters, err := filtersFromRequest(r)
+ if err != nil {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
+ filterMap := map[string][]string{}
+ for _, filter := range filters {
+ split := strings.SplitN(filter, "=", 2)
+ if len(split) > 1 {
+ filterMap[split[0]] = append(filterMap[split[0]], split[1])
+ }
+ }
config, err := runtime.GetConfig()
if err != nil {
utils.InternalServerError(w, err)
@@ -205,7 +207,7 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) {
reports := []*types.NetworkResource{}
logrus.Debugf("netNames: %q", strings.Join(netNames, ", "))
for _, name := range netNames {
- report, err := getNetworkResourceByNameOrID(name, runtime, query.Filters)
+ report, err := getNetworkResourceByNameOrID(name, runtime, filterMap)
if err != nil {
utils.InternalServerError(w, err)
return
diff --git a/pkg/api/handlers/compat/secrets.go b/pkg/api/handlers/compat/secrets.go
index c5ee8c324..86e3887a4 100644
--- a/pkg/api/handlers/compat/secrets.go
+++ b/pkg/api/handlers/compat/secrets.go
@@ -40,7 +40,21 @@ func ListSecrets(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusOK, reports)
+ if utils.IsLibpodRequest(r) {
+ utils.WriteResponse(w, http.StatusOK, reports)
+ return
+ }
+ // Docker compat expects a version field that increments when the secret is updated
+ // We currently can't update a secret, so we default the version to 1
+ compatReports := make([]entities.SecretInfoReportCompat, 0, len(reports))
+ for _, report := range reports {
+ compatRep := entities.SecretInfoReportCompat{
+ SecretInfoReport: *report,
+ Version: entities.SecretVersion{Index: 1},
+ }
+ compatReports = append(compatReports, compatRep)
+ }
+ utils.WriteResponse(w, http.StatusOK, compatReports)
}
func InspectSecret(w http.ResponseWriter, r *http.Request) {
@@ -59,7 +73,21 @@ func InspectSecret(w http.ResponseWriter, r *http.Request) {
utils.SecretNotFound(w, name, errs[0])
return
}
- utils.WriteResponse(w, http.StatusOK, reports[0])
+ if len(reports) < 1 {
+ utils.InternalServerError(w, err)
+ return
+ }
+ if utils.IsLibpodRequest(r) {
+ utils.WriteResponse(w, http.StatusOK, reports[0])
+ return
+ }
+ // Docker compat expects a version field that increments when the secret is updated
+ // We currently can't update a secret, so we default the version to 1
+ compatReport := entities.SecretInfoReportCompat{
+ SecretInfoReport: *reports[0],
+ Version: entities.SecretVersion{Index: 1},
+ }
+ utils.WriteResponse(w, http.StatusOK, compatReport)
}
func RemoveSecret(w http.ResponseWriter, r *http.Request) {
diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go
index c8b777be4..e2e4b53b4 100644
--- a/pkg/api/handlers/libpod/images_pull.go
+++ b/pkg/api/handlers/libpod/images_pull.go
@@ -136,7 +136,8 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
&dockerRegistryOptions,
image.SigningOptions{},
nil,
- util.PullImageAlways)
+ util.PullImageAlways,
+ nil)
if err != nil {
stderr.Write([]byte(err.Error() + "\n"))
} else {
diff --git a/pkg/api/server/register_archive.go b/pkg/api/server/register_archive.go
index 2a5cfba0b..2ac126644 100644
--- a/pkg/api/server/register_archive.go
+++ b/pkg/api/server/register_archive.go
@@ -91,7 +91,7 @@ func (s *APIServer) registerArchiveHandlers(r *mux.Router) error {
Libpod
*/
- // swagger:operation POST /libpod/containers/{name}/archive libpod libpodPutArchive
+ // swagger:operation PUT /libpod/containers/{name}/archive libpod libpodPutArchive
// ---
// summary: Copy files into a container
// description: Copy a tar archive of files into a container
diff --git a/pkg/api/server/register_secrets.go b/pkg/api/server/register_secrets.go
index 1c5f5954b..531623845 100644
--- a/pkg/api/server/register_secrets.go
+++ b/pkg/api/server/register_secrets.go
@@ -115,7 +115,7 @@ func (s *APIServer) registerSecretHandlers(r *mux.Router) error {
// parameters:
// responses:
// '200':
- // "$ref": "#/responses/SecretListResponse"
+ // "$ref": "#/responses/SecretListCompatResponse"
// '500':
// "$ref": "#/responses/InternalError"
r.Handle(VersionedPath("/secrets"), s.APIHandler(compat.ListSecrets)).Methods(http.MethodGet)
@@ -158,7 +158,7 @@ func (s *APIServer) registerSecretHandlers(r *mux.Router) error {
// - application/json
// responses:
// '200':
- // "$ref": "#/responses/SecretInspectResponse"
+ // "$ref": "#/responses/SecretInspectCompatResponse"
// '404':
// "$ref": "#/responses/NoSuchSecret"
// '500':
diff --git a/pkg/autoupdate/autoupdate.go b/pkg/autoupdate/autoupdate.go
index 0cf51e5a6..53095c295 100644
--- a/pkg/autoupdate/autoupdate.go
+++ b/pkg/autoupdate/autoupdate.go
@@ -304,6 +304,7 @@ func updateImage(runtime *libpod.Runtime, name string, options Options) (*image.
image.SigningOptions{},
nil,
util.PullImageAlways,
+ nil,
)
if err != nil {
return nil, err
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index 6e16461e5..27706fd2c 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -185,6 +185,12 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
if options.Squash {
params.Set("squash", "1")
}
+
+ if options.Timestamp != nil {
+ t := *options.Timestamp
+ params.Set("timestamp", strconv.FormatInt(t.Unix(), 10))
+ }
+
var (
headers map[string]string
err error
diff --git a/pkg/checkpoint/checkpoint_restore.go b/pkg/checkpoint/checkpoint_restore.go
index a608762b5..77a993128 100644
--- a/pkg/checkpoint/checkpoint_restore.go
+++ b/pkg/checkpoint/checkpoint_restore.go
@@ -4,15 +4,14 @@ import (
"context"
"io/ioutil"
"os"
- "path/filepath"
+ metadata "github.com/checkpoint-restore/checkpointctl/lib"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/image"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/errorhandling"
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage/pkg/archive"
- jsoniter "github.com/json-iterator/go"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -20,21 +19,6 @@ import (
// Prefixing the checkpoint/restore related functions with 'cr'
-// crImportFromJSON imports the JSON files stored in the exported
-// checkpoint tarball
-func crImportFromJSON(filePath string, v interface{}) error {
- content, err := ioutil.ReadFile(filePath)
- if err != nil {
- return errors.Wrap(err, "failed to read container definition for restore")
- }
- json := jsoniter.ConfigCompatibleWithStandardLibrary
- if err = json.Unmarshal(content, v); err != nil {
- return errors.Wrapf(err, "failed to unmarshal container definition %s for restore", filePath)
- }
-
- return nil
-}
-
// CRImportCheckpoint it the function which imports the information
// from checkpoint tarball and re-creates the container from that information
func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOptions entities.RestoreOptions) ([]*libpod.Container, error) {
@@ -48,13 +32,13 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
options := &archive.TarOptions{
// Here we only need the files config.dump and spec.dump
ExcludePatterns: []string{
- "checkpoint",
- "artifacts",
- "ctr.log",
- "rootfs-diff.tar",
- "network.status",
- "deleted.files",
"volumes",
+ "ctr.log",
+ "artifacts",
+ metadata.RootFsDiffTar,
+ metadata.DeletedFilesFile,
+ metadata.NetworkStatusFile,
+ metadata.CheckpointDirectory,
},
}
dir, err := ioutil.TempDir("", "checkpoint")
@@ -73,13 +57,13 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
// Load spec.dump from temporary directory
dumpSpec := new(spec.Spec)
- if err := crImportFromJSON(filepath.Join(dir, "spec.dump"), dumpSpec); err != nil {
+ if _, err := metadata.ReadJSONFile(dumpSpec, dir, metadata.SpecDumpFile); err != nil {
return nil, err
}
// Load config.dump from temporary directory
config := new(libpod.ContainerConfig)
- if err = crImportFromJSON(filepath.Join(dir, "config.dump"), config); err != nil {
+ if _, err = metadata.ReadJSONFile(config, dir, metadata.ConfigDumpFile); err != nil {
return nil, err
}
@@ -121,7 +105,7 @@ func CRImportCheckpoint(ctx context.Context, runtime *libpod.Runtime, restoreOpt
return nil, err
}
- _, err = runtime.ImageRuntime().New(ctx, config.RootfsImageName, rtc.Engine.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, nil, util.PullImageMissing)
+ _, err = runtime.ImageRuntime().New(ctx, config.RootfsImageName, rtc.Engine.SignaturePolicyPath, "", writer, nil, image.SigningOptions{}, nil, util.PullImageMissing, nil)
if err != nil {
return nil, err
}
diff --git a/pkg/checkpoint/crutils/checkpoint_restore_utils.go b/pkg/checkpoint/crutils/checkpoint_restore_utils.go
new file mode 100644
index 000000000..53ff55865
--- /dev/null
+++ b/pkg/checkpoint/crutils/checkpoint_restore_utils.go
@@ -0,0 +1,191 @@
+package crutils
+
+import (
+ "io"
+ "os"
+ "os/exec"
+ "path/filepath"
+
+ metadata "github.com/checkpoint-restore/checkpointctl/lib"
+ "github.com/containers/storage/pkg/archive"
+ "github.com/opencontainers/selinux/go-selinux/label"
+ "github.com/pkg/errors"
+)
+
+// This file mainly exist to make the checkpoint/restore functions
+// available for other users. One possible candidate would be CRI-O.
+
+// CRImportCheckpointWithoutConfig imports the checkpoint archive (input)
+// into the directory destination without "config.dump" and "spec.dump"
+func CRImportCheckpointWithoutConfig(destination, input string) error {
+ archiveFile, err := os.Open(input)
+ if err != nil {
+ return errors.Wrapf(err, "Failed to open checkpoint archive %s for import", input)
+ }
+
+ defer archiveFile.Close()
+ options := &archive.TarOptions{
+ ExcludePatterns: []string{
+ // Import everything else besides the container config
+ metadata.ConfigDumpFile,
+ metadata.SpecDumpFile,
+ },
+ }
+ if err = archive.Untar(archiveFile, destination, options); err != nil {
+ return errors.Wrapf(err, "Unpacking of checkpoint archive %s failed", input)
+ }
+
+ return nil
+}
+
+// CRRemoveDeletedFiles loads the list of deleted files and if
+// it exists deletes all files listed.
+func CRRemoveDeletedFiles(id, baseDirectory, containerRootDirectory string) error {
+ deletedFiles, _, err := metadata.ReadContainerCheckpointDeletedFiles(baseDirectory)
+ if os.IsNotExist(errors.Unwrap(errors.Unwrap(err))) {
+ // No files to delete. Just return
+ return nil
+ }
+
+ if err != nil {
+ return errors.Wrapf(err, "failed to read deleted files file")
+ }
+
+ for _, deleteFile := range deletedFiles {
+ // Using RemoveAll as deletedFiles, which is generated from 'podman diff'
+ // lists completely deleted directories as a single entry: 'D /root'.
+ if err := os.RemoveAll(filepath.Join(containerRootDirectory, deleteFile)); err != nil {
+ return errors.Wrapf(err, "failed to delete files from container %s during restore", id)
+ }
+ }
+
+ return nil
+}
+
+// CRApplyRootFsDiffTar applies the tar archive found in baseDirectory with the
+// root file system changes on top of containerRootDirectory
+func CRApplyRootFsDiffTar(baseDirectory, containerRootDirectory string) error {
+ rootfsDiffPath := filepath.Join(baseDirectory, metadata.RootFsDiffTar)
+ if _, err := os.Stat(rootfsDiffPath); err != nil {
+ // Only do this if a rootfs-diff.tar actually exists
+ return nil
+ }
+
+ rootfsDiffFile, err := os.Open(rootfsDiffPath)
+ if err != nil {
+ return errors.Wrap(err, "failed to open root file-system diff file")
+ }
+ defer rootfsDiffFile.Close()
+
+ if err := archive.Untar(rootfsDiffFile, containerRootDirectory, nil); err != nil {
+ return errors.Wrapf(err, "failed to apply root file-system diff file %s", rootfsDiffPath)
+ }
+
+ return nil
+}
+
+// CRCreateRootFsDiffTar goes through the 'changes' and can create two files:
+// * metadata.RootFsDiffTar will contain all new and changed files
+// * metadata.DeletedFilesFile will contain a list of deleted files
+// With these two files it is possible to restore the container file system to the same
+// state it was during checkpointing.
+// Changes to directories (owner, mode) are not handled.
+func CRCreateRootFsDiffTar(changes *[]archive.Change, mountPoint, destination string) (includeFiles []string, err error) {
+ if len(*changes) == 0 {
+ return includeFiles, nil
+ }
+
+ var rootfsIncludeFiles []string
+ var deletedFiles []string
+
+ rootfsDiffPath := filepath.Join(destination, metadata.RootFsDiffTar)
+
+ for _, file := range *changes {
+ if file.Kind == archive.ChangeAdd {
+ rootfsIncludeFiles = append(rootfsIncludeFiles, file.Path)
+ continue
+ }
+ if file.Kind == archive.ChangeDelete {
+ deletedFiles = append(deletedFiles, file.Path)
+ continue
+ }
+ fileName, err := os.Stat(file.Path)
+ if err != nil {
+ continue
+ }
+ if !fileName.IsDir() && file.Kind == archive.ChangeModify {
+ rootfsIncludeFiles = append(rootfsIncludeFiles, file.Path)
+ continue
+ }
+ }
+
+ if len(rootfsIncludeFiles) > 0 {
+ rootfsTar, err := archive.TarWithOptions(mountPoint, &archive.TarOptions{
+ Compression: archive.Uncompressed,
+ IncludeSourceDir: true,
+ IncludeFiles: rootfsIncludeFiles,
+ })
+ if err != nil {
+ return includeFiles, errors.Wrapf(err, "error exporting root file-system diff to %q", rootfsDiffPath)
+ }
+ rootfsDiffFile, err := os.Create(rootfsDiffPath)
+ if err != nil {
+ return includeFiles, errors.Wrapf(err, "error creating root file-system diff file %q", rootfsDiffPath)
+ }
+ defer rootfsDiffFile.Close()
+ if _, err = io.Copy(rootfsDiffFile, rootfsTar); err != nil {
+ return includeFiles, err
+ }
+
+ includeFiles = append(includeFiles, metadata.RootFsDiffTar)
+ }
+
+ if len(deletedFiles) == 0 {
+ return includeFiles, nil
+ }
+
+ if _, err := metadata.WriteJSONFile(deletedFiles, destination, metadata.DeletedFilesFile); err != nil {
+ return includeFiles, nil
+ }
+
+ includeFiles = append(includeFiles, metadata.DeletedFilesFile)
+
+ return includeFiles, nil
+}
+
+// CRCreateFileWithLabel creates an empty file and sets the corresponding ('fileLabel')
+// SELinux label on the file.
+// This is necessary for CRIU log files because CRIU infects the processes in
+// the container with a 'parasite' and this will also try to write to the log files
+// from the context of the container processes.
+func CRCreateFileWithLabel(directory, fileName, fileLabel string) error {
+ logFileName := filepath.Join(directory, fileName)
+
+ logFile, err := os.OpenFile(logFileName, os.O_CREATE, 0o600)
+ if err != nil {
+ return errors.Wrapf(err, "failed to create file %q", logFileName)
+ }
+ defer logFile.Close()
+ if err = label.SetFileLabel(logFileName, fileLabel); err != nil {
+ return errors.Wrapf(err, "failed to label file %q", logFileName)
+ }
+
+ return nil
+}
+
+// CRRuntimeSupportsCheckpointRestore tests if the given runtime at 'runtimePath'
+// supports checkpointing. The checkpoint restore interface has no definition
+// but crun implements all commands just as runc does. Whathh runc does it the
+// official definition of the checkpoint/restore interface.
+func CRRuntimeSupportsCheckpointRestore(runtimePath string) bool {
+ // Check if the runtime implements checkpointing. Currently only
+ // runc's and crun's checkpoint/restore implementation is supported.
+ cmd := exec.Command(runtimePath, "checkpoint", "--help")
+ if err := cmd.Start(); err != nil {
+ return false
+ }
+ if err := cmd.Wait(); err == nil {
+ return true
+ }
+ return false
+}
diff --git a/pkg/domain/entities/secrets.go b/pkg/domain/entities/secrets.go
index 3481cbe05..8ede981da 100644
--- a/pkg/domain/entities/secrets.go
+++ b/pkg/domain/entities/secrets.go
@@ -42,6 +42,15 @@ type SecretInfoReport struct {
Spec SecretSpec
}
+type SecretInfoReportCompat struct {
+ SecretInfoReport
+ Version SecretVersion
+}
+
+type SecretVersion struct {
+ Index int
+}
+
type SecretSpec struct {
Name string
Driver SecretDriverSpec
@@ -78,6 +87,13 @@ type SwagSecretListResponse struct {
Body []*SecretInfoReport
}
+// Secret list response
+// swagger:response SecretListCompatResponse
+type SwagSecretListCompatResponse struct {
+ // in:body
+ Body []*SecretInfoReportCompat
+}
+
// Secret inspect response
// swagger:response SecretInspectResponse
type SwagSecretInspectResponse struct {
@@ -85,6 +101,13 @@ type SwagSecretInspectResponse struct {
Body SecretInfoReport
}
+// Secret inspect compat
+// swagger:response SecretInspectCompatResponse
+type SwagSecretInspectCompatResponse struct {
+ // in:body
+ Body SecretInfoReportCompat
+}
+
// No such secret
// swagger:response NoSuchSecret
type SwagErrNoSuchSecret struct {
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 46d967789..562653403 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -247,7 +247,7 @@ func pull(ctx context.Context, runtime *image.Runtime, rawImage string, options
}
if !options.AllTags {
- newImage, err := runtime.New(ctx, rawImage, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, label, options.PullPolicy)
+ newImage, err := runtime.New(ctx, rawImage, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, label, options.PullPolicy, nil)
if err != nil {
return nil, err
}
@@ -280,7 +280,7 @@ func pull(ctx context.Context, runtime *image.Runtime, rawImage string, options
foundIDs := []string{}
for _, tag := range tags {
name := rawImage + ":" + tag
- newImage, err := runtime.New(ctx, name, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways)
+ newImage, err := runtime.New(ctx, name, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, util.PullImageAlways, nil)
if err != nil {
logrus.Errorf("error pulling image %q", name)
continue
diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go
index c5e20a607..b7ca69281 100644
--- a/pkg/domain/infra/abi/play.go
+++ b/pkg/domain/infra/abi/play.go
@@ -221,7 +221,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY
}
// This ensures the image is the image store
- newImage, err := ic.Libpod.ImageRuntime().New(ctx, container.Image, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullPolicy)
+ newImage, err := ic.Libpod.ImageRuntime().New(ctx, container.Image, options.SignaturePolicy, options.Authfile, writer, &dockerRegistryOptions, image.SigningOptions{}, nil, pullPolicy, nil)
if err != nil {
return nil, err
}