Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

podman rmi: refactor logic #5863

Merged
merged 1 commit into from
Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ linters:
- misspell
- prealloc
- unparam
- nakedret
linters-settings:
errcheck:
check-blank: false
Expand Down
2 changes: 1 addition & 1 deletion cmd/podman/containers/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ func run(cmd *cobra.Command, args []string) error {
return nil
}
if runRmi {
_, err := registry.ImageEngine().Delete(registry.GetContext(), []string{args[0]}, entities.ImageDeleteOptions{})
_, err := registry.ImageEngine().Remove(registry.GetContext(), []string{args[0]}, entities.ImageRemoveOptions{})
if err != nil {
logrus.Errorf("%s", errors.Wrapf(err, "failed removing image"))
}
Expand Down
32 changes: 12 additions & 20 deletions cmd/podman/images/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package images

import (
"fmt"
"os"

"github.com/containers/libpod/cmd/podman/registry"
"github.com/containers/libpod/pkg/domain/entities"
Expand All @@ -23,7 +22,7 @@ var (
podman image rm c4dfb1609ee2 93fd78260bd1 c0ed59d05ff7`,
}

imageOpts = entities.ImageDeleteOptions{}
imageOpts = entities.ImageRemoveOptions{}
)

func init() {
Expand All @@ -40,32 +39,25 @@ func imageRemoveFlagSet(flags *pflag.FlagSet) {
flags.BoolVarP(&imageOpts.All, "all", "a", false, "Remove all images")
flags.BoolVarP(&imageOpts.Force, "force", "f", false, "Force Removal of the image")
}
func rm(cmd *cobra.Command, args []string) error {

func rm(cmd *cobra.Command, args []string) error {
if len(args) < 1 && !imageOpts.All {
return errors.Errorf("image name or ID must be specified")
}
if len(args) > 0 && imageOpts.All {
return errors.Errorf("when using the --all switch, you may not pass any images names or IDs")
}
report, err := registry.ImageEngine().Delete(registry.GetContext(), args, imageOpts)
if err != nil {
switch {
case report != nil && report.ImageNotFound != nil:
fmt.Fprintln(os.Stderr, err.Error())
registry.SetExitCode(2)
case report != nil && report.ImageInUse != nil:
fmt.Fprintln(os.Stderr, err.Error())
default:
return err

report, err := registry.ImageEngine().Remove(registry.GetContext(), args, imageOpts)
if report != nil {
for _, u := range report.Untagged {
fmt.Println("Untagged: " + u)
}
for _, d := range report.Deleted {
fmt.Println("Deleted: " + d)
}
registry.SetExitCode(report.ExitCode)
}

for _, u := range report.Untagged {
fmt.Println("Untagged: " + u)
}
for _, d := range report.Deleted {
fmt.Println("Deleted: " + d)
}
return nil
return err
}
3 changes: 2 additions & 1 deletion cmd/podman/system/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ func service(cmd *cobra.Command, args []string) error {

logrus.Warn("This function is EXPERIMENTAL")
fmt.Fprintf(os.Stderr, "This function is EXPERIMENTAL.\n")
return registry.ContainerEngine().RestService(registry.GetContext(), opts)

return restService(opts, cmd.Flags(), registry.PodmanConfig())
}

func resolveApiURI(_url []string) (string, error) {
Expand Down
57 changes: 57 additions & 0 deletions cmd/podman/system/service_abi.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// +build ABISupport

package system

import (
"context"
"net"
"strings"

api "github.com/containers/libpod/pkg/api/server"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
)

func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entities.PodmanConfig) error {
var (
listener *net.Listener
err error
)

if opts.URI != "" {
fields := strings.Split(opts.URI, ":")
if len(fields) == 1 {
return errors.Errorf("%s is an invalid socket destination", opts.URI)
}
address := strings.Join(fields[1:], ":")
l, err := net.Listen(fields[0], address)
if err != nil {
return errors.Wrapf(err, "unable to create socket %s", opts.URI)
}
listener = &l
}

rt, err := infra.GetRuntime(context.Background(), flags, cfg)
if err != nil {
return err
}

server, err := api.NewServerWithSettings(rt, opts.Timeout, listener)
if err != nil {
return err
}
defer func() {
if err := server.Shutdown(); err != nil {
logrus.Warnf("Error when stopping API service: %s", err)
}
}()

err = server.Serve()
if listener != nil {
_ = (*listener).Close()
}
return err
}
14 changes: 14 additions & 0 deletions cmd/podman/system/service_unsupported.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// +build !ABISupport

package system

import (
"errors"

"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/pflag"
)

func restService(opts entities.ServiceOptions, flags *pflag.FlagSet, cfg *entities.PodmanConfig) error {
return errors.New("not supported")
}
15 changes: 12 additions & 3 deletions hack/golangci-lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@
# Need to run linter twice to cover all the build tags code paths

declare -A BUILD_TAGS
# TODO: add systemd tag
BUILD_TAGS[default]="apparmor,seccomp,selinux"
BUILD_TAGS[abi]="${BUILD_TAGS[default]},ABISupport,varlink,!remoteclient"
BUILD_TAGS[tunnel]="${BUILD_TAGS[default]},!ABISupport,!varlink,remoteclient"
BUILD_TAGS[tunnel]="${BUILD_TAGS[default]},!ABISupport,varlink,remoteclient"

declare -A SKIP_DIRS
SKIP_DIRS[abi]=""
# TODO: add "ABISupport" build tag to pkg/api
SKIP_DIRS[tunnel]="pkg/api"

[[ $1 == run ]] && shift

for i in tunnel abi; do
echo Build Tags: ${BUILD_TAGS[$i]}
golangci-lint run --build-tags=${BUILD_TAGS[$i]} "$@"
echo ""
echo Running golangci-lint for "$i"
echo Build Tags "$i": ${BUILD_TAGS[$i]}
echo Skipped directories "$i": ${SKIP_DIRS[$i]}
golangci-lint run --build-tags=${BUILD_TAGS[$i]} --skip-dirs=${SKIP_DIRS[$i]} "$@"
done
4 changes: 2 additions & 2 deletions pkg/api/handlers/compat/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
Expand Down
28 changes: 28 additions & 0 deletions pkg/api/handlers/libpod/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
}
7 changes: 7 additions & 0 deletions pkg/api/handlers/swagger/swagger.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
58 changes: 8 additions & 50 deletions pkg/api/handlers/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
}
Expand Down Expand Up @@ -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"`
Expand All @@ -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 {
Expand Down
32 changes: 32 additions & 0 deletions pkg/api/server/register_images.go
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,38 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/import"), s.APIHandler(libpod.ImagesImport)).Methods(http.MethodPost)
// swagger:operation GET /libpod/images/remove libpod libpodImagesRemove
// ---
// tags:
// - images
// summary: Remove one or more images from the storage.
// description: Remove one or more images from the storage.
// parameters:
// - in: query
// name: images
// description: Images IDs or names to remove.
// type: array
// items:
// type: string
// - in: query
// name: all
// description: Remove all images.
// type: boolean
// default: true
// - in: query
// name: force
// description: Force image removal (including containers using the images).
// type: boolean
// produces:
// - application/json
// responses:
// 200:
// $ref: "#/responses/DocsLibpodImagesRemoveResponse"
// 400:
// $ref: "#/responses/BadParamError"
// 500:
// $ref: '#/responses/InternalError'
r.Handle(VersionedPath("/libpod/images/remove"), s.APIHandler(libpod.ImagesRemove)).Methods(http.MethodGet)
// swagger:operation POST /libpod/images/pull libpod libpodImagesPull
// ---
// tags:
Expand Down
Loading