mirror of
https://github.com/containers/podman.git
synced 2025-10-27 19:34:13 +08:00
Report StatusConflict on Pod opt partial failures
- When one or more containers in the Pod reports an error on an operation report StatusConflict and report the error(s) - jsoniter type encoding used to marshal error as string using error.Error() - Update test framework to allow setting any flag when creating pods - Fix test_resize() result check Fixes #8865 Signed-off-by: Jhon Honce <jhonce@redhat.com>
This commit is contained in:
@ -84,5 +84,5 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) {
|
||||
// reasons.
|
||||
status = http.StatusCreated
|
||||
}
|
||||
utils.WriteResponse(w, status, "")
|
||||
w.WriteHeader(status)
|
||||
}
|
||||
|
||||
@ -139,19 +139,20 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
|
||||
logrus.Errorf("Error cleaning up pod %s container %s: %v", pod.ID(), id, err)
|
||||
}
|
||||
}
|
||||
var errs []error //nolint
|
||||
|
||||
report := entities.PodStopReport{Id: pod.ID()}
|
||||
for id, err := range responses {
|
||||
errs = append(errs, errors.Wrapf(err, "error stopping container %s", id))
|
||||
report.Errs = append(report.Errs, errors.Wrapf(err, "error stopping container %s", id))
|
||||
}
|
||||
report := entities.PodStopReport{
|
||||
Errs: errs,
|
||||
Id: pod.ID(),
|
||||
|
||||
code := http.StatusOK
|
||||
if len(report.Errs) > 0 {
|
||||
code = http.StatusConflict
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
utils.WriteResponse(w, code, report)
|
||||
}
|
||||
|
||||
func PodStart(w http.ResponseWriter, r *http.Request) {
|
||||
var errs []error //nolint
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
name := utils.GetName(r)
|
||||
pod, err := runtime.LookupPod(name)
|
||||
@ -168,19 +169,23 @@ func PodStart(w http.ResponseWriter, r *http.Request) {
|
||||
utils.WriteResponse(w, http.StatusNotModified, "")
|
||||
return
|
||||
}
|
||||
|
||||
responses, err := pod.Start(r.Context())
|
||||
if err != nil && errors.Cause(err) != define.ErrPodPartialFail {
|
||||
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
|
||||
utils.Error(w, "Something went wrong", http.StatusConflict, err)
|
||||
return
|
||||
}
|
||||
|
||||
report := entities.PodStartReport{Id: pod.ID()}
|
||||
for id, err := range responses {
|
||||
errs = append(errs, errors.Wrapf(err, "error starting container %s", id))
|
||||
report.Errs = append(report.Errs, errors.Wrapf(err, "error starting container "+id))
|
||||
}
|
||||
report := entities.PodStartReport{
|
||||
Errs: errs,
|
||||
Id: pod.ID(),
|
||||
|
||||
code := http.StatusOK
|
||||
if len(report.Errs) > 0 {
|
||||
code = http.StatusConflict
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
utils.WriteResponse(w, code, report)
|
||||
}
|
||||
|
||||
func PodDelete(w http.ResponseWriter, r *http.Request) {
|
||||
@ -209,14 +214,11 @@ func PodDelete(w http.ResponseWriter, r *http.Request) {
|
||||
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
report := entities.PodRmReport{
|
||||
Id: pod.ID(),
|
||||
}
|
||||
report := entities.PodRmReport{Id: pod.ID()}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
}
|
||||
|
||||
func PodRestart(w http.ResponseWriter, r *http.Request) {
|
||||
var errs []error //nolint
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
name := utils.GetName(r)
|
||||
pod, err := runtime.LookupPod(name)
|
||||
@ -229,14 +231,17 @@ func PodRestart(w http.ResponseWriter, r *http.Request) {
|
||||
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
report := entities.PodRestartReport{Id: pod.ID()}
|
||||
for id, err := range responses {
|
||||
errs = append(errs, errors.Wrapf(err, "error restarting container %s", id))
|
||||
report.Errs = append(report.Errs, errors.Wrapf(err, "error restarting container %s", id))
|
||||
}
|
||||
report := entities.PodRestartReport{
|
||||
Errs: errs,
|
||||
Id: pod.ID(),
|
||||
|
||||
code := http.StatusOK
|
||||
if len(report.Errs) > 0 {
|
||||
code = http.StatusConflict
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
utils.WriteResponse(w, code, report)
|
||||
}
|
||||
|
||||
func PodPrune(w http.ResponseWriter, r *http.Request) {
|
||||
@ -267,7 +272,6 @@ func PodPruneHelper(r *http.Request) ([]*entities.PodPruneReport, error) {
|
||||
}
|
||||
|
||||
func PodPause(w http.ResponseWriter, r *http.Request) {
|
||||
var errs []error //nolint
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
name := utils.GetName(r)
|
||||
pod, err := runtime.LookupPod(name)
|
||||
@ -280,18 +284,20 @@ func PodPause(w http.ResponseWriter, r *http.Request) {
|
||||
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
report := entities.PodPauseReport{Id: pod.ID()}
|
||||
for id, v := range responses {
|
||||
errs = append(errs, errors.Wrapf(v, "error pausing container %s", id))
|
||||
report.Errs = append(report.Errs, errors.Wrapf(v, "error pausing container %s", id))
|
||||
}
|
||||
report := entities.PodPauseReport{
|
||||
Errs: errs,
|
||||
Id: pod.ID(),
|
||||
|
||||
code := http.StatusOK
|
||||
if len(report.Errs) > 0 {
|
||||
code = http.StatusConflict
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
utils.WriteResponse(w, code, report)
|
||||
}
|
||||
|
||||
func PodUnpause(w http.ResponseWriter, r *http.Request) {
|
||||
var errs []error //nolint
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
name := utils.GetName(r)
|
||||
pod, err := runtime.LookupPod(name)
|
||||
@ -304,14 +310,17 @@ func PodUnpause(w http.ResponseWriter, r *http.Request) {
|
||||
utils.Error(w, "failed to pause pod", http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
report := entities.PodUnpauseReport{Id: pod.ID()}
|
||||
for id, v := range responses {
|
||||
errs = append(errs, errors.Wrapf(v, "error unpausing container %s", id))
|
||||
report.Errs = append(report.Errs, errors.Wrapf(v, "error unpausing container %s", id))
|
||||
}
|
||||
report := entities.PodUnpauseReport{
|
||||
Errs: errs,
|
||||
Id: pod.ID(),
|
||||
|
||||
code := http.StatusOK
|
||||
if len(report.Errs) > 0 {
|
||||
code = http.StatusConflict
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, &report)
|
||||
utils.WriteResponse(w, code, &report)
|
||||
}
|
||||
|
||||
func PodTop(w http.ResponseWriter, r *http.Request) {
|
||||
@ -361,7 +370,6 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
|
||||
runtime = r.Context().Value("runtime").(*libpod.Runtime)
|
||||
decoder = r.Context().Value("decoder").(*schema.Decoder)
|
||||
signal = "SIGKILL"
|
||||
errs []error //nolint
|
||||
)
|
||||
query := struct {
|
||||
Signal string `schema:"signal"`
|
||||
@ -413,16 +421,18 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
report := &entities.PodKillReport{Id: pod.ID()}
|
||||
for _, v := range responses {
|
||||
if v != nil {
|
||||
errs = append(errs, v)
|
||||
report.Errs = append(report.Errs, v)
|
||||
}
|
||||
}
|
||||
report := &entities.PodKillReport{
|
||||
Errs: errs,
|
||||
Id: pod.ID(),
|
||||
|
||||
code := http.StatusOK
|
||||
if len(report.Errs) > 0 {
|
||||
code = http.StatusConflict
|
||||
}
|
||||
utils.WriteResponse(w, http.StatusOK, report)
|
||||
utils.WriteResponse(w, code, report)
|
||||
}
|
||||
|
||||
func PodExists(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/gorilla/mux"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -144,6 +145,50 @@ func WriteResponse(w http.ResponseWriter, code int, value interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
jsoniter.RegisterTypeEncoderFunc("error", MarshalErrorJSON, MarshalErrorJSONIsEmpty)
|
||||
jsoniter.RegisterTypeEncoderFunc("[]error", MarshalErrorSliceJSON, MarshalErrorSliceJSONIsEmpty)
|
||||
}
|
||||
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
// MarshalErrorJSON writes error to stream as string
|
||||
func MarshalErrorJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
p := *((*error)(ptr))
|
||||
if p == nil {
|
||||
stream.WriteNil()
|
||||
} else {
|
||||
stream.WriteString(p.Error())
|
||||
}
|
||||
}
|
||||
|
||||
// MarshalErrorSliceJSON writes []error to stream as []string JSON blob
|
||||
func MarshalErrorSliceJSON(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
a := *((*[]error)(ptr))
|
||||
switch {
|
||||
case len(a) == 0:
|
||||
stream.WriteNil()
|
||||
default:
|
||||
stream.WriteArrayStart()
|
||||
for i, e := range a {
|
||||
if i > 0 {
|
||||
stream.WriteMore()
|
||||
}
|
||||
stream.WriteString(e.Error())
|
||||
}
|
||||
stream.WriteArrayEnd()
|
||||
}
|
||||
}
|
||||
|
||||
func MarshalErrorJSONIsEmpty(_ unsafe.Pointer) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func MarshalErrorSliceJSONIsEmpty(_ unsafe.Pointer) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// WriteJSON writes an interface value encoded as JSON to w
|
||||
func WriteJSON(w http.ResponseWriter, code int, value interface{}) {
|
||||
// FIXME: we don't need to write the header in all/some circumstances.
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
@ -43,6 +43,11 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
|
||||
// $ref: "#/definitions/IdResponse"
|
||||
// 400:
|
||||
// $ref: "#/responses/BadParamError"
|
||||
// 409:
|
||||
// description: status conflict
|
||||
// schema:
|
||||
// type: string
|
||||
// description: message describing error
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/pods/create"), s.APIHandler(libpod.PodCreate)).Methods(http.MethodPost)
|
||||
@ -149,7 +154,7 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
|
||||
// 404:
|
||||
// $ref: "#/responses/NoSuchPod"
|
||||
// 409:
|
||||
// $ref: "#/responses/ConflictError"
|
||||
// $ref: "#/responses/PodKillReport"
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/pods/{name}/kill"), s.APIHandler(libpod.PodKill)).Methods(http.MethodPost)
|
||||
@ -170,6 +175,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
|
||||
// $ref: '#/responses/PodPauseReport'
|
||||
// 404:
|
||||
// $ref: "#/responses/NoSuchPod"
|
||||
// 409:
|
||||
// $ref: '#/responses/PodPauseReport'
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/pods/{name}/pause"), s.APIHandler(libpod.PodPause)).Methods(http.MethodPost)
|
||||
@ -189,6 +196,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
|
||||
// $ref: '#/responses/PodRestartReport'
|
||||
// 404:
|
||||
// $ref: "#/responses/NoSuchPod"
|
||||
// 409:
|
||||
// $ref: "#/responses/PodRestartReport"
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/pods/{name}/restart"), s.APIHandler(libpod.PodRestart)).Methods(http.MethodPost)
|
||||
@ -210,6 +219,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
|
||||
// $ref: "#/responses/PodAlreadyStartedError"
|
||||
// 404:
|
||||
// $ref: "#/responses/NoSuchPod"
|
||||
// 409:
|
||||
// $ref: '#/responses/PodStartReport'
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/pods/{name}/start"), s.APIHandler(libpod.PodStart)).Methods(http.MethodPost)
|
||||
@ -237,6 +248,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
|
||||
// $ref: "#/responses/BadParamError"
|
||||
// 404:
|
||||
// $ref: "#/responses/NoSuchPod"
|
||||
// 409:
|
||||
// $ref: "#/responses/PodStopReport"
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/pods/{name}/stop"), s.APIHandler(libpod.PodStop)).Methods(http.MethodPost)
|
||||
@ -256,6 +269,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
|
||||
// $ref: '#/responses/PodUnpauseReport'
|
||||
// 404:
|
||||
// $ref: "#/responses/NoSuchPod"
|
||||
// 409:
|
||||
// $ref: '#/responses/PodUnpauseReport'
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/pods/{name}/unpause"), s.APIHandler(libpod.PodUnpause)).Methods(http.MethodPost)
|
||||
|
||||
Reference in New Issue
Block a user