diff options
author | Jhon Honce <jhonce@redhat.com> | 2022-02-09 11:17:14 -0700 |
---|---|---|
committer | Jhon Honce <jhonce@redhat.com> | 2022-02-09 14:22:42 -0700 |
commit | c4676c571910d8b27ead751e35cbd877db61f8bd (patch) | |
tree | 5f921f64cb55969a87a48bedf445c8d58fe8cde8 | |
parent | eb0a0db318a988af9ed70f3cc3a68f3b2bf2aa93 (diff) | |
download | podman-c4676c571910d8b27ead751e35cbd877db61f8bd.tar.gz podman-c4676c571910d8b27ead751e35cbd877db61f8bd.tar.bz2 podman-c4676c571910d8b27ead751e35cbd877db61f8bd.zip |
Add version guard to libpod API endpoints
* Ensure meaningful behaviour when called with /v3.x.x semantics
* Change return code to 409 from 500 when client attempts to use an
existing network name
* Update API bats test runner to support /v4.0.0 endpoints by default
Signed-off-by: Jhon Honce <jhonce@redhat.com>
-rw-r--r-- | pkg/api/handlers/libpod/networks.go | 66 | ||||
-rw-r--r-- | pkg/bindings/test/networks_test.go | 4 | ||||
-rw-r--r-- | test/apiv2/35-networks.at | 5 | ||||
-rwxr-xr-x | test/apiv2/test-apiv2 | 10 |
4 files changed, 60 insertions, 25 deletions
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go index 71d46ce70..16f499d4c 100644 --- a/pkg/api/handlers/libpod/networks.go +++ b/pkg/api/handlers/libpod/networks.go @@ -17,22 +17,37 @@ import ( ) func CreateNetwork(w http.ResponseWriter, r *http.Request) { + if v, err := utils.SupportedVersion(r, ">=4.0.0"); err != nil { + utils.BadRequest(w, "version", v.String(), err) + return + } + runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) network := types.Network{} if err := json.NewDecoder(r.Body).Decode(&network); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "decode body")) + utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to decode request JSON payload")) return } ic := abi.ContainerEngine{Libpod: runtime} report, err := ic.NetworkCreate(r.Context(), network) if err != nil { - utils.InternalServerError(w, err) + if errors.Is(err, types.ErrNetworkExists) { + utils.Error(w, http.StatusConflict, err) + } else { + utils.InternalServerError(w, err) + } return } utils.WriteResponse(w, http.StatusOK, report) } + func ListNetworks(w http.ResponseWriter, r *http.Request) { + if v, err := utils.SupportedVersion(r, ">=4.0.0"); err != nil { + utils.BadRequest(w, "version", v.String(), err) + return + } + runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) filterMap, err := util.PrepareFilters(r) if err != nil { @@ -54,6 +69,11 @@ func ListNetworks(w http.ResponseWriter, r *http.Request) { } func RemoveNetwork(w http.ResponseWriter, r *http.Request) { + if v, err := utils.SupportedVersion(r, ">=4.0.0"); err != nil { + utils.BadRequest(w, "version", v.String(), err) + return + } + runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) query := struct { @@ -87,21 +107,18 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) { utils.WriteResponse(w, http.StatusOK, reports) } +// InspectNetwork reports on given network's details func InspectNetwork(w http.ResponseWriter, r *http.Request) { - runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) - decoder := r.Context().Value(api.DecoderKey).(*schema.Decoder) - query := struct { - }{ - // override any golang type defaults - } - if err := decoder.Decode(&query, r.URL.Query()); err != nil { - utils.Error(w, http.StatusInternalServerError, - errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String())) + if v, err := utils.SupportedVersion(r, ">=4.0.0"); err != nil { + utils.BadRequest(w, "version", v.String(), err) return } + + runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) + ic := abi.ContainerEngine{Libpod: runtime} + name := utils.GetName(r) options := entities.InspectOptions{} - ic := abi.ContainerEngine{Libpod: runtime} reports, errs, err := ic.NetworkInspect(r.Context(), []string{name}, options) // If the network cannot be found, we return a 404. if len(errs) > 0 { @@ -117,14 +134,19 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) { // Connect adds a container to a network func Connect(w http.ResponseWriter, r *http.Request) { - runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) + if v, err := utils.SupportedVersion(r, ">=4.0.0"); err != nil { + utils.BadRequest(w, "version", v.String(), err) + return + } + runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) var netConnect entities.NetworkConnectOptions if err := json.NewDecoder(r.Body).Decode(&netConnect); err != nil { - utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()")) + utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "failed to decode request JSON payload")) return } name := utils.GetName(r) + err := runtime.ConnectContainerToNetwork(netConnect.Container, name, netConnect.PerNetworkOptions) if err != nil { if errors.Cause(err) == define.ErrNoSuchCtr { @@ -143,10 +165,15 @@ func Connect(w http.ResponseWriter, r *http.Request) { // ExistsNetwork check if a network exists func ExistsNetwork(w http.ResponseWriter, r *http.Request) { - runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) - name := utils.GetName(r) + if v, err := utils.SupportedVersion(r, ">=4.0.0"); err != nil { + utils.BadRequest(w, "version", v.String(), err) + return + } + runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) ic := abi.ContainerEngine{Libpod: runtime} + + name := utils.GetName(r) report, err := ic.NetworkExists(r.Context(), name) if err != nil { utils.Error(w, http.StatusInternalServerError, err) @@ -161,7 +188,13 @@ func ExistsNetwork(w http.ResponseWriter, r *http.Request) { // Prune removes unused networks func Prune(w http.ResponseWriter, r *http.Request) { + if v, err := utils.SupportedVersion(r, ">=4.0.0"); err != nil { + utils.BadRequest(w, "version", v.String(), err) + return + } + runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime) + ic := abi.ContainerEngine{Libpod: runtime} filterMap, err := util.PrepareFilters(r) if err != nil { @@ -172,7 +205,6 @@ func Prune(w http.ResponseWriter, r *http.Request) { pruneOptions := entities.NetworkPruneOptions{ Filters: *filterMap, } - ic := abi.ContainerEngine{Libpod: runtime} pruneReports, err := ic.NetworkPrune(r.Context(), pruneOptions) if err != nil { utils.Error(w, http.StatusInternalServerError, err) diff --git a/pkg/bindings/test/networks_test.go b/pkg/bindings/test/networks_test.go index ee2d6f472..137db71a3 100644 --- a/pkg/bindings/test/networks_test.go +++ b/pkg/bindings/test/networks_test.go @@ -80,7 +80,7 @@ var _ = Describe("Podman networks", func() { // Valid filter params => network should be pruned now. filters = map[string][]string{ - "until": {"5000000000"}, //June 11, 2128 + "until": {"5000000000"}, // June 11, 2128 } pruneResponse, err = network.Prune(connText, new(network.PruneOptions).WithFilters(filters)) Expect(err).To(BeNil()) @@ -105,7 +105,7 @@ var _ = Describe("Podman networks", func() { _, err = network.Create(connText, &net) Expect(err).ToNot(BeNil()) code, _ := bindings.CheckResponseCode(err) - Expect(code).To(BeNumerically("==", http.StatusInternalServerError)) + Expect(code).To(BeNumerically("==", http.StatusConflict)) }) It("inspect network", func() { diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at index 0e2389bd5..3502b89e0 100644 --- a/test/apiv2/35-networks.at +++ b/test/apiv2/35-networks.at @@ -8,7 +8,10 @@ t GET networks/non-existing-network 404 \ t POST libpod/networks/create name='"network1"' 200 \ .name=network1 \ - .created~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* \ + .created~[0-9]\\{4\\}-[0-9]\\{2\\}-[0-9]\\{2\\}.* + +t POST /v3.4.0/libpod/networks/create name='"bad_version"' 400 \ + .cause='given version is not supported' # --data '{"name":"network2","subnets":[{"subnet":"10.10.254.0/24"}],"Labels":{"abc":"val"}}' t POST libpod/networks/create name='"network2"' \ diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index 56280f04e..bd728e130 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -256,11 +256,11 @@ function t() { # If given path begins with /, use it as-is; otherwise prepend /version/ local url=http://$HOST:$PORT - if expr "$path" : "/" >/dev/null; then - url="$url$path" - else - url="$url/v1.40/$path" - fi + case "$path" in + /*) url="$url$path" ;; + libpod/*) url="$url/v4.0.0/$path" ;; + *) url="$url/v1.41/$path" ;; + esac # Log every action we do echo "-------------------------------------------------------------" >>$LOG |