summaryrefslogtreecommitdiff
path: root/libpod/container_commit.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container_commit.go')
-rw-r--r--libpod/container_commit.go103
1 files changed, 103 insertions, 0 deletions
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
new file mode 100644
index 000000000..7ad393b6c
--- /dev/null
+++ b/libpod/container_commit.go
@@ -0,0 +1,103 @@
+package libpod
+
+import (
+ "strings"
+
+ is "github.com/containers/image/storage"
+ "github.com/pkg/errors"
+ "github.com/projectatomic/libpod/libpod/buildah"
+ "github.com/projectatomic/libpod/libpod/image"
+ "github.com/sirupsen/logrus"
+)
+
+// ContainerCommitOptions is a struct used to commit a container to an image
+// It uses buildah's CommitOptions as a base. Long-term we might wish to
+// add these to the buildah struct once buildah is more integrated with
+//libpod
+type ContainerCommitOptions struct {
+ buildah.CommitOptions
+ Pause bool
+ Author string
+ Message string
+ Changes []string
+}
+
+// Commit commits the changes between a container and its image, creating a new
+// image
+func (c *Container) Commit(destImage string, options ContainerCommitOptions) (*image.Image, error) {
+ if !c.locked {
+ c.lock.Lock()
+ defer c.lock.Unlock()
+
+ if err := c.syncContainer(); err != nil {
+ return nil, err
+ }
+ }
+
+ if c.state.State == ContainerStateRunning && options.Pause {
+ if err := c.runtime.ociRuntime.pauseContainer(c); err != nil {
+ return nil, errors.Wrapf(err, "error pausing container %q", c.ID())
+ }
+ defer func() {
+ if err := c.runtime.ociRuntime.unpauseContainer(c); err != nil {
+ logrus.Errorf("error unpausing container %q: %v", c.ID(), err)
+ }
+ }()
+ }
+
+ sc := image.GetSystemContext(options.SignaturePolicyPath, "", false)
+ builderOptions := buildah.ImportOptions{
+ Container: c.ID(),
+ SignaturePolicyPath: options.SignaturePolicyPath,
+ }
+ commitOptions := buildah.CommitOptions{
+ SignaturePolicyPath: options.SignaturePolicyPath,
+ ReportWriter: options.ReportWriter,
+ SystemContext: sc,
+ }
+ importBuilder, err := buildah.ImportBuilder(c.runtime.store, builderOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ if options.Author != "" {
+ importBuilder.SetMaintainer(options.Author)
+ }
+ if options.Message != "" {
+ importBuilder.SetComment(options.Message)
+ }
+
+ // Process user changes
+ for _, change := range options.Changes {
+ splitChange := strings.Split(change, "=")
+ switch strings.ToUpper(splitChange[0]) {
+ case "CMD":
+ importBuilder.SetCmd(splitChange[1:])
+ case "ENTRYPOINT":
+ importBuilder.SetEntrypoint(splitChange[1:])
+ case "ENV":
+ importBuilder.SetEnv(splitChange[1], splitChange[2])
+ case "EXPOSE":
+ importBuilder.SetPort(splitChange[1])
+ case "LABEL":
+ importBuilder.SetLabel(splitChange[1], splitChange[2])
+ case "STOPSIGNAL":
+ // No Set StopSignal
+ case "USER":
+ importBuilder.SetUser(splitChange[1])
+ case "VOLUME":
+ importBuilder.AddVolume(splitChange[1])
+ case "WORKDIR":
+ importBuilder.SetWorkDir(splitChange[1])
+ }
+ }
+ imageRef, err := is.Transport.ParseStoreReference(c.runtime.store, destImage)
+ if err != nil {
+ return nil, err
+ }
+
+ if err = importBuilder.Commit(imageRef, commitOptions); err != nil {
+ return nil, err
+ }
+ return c.runtime.imageRuntime.NewFromLocal(imageRef.DockerReference().String())
+}