Skip to content

Commit

Permalink
network: add support for podman network update and --network-dns-server
Browse files Browse the repository at this point in the history
* Add support for `podman network update <>`

```console
network update

Description:
  update networks for containers and pods

Usage:
  podman network update [options] NAME

Examples:
  podman network update podman1

Options:
      --dns-add stringArray      add network level nameservers
      --dns-drop stringArray   remove network level nameservers
```

* Add support for `--network-dns-server` to `podman network create`

Extends podman to support recently added features in `netavark` and
`aardvark-dns`

* containers/netavark#497
* containers/aardvark-dns#252
* containers/netavark#503

[NO NEW TESTS NEEDED]
[NO TESTS NEEDED]

Signed-off-by: Aditya R <arajan@redhat.com>
  • Loading branch information
flouthoc committed Jan 12, 2023
1 parent 8a0d25f commit 9d8405b
Show file tree
Hide file tree
Showing 16 changed files with 322 additions and 17 deletions.
18 changes: 11 additions & 7 deletions cmd/podman/networks/create.go
Expand Up @@ -80,6 +80,9 @@ func networkCreateFlags(cmd *cobra.Command) {
flags.BoolVar(&networkCreateOptions.DisableDNS, "disable-dns", false, "disable dns plugin")

flags.BoolVar(&networkCreateOptions.IgnoreIfExists, "ignore", false, "Don't fail if network already exists")
dnsserverFlagName := "dns"
flags.StringArrayVar(&networkCreateOptions.NetworkDNSServers, dnsserverFlagName, nil, "DNS servers this network will use")
_ = cmd.RegisterFlagCompletionFunc(dnsserverFlagName, completion.AutocompleteNone)
}
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Expand Down Expand Up @@ -107,13 +110,14 @@ func networkCreate(cmd *cobra.Command, args []string) error {
}

network := types.Network{
Name: name,
Driver: networkCreateOptions.Driver,
Options: networkCreateOptions.Options,
Labels: networkCreateOptions.Labels,
IPv6Enabled: networkCreateOptions.IPv6,
DNSEnabled: !networkCreateOptions.DisableDNS,
Internal: networkCreateOptions.Internal,
Name: name,
Driver: networkCreateOptions.Driver,
Options: networkCreateOptions.Options,
Labels: networkCreateOptions.Labels,
IPv6Enabled: networkCreateOptions.IPv6,
DNSEnabled: !networkCreateOptions.DisableDNS,
NetworkDNSServers: networkCreateOptions.NetworkDNSServers,
Internal: networkCreateOptions.Internal,
}

if cmd.Flags().Changed(ipamDriverFlagName) {
Expand Down
57 changes: 57 additions & 0 deletions cmd/podman/networks/update.go
@@ -0,0 +1,57 @@
package network

import (
"fmt"

"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v4/cmd/podman/common"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/spf13/cobra"
)

var (
networkUpdateDescription = `Update an existing podman network`
networkUpdateCommand = &cobra.Command{
Use: "update [options] NETWORK",
Short: "update an existing podman network",
Long: networkUpdateDescription,
RunE: networkUpdate,
Args: cobra.ExactArgs(1),
ValidArgsFunction: common.AutocompleteNetworks,
Example: `podman network update podman1`,
}
)

var (
networkUpdateOptions entities.NetworkUpdateOptions
)

func networkUpdateFlags(cmd *cobra.Command) {
flags := cmd.Flags()

addDNSServerFlagName := "dns-add"
flags.StringArrayVar(&networkUpdateOptions.AddDNSServers, addDNSServerFlagName, nil, "add network level nameservers")
removeDNSServerFlagName := "dns-drop"
flags.StringArrayVar(&networkUpdateOptions.RemoveDNSServers, removeDNSServerFlagName, nil, "remove network level nameservers")
_ = cmd.RegisterFlagCompletionFunc(addDNSServerFlagName, completion.AutocompleteNone)
_ = cmd.RegisterFlagCompletionFunc(removeDNSServerFlagName, completion.AutocompleteNone)
}
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: networkUpdateCommand,
Parent: networkCmd,
})
networkUpdateFlags(networkUpdateCommand)
}

func networkUpdate(cmd *cobra.Command, args []string) error {
name := args[0]

err := registry.ContainerEngine().NetworkUpdate(registry.Context(), name, networkUpdateOptions)
if err != nil {
return err
}
fmt.Printf("%s", name)
return nil
}
4 changes: 4 additions & 0 deletions docs/source/markdown/podman-network-create.1.md
Expand Up @@ -24,6 +24,10 @@ release because it is used as a special network mode in **podman run/create --ne
Disables the DNS plugin for this network which if enabled, can perform container to container name
resolution.

#### **--dns**=*ip*

Set network-scoped DNS resolver/nameserver for containers in this network. If not set, the host servers from `/etc/resolv.conf` will be used. It can be overwritten on the container level with the `podman run/create --dns` option. This option can be specified multiple times to set more than one IP.

#### **--driver**, **-d**

Driver to manage the network. Currently `bridge`, `macvlan` and `ipvlan` are supported. Defaults to `bridge`.
Expand Down
37 changes: 37 additions & 0 deletions docs/source/markdown/podman-network-update.1.md
@@ -0,0 +1,37 @@
% podman-network-update 1

## NAME
podman\-network\-update - Update an existing podman network

## SYNOPSIS
**podman network update** [*options*] *network*

## DESCRIPTION
Allow changes to existing container networks. At present, only changes to the DNS servers in use by a network is supported.

NOTE: Only supported with the netavark network backend.


## OPTIONS
#### **--dns-add**

Accepts array of DNS resolvers and add it to the existing list of resolvers configured for a network.

#### **--dns-drop**

Accepts array of DNS resolvers and removes them from the existing list of resolvers configured for a network.

## EXAMPLE

Update a network
```
$ podman network update network1 --dns-add 8.8.8.8,1.1.1.1
podman2
```

Update a network and add/remove dns servers
```
$ podman network update network1 --dns-drop 8.8.8.8 --dns-add 3.3.3.3
```
## SEE ALSO
**[podman(1)](podman.1.md)**, **[podman-network(1)](podman-network.1.md)**, **[podman-network-inspect(1)](podman-network-inspect.1.md)**, **[podman-network-ls(1)](podman-network-ls.1.md)**
1 change: 1 addition & 0 deletions docs/source/markdown/podman-network.1.md
Expand Up @@ -32,6 +32,7 @@ so networks have to be created again after a backend change.
| prune | [podman-network-prune(1)](podman-network-prune.1.md) | Remove all unused networks |
| reload | [podman-network-reload(1)](podman-network-reload.1.md) | Reload network configuration for containers |
| rm | [podman-network-rm(1)](podman-network-rm.1.md) | Remove one or more networks |
| update | [podman-network-upate(1)](podman-network-update.1.md) | Update an existing Podman network |

## SEE ALSO
**[podman(1)](podman.1.md)**, **[containers.conf(5)](https://github.com/containers/common/blob/main/docs/containers.conf.5.md)**
22 changes: 21 additions & 1 deletion pkg/api/handlers/libpod/networks.go
Expand Up @@ -27,7 +27,7 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
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, fmt.Errorf("failed to decode request JSON payload: %w", err))
utils.Error(w, http.StatusInternalServerError, fmt.Errorf("failed to decode JSON request payload: %w", err))
return
}

Expand All @@ -53,6 +53,26 @@ func CreateNetwork(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, report)
}

func UpdateNetwork(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
ic := abi.ContainerEngine{Libpod: runtime}

networkUpdateOptions := entities.NetworkUpdateOptions{}
if err := json.NewDecoder(r.Body).Decode(&networkUpdateOptions); err != nil {
utils.Error(w, http.StatusBadRequest, fmt.Errorf("failed to decode request JSON payload: %w", err))
return
}

name := utils.GetName(r)

err := ic.NetworkUpdate(r.Context(), name, networkUpdateOptions)
if err != nil {
utils.Error(w, http.StatusInternalServerError, err)
}

utils.WriteResponse(w, http.StatusNoContent, nil)
}

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)
Expand Down
4 changes: 4 additions & 0 deletions pkg/api/handlers/swagger/models.go
Expand Up @@ -44,3 +44,7 @@ type networkDisconnectRequest types.NetworkDisconnect
// Network connect
// swagger:model
type networkConnectRequestLibpod entities.NetworkConnectOptions

// Network update
// swagger:model
type networkUpdateRequestLibpod entities.NetworkUpdateOptions
27 changes: 27 additions & 0 deletions pkg/api/server/register_networks.go
Expand Up @@ -234,6 +234,33 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/internalError"
r.HandleFunc(VersionedPath("/libpod/networks/{name}"), s.APIHandler(libpod.RemoveNetwork)).Methods(http.MethodDelete)
// swagger:operation POST /libpod/networks/{name}/update libpod NetworkUpdateLibpod
// ---
// tags:
// - networks
// summary: Update exisiting podman network
// description: Update exisiting podman network
// produces:
// - application/json
// parameters:
// - in: path
// name: name
// type: string
// required: true
// description: the name or ID of the network
// - in: body
// name: update
// description: attributes for updating a netavark network
// schema:
// $ref: "#/definitions/networkUpdateRequestLibpod"
// responses:
// 200:
// description: OK
// 400:
// $ref: "#/responses/badParamError"
// 500:
// $ref: "#/responses/internalError"
r.HandleFunc(VersionedPath("/libpod/networks/{name}/update"), s.APIHandler(libpod.UpdateNetwork)).Methods(http.MethodPost)
// swagger:operation GET /libpod/networks/{name}/exists libpod NetworkExistsLibpod
// ---
// tags:
Expand Down
19 changes: 19 additions & 0 deletions pkg/bindings/network/network.go
Expand Up @@ -50,6 +50,25 @@ func CreateWithOptions(ctx context.Context, network *types.Network, extraCreateO
return report, response.Process(&report)
}

// Updates an existing netavark network config
func Update(ctx context.Context, netNameOrID string, options *UpdateOptions) error {
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
}
networkConfig, err := jsoniter.MarshalToString(options)
if err != nil {
return err
}
reader := strings.NewReader(networkConfig)
response, err := conn.DoRequest(ctx, reader, http.MethodPost, "/networks/%s/update", nil, nil, netNameOrID)
if err != nil {
return err
}
defer response.Body.Close()
return response.Process(nil)
}

// Inspect returns information about a network configuration
func Inspect(ctx context.Context, nameOrID string, _ *InspectOptions) (types.Network, error) {
var net types.Network
Expand Down
8 changes: 8 additions & 0 deletions pkg/bindings/network/types.go
Expand Up @@ -58,6 +58,14 @@ type ListOptions struct {
Filters map[string][]string
}

// NetworkUpdateOptions describes options to update a network
//
//go:generate go run ../generator/generator.go UpdateOptions
type UpdateOptions struct {
AddDNSServers []string `json:"adddnsservers"`
RemoveDNSServers []string `json:"removednsservers"`
}

// DisconnectOptions are optional options for disconnecting
// containers from a network
//
Expand Down
48 changes: 48 additions & 0 deletions pkg/bindings/network/types_update_options.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pkg/domain/entities/engine_container.go
Expand Up @@ -64,6 +64,7 @@ type ContainerEngine interface { //nolint:interfacebloat
KubeApply(ctx context.Context, body io.Reader, opts ApplyOptions) error
NetworkConnect(ctx context.Context, networkname string, options NetworkConnectOptions) error
NetworkCreate(ctx context.Context, network types.Network, createOptions *types.NetworkCreateOptions) (*types.Network, error)
NetworkUpdate(ctx context.Context, networkname string, options NetworkUpdateOptions) error
NetworkDisconnect(ctx context.Context, networkname string, options NetworkDisconnectOptions) error
NetworkExists(ctx context.Context, networkname string) (*BoolReport, error)
NetworkInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]types.Network, []error, error)
Expand Down
25 changes: 16 additions & 9 deletions pkg/domain/entities/network.go
Expand Up @@ -41,21 +41,28 @@ type NetworkRmReport struct {

// NetworkCreateOptions describes options to create a network
type NetworkCreateOptions struct {
DisableDNS bool
Driver string
Gateways []net.IP
Internal bool
Labels map[string]string
MacVLAN string
Ranges []string
Subnets []string
IPv6 bool
DisableDNS bool
Driver string
Gateways []net.IP
Internal bool
Labels map[string]string
MacVLAN string
NetworkDNSServers []string
Ranges []string
Subnets []string
IPv6 bool
// Mapping of driver options and values.
Options map[string]string
// IgnoreIfExists if true, do not fail if the network already exists
IgnoreIfExists bool
}

// NetworkUpdateOptions describes options to update a network
type NetworkUpdateOptions struct {
AddDNSServers []string `json:"adddnsservers"`
RemoveDNSServers []string `json:"removednsservers"`
}

// NetworkCreateReport describes a created network for the cli
type NetworkCreateReport struct {
Name string
Expand Down
11 changes: 11 additions & 0 deletions pkg/domain/infra/abi/network.go
Expand Up @@ -13,6 +13,17 @@ import (
"github.com/containers/podman/v4/pkg/domain/entities"
)

func (ic *ContainerEngine) NetworkUpdate(ctx context.Context, netName string, options entities.NetworkUpdateOptions) error {
var networkUpdateOptions types.NetworkUpdateOptions
networkUpdateOptions.AddDNSServers = options.AddDNSServers
networkUpdateOptions.RemoveDNSServers = options.RemoveDNSServers
err := ic.Libpod.Network().NetworkUpdate(netName, networkUpdateOptions)
if err != nil {
return err
}
return nil
}

func (ic *ContainerEngine) NetworkList(ctx context.Context, options entities.NetworkListOptions) ([]types.Network, error) {
// dangling filter is not provided by netutil
var wantDangling bool
Expand Down
5 changes: 5 additions & 0 deletions pkg/domain/infra/tunnel/network.go
Expand Up @@ -12,6 +12,11 @@ import (
"github.com/containers/podman/v4/pkg/errorhandling"
)

func (ic *ContainerEngine) NetworkUpdate(ctx context.Context, netName string, opts entities.NetworkUpdateOptions) error {
options := new(network.UpdateOptions).WithAddDNSServers(opts.AddDNSServers).WithRemoveDNSServers(opts.RemoveDNSServers)
return network.Update(ic.ClientCtx, netName, options)
}

func (ic *ContainerEngine) NetworkList(ctx context.Context, opts entities.NetworkListOptions) ([]types.Network, error) {
options := new(network.ListOptions).WithFilters(opts.Filters)
return network.List(ic.ClientCtx, options)
Expand Down

0 comments on commit 9d8405b

Please sign in to comment.