aboutsummaryrefslogtreecommitdiff
path: root/cmd/podman/commit.go
blob: 14b7ddace00d1f02937df49c355f832229fed9a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package main

import (
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/pkg/errors"
	"github.com/projectatomic/buildah"
	"github.com/projectatomic/libpod/cmd/podman/libpodruntime"
	"github.com/projectatomic/libpod/libpod"
	"github.com/projectatomic/libpod/libpod/image"
	"github.com/projectatomic/libpod/pkg/util"
	"github.com/urfave/cli"
)

var (
	commitFlags = []cli.Flag{
		cli.StringSliceFlag{
			Name:  "change, c",
			Usage: "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR",
		},
		cli.StringFlag{
			Name:  "format, f",
			Usage: "`format` of the image manifest and metadata",
			Value: "oci",
		},
		cli.StringFlag{
			Name:  "message, m",
			Usage: "Set commit message for imported image",
		},
		cli.StringFlag{
			Name:  "author, a",
			Usage: "Set the author for the image comitted",
		},
		cli.BoolTFlag{
			Name:  "pause, p",
			Usage: "Pause container during commit",
		},
		cli.BoolFlag{
			Name:  "quiet, q",
			Usage: "Suppress output",
		},
	}
	commitDescription = `Create an image from a container's changes.
	 Optionally tag the image created, set the author with the --author flag,
	 set the commit message with the --message flag,
	 and make changes to the instructions with the --change flag.`
	commitCommand = cli.Command{
		Name:        "commit",
		Usage:       "Create new image based on the changed container",
		Description: commitDescription,
		Flags:       commitFlags,
		Action:      commitCmd,
		ArgsUsage:   "CONTAINER [REPOSITORY[:TAG]]",
	}
)

func commitCmd(c *cli.Context) error {
	if err := validateFlags(c, commitFlags); err != nil {
		return err
	}
	runtime, err := libpodruntime.GetRuntime(c)
	if err != nil {
		return errors.Wrapf(err, "could not get runtime")
	}
	defer runtime.Shutdown(false)

	var (
		writer   io.Writer
		mimeType string
	)
	args := c.Args()
	if len(args) != 2 {
		return errors.Errorf("you must provide a container name or ID and a target image name")
	}

	switch c.String("format") {
	case "oci":
		mimeType = buildah.OCIv1ImageManifest
		if c.IsSet("message") {
			return errors.Errorf("messages cannot be added to the OCIv1 image format.")
		}
	case "docker":
		mimeType = buildah.Dockerv2ImageManifest
	default:
		return errors.Errorf("unrecognized image format %q", c.String("format"))
	}
	container := args[0]
	reference := args[1]
	if c.IsSet("change") {
		for _, change := range c.StringSlice("change") {
			splitChange := strings.Split(strings.ToUpper(change), "=")
			if !util.StringInSlice(splitChange[0], []string{"CMD", "ENTRYPOINT", "ENV", "EXPOSE", "LABEL", "STOPSIGNAL", "USER", "VOLUME", "WORKDIR"}) {
				return errors.Errorf("invalid syntax for --change ", change)
			}
		}
	}

	if !c.Bool("quiet") {
		writer = os.Stderr
	}
	ctr, err := runtime.LookupContainer(container)
	if err != nil {
		return errors.Wrapf(err, "error looking up container %q", container)
	}

	sc := image.GetSystemContext(runtime.GetConfig().SignaturePolicyPath, "", false)
	coptions := buildah.CommitOptions{
		SignaturePolicyPath:   runtime.GetConfig().SignaturePolicyPath,
		ReportWriter:          writer,
		SystemContext:         sc,
		PreferredManifestType: mimeType,
	}
	options := libpod.ContainerCommitOptions{
		CommitOptions: coptions,
		Pause:         c.Bool("pause"),
		Message:       c.String("message"),
		Changes:       c.StringSlice("change"),
		Author:        c.String("author"),
	}
	newImage, err := ctr.Commit(getContext(), reference, options)
	if err != nil {
		return err
	}
	fmt.Println(newImage.ID())
	return nil
}