Skip to content

Commit

Permalink
feature: allow --subnet=auto and let the docker runtime auto-choose a…
Browse files Browse the repository at this point in the history
… subnet (by creating/deleting a fake network)
  • Loading branch information
iwilltry42 committed Apr 14, 2021
1 parent 53f8255 commit cbd87f8
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
10 changes: 6 additions & 4 deletions pkg/config/transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,13 @@ func TransformSimpleToClusterConfig(ctx context.Context, runtime runtimes.Runtim
}

if simpleConfig.Subnet != "" {
subnet, err := netaddr.ParseIPPrefix(simpleConfig.Subnet)
if err != nil {
return nil, err
if simpleConfig.Subnet != "auto" {
subnet, err := netaddr.ParseIPPrefix(simpleConfig.Subnet)
if err != nil {
return nil, fmt.Errorf("invalid subnet '%s': %w", simpleConfig.Subnet, err)
}
clusterNetwork.IPAM.IPPrefix = subnet
}
clusterNetwork.IPAM.IPPrefix = subnet
clusterNetwork.IPAM.Managed = true
}

Expand Down
41 changes: 41 additions & 0 deletions pkg/runtimes/docker/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (

runtimeErr "github.com/rancher/k3d/v4/pkg/runtimes/errors"
k3d "github.com/rancher/k3d/v4/pkg/types"
"github.com/rancher/k3d/v4/pkg/util"
log "github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -149,6 +150,16 @@ func (d Docker) CreateNetworkIfNotPresent(ctx context.Context, inNet *k3d.Cluste
Labels: k3d.DefaultObjectLabels,
}

// we want a managed (user-defined) network, but user didn't specify a subnet, so we try to auto-generate one
if inNet.IPAM.Managed && inNet.IPAM.IPPrefix.IsZero() {
log.Traceln("No subnet prefix given, but network should be managed: Trying to get a free subnet prefix...")
freeSubnetPrefix, err := d.getFreeSubnetPrefix(ctx)
if err != nil {
return nil, false, err
}
inNet.IPAM.IPPrefix = freeSubnetPrefix
}

// use user-defined subnet, if given
if !inNet.IPAM.IPPrefix.IsZero() {
netCreateOpts.IPAM = &network.IPAM{
Expand Down Expand Up @@ -295,3 +306,33 @@ func (d Docker) DisconnectNodeFromNetwork(ctx context.Context, node *k3d.Node, n

return docker.NetworkDisconnect(ctx, networkResource.ID, container.ID, true)
}

func (d Docker) getFreeSubnetPrefix(ctx context.Context) (netaddr.IPPrefix, error) {
// (0) create new docker client
docker, err := GetDockerClient()
if err != nil {
return netaddr.IPPrefix{}, fmt.Errorf("failed to create docker client %w", err)
}
defer docker.Close()

// 1. Create a fake network to get auto-generated subnet prefix
fakenetName := fmt.Sprintf("%s-fakenet-%s", k3d.DefaultObjectNamePrefix, util.GenerateRandomString(10))
fakenetResp, err := docker.NetworkCreate(ctx, fakenetName, types.NetworkCreate{})
if err != nil {
return netaddr.IPPrefix{}, fmt.Errorf("failed to create fake network: %w", err)
}

fakenet, err := d.GetNetwork(ctx, &k3d.ClusterNetwork{ID: fakenetResp.ID})
if err != nil {
return netaddr.IPPrefix{}, fmt.Errorf("failed to inspect fake network %s: %w", fakenetResp.ID, err)
}

log.Tracef("Created fake network %s (%s) with subnet prefix %s. Deleting it again to re-use that prefix...", fakenet.Name, fakenet.ID, fakenet.IPAM.IPPrefix.String())

if err := d.DeleteNetwork(ctx, fakenet.ID); err != nil {
return netaddr.IPPrefix{}, fmt.Errorf("failed to delete fake network %s (%s): %w", fakenet.Name, fakenet.ID, err)
}

return fakenet.IPAM.IPPrefix, nil

}

0 comments on commit cbd87f8

Please sign in to comment.