Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 104 additions & 1 deletion cmd/admin/v2/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,44 @@ func newNetworkCmd(c *config.Config) *cobra.Command {
},
}

return genericcli.NewCmds(cmdsConfig)
networkListExternalMembersCmd := &cobra.Command{
Use: "list-external-members <network>",
Short: "lists external members of the network",
Long: "lists switch ports that are members of this network but are not connected to any registered machine.",
RunE: func(cmd *cobra.Command, args []string) error {
return w.listExternalMembers(args)
},
}

networkListExternalMembersCmd.Flags().String("partition", "", "filter by partition")
networkListExternalMembersCmd.Flags().String("rack", "", "filter by rack")
networkListExternalMembersCmd.Flags().String("switch", "", "filter by switch")

networkAddExternalMembersCmd := &cobra.Command{
Use: "add-external-members <network>",
Short: "adds external members to the network",
Long: "adds switch ports of a rack as members to the network.",
RunE: func(cmd *cobra.Command, args []string) error {
return w.addExternalMembers(args)
},
}

networkAddExternalMembersCmd.Flags().String("rack", "", "rack of the external members")
networkAddExternalMembersCmd.Flags().StringSlice("ports", nil, "ports to add to the network")

networkRemoveExternalMembersCmd := &cobra.Command{
Use: "remove-external-members <network>",
Short: "removes external members from the network",
Long: "removes switch ports of a rack from the network.",
RunE: func(cmd *cobra.Command, args []string) error {
return w.removeExternalMembers(args)
},
}

networkRemoveExternalMembersCmd.Flags().String("rack", "", "rack of the external members")
networkRemoveExternalMembersCmd.Flags().StringSlice("ports", nil, "ports to add to the network")

return genericcli.NewCmds(cmdsConfig, networkListExternalMembersCmd, networkAddExternalMembersCmd, networkRemoveExternalMembersCmd)
}

func (c *networkCmd) Get(id string) (*apiv2.Network, error) {
Expand Down Expand Up @@ -223,6 +260,72 @@ func (c *networkCmd) Update(rq *adminv2.NetworkServiceUpdateRequest) (*apiv2.Net
return resp.Network, nil
}

func (c *networkCmd) listExternalMembers(args []string) error {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

nw, err := genericcli.GetExactlyOneArg(args)
if err != nil {
return err
}

res, err := c.c.Client.Adminv2().Network().ListExternalMembers(ctx, &adminv2.NetworkServiceListExternalMembersRequest{
Network: nw,
Query: &apiv2.ExternalNetworkMemberQuery{
Switch: pointer.PointerOrNil(viper.GetString("switch")),
Rack: pointer.PointerOrNil(viper.GetString("rack")),
Partition: pointer.PointerOrNil(viper.GetString("partition")),
},
})
if err != nil {
return err
}

return c.c.ListPrinter.Print(res)
}

func (c *networkCmd) addExternalMembers(args []string) error {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

nw, err := genericcli.GetExactlyOneArg(args)
if err != nil {
return err
}

res, err := c.c.Client.Adminv2().Network().AddExternalMembers(ctx, &adminv2.NetworkServiceAddExternalMembersRequest{
Network: nw,
Rack: viper.GetString("rack"),
Ports: viper.GetStringSlice("ports"),
})
if err != nil {
return err
}

return c.c.ListPrinter.Print(res)
}

func (c *networkCmd) removeExternalMembers(args []string) error {
ctx, cancel := c.c.NewRequestContext()
defer cancel()

nw, err := genericcli.GetExactlyOneArg(args)
if err != nil {
return err
}

res, err := c.c.Client.Adminv2().Network().RemoveExternalMembers(ctx, &adminv2.NetworkServiceRemoveExternalMembersRequest{
Network: nw,
Rack: viper.GetString("rack"),
Ports: viper.GetStringSlice("ports"),
})
if err != nil {
return err
}

return c.c.ListPrinter.Print(res)
}

func (c *networkCmd) Convert(r *apiv2.Network) (string, *adminv2.NetworkServiceCreateRequest, *adminv2.NetworkServiceUpdateRequest, error) {
addressFamily, err := helpers.AddressFamilyFromPrefixes(r.Prefixes...)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions cmd/tableprinters/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ func (t *TablePrinter) ToHeaderAndRows(data any, wide bool) ([]string, [][]strin
return t.NetworkTable(pointer.WrapInSlice(d), wide)
case []*apiv2.Network:
return t.NetworkTable(d, wide)
case *adminv2.NetworkServiceListExternalMembersResponse:
return t.NetworkExternalMembersTable(d.Network, d.Members, wide)
case *adminv2.NetworkServiceAddExternalMembersResponse:
return t.NetworkExternalMembersTable(d.Network, d.Members, wide)
case *adminv2.NetworkServiceRemoveExternalMembersResponse:
return t.NetworkExternalMembersTable(d.Network, d.Members, wide)

case *apiv2.Machine:
return t.MachineTable(pointer.WrapInSlice(d), wide)
Expand Down
48 changes: 48 additions & 0 deletions cmd/tableprinters/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,54 @@ func (t *TablePrinter) NetworkTable(data []*apiv2.Network, wide bool) ([]string,
return header, rows, nil
}

func (t *TablePrinter) NetworkExternalMembersTable(network *apiv2.Network, members []*apiv2.ExternalNetworkMember, wide bool) ([]string, [][]string, error) {
var (
rows = [][]string{}
)

header := []string{"ID", "NAME", "SWITCH", "PARTITION", "RACK", "PORTS"}
if wide {
header = []string{"ID", "NAME", "TYPE", "PREFIXES", "SWITCH", "PARTITION", "RACK", "PORTS"}
}

if len(members) < 1 {
return header, append(rows, []string{network.Id}), nil
}

for i, member := range members {
for j, port := range member.Ports {
var (
id string
name string
nwType string
prefixes string
sw string
partition string
rack string
)
if i == 0 && j == 0 {
id = network.Id
name = pointer.SafeDeref(network.Name)
nwType = network.Type.String()
prefixes = strings.Join(network.Prefixes, ",")
}
if j == 0 {
sw = member.Switch
partition = member.Partition
rack = member.Rack
}

if wide {
rows = append(rows, []string{id, name, nwType, prefixes, sw, partition, rack, port})
} else {
rows = append(rows, []string{id, name, sw, partition, rack, port})
}
}
}

return header, rows, nil
}

func renderNetworkRow(prefix string, n *apiv2.Network, wide bool) ([]string, error) {
var (
id = fmt.Sprintf("%s%s", prefix, n.Id)
Expand Down
3 changes: 3 additions & 0 deletions docs/admin/metalctlv2_admin_network.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ networks can be attached to a machine or firewall such that they can communicate
### SEE ALSO

* [metalctlv2 admin](metalctlv2_admin.md) - admin commands
* [metalctlv2 admin network add-external-members](metalctlv2_admin_network_add-external-members.md) - adds external members to the network
* [metalctlv2 admin network apply](metalctlv2_admin_network_apply.md) - applies one or more networks from a given file
* [metalctlv2 admin network create](metalctlv2_admin_network_create.md) - creates the network
* [metalctlv2 admin network delete](metalctlv2_admin_network_delete.md) - deletes the network
* [metalctlv2 admin network describe](metalctlv2_admin_network_describe.md) - describes the network
* [metalctlv2 admin network edit](metalctlv2_admin_network_edit.md) - edit the network through an editor and update
* [metalctlv2 admin network list](metalctlv2_admin_network_list.md) - list all networks
* [metalctlv2 admin network list-external-members](metalctlv2_admin_network_list-external-members.md) - lists external members of the network
* [metalctlv2 admin network remove-external-members](metalctlv2_admin_network_remove-external-members.md) - removes external members from the network
* [metalctlv2 admin network update](metalctlv2_admin_network_update.md) - updates the network

37 changes: 37 additions & 0 deletions docs/admin/metalctlv2_admin_network_add-external-members.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## metalctlv2 admin network add-external-members

adds external members to the network

### Synopsis

adds switch ports of a rack as members to the network.

```
metalctlv2 admin network add-external-members <network> [flags]
```

### Options

```
-h, --help help for add-external-members
--ports strings ports to add to the network
--rack string rack of the external members
```

### Options inherited from parent commands

```
--api-token string the token used for api requests
--api-url string the url to the metal-stack.io api
-c, --config string alternative config file path, (default is ~/.metal-stack/config.yaml)
--debug debug output
--force-color force colored output even without tty
-o, --output-format string output format (table|wide|markdown|json|yaml|template), wide is a table with more columns. (default "table")
--template string output template for template output-format, go template format. For property names inspect the output of -o json or -o yaml for reference.
--timeout duration request timeout used for api requests
```

### SEE ALSO

* [metalctlv2 admin network](metalctlv2_admin_network.md) - manage network entities

38 changes: 38 additions & 0 deletions docs/admin/metalctlv2_admin_network_list-external-members.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## metalctlv2 admin network list-external-members

lists external members of the network

### Synopsis

lists switch ports that are members of this network but are not connected to any registered machine.

```
metalctlv2 admin network list-external-members <network> [flags]
```

### Options

```
-h, --help help for list-external-members
--partition string filter by partition
--rack string filter by rack
--switch string filter by switch
```

### Options inherited from parent commands

```
--api-token string the token used for api requests
--api-url string the url to the metal-stack.io api
-c, --config string alternative config file path, (default is ~/.metal-stack/config.yaml)
--debug debug output
--force-color force colored output even without tty
-o, --output-format string output format (table|wide|markdown|json|yaml|template), wide is a table with more columns. (default "table")
--template string output template for template output-format, go template format. For property names inspect the output of -o json or -o yaml for reference.
--timeout duration request timeout used for api requests
```

### SEE ALSO

* [metalctlv2 admin network](metalctlv2_admin_network.md) - manage network entities

37 changes: 37 additions & 0 deletions docs/admin/metalctlv2_admin_network_remove-external-members.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## metalctlv2 admin network remove-external-members

removes external members from the network

### Synopsis

removes switch ports of a rack from the network.

```
metalctlv2 admin network remove-external-members <network> [flags]
```

### Options

```
-h, --help help for remove-external-members
--ports strings ports to add to the network
--rack string rack of the external members
```

### Options inherited from parent commands

```
--api-token string the token used for api requests
--api-url string the url to the metal-stack.io api
-c, --config string alternative config file path, (default is ~/.metal-stack/config.yaml)
--debug debug output
--force-color force colored output even without tty
-o, --output-format string output format (table|wide|markdown|json|yaml|template), wide is a table with more columns. (default "table")
--template string output template for template output-format, go template format. For property names inspect the output of -o json or -o yaml for reference.
--timeout duration request timeout used for api requests
```

### SEE ALSO

* [metalctlv2 admin network](metalctlv2_admin_network.md) - manage network entities

10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/fatih/color v1.19.0
github.com/google/go-cmp v0.7.0
github.com/google/uuid v1.6.0
github.com/metal-stack/api v0.5.5
github.com/metal-stack/api v0.5.6-0.20260909090323-c58acb0d1dba
github.com/metal-stack/metal-console v0.7.7-0.20260909095012-75ec3d1e3e1a
github.com/metal-stack/metal-lib v0.26.3
github.com/metal-stack/v v1.0.3
Expand All @@ -24,8 +24,9 @@ require (

require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.36.12-20260825204119-511051f7f437.2 // indirect
buf.build/go/protovalidate v1.3.0 // indirect
buf.build/go/protovalidate v1.4.0 // indirect
buf.build/go/protoyaml v0.7.0 // indirect
cel.dev/cel-go v0.32.0 // indirect
cel.dev/expr v0.25.3 // indirect
filippo.io/edwards25519 v1.2.0 // indirect
github.com/akutz/memconn v0.1.0 // indirect
Expand Down Expand Up @@ -53,7 +54,6 @@ require (
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/cel-go v0.31.0 // indirect
github.com/hdevalence/ed25519consensus v0.2.0 // indirect
github.com/huin/goupnp v1.3.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
Expand Down Expand Up @@ -103,8 +103,8 @@ require (
golang.org/x/time v0.15.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard/windows v1.0.1 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260825221802-da73d73af1c5 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260825221802-da73d73af1c5 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20260831171406-18b4a7587f8a // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260831171406-18b4a7587f8a // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20260224225140-573d5e7127a8 // indirect
Expand Down
Loading