Configure kingpin to allow DCE (#65897)

* Update kingpin

* Convert CLI formatting to use kingpin UsageRenderers

Avoiding the legacy kingpin text/templates allows for DCE to be used
by the linker. The existing formatting has been matched with a
pure Go UsageRenderer.
This commit is contained in:
rosstimothy
2026-04-22 14:57:55 +00:00
committed by GitHub
parent fd2e58696d
commit 88d82cf476
26 changed files with 268 additions and 125 deletions
+2 -2
View File
@@ -10,7 +10,7 @@ require (
)
require (
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.19.13 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.21 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect
@@ -26,4 +26,4 @@ require (
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
)
replace github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
replace github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61
+13 -8
View File
@@ -1,5 +1,5 @@
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b h1:mimo19zliBX/vSQ6PWWSL9lK8qwHozUj03+zLoEB8O0=
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b/go.mod h1:fvzegU4vN3H1qMT+8wDmzjAcDONcgo2/SZ/TyfdUOFs=
github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY=
github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
github.com/aws/aws-sdk-go-v2/config v1.32.13 h1:5KgbxMaS2coSWRrx9TX/QtWbqzgQkOdEa3sZPhBhCSg=
@@ -33,17 +33,22 @@ github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqx
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33 h1:VFER/+0TfRypJhc9XeuggTtEZzhhe75DSVqMv/avHEU=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61 h1:cgG/o1SAL2WK9AtryT/esiuXqCN47f15EwppKgeom60=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61/go.mod h1:usbNrkVhUGh5+Pqd4u5tYKszWmq6YSCApkePRMmJFP8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+1 -1
View File
@@ -295,7 +295,7 @@ require (
)
replace (
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61
github.com/crewjam/saml => github.com/gravitational/saml v0.4.15-teleport.2
github.com/datastax/go-cassandra-native-protocol => github.com/gravitational/go-cassandra-native-protocol v0.0.0-teleport.3
github.com/go-mysql-org/go-mysql => github.com/gravitational/go-mysql v1.9.1-teleport.4
+2 -2
View File
@@ -480,8 +480,8 @@ github.com/gravitational/go-libfido2 v1.5.3-teleport.1 h1:nPfxiTH2Sr3J6zan280fbH
github.com/gravitational/go-libfido2 v1.5.3-teleport.1/go.mod h1:92J9LtSBl0UyUWljElJpTbMMNhC6VeY8dshsu40qjjo=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5 h1:qg8FcGwRACSHortU1UxCSo9nF0t34rPWjk9Nef3j2Ic=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33 h1:VFER/+0TfRypJhc9XeuggTtEZzhhe75DSVqMv/avHEU=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61 h1:cgG/o1SAL2WK9AtryT/esiuXqCN47f15EwppKgeom60=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61/go.mod h1:usbNrkVhUGh5+Pqd4u5tYKszWmq6YSCApkePRMmJFP8=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1 h1:Kt7aT9N7vbZmcMejGXnSAGap8TUwH3fMoHE8cQm14wc=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1/go.mod h1:n4RXV6T3SJ/vrJqmc4vBeHpaBspxWENDD67ssQlXXkg=
github.com/gravitational/predicate v1.3.4 h1:9N3JhBXNPcUh0w8DdlpnVmfnH9Z3xxbw43sD3E19VBE=
+1 -1
View File
@@ -292,7 +292,7 @@ require (
)
replace (
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61
github.com/crewjam/saml => github.com/gravitational/saml v0.4.15-teleport.2
github.com/datastax/go-cassandra-native-protocol => github.com/gravitational/go-cassandra-native-protocol v0.0.0-teleport.3
github.com/go-mysql-org/go-mysql => github.com/gravitational/go-mysql v1.9.1-teleport.4
+2 -2
View File
@@ -476,8 +476,8 @@ github.com/gravitational/go-libfido2 v1.5.3-teleport.1 h1:nPfxiTH2Sr3J6zan280fbH
github.com/gravitational/go-libfido2 v1.5.3-teleport.1/go.mod h1:92J9LtSBl0UyUWljElJpTbMMNhC6VeY8dshsu40qjjo=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5 h1:qg8FcGwRACSHortU1UxCSo9nF0t34rPWjk9Nef3j2Ic=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33 h1:VFER/+0TfRypJhc9XeuggTtEZzhhe75DSVqMv/avHEU=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61 h1:cgG/o1SAL2WK9AtryT/esiuXqCN47f15EwppKgeom60=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61/go.mod h1:usbNrkVhUGh5+Pqd4u5tYKszWmq6YSCApkePRMmJFP8=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1 h1:Kt7aT9N7vbZmcMejGXnSAGap8TUwH3fMoHE8cQm14wc=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1/go.mod h1:n4RXV6T3SJ/vrJqmc4vBeHpaBspxWENDD67ssQlXXkg=
github.com/gravitational/predicate v1.3.4 h1:9N3JhBXNPcUh0w8DdlpnVmfnH9Z3xxbw43sD3E19VBE=
+1 -1
View File
@@ -624,7 +624,7 @@ require (
// when changing the replace directives make sure to also apply the same changes
// to modules that require github.com/gravitational/teleport
replace (
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61
github.com/crewjam/saml => github.com/gravitational/saml v0.4.15-teleport.2
github.com/datastax/go-cassandra-native-protocol => github.com/gravitational/go-cassandra-native-protocol v0.0.0-teleport.3
github.com/go-mysql-org/go-mysql => github.com/gravitational/go-mysql v1.9.1-teleport.4
+2 -2
View File
@@ -787,8 +787,8 @@ github.com/gravitational/go-mysql v1.9.1-teleport.4 h1:2Lt2fcEMrco6apu8jme0mj6OS
github.com/gravitational/go-mysql v1.9.1-teleport.4/go.mod h1:pkllauQtJgHr2mTonYYysOznctozxiWgwpKAez0s+2U=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5 h1:qg8FcGwRACSHortU1UxCSo9nF0t34rPWjk9Nef3j2Ic=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33 h1:VFER/+0TfRypJhc9XeuggTtEZzhhe75DSVqMv/avHEU=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61 h1:cgG/o1SAL2WK9AtryT/esiuXqCN47f15EwppKgeom60=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61/go.mod h1:usbNrkVhUGh5+Pqd4u5tYKszWmq6YSCApkePRMmJFP8=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1 h1:Kt7aT9N7vbZmcMejGXnSAGap8TUwH3fMoHE8cQm14wc=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1/go.mod h1:n4RXV6T3SJ/vrJqmc4vBeHpaBspxWENDD67ssQlXXkg=
github.com/gravitational/predicate v1.3.4 h1:9N3JhBXNPcUh0w8DdlpnVmfnH9Z3xxbw43sD3E19VBE=
+1 -1
View File
@@ -394,7 +394,7 @@ require (
)
replace (
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61
github.com/crewjam/saml => github.com/gravitational/saml v0.4.15-teleport.2
github.com/datastax/go-cassandra-native-protocol => github.com/gravitational/go-cassandra-native-protocol v0.0.0-teleport.3
github.com/go-mysql-org/go-mysql => github.com/gravitational/go-mysql v1.9.1-teleport.4
+2 -2
View File
@@ -529,8 +529,8 @@ github.com/gravitational/go-mysql v1.9.1-teleport.4 h1:2Lt2fcEMrco6apu8jme0mj6OS
github.com/gravitational/go-mysql v1.9.1-teleport.4/go.mod h1:pkllauQtJgHr2mTonYYysOznctozxiWgwpKAez0s+2U=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5 h1:qg8FcGwRACSHortU1UxCSo9nF0t34rPWjk9Nef3j2Ic=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33 h1:VFER/+0TfRypJhc9XeuggTtEZzhhe75DSVqMv/avHEU=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61 h1:cgG/o1SAL2WK9AtryT/esiuXqCN47f15EwppKgeom60=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61/go.mod h1:usbNrkVhUGh5+Pqd4u5tYKszWmq6YSCApkePRMmJFP8=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1 h1:Kt7aT9N7vbZmcMejGXnSAGap8TUwH3fMoHE8cQm14wc=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1/go.mod h1:n4RXV6T3SJ/vrJqmc4vBeHpaBspxWENDD67ssQlXXkg=
github.com/gravitational/predicate v1.3.4 h1:9N3JhBXNPcUh0w8DdlpnVmfnH9Z3xxbw43sD3E19VBE=
+1 -1
View File
@@ -525,7 +525,7 @@ require (
)
replace (
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61
github.com/crewjam/saml => github.com/gravitational/saml v0.4.15-teleport.2
github.com/datastax/go-cassandra-native-protocol => github.com/gravitational/go-cassandra-native-protocol v0.0.0-teleport.3
github.com/go-mysql-org/go-mysql => github.com/gravitational/go-mysql v1.9.1-teleport.4
+2 -2
View File
@@ -729,8 +729,8 @@ github.com/gravitational/go-mysql v1.9.1-teleport.4 h1:2Lt2fcEMrco6apu8jme0mj6OS
github.com/gravitational/go-mysql v1.9.1-teleport.4/go.mod h1:pkllauQtJgHr2mTonYYysOznctozxiWgwpKAez0s+2U=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5 h1:qg8FcGwRACSHortU1UxCSo9nF0t34rPWjk9Nef3j2Ic=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33 h1:VFER/+0TfRypJhc9XeuggTtEZzhhe75DSVqMv/avHEU=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61 h1:cgG/o1SAL2WK9AtryT/esiuXqCN47f15EwppKgeom60=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61/go.mod h1:usbNrkVhUGh5+Pqd4u5tYKszWmq6YSCApkePRMmJFP8=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1 h1:Kt7aT9N7vbZmcMejGXnSAGap8TUwH3fMoHE8cQm14wc=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1/go.mod h1:n4RXV6T3SJ/vrJqmc4vBeHpaBspxWENDD67ssQlXXkg=
github.com/gravitational/predicate v1.3.4 h1:9N3JhBXNPcUh0w8DdlpnVmfnH9Z3xxbw43sD3E19VBE=
+1 -1
View File
@@ -523,7 +523,7 @@ require (
)
replace (
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33
github.com/alecthomas/kingpin/v2 => github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61
github.com/crewjam/saml => github.com/gravitational/saml v0.4.15-teleport.2
github.com/datastax/go-cassandra-native-protocol => github.com/gravitational/go-cassandra-native-protocol v0.0.0-teleport.3
github.com/go-mysql-org/go-mysql => github.com/gravitational/go-mysql v1.9.1-teleport.4
+2 -2
View File
@@ -828,8 +828,8 @@ github.com/gravitational/go-mysql v1.9.1-teleport.4 h1:2Lt2fcEMrco6apu8jme0mj6OS
github.com/gravitational/go-mysql v1.9.1-teleport.4/go.mod h1:pkllauQtJgHr2mTonYYysOznctozxiWgwpKAez0s+2U=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5 h1:qg8FcGwRACSHortU1UxCSo9nF0t34rPWjk9Nef3j2Ic=
github.com/gravitational/httprouter v1.3.1-0.20220408074523-c876c5e705a5/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33 h1:VFER/+0TfRypJhc9XeuggTtEZzhhe75DSVqMv/avHEU=
github.com/gravitational/kingpin/v2 v2.1.11-0.20230515143221-4ec6b70ecd33/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61 h1:cgG/o1SAL2WK9AtryT/esiuXqCN47f15EwppKgeom60=
github.com/gravitational/kingpin/v2 v2.1.11-0.20260417152838-9efcbe7e5d61/go.mod h1:usbNrkVhUGh5+Pqd4u5tYKszWmq6YSCApkePRMmJFP8=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1 h1:Kt7aT9N7vbZmcMejGXnSAGap8TUwH3fMoHE8cQm14wc=
github.com/gravitational/license v0.0.0-20250329001817-070456fa8ec1/go.mod h1:n4RXV6T3SJ/vrJqmc4vBeHpaBspxWENDD67ssQlXXkg=
github.com/gravitational/predicate v1.3.4 h1:9N3JhBXNPcUh0w8DdlpnVmfnH9Z3xxbw43sD3E19VBE=
+66 -69
View File
@@ -30,7 +30,6 @@ import (
"runtime"
"strconv"
"strings"
"text/template"
"unicode"
"github.com/alecthomas/kingpin/v2"
@@ -344,20 +343,7 @@ func InitCLIParser(appName, appHelp string) (app *kingpin.Application) {
// write --help output to stdout instead of stderr
app.UsageWriter(os.Stdout)
// set our own help template
app.UsageFuncs(template.FuncMap{
"CommandPrintfWidth": func(cmds []*kingpin.CmdModel) int {
cmdWidth := defaultCommandPrintfWidth
for _, cmd := range cmds {
if cmd.Hidden {
continue
}
cmdWidth = max(cmdWidth, len(cmd.Name))
}
return cmdWidth
},
})
return app.UsageTemplate(defaultUsageTemplate)
return app.UsageRenderer(renderCompactUsage)
}
// InitHiddenCLIParser initializes a `kingpin.Application` that does not terminate the application
@@ -447,65 +433,76 @@ func needsQuoting(text string) bool {
// defaultCommandPrintfWidth is the default command printf width.
const defaultCommandPrintfWidth = 12
// defaultUsageTemplate is a fmt format that defines the usage template with
// compactly formatted commands. Should be only used in createUsageTemplate.
const defaultUsageTemplate = `{{define "FormatCommand" -}}
{{if .FlagSummary}} {{.FlagSummary}}{{end -}}
{{range .Args}} {{if not .Required}}[{{end}}<{{.Name}}>{{if .Value|IsCumulative}}...{{end}}{{if not .Required}}]{{end}}{{end -}}
{{end -}}
// renderCompactUsage is a kingpin UsageRenderer used by all binaries to
// output usage text. It uses a kingpin UsageRenderer instead of
// UsageTemplate/UsageFuncs in order to avoid text/template (and reflect.MethodByName)
// so that the linker can enable dead-code elimination.
func renderCompactUsage(w io.Writer, ctx *kingpin.UsageContext) error {
width := ctx.Width
{{define "FormatCommands" -}}
{{- $cmdWidth := .Commands | CommandPrintfWidth -}}
{{range .Commands -}}
{{if not .Hidden -}}
{{" "}}{{printf (printf "%%-%ds" $cmdWidth) .Name}}{{if .Default}} (Default){{end}} {{ .Help }}
{{end -}}
{{end -}}
{{end -}}
if ctx.Context.SelectedCommand != nil {
cmd := ctx.Context.SelectedCommand
fmt.Fprintf(w, "usage: %s %s", ctx.App.Name, cmd.String())
kingpin.WriteFormatUsage(w, cmd.FlagGroupModel, cmd.ArgGroupModel, cmd.CmdGroupModel, cmd.Help, width)
} else {
fmt.Fprintf(w, "Usage: %s", ctx.App.Name)
kingpin.WriteFormatUsage(w, ctx.App.FlagGroupModel, ctx.App.ArgGroupModel, ctx.App.CmdGroupModel, ctx.App.Help, width)
}
fmt.Fprintln(w)
{{define "FormatUsage" -}}
{{template "FormatCommand" .}}{{if .Commands}} <command> [<args> ...]{{end}}
{{if .Help}}
{{.Help|Wrap 0 -}}
{{end -}}
if len(ctx.Context.Flags) > 0 {
fmt.Fprintln(w, "Flags:")
kingpin.FormatTwoColumns(w, ctx.Indent, 2, width, kingpin.FlagsToTwoColumns(ctx.Context.Flags))
fmt.Fprintln(w)
}
if len(ctx.Context.Args) > 0 {
fmt.Fprintln(w, "Args:")
kingpin.FormatTwoColumns(w, ctx.Indent, 2, width, kingpin.ArgsToTwoColumns(ctx.Context.Args))
fmt.Fprintln(w)
}
{{end -}}
writeCommands := func(cmds []*kingpin.CmdModel) {
cmdWidth := defaultCommandPrintfWidth
for _, cmd := range cmds {
if cmd.Hidden {
continue
}
cmdWidth = max(cmdWidth, len(cmd.Name))
}
for _, cmd := range cmds {
if cmd.Hidden {
continue
}
fmt.Fprintf(w, " %-*s", cmdWidth, cmd.Name)
if cmd.Default {
fmt.Fprint(w, " (Default)")
}
fmt.Fprintf(w, " %s\n", cmd.Help)
}
}
{{if .Context.SelectedCommand -}}
usage: {{.App.Name}} {{.Context.SelectedCommand}}{{template "FormatUsage" .Context.SelectedCommand}}
{{else -}}
Usage: {{.App.Name}}{{template "FormatUsage" .App}}
{{end -}}
{{if .Context.Flags -}}
Flags:
{{.Context.Flags|FlagsToTwoColumns|FormatTwoColumns}}
{{end -}}
{{if .Context.Args -}}
Args:
{{.Context.Args|ArgsToTwoColumns|FormatTwoColumns}}
{{end -}}
{{if .Context.SelectedCommand -}}
if ctx.Context.SelectedCommand != nil {
if ctx.Context.SelectedCommand.CmdGroupModel != nil && len(ctx.Context.SelectedCommand.Commands) > 0 {
fmt.Fprintln(w, "Commands:")
writeCommands(ctx.Context.SelectedCommand.Commands)
fmt.Fprintln(w)
}
if len(ctx.Context.SelectedCommand.Aliases) > 0 {
fmt.Fprintln(w, "Aliases:")
for _, alias := range ctx.Context.SelectedCommand.Aliases {
fmt.Fprintln(w, alias)
}
fmt.Fprintln(w)
}
} else if ctx.App.CmdGroupModel != nil && len(ctx.App.Commands) > 0 {
fmt.Fprintln(w, "Commands:")
writeCommands(ctx.App.Commands)
fmt.Fprintln(w)
fmt.Fprintf(w, "Try '%s help [command]' to get help for a given command.\n\n", ctx.App.Name)
}
{{ if .Context.SelectedCommand.Commands -}}
Commands:
{{if .Context.SelectedCommand.Commands -}}
{{template "FormatCommands" .Context.SelectedCommand}}
{{end -}}
{{end -}}
{{else if .App.Commands -}}
Commands:
{{template "FormatCommands" .App}}
Try '{{.App.Name}} help [command]' to get help for a given command.
{{end -}}
{{ if .Context.SelectedCommand -}}
Aliases:
{{ range .Context.SelectedCommand.Aliases -}}
{{ . }}
{{end -}}
{{end}}
`
return nil
}
// IsPredicateError determines if the error is from failing to parse predicate expression
// by checking if the error as a string contains predicate keywords.
+53 -4
View File
@@ -262,22 +262,51 @@ func TestFormatCertError(t *testing.T) {
func TestInitCLIParser(t *testing.T) {
makeApp := func(usageWriter io.Writer) *kingpin.Application {
app := InitCLIParser("test", "some help message")
app := InitCLIParser("widget", "Widget is a tool for widgeting. It supports a variety of operations on widgets and the things widgets are made of.")
app.UsageWriter(usageWriter)
app.Terminate(func(int) {})
// Visible top-level flags exercising various attributes (short, envar,
// default, cumulative) plus a hidden flag to confirm it is excluded.
app.Flag("verbose", "Enable verbose output.").Short('v').Bool()
app.Flag("config", "Path to config file.").Short('c').Envar("WIDGET_CONFIG").Default("/etc/widget.yaml").String()
app.Flag("tag", "Tags to apply. Repeatable.").Short('t').Strings()
app.Flag("secret", "Secret flag that should not appear in help.").Hidden().String()
// Simple leaf commands used to exercise top-level command-list
// formatting and the hidden-command filter.
app.Command("hello", "Hello.")
app.Command("very-long-command", "Very long command.")
app.Command("hidden-very-long-command", "This command is hidden.").Hidden()
// Command with subcommand children.
create := app.Command("create", "Create.")
create.Command("box", "Box.")
create.Command("rocket", "Rocket.")
// Command with a default child — regression for #64126.
start := app.Command("start", "Start.")
start.Command("legacy", "Legacy.").Default()
start.Command("workload-identity", "Workload identity.")
// Command with aliases, required args, and a cumulative arg.
ship := app.Command("ship", "Ship a widget to a destination.").Alias("send").Alias("deliver")
ship.Arg("widget", "Name of the widget to ship.").Required().String()
ship.Arg("dest", "Destination, e.g. city or warehouse ID.").Required().String()
ship.Arg("note", "Optional shipping notes, repeatable.").Strings()
ship.Flag("express", "Use express shipping.").Bool()
// Command with children and grandchildren.
inventory := app.Command("inventory", "Manage the widget inventory.")
inventory.Command("list", "List all widgets currently in inventory.")
add := inventory.Command("add", "Add a widget to inventory.")
add.Arg("name", "Widget name.").Required().String()
add.Flag("count", "How many to add.").Default("1").Int()
// Command with a long help blurb that will wrap.
app.Command("reconcile", "Reconcile the local inventory against the remote source of truth. This operation is idempotent and safe to run repeatedly; mismatches are reported but not automatically corrected unless --fix is passed.").
Flag("fix", "Automatically correct any mismatches found during reconciliation.").Bool()
return app
}
@@ -286,8 +315,8 @@ func TestInitCLIParser(t *testing.T) {
inputArgs []string
}{
{
name: "command width expands to longest command",
inputArgs: []string{},
name: "top-level help",
inputArgs: nil,
},
{
name: "command width aligned for subcommand help",
@@ -302,6 +331,26 @@ func TestInitCLIParser(t *testing.T) {
name: "default subcommand does not affect column width",
inputArgs: []string{"start"},
},
{
name: "command with required args, optional cumulative arg, and aliases",
inputArgs: []string{"ship"},
},
{
name: "command with children",
inputArgs: []string{"inventory"},
},
{
name: "nested subcommand with required arg and flag",
inputArgs: []string{"inventory", "add"},
},
{
name: "leaf subcommand under a parent",
inputArgs: []string{"inventory", "list"},
},
{
name: "long help text triggers wrapping",
inputArgs: []string{"reconcile"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
@@ -311,7 +360,7 @@ func TestInitCLIParser(t *testing.T) {
if golden.ShouldSet() {
golden.Set(t, buf.Bytes())
}
require.Equal(t, string(golden.Get(t)), buf.String())
require.Equal(t, golden.Get(t), buf.Bytes())
})
}
}
@@ -1,12 +1,14 @@
usage: test create <command> [<args> ...]
usage: widget create <command> [<args> ...]
Create.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
Commands:
box Box.
rocket Rocket.
Aliases:
@@ -1,8 +1,13 @@
Usage: test <command> [<args> ...]
Usage: widget [<flags>] <command> [<args> ...]
some help message
Widget is a tool for widgeting. It supports a variety of operations on widgets
and the things widgets are made of.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
Commands:
help Show help.
@@ -10,6 +15,9 @@ Commands:
very-long-command Very long command.
create Create.
start Start.
ship Ship a widget to a destination.
inventory Manage the widget inventory.
reconcile Reconcile the local inventory against the remote source of truth. This operation is idempotent and safe to run repeatedly; mismatches are reported but not automatically corrected unless --fix is passed.
Try 'test help [command]' to get help for a given command.
Try 'widget help [command]' to get help for a given command.
@@ -1,15 +0,0 @@
Usage: test <command> [<args> ...]
some help message
Flags:
Commands:
help Show help.
hello Hello.
very-long-command Very long command.
create Create.
start Start.
Try 'test help [command]' to get help for a given command.
@@ -0,0 +1,14 @@
usage: widget inventory <command> [<args> ...]
Manage the widget inventory.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
Commands:
list List all widgets currently in inventory.
add Add a widget to inventory.
@@ -0,0 +1,20 @@
usage: widget ship [<flags>] <widget> <dest> [<note>...]
Ship a widget to a destination.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
--[no-]express Use express shipping.
Args:
<widget> Name of the widget to ship.
<dest> Destination, e.g. city or warehouse ID.
[<note>] Optional shipping notes, repeatable.
Aliases:
send
deliver
@@ -1,12 +1,14 @@
usage: test start <command> [<args> ...]
usage: widget start <command> [<args> ...]
Start.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
Commands:
legacy (Default) Legacy.
workload-identity Workload identity.
Aliases:
@@ -0,0 +1,10 @@
usage: widget inventory list
List all widgets currently in inventory.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
@@ -0,0 +1,14 @@
usage: widget reconcile [<flags>]
Reconcile the local inventory against the remote source of truth. This operation
is idempotent and safe to run repeatedly; mismatches are reported but not
automatically corrected unless --fix is passed.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
--[no-]fix Automatically correct any mismatches found during
reconciliation.
@@ -0,0 +1,14 @@
usage: widget inventory add [<flags>] <name>
Add a widget to inventory.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
--count=1 How many to add.
Args:
<name> Widget name.
@@ -0,0 +1,23 @@
Usage: widget [<flags>] <command> [<args> ...]
Widget is a tool for widgeting. It supports a variety of operations on widgets
and the things widgets are made of.
Flags:
-v, --[no-]verbose Enable verbose output.
-c, --config="/etc/widget.yaml"
Path to config file. ($WIDGET_CONFIG)
-t, --tag=TAG ... Tags to apply. Repeatable.
Commands:
help Show help.
hello Hello.
very-long-command Very long command.
create Create.
start Start.
ship Ship a widget to a destination.
inventory Manage the widget inventory.
reconcile Reconcile the local inventory against the remote source of truth. This operation is idempotent and safe to run repeatedly; mismatches are reported but not automatically corrected unless --fix is passed.
Try 'widget help [command]' to get help for a given command.