Skip to content
Merged
25 changes: 19 additions & 6 deletions docs/stackit_beta_network_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,35 @@ stackit beta network create [flags]
Create a network with name "network-1"
$ stackit beta network create --name network-1

Create an IPv4 network with name "network-1" with DNS name servers and a prefix length
$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix-length 25
Create a non-routed network with name "network-1"
$ stackit beta network create --name network-1 --non-routed

Create an IPv6 network with name "network-1" with DNS name servers and a prefix length
$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix-length 56
Create a network with name "network-1" and no gateway
$ stackit beta network create --name network-1 --no-ipv4-gateway

Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway
$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"

Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway
$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"
```

### Options

```
-h, --help Help for "stackit beta network create"
--ipv4-dns-name-servers strings List of DNS name servers for IPv4
--ipv4-dns-name-servers strings List of DNS name servers for IPv4. Nameservers cannot be defined for routed networks
--ipv4-gateway string The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway
--ipv4-prefix string The IPv4 prefix of the network (CIDR)
--ipv4-prefix-length int The prefix length of the IPv4 network
--ipv6-dns-name-servers strings List of DNS name servers for IPv6
--ipv6-dns-name-servers strings List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks
--ipv6-gateway string The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway
--ipv6-prefix string The IPv6 prefix of the network (CIDR)
--ipv6-prefix-length int The prefix length of the IPv6 network
-n, --name string Network name
--no-ipv4-gateway If set to true, the network doesn't have an IPv4 gateway
--no-ipv6-gateway If set to true, the network doesn't have an IPv6 gateway
--non-routed If set to true, the network is not routed and therefore not accessible from other networks
```

### Options inherited from parent commands
Expand Down
19 changes: 13 additions & 6 deletions docs/stackit_beta_network_update.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,27 @@ stackit beta network update [flags]
Update network with ID "xxx" with new name "network-1-new"
$ stackit beta network update xxx --name network-1-new

Update IPv4 network with ID "xxx" with new name "network-1-new" and new DNS name servers
$ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2"
Update network with ID "xxx" with no gateway
$ stackit beta network update --no-ipv4-gateway

Update IPv6 network with ID "xxx" with new name "network-1-new" and new DNS name servers
$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888"
Update IPv4 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers
$ stackit beta network update xxx --name network-1-new --ipv4-dns-name-servers "2.2.2.2" --ipv4-gateway "10.1.2.3"

Update IPv6 network with ID "xxx" with new name "network-1-new", new gateway and new DNS name servers
$ stackit beta network update xxx --name network-1-new --ipv6-dns-name-servers "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"
```

### Options

```
-h, --help Help for "stackit beta network update"
--ipv4-dns-name-servers strings List of DNS name servers IPv4
--ipv6-dns-name-servers strings List of DNS name servers for IPv6
--ipv4-dns-name-servers strings List of DNS name servers IPv4. Nameservers cannot be defined for routed networks
--ipv4-gateway string The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway
--ipv6-dns-name-servers strings List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks
--ipv6-gateway string The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway
-n, --name string Network name
--no-ipv4-gateway If set to true, the network doesn't have an IPv4 gateway
--no-ipv6-gateway If set to true, the network doesn't have an IPv6 gateway
```

### Options inherited from parent commands
Expand Down
74 changes: 65 additions & 9 deletions internal/cmd/beta/network/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,31 @@ const (
nameFlag = "name"
ipv4DnsNameServersFlag = "ipv4-dns-name-servers"
ipv4PrefixLengthFlag = "ipv4-prefix-length"
ipv4PrefixFlag = "ipv4-prefix"
ipv4GatewayFlag = "ipv4-gateway"
ipv6DnsNameServersFlag = "ipv6-dns-name-servers"
ipv6PrefixLengthFlag = "ipv6-prefix-length"
ipv6PrefixFlag = "ipv6-prefix"
ipv6GatewayFlag = "ipv6-gateway"
nonRoutedFlag = "non-routed"
noIpv4GatewayFlag = "no-ipv4-gateway"
noIpv6GatewayFlag = "no-ipv6-gateway"
)

type inputModel struct {
*globalflags.GlobalFlagModel
Name *string
IPv4DnsNameServers *[]string
IPv4PrefixLength *int64
IPv4Prefix *string
IPv4Gateway *string
IPv6DnsNameServers *[]string
IPv6PrefixLength *int64
IPv6Prefix *string
IPv6Gateway *string
NonRouted bool
NoIPv4Gateway bool
NoIPv6Gateway bool
}

func NewCmd(p *print.Printer) *cobra.Command {
Expand All @@ -50,12 +64,20 @@ func NewCmd(p *print.Printer) *cobra.Command {
`$ stackit beta network create --name network-1`,
),
examples.NewExample(
`Create an IPv4 network with name "network-1" with DNS name servers and a prefix length`,
`$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix-length 25`,
`Create a non-routed network with name "network-1"`,
`$ stackit beta network create --name network-1 --non-routed`,
),
examples.NewExample(
`Create an IPv6 network with name "network-1" with DNS name servers and a prefix length`,
`$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix-length 56`,
`Create a network with name "network-1" and no gateway`,
`$ stackit beta network create --name network-1 --no-ipv4-gateway`,
),
examples.NewExample(
`Create an IPv4 network with name "network-1" with DNS name servers, a prefix and a gateway`,
`$ stackit beta network create --name network-1 --ipv4-dns-name-servers "1.1.1.1,8.8.8.8,9.9.9.9" --ipv4-prefix "10.1.2.0/24" --ipv4-gateway "10.1.2.3"`,
),
examples.NewExample(
`Create an IPv6 network with name "network-1" with DNS name servers, a prefix and a gateway`,
`$ stackit beta network create --name network-1 --ipv6-dns-name-servers "2001:4860:4860::8888,2001:4860:4860::8844" --ipv6-prefix "2001:4860:4860::8888" --ipv6-gateway "2001:4860:4860::8888"`,
),
),
RunE: func(cmd *cobra.Command, _ []string) error {
Expand Down Expand Up @@ -113,10 +135,17 @@ func NewCmd(p *print.Printer) *cobra.Command {

func configureFlags(cmd *cobra.Command) {
cmd.Flags().StringP(nameFlag, "n", "", "Network name")
cmd.Flags().StringSlice(ipv4DnsNameServersFlag, []string{}, "List of DNS name servers for IPv4")
cmd.Flags().StringSlice(ipv4DnsNameServersFlag, []string{}, "List of DNS name servers for IPv4. Nameservers cannot be defined for routed networks")
cmd.Flags().Int64(ipv4PrefixLengthFlag, 0, "The prefix length of the IPv4 network")
cmd.Flags().StringSlice(ipv6DnsNameServersFlag, []string{}, "List of DNS name servers for IPv6")
cmd.Flags().String(ipv4PrefixFlag, "", "The IPv4 prefix of the network (CIDR)")
cmd.Flags().String(ipv4GatewayFlag, "", "The IPv4 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway")
cmd.Flags().StringSlice(ipv6DnsNameServersFlag, []string{}, "List of DNS name servers for IPv6. Nameservers cannot be defined for routed networks")
cmd.Flags().Int64(ipv6PrefixLengthFlag, 0, "The prefix length of the IPv6 network")
cmd.Flags().String(ipv6PrefixFlag, "", "The IPv6 prefix of the network (CIDR)")
cmd.Flags().String(ipv6GatewayFlag, "", "The IPv6 gateway of a network. If not specified, the first IP of the network will be assigned as the gateway")
cmd.Flags().Bool(nonRoutedFlag, false, "If set to true, the network is not routed and therefore not accessible from other networks")
cmd.Flags().Bool(noIpv4GatewayFlag, false, "If set to true, the network doesn't have an IPv4 gateway")
cmd.Flags().Bool(noIpv6GatewayFlag, false, "If set to true, the network doesn't have an IPv6 gateway")

err := flags.MarkFlagsRequired(cmd, nameFlag)
cobra.CheckErr(err)
Expand All @@ -133,8 +162,15 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
Name: flags.FlagToStringPointer(p, cmd, nameFlag),
IPv4DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv4DnsNameServersFlag),
IPv4PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv4PrefixLengthFlag),
IPv4Prefix: flags.FlagToStringPointer(p, cmd, ipv4PrefixFlag),
IPv4Gateway: flags.FlagToStringPointer(p, cmd, ipv4GatewayFlag),
IPv6DnsNameServers: flags.FlagToStringSlicePointer(p, cmd, ipv6DnsNameServersFlag),
IPv6PrefixLength: flags.FlagToInt64Pointer(p, cmd, ipv6PrefixLengthFlag),
IPv6Prefix: flags.FlagToStringPointer(p, cmd, ipv6PrefixFlag),
IPv6Gateway: flags.FlagToStringPointer(p, cmd, ipv6GatewayFlag),
NonRouted: flags.FlagToBoolValue(p, cmd, nonRoutedFlag),
NoIPv4Gateway: flags.FlagToBoolValue(p, cmd, noIpv4GatewayFlag),
NoIPv6Gateway: flags.FlagToBoolValue(p, cmd, noIpv6GatewayFlag),
}

if p.IsVerbosityDebug() {
Expand All @@ -153,22 +189,42 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient *iaas.APICli
req := apiClient.CreateNetwork(ctx, model.ProjectId)
addressFamily := &iaas.CreateNetworkAddressFamily{}

if model.IPv6DnsNameServers != nil || model.IPv6PrefixLength != nil {
if model.IPv6DnsNameServers != nil || model.IPv6PrefixLength != nil || model.IPv6Prefix != nil || model.NoIPv6Gateway || model.IPv6Gateway != nil {
addressFamily.Ipv6 = &iaas.CreateNetworkIPv6Body{
Nameservers: model.IPv6DnsNameServers,
PrefixLength: model.IPv6PrefixLength,
Prefix: model.IPv6Prefix,
}

if model.NoIPv6Gateway {
addressFamily.Ipv6.Gateway = iaas.NewNullableString(nil)
} else if model.IPv6Gateway != nil {
addressFamily.Ipv6.Gateway = iaas.NewNullableString(model.IPv6Gateway)
}
}

if model.IPv4DnsNameServers != nil || model.IPv4PrefixLength != nil {
if model.IPv4DnsNameServers != nil || model.IPv4PrefixLength != nil || model.IPv4Prefix != nil || model.NoIPv4Gateway || model.IPv4Gateway != nil {
addressFamily.Ipv4 = &iaas.CreateNetworkIPv4Body{
Nameservers: model.IPv4DnsNameServers,
PrefixLength: model.IPv4PrefixLength,
Prefix: model.IPv4Prefix,
}

if model.NoIPv4Gateway {
addressFamily.Ipv4.Gateway = iaas.NewNullableString(nil)
} else if model.IPv4Gateway != nil {
addressFamily.Ipv4.Gateway = iaas.NewNullableString(model.IPv4Gateway)
}
}

routed := true
if model.NonRouted {
routed = false
}

payload := iaas.CreateNetworkPayload{
Name: model.Name,
Name: model.Name,
Routed: &routed,
}

if addressFamily.Ipv4 != nil || addressFamily.Ipv6 != nil {
Expand Down
67 changes: 63 additions & 4 deletions internal/cmd/beta/network/create/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,13 @@ func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]st
nameFlag: "example-network-name",
ipv4DnsNameServersFlag: "1.1.1.0,1.1.2.0",
ipv4PrefixLengthFlag: "24",
ipv4PrefixFlag: "10.1.2.0/24",
ipv4GatewayFlag: "10.1.2.3",
ipv6DnsNameServersFlag: "2001:4860:4860::8888,2001:4860:4860::8844",
ipv6PrefixLengthFlag: "24",
ipv6PrefixFlag: "2001:4860:4860::8888",
ipv6GatewayFlag: "2001:4860:4860::8888",
nonRoutedFlag: "false",
}
for _, mod := range mods {
mod(flagValues)
Expand All @@ -47,8 +52,13 @@ func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
Name: utils.Ptr("example-network-name"),
IPv4DnsNameServers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}),
IPv4PrefixLength: utils.Ptr(int64(24)),
IPv4Prefix: utils.Ptr("10.1.2.0/24"),
IPv4Gateway: utils.Ptr("10.1.2.3"),
IPv6DnsNameServers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}),
IPv6PrefixLength: utils.Ptr(int64(24)),
IPv6Prefix: utils.Ptr("2001:4860:4860::8888"),
IPv6Gateway: utils.Ptr("2001:4860:4860::8888"),
NonRouted: false,
}
for _, mod := range mods {
mod(model)
Expand All @@ -68,7 +78,8 @@ func fixtureRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.Ap
func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateNetworkRequest)) iaas.ApiCreateNetworkRequest {
request := testClient.CreateNetwork(testCtx, testProjectId)
request = request.CreateNetworkPayload(iaas.CreateNetworkPayload{
Name: utils.Ptr("example-network-name"),
Name: utils.Ptr("example-network-name"),
Routed: utils.Ptr(true),
})
for _, mod := range mods {
mod(&request)
Expand All @@ -78,15 +89,20 @@ func fixtureRequiredRequest(mods ...func(request *iaas.ApiCreateNetworkRequest))

func fixturePayload(mods ...func(payload *iaas.CreateNetworkPayload)) iaas.CreateNetworkPayload {
payload := iaas.CreateNetworkPayload{
Name: utils.Ptr("example-network-name"),
Name: utils.Ptr("example-network-name"),
Routed: utils.Ptr(true),
AddressFamily: &iaas.CreateNetworkAddressFamily{
Ipv4: &iaas.CreateNetworkIPv4Body{
Nameservers: utils.Ptr([]string{"1.1.1.0", "1.1.2.0"}),
PrefixLength: utils.Ptr(int64(24)),
Prefix: utils.Ptr("10.1.2.0/24"),
Gateway: iaas.NewNullableString(utils.Ptr("10.1.2.3")),
},
Ipv6: &iaas.CreateNetworkIPv6Body{
Nameservers: utils.Ptr([]string{"2001:4860:4860::8888", "2001:4860:4860::8844"}),
PrefixLength: utils.Ptr(int64(24)),
Prefix: utils.Ptr("2001:4860:4860::8888"),
Gateway: iaas.NewNullableString(utils.Ptr("2001:4860:4860::8888")),
},
},
}
Expand Down Expand Up @@ -155,27 +171,69 @@ func TestParseInput(t *testing.T) {
isValid: false,
},
{
description: "use dns servers and prefix",
description: "use dns servers, prefix, gateway and prefix length",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[ipv4DnsNameServersFlag] = "1.1.1.1"
flagValues[ipv4PrefixLengthFlag] = "25"
flagValues[ipv4PrefixFlag] = "10.1.2.0/24"
flagValues[ipv4GatewayFlag] = "10.1.2.3"
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.IPv4DnsNameServers = utils.Ptr([]string{"1.1.1.1"})
model.IPv4PrefixLength = utils.Ptr(int64(25))
model.IPv4Prefix = utils.Ptr("10.1.2.0/24")
model.IPv4Gateway = utils.Ptr("10.1.2.3")
}),
},
{
description: "use ipv6 dns servers and prefix",
description: "use ipv4 gateway nil",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[noIpv4GatewayFlag] = "true"
delete(flagValues, ipv4GatewayFlag)
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.NoIPv4Gateway = true
model.IPv4Gateway = nil
}),
},
{
description: "use ipv6 dns servers, prefix, gateway and prefix length",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[ipv6DnsNameServersFlag] = "2001:4860:4860::8888"
flagValues[ipv6PrefixLengthFlag] = "25"
flagValues[ipv6PrefixFlag] = "2001:4860:4860::8888"
flagValues[ipv6GatewayFlag] = "2001:4860:4860::8888"
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.IPv6DnsNameServers = utils.Ptr([]string{"2001:4860:4860::8888"})
model.IPv6PrefixLength = utils.Ptr(int64(25))
model.IPv6Prefix = utils.Ptr("2001:4860:4860::8888")
model.IPv6Gateway = utils.Ptr("2001:4860:4860::8888")
}),
},
{
description: "use ipv6 gateway nil",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[noIpv6GatewayFlag] = "true"
delete(flagValues, ipv6GatewayFlag)
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.NoIPv6Gateway = true
model.IPv6Gateway = nil
}),
},
{
description: "use routed true",
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
flagValues[nonRoutedFlag] = "false"
}),
isValid: true,
expectedModel: fixtureInputModel(func(model *inputModel) {
model.NonRouted = false
}),
},
}
Expand Down Expand Up @@ -257,6 +315,7 @@ func TestBuildRequest(t *testing.T) {
diff := cmp.Diff(request, tt.expectedRequest,
cmp.AllowUnexported(tt.expectedRequest),
cmpopts.EquateComparable(testCtx),
cmp.AllowUnexported(iaas.NullableString{}),
)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
Expand Down
19 changes: 19 additions & 0 deletions internal/cmd/beta/network/describe/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network)
table.AddSeparator()
}

routed := true
if network.Routed != nil {
routed = *network.Routed
}

table.AddRow("ROUTED", routed)
table.AddSeparator()

if network.Gateway != nil {
table.AddRow("IPv4 GATEWAY", *network.Gateway.Get())
table.AddSeparator()
}

if len(ipv4nameservers) > 0 {
table.AddRow("IPv4 NAME SERVERS", strings.Join(ipv4nameservers, ", "))
}
Expand All @@ -160,6 +173,12 @@ func outputResult(p *print.Printer, outputFormat string, network *iaas.Network)
table.AddRow("IPv4 PREFIXES", strings.Join(ipv4prefixes, ", "))
}
table.AddSeparator()

if network.Gatewayv6 != nil {
table.AddRow("IPv6 GATEWAY", *network.Gatewayv6.Get())
table.AddSeparator()
}

if len(ipv6nameservers) > 0 {
table.AddRow("IPv6 NAME SERVERS", strings.Join(ipv6nameservers, ", "))
}
Expand Down
Loading
Loading