summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrent Baude <bbaude@redhat.com>2020-05-12 13:04:10 -0500
committerBrent Baude <bbaude@redhat.com>2020-05-12 13:23:43 -0500
commitcf502b99feda401ced410fbcfd1a3a2663c7a559 (patch)
tree408c4ae509fc8563da7ae1ac3f8d141cfd96e695
parent5b4e91db73a80f31f67b7c28832527e64b074b74 (diff)
downloadpodman-cf502b99feda401ced410fbcfd1a3a2663c7a559.tar.gz
podman-cf502b99feda401ced410fbcfd1a3a2663c7a559.tar.bz2
podman-cf502b99feda401ced410fbcfd1a3a2663c7a559.zip
enable podman v2 networking for remote client
Signed-off-by: Brent Baude <bbaude@redhat.com>
-rw-r--r--cmd/podman/networks/create.go2
-rw-r--r--cmd/podman/networks/inspect.go2
-rw-r--r--cmd/podman/networks/list.go14
-rw-r--r--cmd/podman/networks/network.go2
-rw-r--r--cmd/podman/networks/rm.go2
-rw-r--r--pkg/api/handlers/libpod/containers_create.go3
-rw-r--r--pkg/api/handlers/libpod/networks.go68
-rw-r--r--pkg/api/handlers/libpod/swagger.go28
-rw-r--r--pkg/api/server/register_networks.go100
-rw-r--r--pkg/api/server/server.go1
-rw-r--r--pkg/api/server/swagger.go9
-rw-r--r--pkg/api/tags.yaml6
-rw-r--r--pkg/bindings/network/network.go62
-rw-r--r--pkg/domain/entities/network.go1
-rw-r--r--pkg/domain/infra/tunnel/network.go27
15 files changed, 273 insertions, 54 deletions
diff --git a/cmd/podman/networks/create.go b/cmd/podman/networks/create.go
index 2bb75ea9e..10973e6bf 100644
--- a/cmd/podman/networks/create.go
+++ b/cmd/podman/networks/create.go
@@ -46,7 +46,7 @@ func networkCreateFlags(flags *pflag.FlagSet) {
}
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: networkCreateCommand,
Parent: networkCmd,
})
diff --git a/cmd/podman/networks/inspect.go b/cmd/podman/networks/inspect.go
index 0bc73579a..60cede894 100644
--- a/cmd/podman/networks/inspect.go
+++ b/cmd/podman/networks/inspect.go
@@ -26,7 +26,7 @@ var (
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: networkinspectCommand,
Parent: networkCmd,
})
diff --git a/cmd/podman/networks/list.go b/cmd/podman/networks/list.go
index e27062255..1c0528e5c 100644
--- a/cmd/podman/networks/list.go
+++ b/cmd/podman/networks/list.go
@@ -4,13 +4,12 @@ import (
"encoding/json"
"fmt"
"html/template"
- "io"
"os"
"strings"
-
- "github.com/containers/libpod/cmd/podman/validate"
+ "text/tabwriter"
"github.com/containers/libpod/cmd/podman/registry"
+ "github.com/containers/libpod/cmd/podman/validate"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/network"
"github.com/spf13/cobra"
@@ -47,7 +46,7 @@ func networkListFlags(flags *pflag.FlagSet) {
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: networklistCommand,
Parent: networkCmd,
})
@@ -57,7 +56,6 @@ func init() {
func networkList(cmd *cobra.Command, args []string) error {
var (
- w io.Writer = os.Stdout
nlprs []NetworkListPrintReports
)
@@ -95,13 +93,11 @@ func networkList(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
+ w := tabwriter.NewWriter(os.Stdout, 8, 2, 2, ' ', 0)
if err := tmpl.Execute(w, nlprs); err != nil {
return err
}
- if flusher, ok := w.(interface{ Flush() error }); ok {
- return flusher.Flush()
- }
- return nil
+ return w.Flush()
}
func quietOut(responses []*entities.NetworkListReport) error {
diff --git a/cmd/podman/networks/network.go b/cmd/podman/networks/network.go
index 56dd390ea..7f38cd2cd 100644
--- a/cmd/podman/networks/network.go
+++ b/cmd/podman/networks/network.go
@@ -20,7 +20,7 @@ var (
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: networkCmd,
})
}
diff --git a/cmd/podman/networks/rm.go b/cmd/podman/networks/rm.go
index dc1eb9909..34d57f6ef 100644
--- a/cmd/podman/networks/rm.go
+++ b/cmd/podman/networks/rm.go
@@ -35,7 +35,7 @@ func networkRmFlags(flags *pflag.FlagSet) {
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
- Mode: []entities.EngineMode{entities.ABIMode},
+ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: networkrmCommand,
Parent: networkCmd,
})
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
index 40b6cacdb..71f440bce 100644
--- a/pkg/api/handlers/libpod/containers_create.go
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -5,10 +5,9 @@ import (
"encoding/json"
"net/http"
- "github.com/containers/libpod/pkg/domain/entities"
-
"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/specgen"
"github.com/containers/libpod/pkg/specgen/generate"
"github.com/pkg/errors"
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index e8a92e93e..7de285e5e 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -1,39 +1,59 @@
package libpod
import (
+ "encoding/json"
"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/containers/libpod/pkg/network"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)
-func CreateNetwork(w http.ResponseWriter, r *http.Request) {}
-func ListNetworks(w http.ResponseWriter, r *http.Request) {
+func CreateNetwork(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
- config, err := runtime.GetConfig()
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ options := entities.NetworkCreateOptions{}
+ if err := json.NewDecoder(r.Body).Decode(&options); err != nil {
+ utils.Error(w, "unable to marshall input", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ return
+ }
+ query := struct {
+ Name string `schema:"name"`
+ }{
+ // override any golang type defaults
+ }
+ 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
+ }
+ ic := abi.ContainerEngine{Libpod: runtime}
+ report, err := ic.NetworkCreate(r.Context(), query.Name, options)
if err != nil {
utils.InternalServerError(w, err)
return
}
- configDir := config.Network.NetworkConfigDir
- if len(configDir) < 1 {
- configDir = network.CNIConfigDir
- }
- networks, err := network.LoadCNIConfsFromDir(configDir)
+ utils.WriteResponse(w, http.StatusOK, report)
+
+}
+func ListNetworks(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ options := entities.NetworkListOptions{}
+ ic := abi.ContainerEngine{Libpod: runtime}
+ reports, err := ic.NetworkList(r.Context(), options)
if err != nil {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusOK, networks)
+ utils.WriteResponse(w, http.StatusOK, reports)
}
func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
- // 200 ok
- // 404 no such
- // 500 internal
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
Force bool `schema:"force"`
@@ -46,22 +66,30 @@ func RemoveNetwork(w http.ResponseWriter, r *http.Request) {
return
}
name := utils.GetName(r)
- if err := network.RemoveNetwork(name); err != nil {
+
+ options := entities.NetworkRmOptions{
+ Force: query.Force,
+ }
+ ic := abi.ContainerEngine{Libpod: runtime}
+ reports, err := ic.NetworkRm(r.Context(), []string{name}, options)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ if reports[0].Err != nil {
// If the network cannot be found, we return a 404.
if errors.Cause(err) == network.ErrNetworkNotFound {
utils.Error(w, "Something went wrong", http.StatusNotFound, err)
return
}
- utils.InternalServerError(w, err)
- return
}
- utils.WriteResponse(w, http.StatusOK, "")
+ utils.WriteResponse(w, http.StatusOK, reports)
}
func InspectNetwork(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"`
}{
// override any golang type defaults
}
@@ -71,7 +99,9 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
return
}
name := utils.GetName(r)
- n, err := network.InspectNetwork(name)
+ options := entities.NetworkInspectOptions{}
+ ic := abi.ContainerEngine{Libpod: runtime}
+ reports, err := ic.NetworkInspect(r.Context(), []string{name}, options)
if err != nil {
// If the network cannot be found, we return a 404.
if errors.Cause(err) == network.ErrNetworkNotFound {
@@ -81,5 +111,5 @@ func InspectNetwork(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}
- utils.WriteResponse(w, http.StatusOK, n)
+ utils.WriteResponse(w, http.StatusOK, reports)
}
diff --git a/pkg/api/handlers/libpod/swagger.go b/pkg/api/handlers/libpod/swagger.go
index 46426eb6b..057fbfb41 100644
--- a/pkg/api/handlers/libpod/swagger.go
+++ b/pkg/api/handlers/libpod/swagger.go
@@ -91,6 +91,34 @@ type swagInfoResponse struct {
Body define.Info
}
+// Network rm
+// swagger:response NetworkRmReport
+type swagNetworkRmReport struct {
+ // in:body
+ Body entities.NetworkRmReport
+}
+
+// Network inspect
+// swagger:response NetworkInspectReport
+type swagNetworkInspectReport struct {
+ // in:body
+ Body []entities.NetworkInspectReport
+}
+
+// Network list
+// swagger:response NetworkListReport
+type swagNetworkListReport struct {
+ // in:body
+ Body []entities.NetworkListReport
+}
+
+// Network create
+// swagger:response NetworkCreateReport
+type swagNetworkCreateReport struct {
+ // in:body
+ Body entities.NetworkCreateReport
+}
+
func ServeSwagger(w http.ResponseWriter, r *http.Request) {
path := DefaultPodmanSwaggerSpec
if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found {
diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go
new file mode 100644
index 000000000..b1189c1f4
--- /dev/null
+++ b/pkg/api/server/register_networks.go
@@ -0,0 +1,100 @@
+package server
+
+import (
+ "net/http"
+
+ "github.com/containers/libpod/pkg/api/handlers/libpod"
+ "github.com/gorilla/mux"
+)
+
+func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
+ // swagger:operation DELETE /libpod/networks/{name} libpod libpodRemoveNetwork
+ // ---
+ // tags:
+ // - networks
+ // summary: Remove a network
+ // description: Remove a CNI configured network
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name of the network
+ // - in: query
+ // name: Force
+ // type: boolean
+ // description: remove containers associated with network
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/NetworkRmReport"
+ // 404:
+ // $ref: "#/responses/NoSuchNetwork"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/networks/{name}"), s.APIHandler(libpod.RemoveNetwork)).Methods(http.MethodDelete)
+ // swagger:operation GET /libpod/networks/{name}/json libpod libpodInspectNetwork
+ // ---
+ // tags:
+ // - networks
+ // summary: Inspect a network
+ // description: Display low level configuration for a CNI network
+ // parameters:
+ // - in: path
+ // name: name
+ // type: string
+ // required: true
+ // description: the name of the network
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/NetworkInspectReport"
+ // 404:
+ // $ref: "#/responses/NoSuchNetwork"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/networks/{name}/json"), s.APIHandler(libpod.InspectNetwork)).Methods(http.MethodGet)
+ // swagger:operation GET /libpod/networks/json libpod libpodListNetwork
+ // ---
+ // tags:
+ // - networks
+ // summary: List networks
+ // description: Display summary of network configurations
+ // produces:
+ // - application/json
+ // responses:
+ // 200:
+ // $ref: "#/responses/NetworkListReport"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/networks/json"), s.APIHandler(libpod.ListNetworks)).Methods(http.MethodGet)
+ // swagger:operation POST /libpod/networks/create libpod libpodCreateNetwork
+ // ---
+ // tags:
+ // - networks
+ // summary: Create network
+ // description: Create a new CNI network configuration
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: query
+ // name: name
+ // type: string
+ // description: optional name for new network
+ // - in: body
+ // name: create
+ // description: attributes for creating a container
+ // schema:
+ // $ref: "#/definitions/NetworkCreateOptions"
+ // responses:
+ // 200:
+ // $ref: "#/responses/NetworkCreateReport"
+ // 400:
+ // $ref: "#/responses/BadParamError"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/networks/create"), s.APIHandler(libpod.CreateNetwork)).Methods(http.MethodPost)
+ return nil
+}
diff --git a/pkg/api/server/server.go b/pkg/api/server/server.go
index a6c5d8e1e..d39528f45 100644
--- a/pkg/api/server/server.go
+++ b/pkg/api/server/server.go
@@ -104,6 +104,7 @@ func newServer(runtime *libpod.Runtime, duration time.Duration, listener *net.Li
server.registerInfoHandlers,
server.registerManifestHandlers,
server.registerMonitorHandlers,
+ server.registerNetworkHandlers,
server.registerPingHandlers,
server.registerPlayHandlers,
server.registerPluginsHandlers,
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index 7776d0e79..ebd99ba27 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -24,6 +24,15 @@ type swagErrNoSuchContainer struct {
}
}
+// No such network
+// swagger:response NoSuchNetwork
+type swagErrNoSuchNetwork struct {
+ // in:body
+ Body struct {
+ entities.ErrorModel
+ }
+}
+
// No such exec instance
// swagger:response NoSuchExecInstance
type swagErrNoSuchExecInstance struct {
diff --git a/pkg/api/tags.yaml b/pkg/api/tags.yaml
index 5b5d9f5bb..1ffb5e940 100644
--- a/pkg/api/tags.yaml
+++ b/pkg/api/tags.yaml
@@ -5,9 +5,11 @@ tags:
description: Actions related to exec
- name: images
description: Actions related to images
- - name: pods
- description: Actions related to manifests
- name: manifests
+ description: Actions related to manifests
+ - name: networks
+ description: Actions related to networks
+ - name: pods
description: Actions related to pods
- name: volumes
description: Actions related to volumes
diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go
index c95b22953..7bba4f478 100644
--- a/pkg/bindings/network/network.go
+++ b/pkg/bindings/network/network.go
@@ -3,40 +3,76 @@ package network
import (
"context"
"net/http"
+ "net/url"
+ "strconv"
+ "strings"
- "github.com/containernetworking/cni/libcni"
"github.com/containers/libpod/pkg/bindings"
+ "github.com/containers/libpod/pkg/domain/entities"
+ jsoniter "github.com/json-iterator/go"
)
-func Create() {}
-func Inspect(ctx context.Context, nameOrID string) (map[string]interface{}, error) {
+// Create makes a new CNI network configuration
+func Create(ctx context.Context, options entities.NetworkCreateOptions, name *string) (*entities.NetworkCreateReport, error) {
+ var report entities.NetworkCreateReport
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+ params := url.Values{}
+ if name != nil {
+ params.Set("name", *name)
+ }
+ networkConfig, err := jsoniter.MarshalToString(options)
+ if err != nil {
+ return nil, err
+ }
+ stringReader := strings.NewReader(networkConfig)
+ response, err := conn.DoRequest(stringReader, http.MethodPost, "/networks/create", params)
+ if err != nil {
+ return nil, err
+ }
+ return &report, response.Process(&report)
+}
+
+// Inspect returns low level information about a CNI network configuration
+func Inspect(ctx context.Context, nameOrID string) ([]entities.NetworkInspectReport, error) {
+ var reports []entities.NetworkInspectReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return nil, err
}
- n := make(map[string]interface{})
response, err := conn.DoRequest(nil, http.MethodGet, "/networks/%s/json", nil, nameOrID)
if err != nil {
- return n, err
+ return nil, err
}
- return n, response.Process(&n)
+ return reports, response.Process(&reports)
}
-func Remove(ctx context.Context, nameOrID string) error {
+// Remove deletes a defined CNI network configuration by name. The optional force boolean
+// will remove all containers associated with the network when set to true. A slice
+// of NetworkRemoveReports are returned.
+func Remove(ctx context.Context, nameOrID string, force *bool) ([]*entities.NetworkRmReport, error) {
+ var reports []*entities.NetworkRmReport
conn, err := bindings.GetClient(ctx)
if err != nil {
- return err
+ return nil, err
}
- response, err := conn.DoRequest(nil, http.MethodDelete, "/networks/%s", nil, nameOrID)
+ params := url.Values{}
+ if force != nil {
+ params.Set("size", strconv.FormatBool(*force))
+ }
+ response, err := conn.DoRequest(nil, http.MethodDelete, "/networks/%s", params, nameOrID)
if err != nil {
- return err
+ return nil, err
}
- return response.Process(nil)
+ return reports, response.Process(&reports)
}
-func List(ctx context.Context) ([]*libcni.NetworkConfigList, error) {
+// List returns a summary of all CNI network configurations
+func List(ctx context.Context) ([]*entities.NetworkListReport, error) {
var (
- netList []*libcni.NetworkConfigList
+ netList []*entities.NetworkListReport
)
conn, err := bindings.GetClient(ctx)
if err != nil {
diff --git a/pkg/domain/entities/network.go b/pkg/domain/entities/network.go
index cffd40899..d001553e0 100644
--- a/pkg/domain/entities/network.go
+++ b/pkg/domain/entities/network.go
@@ -36,6 +36,7 @@ type NetworkRmReport struct {
}
// NetworkCreateOptions describes options to create a network
+// swagger:model NetworkCreateOptions
type NetworkCreateOptions struct {
DisableDNS bool
Driver string
diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go
index 4ff72dcfc..7725d8257 100644
--- a/pkg/domain/infra/tunnel/network.go
+++ b/pkg/domain/infra/tunnel/network.go
@@ -2,22 +2,39 @@ package tunnel
import (
"context"
- "errors"
+ "github.com/containers/libpod/pkg/bindings/network"
"github.com/containers/libpod/pkg/domain/entities"
)
func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.NetworkListOptions) ([]*entities.NetworkListReport, error) {
- return nil, errors.New("not implemented")
+ return network.List(ic.ClientCxt)
}
func (ic *ContainerEngine) NetworkInspect(ctx context.Context, namesOrIds []string, options entities.NetworkInspectOptions) ([]entities.NetworkInspectReport, error) {
- return nil, errors.New("not implemented")
+ var reports []entities.NetworkInspectReport
+ for _, name := range namesOrIds {
+ report, err := network.Inspect(ic.ClientCxt, name)
+ if err != nil {
+ return nil, err
+ }
+ reports = append(reports, report...)
+ }
+ return reports, nil
}
+
func (ic *ContainerEngine) NetworkRm(ctx context.Context, namesOrIds []string, options entities.NetworkRmOptions) ([]*entities.NetworkRmReport, error) {
- return nil, errors.New("not implemented")
+ var reports []*entities.NetworkRmReport
+ for _, name := range namesOrIds {
+ report, err := network.Remove(ic.ClientCxt, name, &options.Force)
+ if err != nil {
+ report[0].Err = err
+ }
+ reports = append(reports, report...)
+ }
+ return reports, nil
}
func (ic *ContainerEngine) NetworkCreate(ctx context.Context, name string, options entities.NetworkCreateOptions) (*entities.NetworkCreateReport, error) {
- return nil, errors.New("not implemented")
+ return network.Create(ic.ClientCxt, options, &name)
}