Skip to content

Commit

Permalink
cli/command/network: rewrite consolidateIpam to take an option-struct
Browse files Browse the repository at this point in the history
Introduce a (non-exported) ipamOptions that collects all options for
creating a network.IPAM, so that this utility is more atomic (potentially
even could be moved to a separate package and exported).

Signed-off-by: Sebastiaan van Stijn <[email protected]>
  • Loading branch information
thaJeztah committed Jul 3, 2024
1 parent 2eb6131 commit b3d8809
Showing 1 changed file with 40 additions and 34 deletions.
74 changes: 40 additions & 34 deletions cli/command/network/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,27 @@ type createOptions struct {
ingress bool
configOnly bool
configFrom string
ipam ipamOptions
}

ipamDriver string
ipamSubnet []string
ipamIPRange []string
ipamGateway []string
ipamAux opts.MapOpts
ipamOpt opts.MapOpts
type ipamOptions struct {
driver string
subnets []string
ipRanges []string
gateways []string
auxAddresses opts.MapOpts
driverOpts opts.MapOpts
}

func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
var ipv6 bool
options := createOptions{
driverOpts: *opts.NewMapOpts(nil, nil),
labels: opts.NewListOpts(opts.ValidateLabel),
ipamAux: *opts.NewMapOpts(nil, nil),
ipamOpt: *opts.NewMapOpts(nil, nil),
ipam: ipamOptions{
auxAddresses: *opts.NewMapOpts(nil, nil),
driverOpts: *opts.NewMapOpts(nil, nil),
},
}

cmd := &cobra.Command{
Expand Down Expand Up @@ -80,19 +85,19 @@ func newCreateCommand(dockerCLI command.Cli) *cobra.Command {
flags.StringVar(&options.configFrom, "config-from", "", "The network from which to copy the configuration")
flags.SetAnnotation("config-from", "version", []string{"1.30"})

flags.StringVar(&options.ipamDriver, "ipam-driver", "default", "IP Address Management Driver")
flags.StringSliceVar(&options.ipamSubnet, "subnet", []string{}, "Subnet in CIDR format that represents a network segment")
flags.StringSliceVar(&options.ipamIPRange, "ip-range", []string{}, "Allocate container ip from a sub-range")
flags.StringSliceVar(&options.ipamGateway, "gateway", []string{}, "IPv4 or IPv6 Gateway for the master subnet")
flags.StringVar(&options.ipam.driver, "ipam-driver", "default", "IP Address Management Driver")
flags.StringSliceVar(&options.ipam.subnets, "subnet", []string{}, "Subnet in CIDR format that represents a network segment")
flags.StringSliceVar(&options.ipam.ipRanges, "ip-range", []string{}, "Allocate container ip from a sub-range")
flags.StringSliceVar(&options.ipam.gateways, "gateway", []string{}, "IPv4 or IPv6 Gateway for the master subnet")

flags.Var(&options.ipamAux, "aux-address", "Auxiliary IPv4 or IPv6 addresses used by Network driver")
flags.Var(&options.ipamOpt, "ipam-opt", "Set IPAM driver specific options")
flags.Var(&options.ipam.auxAddresses, "aux-address", "Auxiliary IPv4 or IPv6 addresses used by Network driver")
flags.Var(&options.ipam.driverOpts, "ipam-opt", "Set IPAM driver specific options")

return cmd
}

func runCreate(ctx context.Context, apiClient client.NetworkAPIClient, output io.Writer, options createOptions) error {
ipamCfg, err := consolidateIpam(options.ipamSubnet, options.ipamIPRange, options.ipamGateway, options.ipamAux.GetAll())
ipamCfg, err := createIPAMConfig(options.ipam)
if err != nil {
return err
}
Expand All @@ -104,13 +109,9 @@ func runCreate(ctx context.Context, apiClient client.NetworkAPIClient, output io
}
}
resp, err := apiClient.NetworkCreate(ctx, options.name, network.CreateOptions{
Driver: options.driver,
Options: options.driverOpts.GetAll(),
IPAM: &network.IPAM{
Driver: options.ipamDriver,
Config: ipamCfg,
Options: options.ipamOpt.GetAll(),
},
Driver: options.driver,
Options: options.driverOpts.GetAll(),
IPAM: ipamCfg,
Internal: options.internal,
EnableIPv6: options.ipv6,
Attachable: options.attachable,
Expand All @@ -130,18 +131,18 @@ func runCreate(ctx context.Context, apiClient client.NetworkAPIClient, output io
// Consolidates the ipam configuration as a group from different related configurations
// user can configure network with multiple non-overlapping subnets and hence it is
// possible to correlate the various related parameters and consolidate them.
// consolidateIpam consolidates subnets, ip-ranges, gateways and auxiliary addresses into
// createIPAMConfig consolidates subnets, ip-ranges, gateways and auxiliary addresses into
// structured ipam data.
//
//nolint:gocyclo
func consolidateIpam(subnets, ranges, gateways []string, auxaddrs map[string]string) ([]network.IPAMConfig, error) {
if len(subnets) < len(ranges) || len(subnets) < len(gateways) {
func createIPAMConfig(options ipamOptions) (*network.IPAM, error) {
if len(options.subnets) < len(options.ipRanges) || len(options.subnets) < len(options.gateways) {
return nil, errors.Errorf("every ip-range or gateway must have a corresponding subnet")
}
iData := map[string]*network.IPAMConfig{}

// Populate non-overlapping subnets into consolidation map
for _, s := range subnets {
for _, s := range options.subnets {
for k := range iData {
ok1, err := subnetMatches(s, k)
if err != nil {
Expand All @@ -159,9 +160,9 @@ func consolidateIpam(subnets, ranges, gateways []string, auxaddrs map[string]str
}

// Validate and add valid ip ranges
for _, r := range ranges {
for _, r := range options.ipRanges {
match := false
for _, s := range subnets {
for _, s := range options.subnets {
ok, err := subnetMatches(s, r)
if err != nil {
return nil, err
Expand All @@ -182,9 +183,9 @@ func consolidateIpam(subnets, ranges, gateways []string, auxaddrs map[string]str
}

// Validate and add valid gateways
for _, g := range gateways {
for _, g := range options.gateways {
match := false
for _, s := range subnets {
for _, s := range options.subnets {
ok, err := subnetMatches(s, g)
if err != nil {
return nil, err
Expand All @@ -205,9 +206,9 @@ func consolidateIpam(subnets, ranges, gateways []string, auxaddrs map[string]str
}

// Validate and add aux-addresses
for key, aa := range auxaddrs {
for key, aa := range options.auxAddresses.GetAll() {
match := false
for _, s := range subnets {
for _, s := range options.subnets {
ok, err := subnetMatches(s, aa)
if err != nil {
return nil, err
Expand All @@ -223,11 +224,16 @@ func consolidateIpam(subnets, ranges, gateways []string, auxaddrs map[string]str
}
}

idl := []network.IPAMConfig{}
idl := make([]network.IPAMConfig, 0, len(iData))
for _, v := range iData {
idl = append(idl, *v)
}
return idl, nil

return &network.IPAM{
Driver: options.driver,
Config: idl,
Options: options.driverOpts.GetAll(),
}, nil
}

func subnetMatches(subnet, data string) (bool, error) {
Expand Down

0 comments on commit b3d8809

Please sign in to comment.