From 28aa9bb3c065e962ac9813527d881bb23a62adef Mon Sep 17 00:00:00 2001 From: Stefan Majer Date: Mon, 27 Feb 2023 11:24:48 +0100 Subject: [PATCH] Add switch ssh|console and show more details (#176) --- .github/workflows/docker.yaml | 2 +- cmd/completion/switch.go | 18 +++++ cmd/machine_test.go | 34 ++++----- cmd/sorters/machine.go | 12 ++- cmd/switch.go | 131 +++++++++++++++++++++++++++----- cmd/switch_test.go | 44 ++++++----- cmd/tableprinters/machine.go | 19 +++-- cmd/tableprinters/switch.go | 27 ++++++- docs/metalctl_machine_list.md | 2 +- docs/metalctl_switch.md | 2 + docs/metalctl_switch_console.md | 50 ++++++++++++ docs/metalctl_switch_ssh.md | 50 ++++++++++++ go.mod | 20 ++--- go.sum | 50 ++++++------ 14 files changed, 353 insertions(+), 108 deletions(-) create mode 100644 cmd/completion/switch.go create mode 100644 docs/metalctl_switch_console.md create mode 100644 docs/metalctl_switch_ssh.md diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index 6d7e3ee3..514c780c 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -23,7 +23,7 @@ jobs: steps: - name: Log in to the container registry - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.DOCKER_REGISTRY_USER }} diff --git a/cmd/completion/switch.go b/cmd/completion/switch.go new file mode 100644 index 00000000..4e91f467 --- /dev/null +++ b/cmd/completion/switch.go @@ -0,0 +1,18 @@ +package completion + +import ( + "github.com/metal-stack/metal-go/api/client/switch_operations" + "github.com/spf13/cobra" +) + +func (c *Completion) SwitchListCompletion(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + resp, err := c.client.SwitchOperations().ListSwitches(switch_operations.NewListSwitchesParams(), nil) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + var names []string + for _, s := range resp.Payload { + names = append(names, *s.ID) + } + return names, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/machine_test.go b/cmd/machine_test.go index e93869a3..00b89247 100644 --- a/cmd/machine_test.go +++ b/cmd/machine_test.go @@ -176,14 +176,14 @@ func Test_MachineCmd_MultiResult(t *testing.T) { machine1, }, wantTable: pointer.Pointer(` -ID LAST EVENT WHEN AGE HOSTNAME PROJECT SIZE IMAGE PARTITION -2 Waiting 1m 1 1 -1 Phoned Home 7d 14d machine-hostname-1 project-1 1 debian-name 1 +ID LAST EVENT WHEN AGE HOSTNAME PROJECT SIZE IMAGE PARTITION RACK +2 Waiting 1m 1 1 rack-1 +1 Phoned Home 7d 14d machine-hostname-1 project-1 1 debian-name 1 rack-1 `), wantWideTable: pointer.Pointer(` -ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION STARTED TAGS LOCK/RESERVE -2 Waiting 1m 1 1 b -1 Phoned Home 7d 14d machine allocation 1 machine-1 machine-hostname-1 project-1 1.1.1.1 1 debian-name 1 2022-05-05T01:02:03Z a +ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION RACK STARTED TAGS LOCK/RESERVE +2 Waiting 1m 1 1 rack-1 b +1 Phoned Home 7d 14d machine allocation 1 machine-1 machine-hostname-1 project-1 1.1.1.1 1 debian-name 1 rack-1 2022-05-05T01:02:03Z a `), template: pointer.Pointer("{{ .id }} {{ .name }}"), wantTemplate: pointer.Pointer(` @@ -191,10 +191,10 @@ ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME 1 machine-1 `), wantMarkdown: pointer.Pointer(` -| ID | | LAST EVENT | WHEN | AGE | HOSTNAME | PROJECT | SIZE | IMAGE | PARTITION | -|----|--|-------------|------|-----|--------------------|-----------|------|-------------|-----------| -| 2 | | Waiting | 1m | | | | 1 | | 1 | -| 1 | | Phoned Home | 7d | 14d | machine-hostname-1 | project-1 | 1 | debian-name | 1 | +| ID | | LAST EVENT | WHEN | AGE | HOSTNAME | PROJECT | SIZE | IMAGE | PARTITION | RACK | +|----|--|-------------|------|-----|--------------------|-----------|------|-------------|-----------|--------| +| 2 | | Waiting | 1m | | | | 1 | | 1 | rack-1 | +| 1 | | Phoned Home | 7d | 14d | machine-hostname-1 | project-1 | 1 | debian-name | 1 | rack-1 | `), }, } @@ -219,21 +219,21 @@ func Test_MachineCmd_SingleResult(t *testing.T) { }, want: machine1, wantTable: pointer.Pointer(` -ID LAST EVENT WHEN AGE HOSTNAME PROJECT SIZE IMAGE PARTITION -1 Phoned Home 7d 14d machine-hostname-1 project-1 1 debian-name 1 +ID LAST EVENT WHEN AGE HOSTNAME PROJECT SIZE IMAGE PARTITION RACK +1 Phoned Home 7d 14d machine-hostname-1 project-1 1 debian-name 1 rack-1 `), wantWideTable: pointer.Pointer(` -ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION STARTED TAGS LOCK/RESERVE -1 Phoned Home 7d 14d machine allocation 1 machine-1 machine-hostname-1 project-1 1.1.1.1 1 debian-name 1 2022-05-05T01:02:03Z a +ID LAST EVENT WHEN AGE DESCRIPTION NAME HOSTNAME PROJECT IPS SIZE IMAGE PARTITION RACK STARTED TAGS LOCK/RESERVE +1 Phoned Home 7d 14d machine allocation 1 machine-1 machine-hostname-1 project-1 1.1.1.1 1 debian-name 1 rack-1 2022-05-05T01:02:03Z a `), template: pointer.Pointer("{{ .id }} {{ .name }}"), wantTemplate: pointer.Pointer(` 1 machine-1 `), wantMarkdown: pointer.Pointer(` -| ID | | LAST EVENT | WHEN | AGE | HOSTNAME | PROJECT | SIZE | IMAGE | PARTITION | -|----|--|-------------|------|-----|--------------------|-----------|------|-------------|-----------| -| 1 | | Phoned Home | 7d | 14d | machine-hostname-1 | project-1 | 1 | debian-name | 1 | +| ID | | LAST EVENT | WHEN | AGE | HOSTNAME | PROJECT | SIZE | IMAGE | PARTITION | RACK | +|----|--|-------------|------|-----|--------------------|-----------|------|-------------|-----------|--------| +| 1 | | Phoned Home | 7d | 14d | machine-hostname-1 | project-1 | 1 | debian-name | 1 | rack-1 | `), }, { diff --git a/cmd/sorters/machine.go b/cmd/sorters/machine.go index 6b3ae2aa..3dd865a7 100644 --- a/cmd/sorters/machine.go +++ b/cmd/sorters/machine.go @@ -28,6 +28,11 @@ func MachineSorter() *multisort.Sorter[*models.V1MachineResponse] { bID := p.SafeDeref(p.SafeDeref(b.Partition).ID) return multisort.Compare(aID, bID, descending) }, + "rack": func(a, b *models.V1MachineResponse, descending bool) multisort.CompareResult { + aID := a.Rackid + bID := b.Rackid + return multisort.Compare(aID, bID, descending) + }, "project": func(a, b *models.V1MachineResponse, descending bool) multisort.CompareResult { aID := p.SafeDeref(p.SafeDeref(a.Allocation).Project) bID := p.SafeDeref(p.SafeDeref(b.Allocation).Project) @@ -79,6 +84,11 @@ func MachineIPMISorter() *multisort.Sorter[*models.V1MachineIPMIResponse] { bID := p.SafeDeref(p.SafeDeref(b.Partition).ID) return multisort.Compare(aID, bID, descending) }, + "rack": func(a, b *models.V1MachineIPMIResponse, descending bool) multisort.CompareResult { + aID := a.Rackid + bID := b.Rackid + return multisort.Compare(aID, bID, descending) + }, "project": func(a, b *models.V1MachineIPMIResponse, descending bool) multisort.CompareResult { aID := p.SafeDeref(p.SafeDeref(a.Allocation).Project) bID := p.SafeDeref(p.SafeDeref(b.Allocation).Project) @@ -102,5 +112,5 @@ func MachineIPMISorter() *multisort.Sorter[*models.V1MachineIPMIResponse] { bEvent := p.SafeDeref(p.SafeDeref(p.FirstOrZero(p.SafeDeref(b.Events).Log)).Event) return multisort.Compare(aEvent, bEvent, descending) }, - }, multisort.Keys{{ID: "partition"}, {ID: "size"}, {ID: "bios"}, {ID: "bmc"}, {ID: "id"}}) + }, multisort.Keys{{ID: "partition"}, {ID: "rack"}, {ID: "size"}, {ID: "bios"}, {ID: "bmc"}, {ID: "id"}}) } diff --git a/cmd/switch.go b/cmd/switch.go index 808af139..d8ae724f 100644 --- a/cmd/switch.go +++ b/cmd/switch.go @@ -3,14 +3,14 @@ package cmd import ( "fmt" "log" - "sort" + "os" + "os/exec" "strings" "github.com/metal-stack/metal-go/api/client/switch_operations" "github.com/metal-stack/metal-go/api/models" "github.com/metal-stack/metal-lib/pkg/genericcli" "github.com/metal-stack/metal-lib/pkg/genericcli/printers" - "github.com/metal-stack/metal-lib/pkg/pointer" "github.com/metal-stack/metalctl/cmd/sorters" "github.com/metal-stack/metalctl/cmd/tableprinters" "github.com/spf13/cobra" @@ -36,10 +36,12 @@ func newSwitchCmd(c *config) *cobra.Command { genericcli.DeleteCmd, genericcli.EditCmd, ), + Aliases: []string{"sw"}, Singular: "switch", Plural: "switches", Description: "switch are the leaf switches in the data center that are controlled by metal-stack.", Sorter: sorters.SwitchSorter(), + ValidArgsFn: c.comp.SwitchListCompletion, DescribePrinter: func() printers.Printer { return c.describePrinter }, ListPrinter: func() printers.Printer { return c.listPrinter }, } @@ -50,6 +52,7 @@ func newSwitchCmd(c *config) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { return w.switchDetail() }, + ValidArgsFunction: c.comp.SwitchListCompletion, } switchReplaceCmd := &cobra.Command{ Use: "replace ", @@ -69,11 +72,29 @@ Operational steps to replace a switch: RunE: func(cmd *cobra.Command, args []string) error { return w.switchReplace(args) }, + ValidArgsFunction: c.comp.SwitchListCompletion, + } + switchSSHCmd := &cobra.Command{ + Use: "ssh ", + Short: "connect to the switch via ssh", + Long: "this requires a network connectivity to the management ip address of the switch.", + RunE: func(cmd *cobra.Command, args []string) error { + return w.switchSSH(args) + }, + ValidArgsFunction: c.comp.SwitchListCompletion, + } + switchConsoleCmd := &cobra.Command{ + Use: "console ", + Short: "connect to the switch console", + Long: "this requires a network connectivity to the ip address of the console server this switch is connected to.", + RunE: func(cmd *cobra.Command, args []string) error { + return w.switchConsole(args) + }, + ValidArgsFunction: c.comp.SwitchListCompletion, } switchDetailCmd.Flags().StringP("filter", "F", "", "filter for site, rack, ID") - - return genericcli.NewCmds(cmdsConfig, switchDetailCmd, switchReplaceCmd) + return genericcli.NewCmds(cmdsConfig, switchDetailCmd, switchReplaceCmd, switchSSHCmd, switchConsoleCmd) } func (c switchCmd) Get(id string) (*models.V1SwitchResponse, error) { @@ -91,13 +112,6 @@ func (c switchCmd) List() ([]*models.V1SwitchResponse, error) { return nil, err } - for _, s := range resp.Payload { - s := s - sort.SliceStable(s.Connections, func(i, j int) bool { - return pointer.SafeDeref(pointer.SafeDeref((pointer.SafeDeref(s.Connections[i])).Nic).Name) < pointer.SafeDeref(pointer.SafeDeref((pointer.SafeDeref(s.Connections[j])).Nic).Name) - }) - } - return resp.Payload, nil } @@ -132,12 +146,22 @@ func (c switchCmd) ToUpdate(r *models.V1SwitchResponse) (*models.V1SwitchUpdateR } func switchResponseToUpdate(r *models.V1SwitchResponse) *models.V1SwitchUpdateRequest { + switchOS := &models.V1SwitchOS{} + if r.Os != nil { + switchOS.Vendor = r.Os.Vendor + switchOS.Vendor = r.Os.Version + } + return &models.V1SwitchUpdateRequest{ - Description: r.Description, - ID: r.ID, - Mode: r.Mode, - Name: r.Name, - RackID: r.RackID, + ConsoleCommand: r.ConsoleCommand, + Description: r.Description, + ID: r.ID, + ManagementIP: "", + ManagementUser: "", + Mode: r.Mode, + Name: r.Name, + Os: switchOS, + RackID: r.RackID, } } @@ -182,12 +206,22 @@ func (c *switchCmd) switchReplace(args []string) error { return err } + switchOS := &models.V1SwitchOS{} + if resp.Os != nil { + switchOS.Vendor = resp.Os.Vendor + switchOS.Vendor = resp.Os.Version + } + uresp, err := c.Update(&models.V1SwitchUpdateRequest{ - ID: resp.ID, - Name: resp.Name, - Description: resp.Description, - RackID: resp.RackID, - Mode: "replace", + ConsoleCommand: "", + Description: resp.Description, + ID: resp.ID, + ManagementIP: "", + ManagementUser: "", + Mode: "replace", + Name: resp.Name, + Os: switchOS, + RackID: resp.RackID, }) if err != nil { return err @@ -195,3 +229,58 @@ func (c *switchCmd) switchReplace(args []string) error { return c.describePrinter.Print(uresp) } + +func (c *switchCmd) switchSSH(args []string) error { + id, err := genericcli.GetExactlyOneArg(args) + if err != nil { + return err + } + + resp, err := c.Get(id) + if err != nil { + return err + } + if resp.ManagementIP == "" || resp.ManagementUser == "" { + return fmt.Errorf("unable to connect to switch by ssh because no ip and user was stored for this switch, please restart metal-core on this switch") + } + + // nolint: gosec + cmd := exec.Command("ssh", fmt.Sprintf("%s@%s", resp.ManagementUser, resp.ManagementIP)) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + return cmd.Run() +} + +func (c *switchCmd) switchConsole(args []string) error { + id, err := genericcli.GetExactlyOneArg(args) + if err != nil { + return err + } + + resp, err := c.Get(id) + if err != nil { + return err + } + + if resp.ConsoleCommand == "" { + return fmt.Errorf(` +unable to connect to console because no console_command was specified for this switch +You can add a working console_command to every switch with metalctl switch edit +A sample would look like: + +telnet console-server 7008`) + } + parts := strings.Fields(resp.ConsoleCommand) + + // nolint: gosec + cmd := exec.Command(parts[0]) + if len(parts) > 1 { + // nolint: gosec + cmd = exec.Command(parts[0], parts[1:]...) + } + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + return cmd.Run() +} diff --git a/cmd/switch_test.go b/cmd/switch_test.go index c77437f5..31a03adc 100644 --- a/cmd/switch_test.go +++ b/cmd/switch_test.go @@ -59,6 +59,12 @@ var ( }, Partition: partition1, RackID: pointer.Pointer("rack-1"), + Os: &models.V1SwitchOS{ + Vendor: "SONiC", + Version: "1", + }, + ManagementIP: "1.2.3.4", + ManagementUser: "root", } switch2 = &models.V1SwitchResponse{ Connections: []*models.V1SwitchConnection{ @@ -102,6 +108,10 @@ var ( }, Partition: partition1, RackID: pointer.Pointer("rack-1"), + Os: &models.V1SwitchOS{ + Vendor: "Cumulus", + Version: "2", + }, } ) @@ -127,14 +137,14 @@ func Test_SwitchCmd_MultiResult(t *testing.T) { switch2, }, wantTable: pointer.Pointer(` -ID PARTITION RACK STATUS -1 1 rack-1  ● -2 1 rack-1  ● +ID PARTITION RACK OS STATUS +1 1 rack-1 🦔  ● +2 1 rack-1 🐢  ● `), wantWideTable: pointer.Pointer(` -ID PARTITION RACK MODE LAST SYNC SYNC DURATION LAST SYNC ERROR -1 1 rack-1 operational 0s 1s 5m ago: error -2 1 rack-1 operational 0s 1s 5m ago: error +ID PARTITION RACK OS IP MODE LAST SYNC SYNC DURATION LAST SYNC ERROR +1 1 rack-1 SONiC/1 1.2.3.4 operational 0s 1s 5m ago: error +2 1 rack-1 Cumulus/2 operational 0s 1s 5m ago: error `), template: pointer.Pointer("{{ .id }} {{ .name }}"), wantTemplate: pointer.Pointer(` @@ -142,10 +152,10 @@ ID PARTITION RACK MODE LAST SYNC SYNC DURATION LAST SYNC ER 2 switch-2 `), wantMarkdown: pointer.Pointer(` -| ID | PARTITION | RACK | STATUS | -|----|-----------|--------|--------| -| 1 | 1 | rack-1 |  ● | -| 2 | 1 | rack-1 |  ● | +| ID | PARTITION | RACK | OS | STATUS | +|----|-----------|--------|----|--------| +| 1 | 1 | rack-1 | 🦔 |  ● | +| 2 | 1 | rack-1 | 🐢 |  ● | `), }, } @@ -170,21 +180,21 @@ func Test_SwitchCmd_SingleResult(t *testing.T) { }, want: switch1, wantTable: pointer.Pointer(` -ID PARTITION RACK STATUS -1 1 rack-1  ● +ID PARTITION RACK OS STATUS +1 1 rack-1 🦔  ● `), wantWideTable: pointer.Pointer(` -ID PARTITION RACK MODE LAST SYNC SYNC DURATION LAST SYNC ERROR -1 1 rack-1 operational 0s 1s 5m ago: error +ID PARTITION RACK OS IP MODE LAST SYNC SYNC DURATION LAST SYNC ERROR +1 1 rack-1 SONiC/1 1.2.3.4 operational 0s 1s 5m ago: error `), template: pointer.Pointer("{{ .id }} {{ .name }}"), wantTemplate: pointer.Pointer(` 1 switch-1 `), wantMarkdown: pointer.Pointer(` -| ID | PARTITION | RACK | STATUS | -|----|-----------|--------|--------| -| 1 | 1 | rack-1 |  ● | +| ID | PARTITION | RACK | OS | STATUS | +|----|-----------|--------|----|--------| +| 1 | 1 | rack-1 | 🦔 |  ● | `), }, { diff --git a/cmd/tableprinters/machine.go b/cmd/tableprinters/machine.go index 61885d49..1207046a 100644 --- a/cmd/tableprinters/machine.go +++ b/cmd/tableprinters/machine.go @@ -19,9 +19,9 @@ func (t *TablePrinter) MachineTable(data []*models.V1MachineResponse, wide bool) rows [][]string ) - header := []string{"ID", "", "Last Event", "When", "Age", "Hostname", "Project", "Size", "Image", "Partition"} + header := []string{"ID", "", "Last Event", "When", "Age", "Hostname", "Project", "Size", "Image", "Partition", "Rack"} if wide { - header = []string{"ID", "Last Event", "When", "Age", "Description", "Name", "Hostname", "Project", "IPs", "Size", "Image", "Partition", "Started", "Tags", "Lock/Reserve"} + header = []string{"ID", "Last Event", "When", "Age", "Description", "Name", "Hostname", "Project", "IPs", "Size", "Image", "Partition", "Rack", "Started", "Tags", "Lock/Reserve"} } for _, machine := range data { @@ -40,6 +40,8 @@ func (t *TablePrinter) MachineTable(data []*models.V1MachineResponse, wide bool) hostname := pointer.SafeDeref(alloc.Hostname) image := pointer.SafeDeref(alloc.Image).Name + rack := machine.Rackid + truncatedHostname := genericcli.TruncateEnd(hostname, 30) var nwIPs []string @@ -75,9 +77,9 @@ func (t *TablePrinter) MachineTable(data []*models.V1MachineResponse, wide bool) emojis, _ := t.getMachineStatusEmojis(machine.Liveliness, machine.Events, machine.State, alloc.Vpn) if wide { - rows = append(rows, []string{machineID, lastEvent, when, age, desc, name, hostname, project, ips, sizeID, image, partitionID, started, tags, reserved}) + rows = append(rows, []string{machineID, lastEvent, when, age, desc, name, hostname, project, ips, sizeID, image, partitionID, rack, started, tags, reserved}) } else { - rows = append(rows, []string{machineID, emojis, lastEvent, when, age, truncatedHostname, project, sizeID, image, partitionID}) + rows = append(rows, []string{machineID, emojis, lastEvent, when, age, truncatedHostname, project, sizeID, image, partitionID, rack}) } } @@ -147,9 +149,9 @@ func (t *TablePrinter) MachineIPMITable(data []*models.V1MachineIPMIResponse, wi rows [][]string ) - header := []string{"ID", "", "Power", "IP", "Mac", "Board Part Number", "Bios Version", "BMC Version", "Size", "Partition"} + header := []string{"ID", "", "Power", "IP", "Mac", "Board Part Number", "Bios Version", "BMC Version", "Size", "Partition", "Rack"} if wide { - header = []string{"ID", "Status", "Power", "IP", "Mac", "Board Part Number", "Chassis Serial", "Product Serial", "Bios Version", "BMC Version", "Size", "Partition"} + header = []string{"ID", "Status", "Power", "IP", "Mac", "Board Part Number", "Chassis Serial", "Product Serial", "Bios Version", "BMC Version", "Size", "Partition", "Rack"} } for _, machine := range data { @@ -166,6 +168,7 @@ func (t *TablePrinter) MachineIPMITable(data []*models.V1MachineIPMIResponse, wi power := color.WhiteString(dot) powerText := "" ipmi := machine.Ipmi + rack := machine.Rackid if ipmi != nil { ipAddress = pointer.SafeDeref(ipmi.Address) @@ -191,9 +194,9 @@ func (t *TablePrinter) MachineIPMITable(data []*models.V1MachineIPMIResponse, wi emojis, wideEmojis := t.getMachineStatusEmojis(machine.Liveliness, machine.Events, machine.State, nil) if wide { - rows = append(rows, []string{id, wideEmojis, powerText, ipAddress, mac, bpn, cs, ps, biosVersion, bmcVersion, size, partition}) + rows = append(rows, []string{id, wideEmojis, powerText, ipAddress, mac, bpn, cs, ps, biosVersion, bmcVersion, size, partition, rack}) } else { - rows = append(rows, []string{id, emojis, power, ipAddress, mac, bpn, biosVersion, bmcVersion, size, partition}) + rows = append(rows, []string{id, emojis, power, ipAddress, mac, bpn, biosVersion, bmcVersion, size, partition, rack}) } } diff --git a/cmd/tableprinters/switch.go b/cmd/tableprinters/switch.go index 375b56e0..7850ef5e 100644 --- a/cmd/tableprinters/switch.go +++ b/cmd/tableprinters/switch.go @@ -2,6 +2,7 @@ package tableprinters import ( "fmt" + "strings" "time" "github.com/fatih/color" @@ -14,9 +15,9 @@ func (t *TablePrinter) SwitchTable(data []*models.V1SwitchResponse, wide bool) ( rows [][]string ) - header := []string{"ID", "Partition", "Rack", "Status"} + header := []string{"ID", "Partition", "Rack", "OS", "Status"} if wide { - header = []string{"ID", "Partition", "Rack", "Mode", "Last Sync", "Sync Duration", "Last Sync Error"} + header = []string{"ID", "Partition", "Rack", "OS", "IP", "Mode", "Last Sync", "Sync Duration", "Last Sync Error"} } for _, s := range data { @@ -59,10 +60,28 @@ func (t *TablePrinter) SwitchTable(data []*models.V1SwitchResponse, wide bool) ( mode = "operational" } + os := "" + osIcon := "" + if s.Os != nil { + switch strings.ToLower(s.Os.Vendor) { + case "cumulus": + osIcon = "🐢" + case "sonic": + osIcon = "🦔" + default: + osIcon = s.Os.Vendor + } + + os = s.Os.Vendor + if s.Os.Version != "" { + os = os + "/" + s.Os.Version + } + } + if wide { - rows = append(rows, []string{id, partition, rack, mode, syncAgeStr, syncDurStr, syncError}) + rows = append(rows, []string{id, partition, rack, os, s.ManagementIP, mode, syncAgeStr, syncDurStr, syncError}) } else { - rows = append(rows, []string{id, partition, rack, shortStatus}) + rows = append(rows, []string{id, partition, rack, osIcon, shortStatus}) } } diff --git a/docs/metalctl_machine_list.md b/docs/metalctl_machine_list.md index 8e245808..d1b2fa7b 100644 --- a/docs/metalctl_machine_list.md +++ b/docs/metalctl_machine_list.md @@ -35,7 +35,7 @@ metalctl machine list [flags] --partition string partition to filter [optional] --project string allocation project to filter [optional] --size string size to filter [optional] - --sort-by strings sort by (comma separated) column(s), sort direction can be changed by appending :asc or :desc behind the column identifier. possible values: age|event|id|image|liveliness|partition|project|size|when + --sort-by strings sort by (comma separated) column(s), sort direction can be changed by appending :asc or :desc behind the column identifier. possible values: age|event|id|image|liveliness|partition|project|rack|size|when --tags strings tags to filter, use it like: --tags "tag1,tag2" or --tags "tag3". ``` diff --git a/docs/metalctl_switch.md b/docs/metalctl_switch.md index b2bb9655..fbe8b5e3 100644 --- a/docs/metalctl_switch.md +++ b/docs/metalctl_switch.md @@ -43,11 +43,13 @@ switch are the leaf switches in the data center that are controlled by metal-sta ### SEE ALSO * [metalctl](metalctl.md) - a cli to manage entities in the metal-stack api +* [metalctl switch console](metalctl_switch_console.md) - connect to the switch console * [metalctl switch delete](metalctl_switch_delete.md) - deletes the switch * [metalctl switch describe](metalctl_switch_describe.md) - describes the switch * [metalctl switch detail](metalctl_switch_detail.md) - switch details * [metalctl switch edit](metalctl_switch_edit.md) - edit the switch through an editor and update * [metalctl switch list](metalctl_switch_list.md) - list all switches * [metalctl switch replace](metalctl_switch_replace.md) - put a leaf switch into replace mode in preparation for physical replacement. For a description of the steps involved see the long help. +* [metalctl switch ssh](metalctl_switch_ssh.md) - connect to the switch via ssh * [metalctl switch update](metalctl_switch_update.md) - updates the switch diff --git a/docs/metalctl_switch_console.md b/docs/metalctl_switch_console.md new file mode 100644 index 00000000..fd5dc27a --- /dev/null +++ b/docs/metalctl_switch_console.md @@ -0,0 +1,50 @@ +## metalctl switch console + +connect to the switch console + +### Synopsis + +this requires a network connectivity to the ip address of the console server this switch is connected to. + +``` +metalctl switch console [flags] +``` + +### Options + +``` + -h, --help help for console +``` + +### Options inherited from parent commands + +``` + --api-token string api token to authenticate. Can be specified with METALCTL_API_TOKEN environment variable. + --api-url string api server address. Can be specified with METALCTL_API_URL environment variable. + -c, --config string alternative config file path, (default is ~/.metalctl/config.yaml). + Example config.yaml: + + --- + apitoken: "alongtoken" + ... + + + --debug debug output + --force-color force colored output even without tty + --kubeconfig string Path to the kube-config to use for authentication and authorization. Is updated by login. Uses default path if not specified. + --no-headers do not print headers of table output format (default print headers) + -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. + Example for machines: + + metalctl machine list -o template --template "{{ .id }}:{{ .size.id }}" + + + --yes-i-really-mean-it skips security prompts (which can be dangerous to set blindly because actions can lead to data loss or additional costs) +``` + +### SEE ALSO + +* [metalctl switch](metalctl_switch.md) - manage switch entities + diff --git a/docs/metalctl_switch_ssh.md b/docs/metalctl_switch_ssh.md new file mode 100644 index 00000000..2c4deaa4 --- /dev/null +++ b/docs/metalctl_switch_ssh.md @@ -0,0 +1,50 @@ +## metalctl switch ssh + +connect to the switch via ssh + +### Synopsis + +this requires a network connectivity to the management ip address of the switch. + +``` +metalctl switch ssh [flags] +``` + +### Options + +``` + -h, --help help for ssh +``` + +### Options inherited from parent commands + +``` + --api-token string api token to authenticate. Can be specified with METALCTL_API_TOKEN environment variable. + --api-url string api server address. Can be specified with METALCTL_API_URL environment variable. + -c, --config string alternative config file path, (default is ~/.metalctl/config.yaml). + Example config.yaml: + + --- + apitoken: "alongtoken" + ... + + + --debug debug output + --force-color force colored output even without tty + --kubeconfig string Path to the kube-config to use for authentication and authorization. Is updated by login. Uses default path if not specified. + --no-headers do not print headers of table output format (default print headers) + -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. + Example for machines: + + metalctl machine list -o template --template "{{ .id }}:{{ .size.id }}" + + + --yes-i-really-mean-it skips security prompts (which can be dangerous to set blindly because actions can lead to data loss or additional costs) +``` + +### SEE ALSO + +* [metalctl switch](metalctl_switch.md) - manage switch entities + diff --git a/go.mod b/go.mod index 1b577ec5..c19d7d30 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-openapi/runtime v0.25.0 github.com/go-openapi/strfmt v0.21.3 github.com/google/go-cmp v0.5.9 - github.com/metal-stack/metal-go v0.22.0 + github.com/metal-stack/metal-go v0.22.1 github.com/metal-stack/metal-lib v0.11.3 github.com/metal-stack/updater v1.1.4 github.com/metal-stack/v v1.0.3 @@ -19,13 +19,13 @@ require ( github.com/spf13/cobra v1.6.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.15.0 - github.com/stretchr/testify v1.8.1 - github.com/tailscale/golang-x-crypto v0.0.0-20221102133106-bc99ab8c2d17 + github.com/stretchr/testify v1.8.2 + github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 go.uber.org/zap v1.24.0 - golang.org/x/exp v0.0.0-20230223210539-50820d90acfd + golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 golang.org/x/term v0.5.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d + k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b tailscale.com v1.34.0 ) @@ -98,7 +98,7 @@ require ( github.com/josharian/native v1.1.0 // indirect github.com/jsimonetti/rtnetlink v1.3.1 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.15.15 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect github.com/lestrrat-go/blackmagic v1.0.1 // indirect @@ -111,7 +111,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/mdlayher/genetlink v1.2.0 // indirect + github.com/mdlayher/genetlink v1.3.1 // indirect github.com/mdlayher/netlink v1.7.1 // indirect github.com/mdlayher/sdnotify v1.0.0 // indirect github.com/mdlayher/socket v0.4.0 // indirect @@ -127,7 +127,7 @@ require ( github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rivo/uniseg v0.4.2 // indirect + github.com/rivo/uniseg v0.4.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/spf13/cast v1.5.0 // indirect @@ -138,11 +138,11 @@ require ( github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 // indirect github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 // indirect github.com/tcnksm/go-httpstat v0.2.0 // indirect - github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect + github.com/u-root/uio v0.0.0-20221213070652-c3537552635f // indirect github.com/vishvananda/netlink v1.2.1-beta.2 // indirect github.com/vishvananda/netns v0.0.4 // indirect github.com/x448/float16 v0.8.4 // indirect - go.mongodb.org/mongo-driver v1.11.0 // indirect + go.mongodb.org/mongo-driver v1.11.1 // indirect go.opentelemetry.io/otel v1.11.1 // indirect go.opentelemetry.io/otel/trace v1.11.1 // indirect go.uber.org/atomic v1.10.0 // indirect diff --git a/go.sum b/go.sum index 73ab1cff..4d4d8a2e 100644 --- a/go.sum +++ b/go.sum @@ -287,7 +287,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -354,7 +353,7 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= @@ -374,8 +373,8 @@ github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0Lh github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kortschak/wol v0.0.0-20200729010619-da482cc4850a h1:+RR6SqnTkDLWyICxS1xpjCi/3dhyV+TgZwA6Ww3KncQ= @@ -426,24 +425,22 @@ github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRC github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= -github.com/mdlayher/genetlink v1.2.0 h1:4yrIkRV5Wfk1WfpWTcoOlGmsWgQj3OtQN9ZsbrE+XtU= -github.com/mdlayher/genetlink v1.2.0/go.mod h1:ra5LDov2KrUCZJiAtEvXXZBxGMInICMXIwshlJ+qRxQ= +github.com/mdlayher/genetlink v1.3.1 h1:roBiPnual+eqtRkKX2Jb8UQN5ZPWnhDCGj/wR6Jlz2w= +github.com/mdlayher/genetlink v1.3.1/go.mod h1:uaIPxkWmGk753VVIzDtROxQ8+T+dkHqOI0vB1NA9S/Q= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= -github.com/mdlayher/netlink v1.6.0/go.mod h1:0o3PlBmGst1xve7wQ7j/hwpNaFaH4qCRyWCdcZk8/vA= github.com/mdlayher/netlink v1.7.1 h1:FdUaT/e33HjEXagwELR8R3/KL1Fq5x3G5jgHLp/BTmg= github.com/mdlayher/netlink v1.7.1/go.mod h1:nKO5CSjE/DJjVhk/TNp6vCE1ktVxEA8VEh8drhZzxsQ= github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ3c= github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE= -github.com/mdlayher/socket v0.1.1/go.mod h1:mYV5YIZAfHh4dzDVzI8x8tWLWCliuX8Mon5Awbj+qDs= github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw= github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc= -github.com/metal-stack/metal-go v0.22.0 h1:bYAMplUjmGu62RVAVyWNMEetnExnfvwyOuf7m82ujvg= -github.com/metal-stack/metal-go v0.22.0/go.mod h1:IZ7qY6dUAi72ZTz7Ni5cwWzzUXJj2Or1t04c3u4AUzU= +github.com/metal-stack/metal-go v0.22.1 h1:obKgLfd46VsznNZtBjQQUuRJ1fqcyitYgBGAg69S44Y= +github.com/metal-stack/metal-go v0.22.1/go.mod h1:IZ7qY6dUAi72ZTz7Ni5cwWzzUXJj2Or1t04c3u4AUzU= github.com/metal-stack/metal-lib v0.11.3 h1:0VyfzyfwTYuaKn7ggok6ieU1MDY+RfbxOTL+Bji89x4= github.com/metal-stack/metal-lib v0.11.3/go.mod h1:Ge1ypz6aOf2ab98kr8GYMXD8eZ7VfKFUfUE3p/8Sm3g= github.com/metal-stack/security v0.6.6 h1:KSPNN8YZd2EJEjsJ0xCBcd5o53uU0iFupahHA9Twuh0= @@ -492,8 +489,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= -github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -536,14 +533,15 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d h1:K3j02b5j2Iw1xoggN9B2DIEkhWGheqFOeDkdJdBrJI8= github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d/go.mod h1:2P+hpOwd53e7JMX/L4f3VXkv1G+33ES6IWZSrkIeWNs= -github.com/tailscale/golang-x-crypto v0.0.0-20221102133106-bc99ab8c2d17 h1:cSm67hIDABvL13S0n9TNoVhzYwjb24M46znbABLll18= -github.com/tailscale/golang-x-crypto v0.0.0-20221102133106-bc99ab8c2d17/go.mod h1:95n9fbUCixVSI4QXLEvdKJjnYK2eUlkTx9+QwLPXFKU= +github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2 h1:pBpqbsyX9H8c26oPYC2H+232HOdp1gDnCztoKmKWKDA= +github.com/tailscale/golang-x-crypto v0.0.0-20221115211329-17a3db2c30d2/go.mod h1:V2G8jyemEGZWKQ+3xNn4+bOx+FuoXU9Zc5GUsZMthBg= github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05 h1:4chzWmimtJPxRs2O36yuGRW3f9SYV+bMTTvMBI0EKio= github.com/tailscale/goupnp v1.0.1-0.20210804011211-c64d0f06ea05/go.mod h1:PdCqy9JzfWMJf1H5UJW2ip33/d4YkoKN0r67yKH1mG8= github.com/tailscale/netlink v1.1.1-0.20211101221916-cabfb018fe85 h1:zrsUcqrG2uQSPhaUPjUQwozcRdDdSxxqhNgNZ3drZFk= @@ -553,8 +551,8 @@ github.com/tcnksm/go-httpstat v0.2.0/go.mod h1:s3JVJFtQxtBEBC9dwcdTTXS9xFnM3SXAZ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= +github.com/u-root/uio v0.0.0-20221213070652-c3537552635f h1:dpx1PHxYqAnXzbryJrWP1NQLzEjwcVgFLhkknuFQ7ww= +github.com/u-root/uio v0.0.0-20221213070652-c3537552635f/go.mod h1:IogEAUBXDEwX7oR/BMmCctShYs80ql4hF0ySdzGxf7E= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= @@ -580,8 +578,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= -go.mongodb.org/mongo-driver v1.11.0 h1:FZKhBSTydeuffHj9CBjXlR8vQLee1cQyTWYPA6/tqiE= -go.mongodb.org/mongo-driver v1.11.0/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= +go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -631,8 +629,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230223210539-50820d90acfd h1:wtFuj4DoOcAdb82Zh2PI90xiaqgp7maYA7KxjQXVtkY= -golang.org/x/exp v0.0.0-20230223210539-50820d90acfd/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI= +golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/exp/typeparams v0.0.0-20220328175248-053ad81199eb h1:fP6C8Xutcp5AlakmT/SkQot0pMicROAsEX7OfNPuG10= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -697,9 +695,7 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= -golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= @@ -787,11 +783,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1019,8 +1013,8 @@ honnef.co/go/tools v0.4.0-0.dev.0.20220517111757-f4a2f64ce238 h1:8Vr1KP9OTjoKQSS howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= inet.af/peercred v0.0.0-20210906144145-0893ea02156a h1:qdkS8Q5/i10xU2ArJMKYhVa1DORzBfYS/qA2UK2jheg= inet.af/peercred v0.0.0-20210906144145-0893ea02156a/go.mod h1:FjawnflS/udxX+SvpsMgZfdqx2aykOlkISeAsADi5IU= -k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d h1:oFDpQ7FfzinCtrFOl4izwOWsdTprlS2A9IXBENMW0UA= -k8s.io/kube-openapi v0.0.0-20230217203603-ff9a8e8fa21d/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= +k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b h1:4dkmFEDQj0ZBLKCxJ0R+qzhvZmEvRdRaaZAE06tR/Lg= +k8s.io/kube-openapi v0.0.0-20230224204730-66828de6f33b/go.mod h1:y5VtZWM9sHHc2ZodIH/6SHzXj+TPU5USoA8lcIeKEKY= nhooyr.io/websocket v1.8.7 h1:usjR2uOr/zjjkVMy0lW+PPohFok7PCow5sDjLgX4P4g= nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=