Fix tsh ls -R -v formatting (#69562)

https://github.com/gravitational/teleport/pull/69282 incorrectly moved the
columns for recusrive listings which resulted in the data being presented
incorrectly. Equivalent golden tests for non-recursive listings have been
added to catch and prevent future regressions.
This commit is contained in:
rosstimothy
2026-08-11 19:55:45 +00:00
committed by GitHub
parent 5cf14ff0e2
commit 654ec63590
8 changed files with 123 additions and 2 deletions
@@ -0,0 +1,5 @@
Proxy Cluster SSH Server ID Hostname Address Labels
--------------- ------- --------------- --------------- ---------- ------------
proxy.exampl... root unscoped-uui... unscoped-hos... 1.2.3.4:22 env=produ...
proxy.exampl... leaf /west::scope... scoped-host 5.6.7.8:22 env=stagi...
@@ -0,0 +1,4 @@
Proxy Cluster SSH Server ID Hostname Address Labels
--------------- ------- --------------- ----------- ---------- -----------
proxy.exampl... leaf /west::scope... scoped-host 5.6.7.8:22 env=staging
@@ -0,0 +1,4 @@
Proxy Cluster Hostname Address Labels
------------------- ------- ------------- ---------- --------------
proxy.example.co... root unscoped-host 1.2.3.4:22 env=production
@@ -0,0 +1,5 @@
Proxy Cluster SSH Server ID Hostname Address Labels
--------------------- ------- ------------------ ------------- ---------- --------------
proxy.example.com:443 root unscoped-uuid unscoped-host 1.2.3.4:22 env=production
proxy.example.com:443 leaf /west::scoped-uuid scoped-host 5.6.7.8:22 env=staging
@@ -0,0 +1,4 @@
Proxy Cluster SSH Server ID Hostname Address Labels
--------------------- ------- ------------------ ----------- ---------- -----------
proxy.example.com:443 leaf /west::scoped-uuid scoped-host 5.6.7.8:22 env=staging
@@ -0,0 +1,4 @@
Proxy Cluster SSH Server ID Hostname Address Labels
--------------------- ------- ------------- ------------- ---------- --------------
proxy.example.com:443 root unscoped-uuid unscoped-host 1.2.3.4:22 env=production
+2 -2
View File
@@ -3249,10 +3249,10 @@ func printNodesWithClusters(nodes []nodeListing, verbose bool, output io.Writer)
var t asciitable.Table
if verbose {
t = asciitable.MakeTable([]string{"SSH Server ID", "Proxy", "Cluster", "Hostname", "Address", "Labels"}, rows...)
t = asciitable.MakeTable([]string{"Proxy", "Cluster", "SSH Server ID", "Hostname", "Address", "Labels"}, rows...)
} else {
if withScope {
t = asciitable.MakeTableWithTruncatedColumn([]string{"SSH Server ID", "Proxy", "Cluster", "Hostname", "Address", "Labels"}, rows, "Labels")
t = asciitable.MakeTableWithTruncatedColumn([]string{"Proxy", "Cluster", "SSH Server ID", "Hostname", "Address", "Labels"}, rows, "Labels")
} else {
t = asciitable.MakeTableWithTruncatedColumn([]string{"Proxy", "Cluster", "Hostname", "Address", "Labels"}, rows, "Labels")
}
+95
View File
@@ -1329,6 +1329,101 @@ func TestPrintNodesAsText(t *testing.T) {
}
}
// TestPrintNodesWithClusters verifies the expected behavior of recursive node listings.
func TestPrintNodesWithClusters(t *testing.T) {
t.Parallel()
unscoped := &types.ServerV2{
Kind: types.KindNode,
Metadata: types.Metadata{
Name: "unscoped-uuid",
Labels: map[string]string{
"env": "production",
},
},
Spec: types.ServerSpecV2{
Addr: "1.2.3.4:22",
Hostname: "unscoped-host",
},
Version: types.V2,
}
scoped := &types.ServerV2{
Kind: types.KindNode,
Metadata: types.Metadata{
Name: "scoped-uuid",
Labels: map[string]string{
"env": "staging",
},
},
Scope: "/west",
Spec: types.ServerSpecV2{
Addr: "5.6.7.8:22",
Hostname: "scoped-host",
},
Version: types.V2,
}
unscopedListing := nodeListing{
Proxy: "proxy.example.com:443",
Cluster: "root",
Node: unscoped,
}
scopedListing := nodeListing{
Proxy: "proxy.example.com:443",
Cluster: "leaf",
Node: scoped,
}
mixedListings := []nodeListing{unscopedListing, scopedListing}
tests := []struct {
name string
nodes []nodeListing
verbose bool
}{
{
name: "non-verbose unscoped",
nodes: []nodeListing{unscopedListing},
},
{
name: "non-verbose scoped",
nodes: []nodeListing{scopedListing},
},
{
name: "non-verbose mixed scopes",
nodes: mixedListings,
},
{
name: "verbose unscoped",
nodes: []nodeListing{unscopedListing},
verbose: true,
},
{
name: "verbose scoped",
nodes: []nodeListing{scopedListing},
verbose: true,
},
{
name: "verbose mixed scopes",
nodes: mixedListings,
verbose: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var buf bytes.Buffer
require.NoError(t, printNodesWithClusters(tt.nodes, tt.verbose, &buf))
if golden.ShouldSet() {
golden.Set(t, buf.Bytes())
}
require.Equal(t, string(golden.Get(t)), buf.String())
})
}
}
func TestMakeClient(t *testing.T) {
t.Parallel()