mirror of
https://github.com/containers/podman.git
synced 2025-06-23 10:38:20 +08:00
Merge pull request #5588 from baude/apiv2commitfix
apiv2 container commit for libpod
This commit is contained in:
@ -10,12 +10,15 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/image/v5/docker"
|
||||
"github.com/containers/image/v5/docker/reference"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/image"
|
||||
image2 "github.com/containers/libpod/libpod/image"
|
||||
"github.com/containers/libpod/pkg/api/handlers"
|
||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
@ -416,3 +419,84 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
utils.WriteResponse(w, http.StatusOK, res)
|
||||
}
|
||||
|
||||
func CommitContainer(w http.ResponseWriter, r *http.Request) {
|
||||
var (
|
||||
destImage string
|
||||
mimeType string
|
||||
)
|
||||
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
|
||||
query := struct {
|
||||
Author string `schema:"author"`
|
||||
Changes []string `schema:"changes"`
|
||||
Comment string `schema:"comment"`
|
||||
Container string `schema:"container"`
|
||||
Format string `schema:"format"`
|
||||
Pause bool `schema:"pause"`
|
||||
Repo string `schema:"repo"`
|
||||
Tag string `schema:"tag"`
|
||||
}{
|
||||
Format: "oci",
|
||||
}
|
||||
|
||||
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
||||
return
|
||||
}
|
||||
rtc, err := runtime.GetConfig()
|
||||
if err != nil {
|
||||
utils.Error(w, "failed to get runtime config", http.StatusInternalServerError, errors.Wrap(err, "failed to get runtime config"))
|
||||
return
|
||||
}
|
||||
sc := image2.GetSystemContext(rtc.SignaturePolicyPath, "", false)
|
||||
tag := "latest"
|
||||
options := libpod.ContainerCommitOptions{
|
||||
Pause: true,
|
||||
}
|
||||
switch query.Format {
|
||||
case "oci":
|
||||
mimeType = buildah.OCIv1ImageManifest
|
||||
if len(query.Comment) > 0 {
|
||||
utils.InternalServerError(w, errors.New("messages are only compatible with the docker image format (-f docker)"))
|
||||
return
|
||||
}
|
||||
case "docker":
|
||||
mimeType = manifest.DockerV2Schema2MediaType
|
||||
default:
|
||||
utils.InternalServerError(w, errors.Errorf("unrecognized image format %q", query.Format))
|
||||
return
|
||||
}
|
||||
options.CommitOptions = buildah.CommitOptions{
|
||||
SignaturePolicyPath: rtc.SignaturePolicyPath,
|
||||
ReportWriter: os.Stderr,
|
||||
SystemContext: sc,
|
||||
PreferredManifestType: mimeType,
|
||||
}
|
||||
|
||||
if len(query.Tag) > 0 {
|
||||
tag = query.Tag
|
||||
}
|
||||
options.Message = query.Comment
|
||||
options.Author = query.Author
|
||||
options.Pause = query.Pause
|
||||
options.Changes = query.Changes
|
||||
ctr, err := runtime.LookupContainer(query.Container)
|
||||
if err != nil {
|
||||
utils.Error(w, "failed to lookup container", http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
// I know mitr hates this ... but doing for now
|
||||
if len(query.Repo) > 1 {
|
||||
destImage = fmt.Sprintf("%s:%s", query.Repo, tag)
|
||||
}
|
||||
|
||||
commitImage, err := ctr.Commit(r.Context(), destImage, options)
|
||||
if err != nil && !strings.Contains(err.Error(), "is not running") {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "CommitFailure"))
|
||||
return
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, handlers.IDResponse{ID: commitImage.ID()}) // nolint
|
||||
}
|
||||
|
@ -978,6 +978,7 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
|
||||
// name: container
|
||||
// type: string
|
||||
// description: the name or ID of a container
|
||||
// required: true
|
||||
// - in: query
|
||||
// name: repo
|
||||
// type: string
|
||||
@ -1000,8 +1001,14 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
|
||||
// description: pause the container before committing it
|
||||
// - in: query
|
||||
// name: changes
|
||||
// description: instructions to apply while committing in Dockerfile format (i.e. "CMD=/bin/foo")
|
||||
// type: array
|
||||
// items:
|
||||
// type: string
|
||||
// - in: query
|
||||
// name: format
|
||||
// type: string
|
||||
// description: instructions to apply while committing in Dockerfile format
|
||||
// description: format of the image manifest and metadata (default "oci")
|
||||
// produces:
|
||||
// - application/json
|
||||
// responses:
|
||||
@ -1011,6 +1018,6 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
|
||||
// $ref: '#/responses/NoSuchImage'
|
||||
// 500:
|
||||
// $ref: '#/responses/InternalError'
|
||||
r.Handle(VersionedPath("/commit"), s.APIHandler(compat.CommitContainer)).Methods(http.MethodPost)
|
||||
r.Handle(VersionedPath("/libpod/commit"), s.APIHandler(libpod.CommitContainer)).Methods(http.MethodPost)
|
||||
return nil
|
||||
}
|
||||
|
49
pkg/bindings/containers/commit.go
Normal file
49
pkg/bindings/containers/commit.go
Normal file
@ -0,0 +1,49 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/libpod/pkg/api/handlers"
|
||||
"github.com/containers/libpod/pkg/bindings"
|
||||
)
|
||||
|
||||
// Commit creates a container image from a container. The container is defined by nameOrId. Use
|
||||
// the CommitOptions for finer grain control on characteristics of the resulting image.
|
||||
func Commit(ctx context.Context, nameOrId string, options CommitOptions) (handlers.IDResponse, error) {
|
||||
id := handlers.IDResponse{}
|
||||
conn, err := bindings.GetClient(ctx)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
params := url.Values{}
|
||||
params.Set("container", nameOrId)
|
||||
if options.Author != nil {
|
||||
params.Set("author", *options.Author)
|
||||
}
|
||||
for _, change := range options.Changes {
|
||||
params.Set("changes", change)
|
||||
}
|
||||
if options.Comment != nil {
|
||||
params.Set("comment", *options.Comment)
|
||||
}
|
||||
if options.Format != nil {
|
||||
params.Set("format", *options.Format)
|
||||
}
|
||||
if options.Pause != nil {
|
||||
params.Set("pause", strconv.FormatBool(*options.Pause))
|
||||
}
|
||||
if options.Repo != nil {
|
||||
params.Set("repo", *options.Repo)
|
||||
}
|
||||
if options.Tag != nil {
|
||||
params.Set("tag", *options.Tag)
|
||||
}
|
||||
response, err := conn.DoRequest(nil, http.MethodPost, "/commit", params)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return id, response.Process(&id)
|
||||
}
|
@ -11,3 +11,16 @@ type LogOptions struct {
|
||||
Timestamps *bool
|
||||
Until *string
|
||||
}
|
||||
|
||||
// CommitOptions describe details about the resulting commited
|
||||
// image as defined by repo and tag. None of these options
|
||||
// are required.
|
||||
type CommitOptions struct {
|
||||
Author *string
|
||||
Changes []string
|
||||
Comment *string
|
||||
Format *string
|
||||
Pause *bool
|
||||
Repo *string
|
||||
Tag *string
|
||||
}
|
||||
|
@ -80,8 +80,7 @@ var _ = Describe("Podman pods", func() {
|
||||
// The test validates the list pod endpoint with passing filters as the params.
|
||||
It("List pods with filters", func() {
|
||||
var (
|
||||
newpod2 string = "newpod2"
|
||||
trueFlag = true
|
||||
newpod2 string = "newpod2"
|
||||
)
|
||||
bt.Podcreate(&newpod2)
|
||||
_, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
|
||||
|
Reference in New Issue
Block a user