[client] Add --table output to netbird status (#8305)

This commit is contained in:
Misha Bragin
2026-10-24 14:01:45 -04:00
committed by GitHub
parent 9dd51ca42e
commit dd38fabc82
4 changed files with 296 additions and 2 deletions
+6 -2
View File
@@ -19,6 +19,7 @@ import (
var (
detailFlag bool
tableFlag bool
ipv4Flag bool
ipv6Flag bool
jsonFlag bool
@@ -43,11 +44,12 @@ func init() {
ipsFilterMap = make(map[string]struct{})
prefixNamesFilterMap = make(map[string]struct{})
statusCmd.PersistentFlags().BoolVarP(&detailFlag, "detail", "d", false, "display detailed status information in human-readable format")
statusCmd.PersistentFlags().BoolVarP(&tableFlag, "table", "t", false, "display peers in a table, supports the --filter-by-* flags")
statusCmd.PersistentFlags().BoolVarP(&jsonFlag, "json", "j", false, "display detailed status information in json format")
statusCmd.PersistentFlags().BoolVarP(&yamlFlag, "yaml", "y", false, "display detailed status information in yaml format")
statusCmd.PersistentFlags().BoolVarP(&ipv4Flag, "ipv4", "4", false, "display only NetBird IPv4 of this peer, e.g., --ipv4 will output 100.64.0.33")
statusCmd.PersistentFlags().BoolVarP(&ipv6Flag, "ipv6", "6", false, "display only NetBird IPv6 of this peer")
statusCmd.MarkFlagsMutuallyExclusive("detail", "json", "yaml", "ipv4", "ipv6")
statusCmd.MarkFlagsMutuallyExclusive("detail", "table", "json", "yaml", "ipv4", "ipv6")
statusCmd.PersistentFlags().StringSliceVarP(&ipsFilter, "filter-by-ips", "I", []string{}, "filters the detailed output by a list of one or more IPs (v4 or v6), e.g., --filter-by-ips 100.64.0.100,fd00::1")
statusCmd.PersistentFlags().StringSliceVarP(&prefixNamesFilter, "filter-by-names", "N", []string{}, "filters the detailed output by a list of one or more peer FQDN or hostnames, e.g., --filter-by-names peer-a,peer-b.netbird.cloud")
statusCmd.PersistentFlags().StringVarP(&statusFilter, "filter-by-status", "S", "", "filters the detailed output by connection status(idle|connecting|connected), e.g., --filter-by-status connected")
@@ -143,6 +145,8 @@ func statusFunc(cmd *cobra.Command, args []string) error {
switch {
case detailFlag:
statusOutputString = outputInformationHolder.FullDetailSummary()
case tableFlag:
statusOutputString = outputInformationHolder.PeersTable()
case jsonFlag:
statusOutputString, err = outputInformationHolder.JSON()
case yamlFlag:
@@ -238,7 +242,7 @@ func parseFilters() error {
}
func enableDetailFlagWhenFilterFlag() {
if !detailFlag && !jsonFlag && !yamlFlag {
if !detailFlag && !jsonFlag && !yamlFlag && !tableFlag {
detailFlag = true
}
}
+59
View File
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParsingOfIP(t *testing.T) {
@@ -13,3 +14,61 @@ func TestParsingOfIP(t *testing.T) {
assert.Equal(t, "192.168.178.123\n", parsedIP)
}
// resetStatusFlags restores only the status-specific output flags. The global
// root flags (setup-key and friends) are shared with other tests in the
// package, so they must not be touched here.
func resetStatusFlags(t *testing.T) {
t.Helper()
t.Cleanup(func() {
for _, name := range []string{"detail", "table", "json", "yaml", "ipv4", "ipv6"} {
f := statusCmd.Flags().Lookup(name)
require.NotNil(t, f, "flag %s must exist", name)
require.NoError(t, f.Value.Set(f.DefValue))
f.Changed = false
}
})
}
func TestStatusTableFlagExclusive(t *testing.T) {
for _, other := range []string{"detail", "json", "yaml", "ipv4", "ipv6"} {
t.Run(other, func(t *testing.T) {
resetStatusFlags(t)
require.NoError(t, statusCmd.Flags().Set("table", "true"))
require.NoError(t, statusCmd.Flags().Set(other, "true"))
assert.Error(t, statusCmd.ValidateFlagGroups(), "--table with --%s must be rejected", other)
})
}
t.Run("alone", func(t *testing.T) {
resetStatusFlags(t)
require.NoError(t, statusCmd.Flags().Set("table", "true"))
assert.NoError(t, statusCmd.ValidateFlagGroups())
})
}
func TestFilterEnablesDetailOnlyWithoutOutputFormat(t *testing.T) {
tests := []struct {
name string
table bool
json bool
wantDetail bool
}{
{name: "no format", wantDetail: true},
{name: "table", table: true, wantDetail: false},
{name: "json", json: true, wantDetail: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resetStatusFlags(t)
tableFlag, jsonFlag = tt.table, tt.json
enableDetailFlagWhenFilterFlag()
assert.Equal(t, tt.wantDetail, detailFlag)
})
}
}