diff options
Diffstat (limited to 'pkg/api/handlers')
-rw-r--r-- | pkg/api/handlers/compat/containers_prune.go | 2 | ||||
-rw-r--r-- | pkg/api/handlers/compat/containers_top.go | 10 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_build.go | 72 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_prune.go | 19 | ||||
-rw-r--r-- | pkg/api/handlers/compat/images_remove.go | 35 | ||||
-rw-r--r-- | pkg/api/handlers/compat/resize.go | 22 | ||||
-rw-r--r-- | pkg/api/handlers/compat/version.go | 6 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images.go | 18 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/pods.go | 12 | ||||
-rw-r--r-- | pkg/api/handlers/types.go | 4 | ||||
-rw-r--r-- | pkg/api/handlers/types/types.go | 23 | ||||
-rw-r--r-- | pkg/api/handlers/utils/images.go | 14 |
12 files changed, 156 insertions, 81 deletions
diff --git a/pkg/api/handlers/compat/containers_prune.go b/pkg/api/handlers/compat/containers_prune.go index e37929d27..61ea7a89e 100644 --- a/pkg/api/handlers/compat/containers_prune.go +++ b/pkg/api/handlers/compat/containers_prune.go @@ -23,7 +23,7 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) { filterFuncs := make([]libpod.ContainerFilter, 0, len(*filtersMap)) for k, v := range *filtersMap { - generatedFunc, err := filters.GenerateContainerFilterFuncs(k, v, runtime) + generatedFunc, err := filters.GeneratePruneContainerFilterFuncs(k, v, runtime) if err != nil { utils.InternalServerError(w, err) return diff --git a/pkg/api/handlers/compat/containers_top.go b/pkg/api/handlers/compat/containers_top.go index ab9f613af..cae044a89 100644 --- a/pkg/api/handlers/compat/containers_top.go +++ b/pkg/api/handlers/compat/containers_top.go @@ -46,8 +46,16 @@ func TopContainer(w http.ResponseWriter, r *http.Request) { var body = handlers.ContainerTopOKBody{} if len(output) > 0 { body.Titles = strings.Split(output[0], "\t") + for i := range body.Titles { + body.Titles[i] = strings.TrimSpace(body.Titles[i]) + } + for _, line := range output[1:] { - body.Processes = append(body.Processes, strings.Split(line, "\t")) + process := strings.Split(line, "\t") + for i := range process { + process[i] = strings.TrimSpace(process[i]) + } + body.Processes = append(body.Processes, process) } } utils.WriteJSON(w, http.StatusOK, body) diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 7751b91a7..6dac789d6 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -13,7 +13,7 @@ import ( "time" "github.com/containers/buildah" - "github.com/containers/buildah/imagebuildah" + buildahDefine "github.com/containers/buildah/define" "github.com/containers/buildah/util" "github.com/containers/image/v5/types" "github.com/containers/podman/v3/libpod" @@ -69,7 +69,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { BuildArgs string `schema:"buildargs"` CacheFrom string `schema:"cachefrom"` Compression uint64 `schema:"compression"` - ConfigureNetwork int64 `schema:"networkmode"` + ConfigureNetwork string `schema:"networkmode"` CpuPeriod uint64 `schema:"cpuperiod"` // nolint CpuQuota int64 `schema:"cpuquota"` // nolint CpuSetCpus string `schema:"cpusetcpus"` // nolint @@ -84,7 +84,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { ForceRm bool `schema:"forcerm"` From string `schema:"from"` HTTPProxy bool `schema:"httpproxy"` - Isolation int64 `schema:"isolation"` + Isolation string `schema:"isolation"` Ignore bool `schema:"ignore"` Jobs int `schema:"jobs"` // nolint Labels string `schema:"labels"` @@ -98,6 +98,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { OutputFormat string `schema:"outputformat"` Platform string `schema:"platform"` Pull bool `schema:"pull"` + PullPolicy string `schema:"pullpolicy"` Quiet bool `schema:"q"` Registry string `schema:"registry"` Rm bool `schema:"rm"` @@ -199,15 +200,17 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { } format := buildah.Dockerv2ImageManifest registry := query.Registry - isolation := buildah.IsolationChroot - /* - // FIXME, This is very broken. Buildah will only work with chroot - isolation := buildah.IsolationDefault - */ + isolation := buildah.IsolationDefault if utils.IsLibpodRequest(r) { - // isolation = buildah.Isolation(query.Isolation) + isolation = parseLibPodIsolation(query.Isolation) registry = "" format = query.OutputFormat + } else { + if _, found := r.URL.Query()["isolation"]; found { + if query.Isolation != "" && query.Isolation != "default" { + logrus.Debugf("invalid `isolation` parameter: %q", query.Isolation) + } + } } var additionalTags []string if len(query.Tag) > 1 { @@ -273,10 +276,14 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { jobs = query.Jobs } - pullPolicy := buildah.PullIfMissing - if _, found := r.URL.Query()["pull"]; found { - if query.Pull { - pullPolicy = buildah.PullAlways + pullPolicy := buildahDefine.PullIfMissing + if utils.IsLibpodRequest(r) { + pullPolicy = buildahDefine.PolicyMap[query.PullPolicy] + } else { + if _, found := r.URL.Query()["pull"]; found { + if query.Pull { + pullPolicy = buildahDefine.PullAlways + } } } @@ -307,7 +314,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()")) return } - buildOptions := imagebuildah.BuildOptions{ + buildOptions := buildahDefine.BuildOptions{ AddCapabilities: addCaps, AdditionalTags: additionalTags, Annotations: annotations, @@ -329,7 +336,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { CNIConfigDir: rtc.Network.CNIPluginDirs[0], CNIPluginPath: util.DefaultCNIPluginPath, Compression: compression, - ConfigureNetwork: buildah.NetworkConfigurationPolicy(query.ConfigureNetwork), + ConfigureNetwork: parseNetworkConfigurationPolicy(query.ConfigureNetwork), ContextDirectory: contextDirectory, Devices: devices, DropCapabilities: dropCaps, @@ -342,6 +349,7 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { Jobs: &jobs, Labels: labels, Layers: query.Layers, + LogRusage: query.LogRusage, Manifest: query.Manifest, MaxPullPushRetries: 3, NamespaceOptions: nsoptions, @@ -459,6 +467,40 @@ loop: } } +func parseNetworkConfigurationPolicy(network string) buildah.NetworkConfigurationPolicy { + if val, err := strconv.Atoi(network); err == nil { + return buildah.NetworkConfigurationPolicy(val) + } + switch network { + case "NetworkDefault": + return buildah.NetworkDefault + case "NetworkDisabled": + return buildah.NetworkDisabled + case "NetworkEnabled": + return buildah.NetworkEnabled + default: + return buildah.NetworkDefault + } +} + +func parseLibPodIsolation(isolation string) buildah.Isolation { // nolint + if val, err := strconv.Atoi(isolation); err == nil { + return buildah.Isolation(val) + } + switch isolation { + case "IsolationDefault", "default": + return buildah.IsolationDefault + case "IsolationOCI": + return buildah.IsolationOCI + case "IsolationChroot": + return buildah.IsolationChroot + case "IsolationOCIRootless": + return buildah.IsolationOCIRootless + default: + return buildah.IsolationDefault + } +} + func extractTarFile(r *http.Request) (string, error) { // build a home for the request body anchorDir, err := ioutil.TempDir("", "libpod_builder") diff --git a/pkg/api/handlers/compat/images_prune.go b/pkg/api/handlers/compat/images_prune.go index 63daaa780..ddf559ec6 100644 --- a/pkg/api/handlers/compat/images_prune.go +++ b/pkg/api/handlers/compat/images_prune.go @@ -8,8 +8,8 @@ import ( "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/pkg/api/handlers" "github.com/containers/podman/v3/pkg/api/handlers/utils" + "github.com/containers/podman/v3/pkg/util" "github.com/docker/docker/api/types" - "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -17,27 +17,20 @@ func PruneImages(w http.ResponseWriter, r *http.Request) { var ( filters []string ) - decoder := r.Context().Value("decoder").(*schema.Decoder) runtime := r.Context().Value("runtime").(*libpod.Runtime) - query := struct { - All bool - Filters map[string][]string `schema:"filters"` - }{ - // This is where you can override the golang default value for one of fields - } - - 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())) + filterMap, err := util.PrepareFilters(r) + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } - for k, v := range query.Filters { + for k, v := range *filterMap { for _, val := range v { filters = append(filters, fmt.Sprintf("%s=%s", k, val)) } } - imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters) + imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), false, filters) if err != nil { utils.InternalServerError(w, err) return diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go index 874c57f16..e89558a86 100644 --- a/pkg/api/handlers/compat/images_remove.go +++ b/pkg/api/handlers/compat/images_remove.go @@ -4,7 +4,10 @@ import ( "net/http" "github.com/containers/podman/v3/libpod" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/api/handlers/utils" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/domain/infra/abi" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -30,28 +33,32 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) { } } name := utils.GetName(r) - newImage, err := runtime.ImageRuntime().NewFromLocal(name) - if err != nil { - utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) - return + imageEngine := abi.ImageEngine{Libpod: runtime} + + options := entities.ImageRemoveOptions{ + Force: query.Force, } + report, rmerrors := imageEngine.Remove(r.Context(), []string{name}, options) + if len(rmerrors) > 0 && rmerrors[0] != nil { + err := rmerrors[0] + if errors.Cause(err) == define.ErrNoSuchImage { + utils.ImageNotFound(w, name, errors.Wrapf(err, "failed to find image %s", name)) + return + } - results, err := runtime.RemoveImage(r.Context(), newImage, query.Force) - if err != nil { utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err) return } - - response := make([]map[string]string, 0, len(results.Untagged)+1) - deleted := make(map[string]string, 1) - deleted["Deleted"] = results.Deleted - response = append(response, deleted) - - for _, u := range results.Untagged { + response := make([]map[string]string, 0, len(report.Untagged)+1) + for _, d := range report.Deleted { + deleted := make(map[string]string, 1) + deleted["Deleted"] = d + response = append(response, deleted) + } + for _, u := range report.Untagged { untagged := make(map[string]string, 1) untagged["Untagged"] = u response = append(response, untagged) } - utils.WriteResponse(w, http.StatusOK, response) } diff --git a/pkg/api/handlers/compat/resize.go b/pkg/api/handlers/compat/resize.go index 1bf7ad460..23ed33a22 100644 --- a/pkg/api/handlers/compat/resize.go +++ b/pkg/api/handlers/compat/resize.go @@ -19,8 +19,9 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { // /containers/{id}/resize query := struct { - Height uint16 `schema:"h"` - Width uint16 `schema:"w"` + Height uint16 `schema:"h"` + Width uint16 `schema:"w"` + IgnoreNotRunning bool `schema:"running"` }{ // override any golang type defaults } @@ -48,14 +49,17 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { if state, err := ctnr.State(); err != nil { utils.InternalServerError(w, errors.Wrapf(err, "cannot obtain container state")) return - } else if state != define.ContainerStateRunning { + } else if state != define.ContainerStateRunning && !query.IgnoreNotRunning { utils.Error(w, "Container not running", http.StatusConflict, fmt.Errorf("container %q in wrong state %q", name, state.String())) return } + // If container is not running, ignore since this can be a race condition, and is expected if err := ctnr.AttachResize(sz); err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "cannot resize container")) - return + if errors.Cause(err) != define.ErrCtrStateInvalid || !query.IgnoreNotRunning { + utils.InternalServerError(w, errors.Wrapf(err, "cannot resize container")) + return + } } // This is not a 204, even though we write nothing, for compatibility // reasons. @@ -70,14 +74,16 @@ func ResizeTTY(w http.ResponseWriter, r *http.Request) { if state, err := ctnr.State(); err != nil { utils.InternalServerError(w, errors.Wrapf(err, "cannot obtain session container state")) return - } else if state != define.ContainerStateRunning { + } else if state != define.ContainerStateRunning && !query.IgnoreNotRunning { utils.Error(w, "Container not running", http.StatusConflict, fmt.Errorf("container %q in wrong state %q", name, state.String())) return } if err := ctnr.ExecResize(name, sz); err != nil { - utils.InternalServerError(w, errors.Wrapf(err, "cannot resize session")) - return + if errors.Cause(err) != define.ErrCtrStateInvalid || !query.IgnoreNotRunning { + utils.InternalServerError(w, errors.Wrapf(err, "cannot resize session")) + return + } } // This is not a 204, even though we write nothing, for compatibility // reasons. diff --git a/pkg/api/handlers/compat/version.go b/pkg/api/handlers/compat/version.go index fae147440..f1cd77a9a 100644 --- a/pkg/api/handlers/compat/version.go +++ b/pkg/api/handlers/compat/version.go @@ -10,8 +10,8 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/api/handlers/utils" "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/domain/entities/types" "github.com/containers/podman/v3/version" - docker "github.com/docker/docker/api/types" "github.com/pkg/errors" ) @@ -32,7 +32,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { return } - components := []docker.ComponentVersion{{ + components := []types.ComponentVersion{{ Name: "Podman Engine", Version: versionInfo.Version, Details: map[string]string{ @@ -52,7 +52,7 @@ func VersionHandler(w http.ResponseWriter, r *http.Request) { minVersion := version.APIVersion[version.Compat][version.MinimalAPI] utils.WriteResponse(w, http.StatusOK, entities.ComponentVersion{ - Version: docker.Version{ + Version: types.Version{ Platform: struct { Name string }{ diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go index 1f306a533..158babcdc 100644 --- a/pkg/api/handlers/libpod/images.go +++ b/pkg/api/handlers/libpod/images.go @@ -22,6 +22,7 @@ import ( "github.com/containers/podman/v3/pkg/domain/entities" "github.com/containers/podman/v3/pkg/domain/infra/abi" "github.com/containers/podman/v3/pkg/errorhandling" + "github.com/containers/podman/v3/pkg/util" utils2 "github.com/containers/podman/v3/utils" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -125,31 +126,32 @@ func PruneImages(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"` - Filters map[string][]string `schema:"filters"` + All bool `schema:"all"` }{ // override any golang type defaults } - if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, + filterMap, err := util.PrepareFilters(r) + + if dErr := decoder.Decode(&query, r.URL.Query()); dErr != nil || err != nil { + utils.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return } var libpodFilters = []string{} if _, found := r.URL.Query()["filters"]; found { - dangling := query.Filters["all"] + dangling := (*filterMap)["all"] if len(dangling) > 0 { - query.All, err = strconv.ParseBool(query.Filters["all"][0]) + query.All, err = strconv.ParseBool((*filterMap)["all"][0]) if err != nil { utils.InternalServerError(w, err) return } } // dangling is special and not implemented in the libpod side of things - delete(query.Filters, "dangling") - for k, v := range query.Filters { + delete(*filterMap, "dangling") + for k, v := range *filterMap { libpodFilters = append(libpodFilters, fmt.Sprintf("%s=%s", k, v[0])) } } diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index 89a4a451f..4dc8740e2 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -44,13 +44,9 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { func Pods(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) - decoder := r.Context().Value("decoder").(*schema.Decoder) - query := struct { - Filters map[string][]string `schema:"filters"` - }{ - // override any golang type defaults - } - if err := decoder.Decode(&query, r.URL.Query()); err != nil { + + filterMap, err := util.PrepareFilters(r) + if err != nil { utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) return @@ -58,7 +54,7 @@ func Pods(w http.ResponseWriter, r *http.Request) { containerEngine := abi.ContainerEngine{Libpod: runtime} podPSOptions := entities.PodPSOptions{ - Filters: query.Filters, + Filters: *filterMap, } pods, err := containerEngine.PodPs(r.Context(), podPSOptions) if err != nil { diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go index f5eaf6f6d..736203171 100644 --- a/pkg/api/handlers/types.go +++ b/pkg/api/handlers/types.go @@ -28,10 +28,6 @@ type ContainerConfig struct { dockerContainer.Config } -type LibpodImagesLoadReport struct { - ID string `json:"id"` -} - type LibpodImagesPullReport struct { entities.ImagePullReport } diff --git a/pkg/api/handlers/types/types.go b/pkg/api/handlers/types/types.go new file mode 100644 index 000000000..71165364f --- /dev/null +++ b/pkg/api/handlers/types/types.go @@ -0,0 +1,23 @@ +package types + +import ( + "github.com/containers/podman/v3/pkg/domain/entities" +) + +// 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. + Errors []string +} + +// HistoryResponse provides details on image layers +type HistoryResponse struct { + ID string `json:"Id"` + Created int64 + CreatedBy string + Tags []string + Size int64 + Comment string +} diff --git a/pkg/api/handlers/utils/images.go b/pkg/api/handlers/utils/images.go index 743629db8..da3c9e985 100644 --- a/pkg/api/handlers/utils/images.go +++ b/pkg/api/handlers/utils/images.go @@ -11,6 +11,7 @@ import ( "github.com/containers/image/v5/types" "github.com/containers/podman/v3/libpod" "github.com/containers/podman/v3/libpod/image" + "github.com/containers/podman/v3/pkg/util" "github.com/gorilla/schema" "github.com/pkg/errors" ) @@ -58,13 +59,17 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) { runtime := r.Context().Value("runtime").(*libpod.Runtime) query := struct { All bool - Filters map[string][]string `schema:"filters"` Digests bool Filter string // Docker 1.24 compatibility }{ // This is where you can override the golang default value for one of fields } + filterMap, err := util.PrepareFilters(r) + if err != nil { + return nil, err + } + if err := decoder.Decode(&query, r.URL.Query()); err != nil { return nil, err } @@ -72,12 +77,9 @@ func GetImages(w http.ResponseWriter, r *http.Request) ([]*image.Image, error) { if _, found := r.URL.Query()["digests"]; found && query.Digests { UnSupportedParameter("digests") } - var ( - images []*image.Image - err error - ) + var images []*image.Image - queryFilters := query.Filters + queryFilters := *filterMap if !IsLibpodRequest(r) && len(query.Filter) > 0 { // Docker 1.24 compatibility if queryFilters == nil { queryFilters = make(map[string][]string) |