Skip to content

Commit

Permalink
Dualstack support (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
majst01 authored Feb 19, 2025
1 parent 0c1a2d7 commit 5e1a339
Show file tree
Hide file tree
Showing 19 changed files with 294 additions and 199 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM alpine:3.20
FROM alpine:3.21
LABEL maintainer="metal-stack authors <[email protected]>"
COPY bin/metalctl-linux-amd64 /metalctl
ENTRYPOINT ["/metalctl"]
2 changes: 1 addition & 1 deletion Dockerfile.test
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.23
FROM golang:1.24
WORKDIR /work
COPY go.* .
RUN go mod download
Expand Down
5 changes: 5 additions & 0 deletions cmd/completion/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package completion

import (
"github.com/metal-stack/metal-go/api/client/ip"
"github.com/metal-stack/metal-go/api/models"
"github.com/spf13/cobra"
)

Expand All @@ -16,3 +17,7 @@ func (c *Completion) IpListCompletion(cmd *cobra.Command, args []string, toCompl
}
return names, cobra.ShellCompDirectiveNoFileComp
}

func (c *Completion) IPAddressFamilyCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{models.V1IPAllocateRequestAddressfamilyIPV4, models.V1IPAllocateRequestAddressfamilyIPV6}, cobra.ShellCompDirectiveNoFileComp
}
5 changes: 5 additions & 0 deletions cmd/completion/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package completion

import (
"github.com/metal-stack/metal-go/api/client/network"
"github.com/metal-stack/metal-go/api/models"

"github.com/spf13/cobra"
)

Expand All @@ -28,3 +30,6 @@ func (c *Completion) NetworkDestinationPrefixesCompletion(cmd *cobra.Command, ar
}
return prefixes, cobra.ShellCompDirectiveNoFileComp
}
func (c *Completion) NetworkAddressFamilyCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{models.V1NetworkAllocateRequestAddressfamilyIPV4, models.V1NetworkAllocateRequestAddressfamilyIPV6}, cobra.ShellCompDirectiveNoFileComp
}
19 changes: 13 additions & 6 deletions cmd/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ func newIPCmd(c *config) *cobra.Command {
cmd.Flags().StringP("network", "", "", "network from where the IP should be allocated.")
cmd.Flags().StringP("project", "", "", "project for which the IP should be allocated.")
cmd.Flags().StringSliceP("tags", "", nil, "tags to attach to the IP.")
cmd.Flags().StringP("addressfamily", "", "", "addressfamily of the ip to acquire, defaults to IPv4 [optional]")
genericcli.Must(cmd.RegisterFlagCompletionFunc("network", c.comp.NetworkListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("type", cobra.FixedCompletions([]string{models.V1IPAllocateRequestTypeEphemeral, models.V1IPAllocateRequestTypeStatic}, cobra.ShellCompDirectiveNoFileComp)))
genericcli.Must(cmd.RegisterFlagCompletionFunc("addressfamily", c.comp.IPAddressFamilyCompletion))
},
ListCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().StringP("ipaddress", "", "", "ipaddress to filter [optional]")
Expand All @@ -62,11 +64,13 @@ func newIPCmd(c *config) *cobra.Command {
cmd.Flags().StringP("network", "", "", "network to filter [optional]")
cmd.Flags().StringP("name", "", "", "name to filter [optional]")
cmd.Flags().StringSliceP("tags", "", nil, "tags to filter [optional]")
cmd.Flags().StringP("addressfamily", "", "", "addressfamily of the ip to filter, defaults to all addressfamilies [optional]")
genericcli.Must(cmd.RegisterFlagCompletionFunc("ipaddress", c.comp.IpListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("network", c.comp.NetworkListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("type", cobra.FixedCompletions([]string{models.V1IPAllocateRequestTypeEphemeral, models.V1IPAllocateRequestTypeStatic}, cobra.ShellCompDirectiveNoFileComp)))
genericcli.Must(cmd.RegisterFlagCompletionFunc("machineid", c.comp.MachineListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("addressfamily", c.comp.IPAddressFamilyCompletion))
},
DeleteCmdMutateFn: func(cmd *cobra.Command) {
cmd.Aliases = append(cmd.Aliases, "free")
Expand Down Expand Up @@ -105,6 +109,7 @@ func (c *ipCmd) List() ([]*models.V1IPResponse, error) {
Machineid: viper.GetString("machineid"),
Networkprefix: viper.GetString("prefix"),
Tags: viper.GetStringSlice("tags"),
Addressfamily: viper.GetString("addressfamily"),
}), nil)
if err != nil {
return nil, err
Expand Down Expand Up @@ -169,6 +174,7 @@ func ipResponseToCreate(r *models.V1IPResponse) *ipAllocateRequest {
if r.Ipaddress != nil {
ip = *r.Ipaddress
}

return &ipAllocateRequest{
SpecificIP: ip,
V1IPAllocateRequest: &models.V1IPAllocateRequest{
Expand Down Expand Up @@ -196,12 +202,13 @@ func (c *ipCmd) createRequestFromCLI() (*ipAllocateRequest, error) {
return &ipAllocateRequest{
SpecificIP: viper.GetString("ipaddress"),
V1IPAllocateRequest: &models.V1IPAllocateRequest{
Description: viper.GetString("description"),
Name: viper.GetString("name"),
Networkid: pointer.Pointer(viper.GetString("network")),
Projectid: pointer.Pointer(viper.GetString("project")),
Type: pointer.Pointer(viper.GetString("type")),
Tags: viper.GetStringSlice("tags"),
Description: viper.GetString("description"),
Name: viper.GetString("name"),
Networkid: pointer.Pointer(viper.GetString("network")),
Projectid: pointer.Pointer(viper.GetString("project")),
Type: pointer.Pointer(viper.GetString("type")),
Tags: viper.GetStringSlice("tags"),
Addressfamily: viper.GetString("addressfamily"),
},
}, nil
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/ip_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ IP ALLOCATION UUID DESCRIPTION NAME NETWORK PROJECT TYPE
"--type", *want.Type,
"--tags", strings.Join(want.Tags, ","),
}
assertExhaustiveArgs(t, args, commonExcludedFileArgs()...)
assertExhaustiveArgs(t, args, append(commonExcludedFileArgs(), "addressfamily")...)
return args
},
mocks: &client.MetalMockFns{
Expand Down
37 changes: 37 additions & 0 deletions cmd/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ func newNetworkCmd(c *config) *cobra.Command {
cmd.Flags().StringP("name", "n", "", "name of the network to create. [optional]")
cmd.Flags().StringP("partition", "p", "", "partition where this network should exist.")
cmd.Flags().StringP("project", "", "", "project of the network to create. [optional]")
cmd.Flags().Int64("default-ipv4-child-prefix-length", 0, "default child prefix length for ipv4 prefixes for private super networks.")
cmd.Flags().Int64("default-ipv6-child-prefix-length", 0, "default child prefix length for ipv6 prefixes for private super networks.")
cmd.Flags().StringSlice("prefixes", []string{}, "prefixes in this network.")
cmd.Flags().StringSlice("labels", []string{}, "add initial labels, must be in the form of key=value, use it like: --labels \"key1=value1,key2=value2\".")
cmd.Flags().StringSlice("destination-prefixes", []string{}, "destination prefixes in this network.")
Expand All @@ -70,8 +72,10 @@ func newNetworkCmd(c *config) *cobra.Command {
cmd.Flags().Int64P("vrf", "", 0, "vrf to filter [optional]")
cmd.Flags().StringSlice("prefixes", []string{}, "prefixes to filter, use it like: --prefixes prefix1,prefix2.")
cmd.Flags().StringSlice("destination-prefixes", []string{}, "destination prefixes to filter, use it like: --destination-prefixes prefix1,prefix2.")
cmd.Flags().String("addressfamily", "", "addressfamily to filter, either ipv4 or ipv6 [optional]")
genericcli.Must(cmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("partition", c.comp.PartitionListCompletion))
genericcli.Must(cmd.RegisterFlagCompletionFunc("addressfamily", c.comp.NetworkAddressFamilyCompletion))
},
UpdateCmdMutateFn: func(cmd *cobra.Command) {
cmd.Flags().String("name", "", "the name of the network [optional]")
Expand Down Expand Up @@ -105,6 +109,16 @@ func newNetworkCmd(c *config) *cobra.Command {
return err
}

var (
length = make(map[string]int64)
)
if viper.IsSet("ipv4-prefix-length") {
length[models.V1IPAllocateRequestAddressfamilyIPV4] = viper.GetInt64("ipv4-prefix-length")
}
if viper.IsSet("ipv6-prefix-length") {
length[models.V1IPAllocateRequestAddressfamilyIPV6] = viper.GetInt64("ipv6-prefix-length")
}

return w.childCLI.CreateAndPrint(&models.V1NetworkAllocateRequest{
Description: viper.GetString("description"),
Name: viper.GetString("name"),
Expand All @@ -114,6 +128,8 @@ func newNetworkCmd(c *config) *cobra.Command {
Labels: labels,
Destinationprefixes: destinationPrefixes,
Nat: nat,
Addressfamily: viper.GetString("addressfamily"),
Length: length,
}, c.describePrinter)
}

Expand Down Expand Up @@ -142,8 +158,12 @@ func newNetworkCmd(c *config) *cobra.Command {
allocateCmd.Flags().StringSlice("labels", []string{}, "labels for this network. [optional]")
allocateCmd.Flags().BoolP("dmz", "", false, "use this private network as dmz. [optional]")
allocateCmd.Flags().BoolP("shared", "", false, "shared allows usage of this private network from other networks")
allocateCmd.Flags().StringP("addressfamily", "", "", "addressfamily of the network to acquire, if not specified the network inherits the address families from the parent [optional]")
allocateCmd.Flags().Int64P("ipv4-prefix-length", "", 0, "ipv4 prefix bit length of the network to create, defaults to default child prefix length of the parent network. [optional]")
allocateCmd.Flags().Int64P("ipv6-prefix-length", "", 0, "ipv6 prefix bit length of the network to create, defaults to default child prefix length of the parent network. [optional]")
genericcli.Must(allocateCmd.RegisterFlagCompletionFunc("project", c.comp.ProjectListCompletion))
genericcli.Must(allocateCmd.RegisterFlagCompletionFunc("partition", c.comp.PartitionListCompletion))
genericcli.Must(allocateCmd.RegisterFlagCompletionFunc("addressfamily", c.comp.NetworkAddressFamilyCompletion))

genericcli.Must(allocateCmd.MarkFlagRequired("name"))
genericcli.Must(allocateCmd.MarkFlagRequired("project"))
Expand Down Expand Up @@ -179,6 +199,7 @@ func (c *networkCmd) List() ([]*models.V1NetworkResponse, error) {
Prefixes: viper.GetStringSlice("prefixes"),
Destinationprefixes: viper.GetStringSlice("destination-prefixes"),
Parentnetworkid: viper.GetString("parent"),
Addressfamily: viper.GetString("addressfamily"),
}), nil)
if err != nil {
return nil, err
Expand Down Expand Up @@ -235,6 +256,7 @@ func networkResponseToCreate(r *models.V1NetworkResponse) *models.V1NetworkCreat
Nat: r.Nat,
Parentnetworkid: r.Parentnetworkid,
Partitionid: r.Partitionid,
Defaultchildprefixlength: r.Defaultchildprefixlength,
Prefixes: r.Prefixes,
Privatesuper: r.Privatesuper,
Projectid: r.Projectid,
Expand All @@ -256,6 +278,7 @@ func networkResponseToUpdate(r *models.V1NetworkResponse) *models.V1NetworkUpdat
Prefixes: r.Prefixes,
Shared: r.Shared,
AdditionalAnnouncableCIDRs: r.AdditionalAnnouncableCIDRs,
Defaultchildprefixlength: r.Defaultchildprefixlength,
}
}

Expand All @@ -265,6 +288,18 @@ func (c *networkCmd) createRequestFromCLI() (*models.V1NetworkCreateRequest, err
return nil, err
}

var defaultChildPrefixLengths map[string]int64
if viper.GetBool("privatesuper") {
defaultChildPrefixLengths = map[string]int64{}

if length := viper.GetInt64("default-ipv4-child-prefix-length"); length > 0 {
defaultChildPrefixLengths[models.V1IPAllocateRequestAddressfamilyIPV4] = length
}
if length := viper.GetInt64("default-ipv6-child-prefix-length"); length > 0 {
defaultChildPrefixLengths[models.V1IPAllocateRequestAddressfamilyIPV6] = length
}
}

return &models.V1NetworkCreateRequest{
ID: pointer.Pointer(viper.GetString("id")),
Description: viper.GetString("description"),
Expand All @@ -280,6 +315,7 @@ func (c *networkCmd) createRequestFromCLI() (*models.V1NetworkCreateRequest, err
Vrfshared: viper.GetBool("vrfshared"),
Labels: lbs,
AdditionalAnnouncableCIDRs: viper.GetStringSlice("additional-announcable-cidrs"),
Defaultchildprefixlength: defaultChildPrefixLengths,
}, nil
}

Expand Down Expand Up @@ -375,6 +411,7 @@ func (c *networkCmd) updateRequestFromCLI(args []string) (*models.V1NetworkUpdat
Prefixes: nil,
Shared: shared,
AdditionalAnnouncableCIDRs: additionalCidrs,
Defaultchildprefixlength: resp.Defaultchildprefixlength,
}
addPrefixes = sets.New(viper.GetStringSlice("add-prefixes")...)
removePrefixes = sets.New(viper.GetStringSlice("remove-prefixes")...)
Expand Down
Loading

0 comments on commit 5e1a339

Please sign in to comment.