diff options
Diffstat (limited to 'pkg/api')
| -rw-r--r-- | pkg/api/handlers/compat/containers_stats.go | 2 | ||||
| -rw-r--r-- | pkg/api/handlers/libpod/generate.go | 38 | ||||
| -rw-r--r-- | pkg/api/handlers/libpod/images.go | 51 | ||||
| -rw-r--r-- | pkg/api/handlers/libpod/play.go | 64 | ||||
| -rw-r--r-- | pkg/api/handlers/swagger/swagger.go | 7 | ||||
| -rw-r--r-- | pkg/api/handlers/types.go | 2 | ||||
| -rw-r--r-- | pkg/api/server/register_generate.go | 41 | ||||
| -rw-r--r-- | pkg/api/server/register_images.go | 64 | ||||
| -rw-r--r-- | pkg/api/server/register_play.go | 42 | ||||
| -rw-r--r-- | pkg/api/server/server.go | 2 | 
10 files changed, 275 insertions, 38 deletions
diff --git a/pkg/api/handlers/compat/containers_stats.go b/pkg/api/handlers/compat/containers_stats.go index 53ad0a632..62ccd2b93 100644 --- a/pkg/api/handlers/compat/containers_stats.go +++ b/pkg/api/handlers/compat/containers_stats.go @@ -50,7 +50,7 @@ func StatsContainer(w http.ResponseWriter, r *http.Request) {  		return  	} -	stats, err := ctnr.GetContainerStats(&libpod.ContainerStats{}) +	stats, err := ctnr.GetContainerStats(&define.ContainerStats{})  	if err != nil {  		utils.InternalServerError(w, errors.Wrapf(err, "Failed to obtain Container %s stats", name))  		return diff --git a/pkg/api/handlers/libpod/generate.go b/pkg/api/handlers/libpod/generate.go new file mode 100644 index 000000000..23320d346 --- /dev/null +++ b/pkg/api/handlers/libpod/generate.go @@ -0,0 +1,38 @@ +package libpod + +import ( +	"net/http" + +	"github.com/containers/libpod/libpod" +	"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/gorilla/schema" +	"github.com/pkg/errors" +) + +func GenerateKube(w http.ResponseWriter, r *http.Request) { +	runtime := r.Context().Value("runtime").(*libpod.Runtime) +	decoder := r.Context().Value("decoder").(*schema.Decoder) +	query := struct { +		Service bool `schema:"service"` +	}{ +		// Defaults would go here. +	} + +	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 +	} + +	containerEngine := abi.ContainerEngine{Libpod: runtime} +	options := entities.GenerateKubeOptions{Service: query.Service} +	report, err := containerEngine.GenerateKube(r.Context(), utils.GetName(r), options) +	if err != nil { +		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error generating YAML")) +		return +	} + +	utils.WriteResponse(w, http.StatusOK, report.Reader) +} diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index f7be5ce9a..93b4564a1 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -23,6 +23,7 @@ import (  	"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/errorhandling"  	"github.com/containers/libpod/pkg/util"  	utils2 "github.com/containers/libpod/utils"  	"github.com/gorilla/schema" @@ -700,8 +701,8 @@ 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) { +// ImagesBatchRemove is the endpoint for batch image removal. +func ImagesBatchRemove(w http.ResponseWriter, r *http.Request) {  	runtime := r.Context().Value("runtime").(*libpod.Runtime)  	decoder := r.Context().Value("decoder").(*schema.Decoder)  	query := struct { @@ -722,7 +723,49 @@ func ImagesRemove(w http.ResponseWriter, r *http.Request) {  	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()} +	rmReport, rmErrors := imageEngine.Remove(r.Context(), query.Images, opts) + +	strErrs := errorhandling.ErrorsToStrings(rmErrors) +	report := handlers.LibpodImagesRemoveReport{ImageRemoveReport: *rmReport, Errors: strErrs}  	utils.WriteResponse(w, http.StatusOK, report)  } + +// ImagesRemove is the endpoint for removing one image. +func ImagesRemove(w http.ResponseWriter, r *http.Request) { +	runtime := r.Context().Value("runtime").(*libpod.Runtime) +	decoder := r.Context().Value("decoder").(*schema.Decoder) +	query := struct { +		Force bool `schema:"force"` +	}{ +		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{Force: query.Force} +	imageEngine := abi.ImageEngine{Libpod: runtime} +	rmReport, rmErrors := imageEngine.Remove(r.Context(), []string{utils.GetName(r)}, opts) + +	// In contrast to batch-removal, where we're only setting the exit +	// code, we need to have another closer look at the errors here and set +	// the appropriate http status code. + +	switch rmReport.ExitCode { +	case 0: +		report := handlers.LibpodImagesRemoveReport{ImageRemoveReport: *rmReport, Errors: []string{}} +		utils.WriteResponse(w, http.StatusOK, report) +	case 1: +		// 404 - no such image +		utils.Error(w, "error removing image", http.StatusNotFound, errorhandling.JoinErrors(rmErrors)) +	case 2: +		// 409 - conflict error (in use by containers) +		utils.Error(w, "error removing image", http.StatusConflict, errorhandling.JoinErrors(rmErrors)) +	default: +		// 500 - internal error +		utils.Error(w, "failed to remove image", http.StatusInternalServerError, errorhandling.JoinErrors(rmErrors)) +	} +} diff --git a/pkg/api/handlers/libpod/play.go b/pkg/api/handlers/libpod/play.go new file mode 100644 index 000000000..26e02bf4f --- /dev/null +++ b/pkg/api/handlers/libpod/play.go @@ -0,0 +1,64 @@ +package libpod + +import ( +	"io" +	"io/ioutil" +	"net/http" +	"os" + +	"github.com/containers/image/v5/types" +	"github.com/containers/libpod/libpod" +	"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/gorilla/schema" +	"github.com/pkg/errors" +) + +func PlayKube(w http.ResponseWriter, r *http.Request) { +	runtime := r.Context().Value("runtime").(*libpod.Runtime) +	decoder := r.Context().Value("decoder").(*schema.Decoder) +	query := struct { +		Network   string `schema:"reference"` +		TLSVerify bool   `schema:"tlsVerify"` +	}{ +		TLSVerify: true, +	} + +	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 +	} + +	// Fetch the K8s YAML file from the body, and copy it to a temp file. +	tmpfile, err := ioutil.TempFile("", "libpod-play-kube.yml") +	if err != nil { +		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile")) +		return +	} +	defer os.Remove(tmpfile.Name()) +	if _, err := io.Copy(tmpfile, r.Body); err != nil && err != io.EOF { +		tmpfile.Close() +		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to write archive to temporary file")) +		return +	} +	if err := tmpfile.Close(); err != nil { +		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error closing temporary file")) +		return +	} + +	containerEngine := abi.ContainerEngine{Libpod: runtime} +	options := entities.PlayKubeOptions{Network: query.Network, Quiet: true} +	if _, found := r.URL.Query()["tlsVerify"]; found { +		options.SkipTLSVerify = types.NewOptionalBool(!query.TLSVerify) +	} + +	report, err := containerEngine.PlayKube(r.Context(), tmpfile.Name(), options) +	if err != nil { +		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error playing YAML file")) +		return +	} + +	utils.WriteResponse(w, http.StatusOK, report) +} diff --git a/pkg/api/handlers/swagger/swagger.go b/pkg/api/handlers/swagger/swagger.go index 0aceaf5f6..5d125417b 100644 --- a/pkg/api/handlers/swagger/swagger.go +++ b/pkg/api/handlers/swagger/swagger.go @@ -56,6 +56,13 @@ type swagLibpodImagesRemoveResponse struct {  	Body handlers.LibpodImagesRemoveReport  } +// PlayKube response +// swagger:response DocsLibpodPlayKubeResponse +type swagLibpodPlayKubeResponse struct { +	// in:body +	Body entities.PlayKubeReport +} +  // Delete response  // swagger:response DocsImageDeleteResponse  type swagImageDeleteResponse struct { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index 58a12ea6a..a7abf59c0 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -41,7 +41,7 @@ type LibpodImagesPullReport struct {  type LibpodImagesRemoveReport struct {  	entities.ImageRemoveReport  	// Image removal requires is to return data and an error. -	Error string +	Errors []string  }  type ContainersPruneReport struct { diff --git a/pkg/api/server/register_generate.go b/pkg/api/server/register_generate.go new file mode 100644 index 000000000..391e60111 --- /dev/null +++ b/pkg/api/server/register_generate.go @@ -0,0 +1,41 @@ +package server + +import ( +	"net/http" + +	"github.com/containers/libpod/pkg/api/handlers/libpod" +	"github.com/gorilla/mux" +) + +func (s *APIServer) registerGenerateHandlers(r *mux.Router) error { +	// swagger:operation GET /libpod/generate/{name:.*}/kube libpod libpodGenerateKube +	// --- +	// tags: +	//  - containers +	//  - pods +	// summary: Play a Kubernetes YAML file. +	// description: Create and run pods based on a Kubernetes YAML file (pod or service kind). +	// parameters: +	//  - in: path +	//    name: name:.* +	//    type: string +	//    required: true +	//    description: Name or ID of the container or pod. +	//  - in: query +	//    name: service +	//    type: boolean +	//    default: false +	//    description: Generate YAML for a Kubernetes service object. +	// produces: +	// - application/json +	// responses: +	//   200: +	//     description: no error +	//     schema: +	//      type: string +	//      format: binary +	//   500: +	//     $ref: "#/responses/InternalError" +	r.HandleFunc(VersionedPath("/libpod/generate/{name:.*}/kube"), s.APIHandler(libpod.GenerateKube)).Methods(http.MethodGet) +	return nil +} diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index f59dca6f5..0e8d68b7e 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -822,7 +822,7 @@ 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 +	// swagger:operation DELETE /libpod/images/remove libpod libpodImagesRemove  	// ---  	// tags:  	//  - images @@ -853,7 +853,37 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {  	//     $ref: "#/responses/BadParamError"  	//   500:  	//     $ref: '#/responses/InternalError' -	r.Handle(VersionedPath("/libpod/images/remove"), s.APIHandler(libpod.ImagesRemove)).Methods(http.MethodGet) +	r.Handle(VersionedPath("/libpod/images/remove"), s.APIHandler(libpod.ImagesBatchRemove)).Methods(http.MethodDelete) +	// swagger:operation DELETE /libpod/images/{name:.*}/remove libpod libpodRemoveImage +	// --- +	// tags: +	//  - images +	// summary: Remove an image from the local storage. +	// description: Remove an image from the local storage. +	// parameters: +	//  - in: path +	//    name: name:.* +	//    type: string +	//    required: true +	//    description: name or ID of image to remove +	//  - in: query +	//    name: force +	//    type: boolean +	//    description: remove the image even if used by containers or has other tags +	// produces: +	// - application/json +	// responses: +	//   200: +	//     $ref: "#/responses/DocsImageDeleteResponse" +	//   400: +	//     $ref: "#/responses/BadParamError" +	//   404: +	//     $ref: '#/responses/NoSuchImage' +	//   409: +	//     $ref: '#/responses/ConflictError' +	//   500: +	//     $ref: '#/responses/InternalError' +	r.Handle(VersionedPath("/libpod/images/{name:.*}/remove"), s.APIHandler(libpod.ImagesRemove)).Methods(http.MethodDelete)  	// swagger:operation POST /libpod/images/pull libpod libpodImagesPull  	// ---  	// tags: @@ -952,36 +982,6 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error {  	//   500:  	//      $ref: '#/responses/InternalError'  	r.Handle(VersionedPath("/libpod/images/search"), s.APIHandler(libpod.SearchImages)).Methods(http.MethodGet) -	// swagger:operation DELETE /libpod/images/{name:.*} libpod libpodRemoveImage -	// --- -	// tags: -	//  - images -	// summary: Remove Image -	// description: Delete an image from local store -	// parameters: -	//  - in: path -	//    name: name:.* -	//    type: string -	//    required: true -	//    description: name or ID of image to delete -	//  - in: query -	//    name: force -	//    type: boolean -	//    description: remove the image even if used by containers or has other tags -	// produces: -	// - application/json -	// responses: -	//   200: -	//     $ref: "#/responses/DocsImageDeleteResponse" -	//   400: -	//     $ref: "#/responses/BadParamError" -	//   404: -	//     $ref: '#/responses/NoSuchImage' -	//   409: -	//     $ref: '#/responses/ConflictError' -	//   500: -	//     $ref: '#/responses/InternalError' -	r.Handle(VersionedPath("/libpod/images/{name:.*}"), s.APIHandler(compat.RemoveImage)).Methods(http.MethodDelete)  	// swagger:operation GET /libpod/images/{name:.*}/get libpod libpodExportImage  	// ---  	// tags: diff --git a/pkg/api/server/register_play.go b/pkg/api/server/register_play.go new file mode 100644 index 000000000..d04879c19 --- /dev/null +++ b/pkg/api/server/register_play.go @@ -0,0 +1,42 @@ +package server + +import ( +	"net/http" + +	"github.com/containers/libpod/pkg/api/handlers/libpod" +	"github.com/gorilla/mux" +) + +func (s *APIServer) registerPlayHandlers(r *mux.Router) error { +	// swagger:operation POST /libpod/play/kube libpod libpodPlayKube +	// --- +	// tags: +	//  - containers +	//  - pods +	// summary: Play a Kubernetes YAML file. +	// description: Create and run pods based on a Kubernetes YAML file (pod or service kind). +	// parameters: +	//  - in: query +	//    name: network +	//    type: string +	//    description: Connect the pod to this network. +	//  - in: query +	//    name: tlsVerify +	//    type: boolean +	//    default: true +	//    description: Require HTTPS and verify signatures when contating registries. +	//  - in: body +	//    name: request +	//    description: Kubernetes YAML file. +	//    schema: +	//      type: string +	// produces: +	// - application/json +	// responses: +	//   200: +	//     $ref: "#/responses/DocsLibpodPlayKubeResponse" +	//   500: +	//     $ref: "#/responses/InternalError" +	r.HandleFunc(VersionedPath("/libpod/play/kube"), s.APIHandler(libpod.PlayKube)).Methods(http.MethodPost) +	return nil +} diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go index ce2d152e0..a6c5d8e1e 100644 --- a/pkg/api/server/server.go +++ b/pkg/api/server/server.go @@ -98,12 +98,14 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li  		server.registerDistributionHandlers,  		server.registerEventsHandlers,  		server.registerExecHandlers, +		server.registerGenerateHandlers,  		server.registerHealthCheckHandlers,  		server.registerImagesHandlers,  		server.registerInfoHandlers,  		server.registerManifestHandlers,  		server.registerMonitorHandlers,  		server.registerPingHandlers, +		server.registerPlayHandlers,  		server.registerPluginsHandlers,  		server.registerPodsHandlers,  		server.RegisterSwaggerHandlers,  | 
