podman rmi: refactor logic

While this commit was initially meant to fix #5847, it has turned into a
bigger refactoring which I did not manage to break into smaller pieces:

 * Fix #5847 by refactoring the image-removal logic.

 * Make the api handler for image-removal use the ABI code. This way,
   both (i.e., ABI and Tunnel) end up using the same code.  Achieving
   this code share required to move some code around to prevent circular
   dependencies.

 * Everything in pkg/api (excluding pkg/api/types) must now only be
   accessed from code using `ABISupport`.

 * Avoid imports from entities on handlers to prevent circular
   dependencies.

 * Move `podman system service` logic into `cmd` to prevent circular
   dependencies - it depends on pkg/api.

 * Also remove the build header from infra/abi files.  It will otherwise
   confuse swagger and other tools; errors we cannot fix as go doesn't
   expose a build-tag env variable.

Fixes: #5847
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
This commit is contained in:
Valentin Rothberg
2020-04-17 13:34:14 +02:00
parent 89276a5f92
commit 09dc701097
34 changed files with 423 additions and 259 deletions

View File

@ -6,8 +6,8 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/events"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/gorilla/schema"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
@ -70,7 +70,7 @@ func GetEvents(w http.ResponseWriter, r *http.Request) {
coder.SetEscapeHTML(true)
for event := range eventChannel {
e := handlers.EventToApiEvent(event)
e := entities.ConvertToEntitiesEvent(*event)
if err := coder.Encode(e); err != nil {
logrus.Errorf("unable to write json: %q", err)
}

View File

@ -22,6 +22,7 @@ import (
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi"
"github.com/containers/libpod/pkg/util"
utils2 "github.com/containers/libpod/utils"
"github.com/gorilla/schema"
@ -698,3 +699,30 @@ func SearchImages(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, reports)
}
// ImagesRemove is the endpoint for image removal.
func ImagesRemove(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
All bool `schema:"all"`
Force bool `schema:"force"`
Images []string `schema:"images"`
}{
All: false,
Force: false,
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}
opts := entities.ImageRemoveOptions{All: query.All, Force: query.Force}
imageEngine := abi.ImageEngine{Libpod: runtime}
rmReport, rmError := imageEngine.Remove(r.Context(), query.Images, opts)
report := handlers.LibpodImagesRemoveReport{ImageRemoveReport: *rmReport, Error: rmError.Error()}
utils.WriteResponse(w, http.StatusOK, report)
}

View File

@ -49,6 +49,13 @@ type swagLibpodImagesPullResponse struct {
Body handlers.LibpodImagesPullReport
}
// Remove response
// swagger:response DocsLibpodImagesRemoveResponse
type swagLibpodImagesRemoveResponse struct {
// in:body
Body handlers.LibpodImagesRemoveReport
}
// Delete response
// swagger:response DocsImageDeleteResponse
type swagImageDeleteResponse struct {

View File

@ -4,16 +4,13 @@ import (
"context"
"encoding/json"
"fmt"
"strconv"
"time"
"github.com/containers/image/v5/manifest"
"github.com/containers/libpod/libpod/events"
libpodImage "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
docker "github.com/docker/docker/api/types"
dockerContainer "github.com/docker/docker/api/types/container"
dockerEvents "github.com/docker/docker/api/types/events"
dockerNetwork "github.com/docker/docker/api/types/network"
"github.com/docker/go-connections/nat"
"github.com/pkg/errors"
@ -39,6 +36,14 @@ type LibpodImagesPullReport struct {
ID string `json:"id"`
}
// LibpodImagesRemoveReport is the return type for image removal via the rest
// api.
type LibpodImagesRemoveReport struct {
entities.ImageRemoveReport
// Image removal requires is to return data and an error.
Error string
}
type ContainersPruneReport struct {
docker.ContainersPruneReport
}
@ -143,10 +148,6 @@ type PodCreateConfig struct {
Share string `json:"share"`
}
type Event struct {
dockerEvents.Message
}
type HistoryResponse struct {
ID string `json:"Id"`
Created int64 `json:"Created"`
@ -173,49 +174,6 @@ type ExecCreateResponse struct {
docker.IDResponse
}
func (e *Event) ToLibpodEvent() *events.Event {
exitCode, err := strconv.Atoi(e.Actor.Attributes["containerExitCode"])
if err != nil {
return nil
}
status, err := events.StringToStatus(e.Action)
if err != nil {
return nil
}
t, err := events.StringToType(e.Type)
if err != nil {
return nil
}
lp := events.Event{
ContainerExitCode: exitCode,
ID: e.Actor.ID,
Image: e.Actor.Attributes["image"],
Name: e.Actor.Attributes["name"],
Status: status,
Time: time.Unix(e.Time, e.TimeNano),
Type: t,
}
return &lp
}
func EventToApiEvent(e *events.Event) *Event {
return &Event{dockerEvents.Message{
Type: e.Type.String(),
Action: e.Status.String(),
Actor: dockerEvents.Actor{
ID: e.ID,
Attributes: map[string]string{
"image": e.Image,
"name": e.Name,
"containerExitCode": strconv.Itoa(e.ContainerExitCode),
},
},
Scope: "local",
Time: e.Time.Unix(),
TimeNano: e.Time.UnixNano(),
}}
}
func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) {
containers, err := l.Containers()
if err != nil {