From 483605e099e53a7f23a990dee07241a4767c79d1 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Wed, 5 Aug 2020 18:24:00 +0300 Subject: [PATCH 01/41] First prototype of transition to cobra --- go.mod | 4 +- go.sum | 99 +++++++++++++++++--- internals/cli/env.go | 124 ++++++++++++++++++------- internals/secrethub/app.go | 82 ++++++++-------- internals/secrethub/clear_clipboard.go | 5 +- internals/secrethub/command/command.go | 10 +- internals/secrethub/flags.go | 10 +- internals/secrethub/read.go | 6 +- 8 files changed, 230 insertions(+), 110 deletions(-) diff --git a/go.mod b/go.mod index 227fefe6..cdabf7d5 100644 --- a/go.mod +++ b/go.mod @@ -18,13 +18,13 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/secrethub/demo-app v0.1.0 github.com/secrethub/secrethub-go v0.30.0 + github.com/spf13/cobra v1.0.0 + github.com/spf13/pflag v1.0.5 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d golang.org/x/sys v0.0.0-20200501052902-10377860bb8e golang.org/x/text v0.3.2 google.golang.org/api v0.26.0 - google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 gopkg.in/yaml.v2 v2.2.2 gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 4a4de5e0..209c0ae5 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022 h1:y8Gs8CzNfDF5AZvjr+5UyGQvQEBL7pwo+v+wX6q9JI8= github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/alecthomas/kingpin v0.0.0-20190930021037-0a108b7f5563 h1:YT8l7Flq7VNXnjqwtjCF9bzffTPGgedBC+xyj88lVe4= github.com/alecthomas/kingpin v0.0.0-20190930021037-0a108b7f5563/go.mod h1:idxgS9pV6OOpAhZvx+gcoGRMX9/tt0iqkw/pNxI0C14= github.com/alecthomas/kingpin v1.3.8-0.20200323085623-b6657d9477a6 h1:nesv3dEn8GDv0ZMxkoCSvrxOE5KbzXXHtWEqJvYA/gw= @@ -39,6 +40,7 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5Vpd github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf h1:eg0MeVzsP1G42dRafH3vf+al2vQIJU0YHX+1Tw87oco= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/atotto/clipboard v0.1.2 h1:YZCtFu5Ie8qX2VmVTBnrqLSiU9XOWwqNRmdT3gIQzbY= @@ -47,18 +49,29 @@ github.com/aws/aws-sdk-go v1.19.38 h1:WKjobgPO4Ua1ww2NJJl2/zQNreUZxvqmEzwMlRjjm9 github.com/aws/aws-sdk-go v1.19.38/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.49 h1:j5R2Ey+g8qaiy2NJ9iH+KWzDWS4SjXRCjhc22EeQVE4= github.com/aws/aws-sdk-go v1.25.49/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU= github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/docker v1.13.1 h1:IkZjBSIc8hBjLpqeAbeE5mca5mNgeatLHBy3GO78BWo= github.com/docker/docker v1.13.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk= @@ -69,16 +82,25 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-chi/chi v4.0.1+incompatible h1:RSRC5qmFPtO90t7pTL0DBMNpZFsb/sHF3RXVlDgFisA= github.com/go-chi/chi v4.0.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= @@ -119,14 +141,26 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -134,6 +168,7 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9 h1:SmVbOZFWAlyQshuMfOkiAx1f5oUTsOGG5IXplAEYeeM= github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc= github.com/masterzen/winrm v0.0.0-20190308153735-1d17eaf15943 h1:Bteu9XN1gkBePnKr0v1edkUo2LJRsmK5ne2FrC6yVW4= @@ -145,41 +180,57 @@ github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-shellwords v1.0.6 h1:9Jok5pILi5S1MnDirGVTufYGtksUs/V2BWUP3ZkeUUI= github.com/mattn/go-shellwords v1.0.6/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/secrethub/demo-app v0.1.0 h1:HwPPxuiSvx4TBE7Qppzu3A9eHqmsBrIz4Ko8u8pqMqw= github.com/secrethub/demo-app v0.1.0/go.mod h1:ymjm8+WXTSDTFqsGVBNVmHSnwtZMYi7KptHvpo/fLH4= github.com/secrethub/secrethub-cli v0.30.0/go.mod h1:dC0wd40v+iQdV83/0rUrOa01LYq+8Yj2AtJB1vzh2ao= github.com/secrethub/secrethub-go v0.21.0/go.mod h1:rc2IfKKBJ4L0wGec0u4XnF5/pe0FFPE4Q1MWfrFso7s= -github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36 h1:kRVdL7PRfR80xjpOxFy1O0JROVpILWc2FZWE7Ni2Z2M= -github.com/secrethub/secrethub-go v0.29.1-0.20200626075900-f7c68f70dc36/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add h1:+DzHsSjht15ycb7GFmyfmQ39gy8ZtA7FjWfJbWUPIYk= -github.com/secrethub/secrethub-go v0.29.1-0.20200630121846-9adfc0eb3add/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a h1:rtFQLsSWGkdqd6LQFbgHsG/be60Cpqv8tc1w4XoKgKM= -github.com/secrethub/secrethub-go v0.29.1-0.20200702094400-d465926a4a6a/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91 h1:10KZJ3o7hodrTO1xAP1uNhDWSlLV9Bh9RqRFtiNCYJ4= -github.com/secrethub/secrethub-go v0.29.1-0.20200702114848-1a3657310d91/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4 h1:TszZ+u/DRpPjaAGwEFSQNHkWhG4QR3KBxQJ66NfTAMk= -github.com/secrethub/secrethub-go v0.29.1-0.20200703092019-9f5d3de9b0e4/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d h1:tADItWP+YXaGLD1ZMFocxDaKKVcu8wXgEulbcUmX4Ec= -github.com/secrethub/secrethub-go v0.29.1-0.20200703150346-411544a71e9d/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= -github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597 h1:uC9ODMKaqBo1k8fxmFSWGkLr05TgEd3t4mHqJ8Jo9Gc= -github.com/secrethub/secrethub-go v0.29.1-0.20200707154958-5e5602145597/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= github.com/secrethub/secrethub-go v0.30.0 h1:Nh1twPDwPbYQj/cYc1NG+j7sv76LZiXLPovyV83tZj0= github.com/secrethub/secrethub-go v0.30.0/go.mod h1:tDeBtyjfFQX3UqgaZfY+H4dYkcGfiVzrwLDf0XtfOrw= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= @@ -188,15 +239,24 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 h1:U5I57s4ISLpeeLYl8b3MsainSSh9F+mRXauln37b50I= github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07/go.mod h1:XlXBIfkGawHNVOHlenOaBW7zlfCh8LovwjOgjamYnkQ= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 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= go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a h1:YX8ljsm6wXlHZO+aRz9Exqr0evNhKRNe5K/gi+zKh4U= @@ -236,6 +296,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -269,6 +331,9 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= @@ -301,6 +366,7 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -378,6 +444,7 @@ google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYU google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -393,10 +460,14 @@ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQ google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= diff --git a/internals/cli/env.go b/internals/cli/env.go index 21c16046..33bcd421 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -2,13 +2,16 @@ package cli import ( "fmt" + "github.com/spf13/pflag" "io" "os" + "strconv" "strings" "text/tabwriter" + "time" "bitbucket.org/zombiezen/cardcpx/natsort" - "github.com/alecthomas/kingpin" + "github.com/spf13/cobra" ) var ( @@ -21,53 +24,53 @@ var ( // App represents a command-line application that wraps the // kingpin library and adds additional functionality. type App struct { - *kingpin.Application - + Application cobra.Command name string delimiters []string separator string knownEnvVars map[string]struct{} - extraEnvVarFuncs [](func(key string) bool) + extraEnvVarFuncs []func(key string) bool } // NewApp defines a new command-line application. func NewApp(name, help string) *App { return &App{ - Application: kingpin.New(name, help), + Application: cobra.Command{Use: name, Short: help}, name: formatName(name, "", DefaultEnvSeparator, DefaultCommandDelimiters...), delimiters: DefaultCommandDelimiters, separator: DefaultEnvSeparator, knownEnvVars: make(map[string]struct{}), - extraEnvVarFuncs: [](func(string) bool){}, + extraEnvVarFuncs: []func(string) bool{}, } } // Command defines a new top-level command with the given name and help text. func (a *App) Command(name, help string) *CommandClause { return &CommandClause{ - CmdClause: a.Application.Command(name, help), - name: name, - app: a, + Command: func() *cobra.Command { + newCommand := &cobra.Command{Use: name, Short: help} + a.Application.AddCommand(newCommand) + return newCommand + }(), + name: name, + app: a, } } -// Version adds a flag for displaying the application version number. -func (a *App) Version(version string) *App { - a.Application = a.Application.Version(version) - return a -} - +// +//// Version adds a flag for displaying the application version number. +//func (a *App) Version(version string) *App { +// a.Application = a.Application.Version(version) +// return a +//} +// // Flag defines a new flag with the given long name and help text, // adding an environment variable default configurable by APP_FLAG_NAME. func (a *App) Flag(name, help string) *Flag { envVar := formatName(name, a.name, a.separator, a.delimiters...) a.registerEnvVar(envVar) - flag := a.Application.Flag(name, help).Envar(envVar) - return &Flag{ - FlagClause: flag, - app: a, - envVar: envVar, - } + flag := a.Flag(name, help).Envar(envVar) + return flag } // registerEnvVar ensures the App recognizes an environment variable. @@ -165,27 +168,38 @@ func (a *App) CheckStrictEnv() error { // CommandClause represents a command clause in a command0-line application. type CommandClause struct { - *kingpin.CmdClause + *cobra.Command name string app *App } // Command adds a new subcommand to this command. -func (cmd *CommandClause) Command(name, help string) *CommandClause { +func (cmd *CommandClause) CreateCommand(name, help string) *CommandClause { return &CommandClause{ - CmdClause: cmd.CmdClause.Command(name, help), - name: name, - app: cmd.app, + Command: func() *cobra.Command { + newCommand := &cobra.Command{Use: name, Short: help} + return newCommand + }(), + name: name, + app: cmd.app, } } // Hidden hides the command in help texts. func (cmd *CommandClause) Hidden() *CommandClause { - cmd.CmdClause = cmd.CmdClause.Hidden() + cmd.Command.Hidden = true return cmd } +func (cmd *CommandClause) FullCommand() string { + out := []string{cmd.name} + //for p := cmd.parent; p != nil; p = p.parent { + // out = append([]string{p.name}, out...) + //} + return strings.Join(out, " ") +} + // Flag defines a new flag with the given long name and help text, // adding an environment variable default configurable by APP_COMMAND_FLAG_NAME. // The help text is suffixed with a description of secrthe environment variable default. @@ -195,17 +209,17 @@ func (cmd *CommandClause) Flag(name, help string) *Flag { envVar := formatName(name, prefix, cmd.app.separator, cmd.app.delimiters...) cmd.app.registerEnvVar(envVar) - flag := cmd.CmdClause.Flag(name, help).Envar(envVar) + flag := cmd.Command.Flag(name) return &Flag{ - FlagClause: flag, - app: cmd.app, - envVar: envVar, + Flag: flag, + app: cmd.app, + envVar: envVar, } } // Flag represents a command-line flag. type Flag struct { - *kingpin.FlagClause + *pflag.Flag envVar string app *App @@ -220,7 +234,7 @@ func (f *Flag) Envar(name string) *Flag { } f.app.registerEnvVar(name) f.envVar = name - f.FlagClause = f.FlagClause.Envar(f.envVar) + //f.Flag = f.Flag.Envar(f.envVar) return f } @@ -230,16 +244,56 @@ func (f *Flag) NoEnvar() *Flag { f.app.unregisterEnvVar(f.envVar) } f.envVar = "" - f.FlagClause = f.FlagClause.NoEnvar() + //f.Flag = f.FlagClause.NoEnvar() return f } // Hidden hides the flag in help texts. func (f *Flag) Hidden() *Flag { - f.FlagClause = f.FlagClause.Hidden() + f.Flag.Hidden = true + return f +} + +// Short puts the shorthand of the flag. +func (f *Flag) Short(s rune) *Flag { + f.Flag.Shorthand = string(s) + return f +} + +func (f *Flag) Default(val string) *Flag { + f.Flag.DefValue = val + return f +} + +func (f *Flag) PlaceHolder(val string) *Flag { + if f.Flag.DefValue != "" { + f.Flag.DefValue = val + } + return f +} + +func (f *Flag) SetValue(location interface{}) *Flag { + location = f.Value return f } +// Hidden hides the command in help texts. +func (f *Flag) BoolVar(location *bool) *Flag { + intermediary, _ := strconv.ParseBool(f.Value.String()) + location = &intermediary + return f +} + +func (f *Flag) StringVar(location *string) *Flag { + intermediary := f.Value.String() + location = &intermediary + return f +} + +func (f *Flag) DurationVar(location *time.Duration) *Flag { + return f.SetValue(&location) +} + // formatName takes a name and converts it to an uppercased name, // joined by the given separator and prefixed with the given prefix. func formatName(name, prefix, separator string, delimiters ...string) string { diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index e95a9c8b..d89d369a 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -2,17 +2,13 @@ package secrethub import ( "fmt" - "strings" - "text/template" - "github.com/secrethub/secrethub-cli/internals/cli" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/demo" + "strings" "github.com/secrethub/secrethub-go/internals/errio" "github.com/secrethub/secrethub-go/pkg/secrethub" - - "github.com/alecthomas/kingpin" ) const ( @@ -106,58 +102,58 @@ func NewApp() *App { app.clientFactory.Register(app.cli) app.registerCommands() - app.cli.UsageTemplate(DefaultUsageTemplate) - app.cli.UsageFuncs(template.FuncMap{ - "ManagementCommands": func(cmds []*kingpin.CmdModel) []*kingpin.CmdModel { - var res []*kingpin.CmdModel - for _, cmd := range cmds { - if len(cmd.Commands) > 0 { - res = append(res, cmd) - } - } - return res - }, - "RootCommands": func(cmds []*kingpin.CmdModel) []*kingpin.CmdModel { - var res []*kingpin.CmdModel - for _, cmd := range cmds { - if len(cmd.Commands) == 0 { - res = append(res, cmd) - } - } - return res - }, - "CommandsToTwoColumns": func(cmds []*kingpin.CmdModel) [][2]string { - var rows [][2]string - for _, cmd := range cmds { - if !cmd.Hidden { - rows = append(rows, [2]string{cmd.Name, cmd.Help}) - } - } - return rows - }, - }) + //app.cli.UsageTemplate(DefaultUsageTemplate) + //app.cli.UsageFuncs(template.FuncMap{ + // "ManagementCommands": func(cmds []*kingpin.CmdModel) []*kingpin.CmdModel { + // var res []*kingpin.CmdModel + // for _, cmd := range cmds { + // if len(cmd.Commands) > 0 { + // res = append(res, cmd) + // } + // } + // return res + // }, + // "RootCommands": func(cmds []*kingpin.CmdModel) []*kingpin.CmdModel { + // var res []*kingpin.CmdModel + // for _, cmd := range cmds { + // if len(cmd.Commands) == 0 { + // res = append(res, cmd) + // } + // } + // return res + // }, + // "CommandsToTwoColumns": func(cmds []*kingpin.CmdModel) [][2]string { + // var rows [][2]string + // for _, cmd := range cmds { + // if !cmd.Hidden { + // rows = append(rows, [2]string{cmd.Name, cmd.Help}) + // } + // } + // return rows + // }, + //}) return &app } // Version adds a flag for displaying the application version number. -func (app *App) Version(version string, commit string) *App { - app.cli = app.cli.Version(ApplicationName + " version " + version + ", build " + commit) - return app -} +//func (app *App) Version(version string, commit string) *App { +// app.cli = app.cli.Version(ApplicationName + " version " + version + ", build " + commit) +// return app +//} // Run builds the command-line application, parses the arguments, // configures global behavior and executes the command given by the args. func (app *App) Run(args []string) error { // Parse also executes the command when parsing is successful. - _, err := app.cli.Parse(args) + err := app.cli.Application.Execute() return err } // Model returns the CLI application model containing all the SecretHub CLI commands, flags, and args. -func (app *App) Model() *kingpin.ApplicationModel { - return app.cli.Model() -} +//func (app *App) Model() *kingpin.ApplicationModel { +// return app.cli.Model() +//} // registerCommands initializes all commands and registers them on the app. func (app *App) registerCommands() { diff --git a/internals/secrethub/clear_clipboard.go b/internals/secrethub/clear_clipboard.go index 34902181..e49b4836 100644 --- a/internals/secrethub/clear_clipboard.go +++ b/internals/secrethub/clear_clipboard.go @@ -2,6 +2,7 @@ package secrethub import ( "encoding/hex" + "github.com/spf13/cobra" "time" "github.com/secrethub/secrethub-cli/internals/cli/clip" @@ -31,14 +32,14 @@ func NewClearClipboardCommand() *ClearClipboardCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ClearClipboardCommand) Register(r command.Registerer) { clause := r.Command("clipboard-clear", "Removes secret from clipboard.").Hidden() - clause.Arg("hash", "Hash from the secret to be cleared").Required().HexBytesVar(&cmd.hash) + //clause.Arg("hash", "Hash from the secret to be cleared").Required().HexBytesVar(&cmd.hash) clause.Flag("timeout", "Time to wait before clearing in seconds").DurationVar(&cmd.timeout) command.BindAction(clause, cmd.Run) } // Run handles the command with the options as specified in the command. -func (cmd *ClearClipboardCommand) Run() error { +func (cmd *ClearClipboardCommand) Run(c *cobra.Command, args []string) error { if cmd.timeout > 0 { time.Sleep(cmd.timeout) } diff --git a/internals/secrethub/command/command.go b/internals/secrethub/command/command.go index 8596e949..8c883621 100644 --- a/internals/secrethub/command/command.go +++ b/internals/secrethub/command/command.go @@ -1,7 +1,7 @@ package command import ( - "github.com/alecthomas/kingpin" + "github.com/spf13/cobra" "github.com/secrethub/secrethub-cli/internals/cli" ) @@ -13,10 +13,6 @@ type Registerer interface { // BindAction binds a function to a command clause, so that // it is executed when the command is parsed. -func BindAction(clause *cli.CommandClause, fn func() error) { - clause.Action( - func(*kingpin.ParseContext) error { - return fn() - }, - ) +func BindAction(clause *cli.CommandClause, fn func(cmd *cobra.Command, args []string) error) { + clause.RunE = fn } diff --git a/internals/secrethub/flags.go b/internals/secrethub/flags.go index 7dba437b..ff2937f4 100644 --- a/internals/secrethub/flags.go +++ b/internals/secrethub/flags.go @@ -1,8 +1,8 @@ package secrethub import ( - "github.com/alecthomas/kingpin" "github.com/secrethub/secrethub-cli/internals/cli" + "github.com/spf13/pflag" ) // FlagRegisterer allows others to register flags on it. @@ -10,10 +10,10 @@ type FlagRegisterer interface { Flag(name, help string) *cli.Flag } -func registerTimestampFlag(r FlagRegisterer) *kingpin.FlagClause { - return r.Flag("timestamp", "Show timestamps formatted to RFC3339 instead of human readable durations.").Short('T') +func registerTimestampFlag(r FlagRegisterer) *pflag.Flag { + return r.Flag("timestamp", "Show timestamps formatted to RFC3339 instead of human readable durations.").Short('T').Flag } -func registerForceFlag(r FlagRegisterer) *kingpin.FlagClause { - return r.Flag("force", "Ignore confirmation and fail instead of prompt for missing arguments.").Short('f') +func registerForceFlag(r FlagRegisterer) *pflag.Flag { + return r.Flag("force", "Ignore confirmation and fail instead of prompt for missing arguments.").Short('f').Flag } diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index 295a4ea1..a57b8e41 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -2,6 +2,7 @@ package secrethub import ( "fmt" + "github.com/spf13/cobra" "io/ioutil" "time" @@ -42,7 +43,7 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.Command("read", "Read a secret.") - clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathOptionalVersionPlaceHolder).SetValue(&cmd.path) + //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathOptionalVersionPlaceHolder).SetValue(&cmd.path) clause.Flag( "clip", fmt.Sprintf( @@ -58,7 +59,8 @@ func (cmd *ReadCommand) Register(r command.Registerer) { } // Run handles the command with the options as specified in the command. -func (cmd *ReadCommand) Run() error { +func (cmd *ReadCommand) Run(c *cobra.Command, args []string) error { + cmd.path = api.SecretPath(args[0]) client, err := cmd.newClient() if err != nil { return err From 2582da5df77fccea474decbc8ca4374b5db6a6fa Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 6 Aug 2020 12:03:43 +0300 Subject: [PATCH 02/41] Small adjustment to flags + fullCommand works --- internals/cli/env.go | 6 +----- internals/secrethub/flags.go | 9 ++++----- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 33bcd421..58b0cae6 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -193,11 +193,7 @@ func (cmd *CommandClause) Hidden() *CommandClause { } func (cmd *CommandClause) FullCommand() string { - out := []string{cmd.name} - //for p := cmd.parent; p != nil; p = p.parent { - // out = append([]string{p.name}, out...) - //} - return strings.Join(out, " ") + return strings.Join(os.Args[:], " ") } // Flag defines a new flag with the given long name and help text, diff --git a/internals/secrethub/flags.go b/internals/secrethub/flags.go index ff2937f4..32629632 100644 --- a/internals/secrethub/flags.go +++ b/internals/secrethub/flags.go @@ -2,7 +2,6 @@ package secrethub import ( "github.com/secrethub/secrethub-cli/internals/cli" - "github.com/spf13/pflag" ) // FlagRegisterer allows others to register flags on it. @@ -10,10 +9,10 @@ type FlagRegisterer interface { Flag(name, help string) *cli.Flag } -func registerTimestampFlag(r FlagRegisterer) *pflag.Flag { - return r.Flag("timestamp", "Show timestamps formatted to RFC3339 instead of human readable durations.").Short('T').Flag +func registerTimestampFlag(r FlagRegisterer) *cli.Flag { + return r.Flag("timestamp", "Show timestamps formatted to RFC3339 instead of human readable durations.").Short('T') } -func registerForceFlag(r FlagRegisterer) *pflag.Flag { - return r.Flag("force", "Ignore confirmation and fail instead of prompt for missing arguments.").Short('f').Flag +func registerForceFlag(r FlagRegisterer) *cli.Flag { + return r.Flag("force", "Ignore confirmation and fail instead of prompt for missing arguments.").Short('f') } From d35f8d162dd550c0c712464fde0e38fe34a3dc2a Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Thu, 6 Aug 2020 12:06:24 +0300 Subject: [PATCH 03/41] environment functions --- internals/cli/env.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 58b0cae6..4a07d2a2 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -230,7 +230,7 @@ func (f *Flag) Envar(name string) *Flag { } f.app.registerEnvVar(name) f.envVar = name - //f.Flag = f.Flag.Envar(f.envVar) + f.Flag.DefValue = f.envVar return f } @@ -240,7 +240,7 @@ func (f *Flag) NoEnvar() *Flag { f.app.unregisterEnvVar(f.envVar) } f.envVar = "" - //f.Flag = f.FlagClause.NoEnvar() + f.Flag.DefValue = "" return f } From 570b3fd21276c535c9d93e352c38a87ae07b1c69 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Sat, 8 Aug 2020 10:29:40 +0300 Subject: [PATCH 04/41] Adjust all files to new version of env (cobra adapted) --- cmd/secrethub/main.go | 2 +- internals/cli/env.go | 83 +++++++++++++++---- internals/demo/command.go | 58 ++++++------- internals/demo/init.go | 4 +- internals/secrethub/account.go | 2 +- internals/secrethub/account_email_verify.go | 4 +- internals/secrethub/account_init.go | 4 +- internals/secrethub/account_inspect.go | 4 +- internals/secrethub/acl.go | 2 +- internals/secrethub/acl_check.go | 26 +++++- internals/secrethub/acl_list.go | 19 ++++- internals/secrethub/acl_rm.go | 24 ++++-- internals/secrethub/acl_set.go | 30 +++++-- internals/secrethub/app.go | 13 ++- internals/secrethub/audit.go | 20 ++++- internals/secrethub/clear.go | 4 +- internals/secrethub/clear_clipboard.go | 13 ++- internals/secrethub/command/command.go | 11 ++- internals/secrethub/config.go | 2 +- .../secrethub/config_update_passphrase.go | 4 +- internals/secrethub/config_upgrade.go | 4 +- internals/secrethub/credential.go | 2 +- internals/secrethub/credential_backup.go | 4 +- internals/secrethub/credential_disable.go | 17 +++- internals/secrethub/credential_list.go | 4 +- internals/secrethub/credential_store.go | 5 +- internals/secrethub/env.go | 2 +- internals/secrethub/env_ls.go | 4 +- internals/secrethub/env_read.go | 15 +++- internals/secrethub/generate.go | 28 +++++-- internals/secrethub/init.go | 4 +- internals/secrethub/inject.go | 4 +- internals/secrethub/inspect.go | 17 +++- internals/secrethub/keyring_clear.go | 4 +- internals/secrethub/list.go | 20 ++++- internals/secrethub/mkdir.go | 18 +++- internals/secrethub/org.go | 2 +- internals/secrethub/org_init.go | 4 +- internals/secrethub/org_inspect.go | 18 +++- internals/secrethub/org_invite.go | 21 ++++- internals/secrethub/org_list_users.go | 18 +++- internals/secrethub/org_ls.go | 4 +- internals/secrethub/org_purchase.go | 4 +- internals/secrethub/org_revoke.go | 21 ++++- internals/secrethub/org_rm.go | 18 +++- internals/secrethub/org_set_role.go | 24 ++++-- internals/secrethub/path_placeholders.go | 16 ++-- internals/secrethub/printenv.go | 4 +- internals/secrethub/read.go | 22 +++-- internals/secrethub/repo.go | 2 +- internals/secrethub/repo_export.go | 23 ++++- internals/secrethub/repo_init.go | 18 +++- internals/secrethub/repo_inspect.go | 18 +++- internals/secrethub/repo_invite.go | 21 ++++- internals/secrethub/repo_ls.go | 20 ++++- internals/secrethub/repo_revoke.go | 23 ++++- internals/secrethub/repo_rm.go | 18 +++- internals/secrethub/rm.go | 17 +++- internals/secrethub/run.go | 16 +++- internals/secrethub/service.go | 2 +- internals/secrethub/service_aws.go | 2 +- internals/secrethub/service_aws_init.go | 17 +++- internals/secrethub/service_deploy.go | 2 +- internals/secrethub/service_deploy_winrm.go | 17 +++- internals/secrethub/service_gcp.go | 2 +- internals/secrethub/service_gcp_init.go | 18 +++- internals/secrethub/service_gcp_link.go | 63 +++++++++++--- internals/secrethub/service_init.go | 17 +++- internals/secrethub/service_ls.go | 17 +++- internals/secrethub/set.go | 4 +- internals/secrethub/signup.go | 4 +- internals/secrethub/tree.go | 17 +++- internals/secrethub/write.go | 17 +++- 73 files changed, 780 insertions(+), 252 deletions(-) diff --git a/cmd/secrethub/main.go b/cmd/secrethub/main.go index 3bd45810..5673cfe8 100644 --- a/cmd/secrethub/main.go +++ b/cmd/secrethub/main.go @@ -8,7 +8,7 @@ import ( ) func main() { - err := secrethub.NewApp().Version(secrethub.Version, secrethub.Commit).Run(os.Args[1:]) + err := secrethub.NewApp().Run(os.Args[1:]) if err != nil { handleError(err) } diff --git a/internals/cli/env.go b/internals/cli/env.go index 4a07d2a2..ce0a2492 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -2,8 +2,8 @@ package cli import ( "fmt" - "github.com/spf13/pflag" "io" + "net/url" "os" "strconv" "strings" @@ -12,6 +12,7 @@ import ( "bitbucket.org/zombiezen/cardcpx/natsort" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) var ( @@ -45,7 +46,7 @@ func NewApp(name, help string) *App { } // Command defines a new top-level command with the given name and help text. -func (a *App) Command(name, help string) *CommandClause { +func (a *App) CreateCommand(name, help string) *CommandClause { return &CommandClause{ Command: func() *cobra.Command { newCommand := &cobra.Command{Use: name, Short: help} @@ -69,8 +70,12 @@ func (a *App) Command(name, help string) *CommandClause { func (a *App) Flag(name, help string) *Flag { envVar := formatName(name, a.name, a.separator, a.delimiters...) a.registerEnvVar(envVar) - flag := a.Flag(name, help).Envar(envVar) - return flag + flag := Flag{ + Flag: &pflag.Flag{Name: name, Usage: help}, + envVar: envVar, + app: a, + } + return flag.Envar(envVar) } // registerEnvVar ensures the App recognizes an environment variable. @@ -196,6 +201,18 @@ func (cmd *CommandClause) FullCommand() string { return strings.Join(os.Args[:], " ") } +func (cmd *CommandClause) HelpLong(helpLong string) { + cmd.Long = helpLong +} + +func (cmd *CommandClause) Alias(alias string) { + if cmd.Aliases == nil { + cmd.Aliases = []string{alias} + } else { + cmd.Aliases = append(cmd.Aliases, alias) + } +} + // Flag defines a new flag with the given long name and help text, // adding an environment variable default configurable by APP_COMMAND_FLAG_NAME. // The help text is suffixed with a description of secrthe environment variable default. @@ -205,7 +222,7 @@ func (cmd *CommandClause) Flag(name, help string) *Flag { envVar := formatName(name, prefix, cmd.app.separator, cmd.app.delimiters...) cmd.app.registerEnvVar(envVar) - flag := cmd.Command.Flag(name) + flag := &pflag.Flag{Name: name, Usage: help} return &Flag{ Flag: flag, app: cmd.app, @@ -230,7 +247,7 @@ func (f *Flag) Envar(name string) *Flag { } f.app.registerEnvVar(name) f.envVar = name - f.Flag.DefValue = f.envVar + f.Flag.DefValue = os.Getenv(f.envVar) return f } @@ -257,39 +274,73 @@ func (f *Flag) Short(s rune) *Flag { } func (f *Flag) Default(val string) *Flag { - f.Flag.DefValue = val + if f.Flag.DefValue == "" { + f.Flag.DefValue = val + } return f } func (f *Flag) PlaceHolder(val string) *Flag { - if f.Flag.DefValue != "" { - f.Flag.DefValue = val - } return f } +// TODO Implement it properly +func (f *Flag) HintOptions(options ...string) *Flag { + return f +} + +// TODO Implement it properly func (f *Flag) SetValue(location interface{}) *Flag { - location = f.Value + //if f.Value != nil { + // location = &f.Value + //} return f } // Hidden hides the command in help texts. func (f *Flag) BoolVar(location *bool) *Flag { - intermediary, _ := strconv.ParseBool(f.Value.String()) - location = &intermediary + if f.Value != nil { + intermediary, _ := strconv.ParseBool(f.Value.String()) + *location = intermediary + } else { + *location = false + } + return f } func (f *Flag) StringVar(location *string) *Flag { - intermediary := f.Value.String() - location = &intermediary + if f.Value != nil { + *location = f.Value.String() + } else { + *location = f.DefValue + } return f } +// TODO Implement the following functions properly func (f *Flag) DurationVar(location *time.Duration) *Flag { - return f.SetValue(&location) + return f +} + +func (f *Flag) URLVar(location **url.URL) *Flag { + return f +} + +func (f *Flag) IntVar(location *int) *Flag { + return f +} + +func (f *Flag) ExistingFileVar(location *string) *Flag { + return f } +func (f *Flag) StringMapVar(location *map[string]string) *Flag { + return f +} + +// End of TODO + // formatName takes a name and converts it to an uppercased name, // joined by the given separator and prefixed with the given prefix. func formatName(name, prefix, separator string, delimiters ...string) string { diff --git a/internals/demo/command.go b/internals/demo/command.go index 6cbed4ab..3d113feb 100644 --- a/internals/demo/command.go +++ b/internals/demo/command.go @@ -1,31 +1,31 @@ package demo -import ( - "github.com/secrethub/demo-app/cli" - - "github.com/secrethub/secrethub-cli/internals/cli/ui" - "github.com/secrethub/secrethub-cli/internals/secrethub/command" -) - -// Command is a command to run the secrethub example app. -type Command struct { - io ui.IO - newClient newClientFunc -} - -// NewCommand creates a new example app command. -func NewCommand(io ui.IO, newClient newClientFunc) *Command { - return &Command{ - io: io, - newClient: newClient, - } -} - -// Register registers the command, arguments and flags on the provided Registerer. -func (cmd *Command) Register(r command.Registerer) { - clause := r.Command("demo", "Manage the demo application.") - clause.Hidden() - - NewInitCommand(cmd.io, cmd.newClient).Register(clause) - cli.NewServeCommand(cmd.io).Register(clause) -} +//import ( +// "github.com/secrethub/demo-app/cli" +// +// "github.com/secrethub/secrethub-cli/internals/cli/ui" +// "github.com/secrethub/secrethub-cli/internals/secrethub/command" +//) +// +//// Command is a command to run the secrethub example app. +//type Command struct { +// io ui.IO +// newClient newClientFunc +//} +// +//// NewCommand creates a new example app command. +//func NewCommand(io ui.IO, newClient newClientFunc) *Command { +// return &Command{ +// io: io, +// newClient: newClient, +// } +//} +// +//// Register registers the command, arguments and flags on the provided Registerer. +//func (cmd *Command) Register(r command.Registerer) { +// clause := r.CreateCommand("demo", "Manage the demo application.") +// clause.Hidden() +// +// NewInitCommand(cmd.io, cmd.newClient).Register(clause) +// cli.NewServeCommand(cmd.io).Register(clause) +//} diff --git a/internals/demo/init.go b/internals/demo/init.go index 2efd5d02..183d9475 100644 --- a/internals/demo/init.go +++ b/internals/demo/init.go @@ -34,12 +34,12 @@ func NewInitCommand(io ui.IO, newClient newClientFunc) *InitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *InitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Create the secrets necessary to connect with the demo application.") + clause := r.CreateCommand("init", "Create the secrets necessary to connect with the demo application.") clause.HelpLong("demo init creates a repository with the username and password needed to connect to the demo API.") clause.Flag("repo", "The path of the repository to create. Defaults to a "+defaultDemoRepo+" repo in your personal namespace.").SetValue(&cmd.repo) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run handles the command with the options as specified in the command. diff --git a/internals/secrethub/account.go b/internals/secrethub/account.go index 31f65ce0..7fc1c89a 100644 --- a/internals/secrethub/account.go +++ b/internals/secrethub/account.go @@ -23,7 +23,7 @@ func NewAccountCommand(io ui.IO, newClient newClientFunc, credentialStore Creden // Register registers the command and its sub-commands on the provided Registerer. func (cmd *AccountCommand) Register(r command.Registerer) { - clause := r.Command("account", "Manage your personal account.") + clause := r.CreateCommand("account", "Manage your personal account.") NewAccountInspectCommand(cmd.io, cmd.newClient).Register(clause) NewAccountInitCommand(cmd.io, cmd.newClient, cmd.credentialStore).Register(clause) NewAccountEmailVerifyCommand(cmd.io, cmd.newClient).Register(clause) diff --git a/internals/secrethub/account_email_verify.go b/internals/secrethub/account_email_verify.go index 0181274c..a97f92a8 100644 --- a/internals/secrethub/account_email_verify.go +++ b/internals/secrethub/account_email_verify.go @@ -23,12 +23,12 @@ func NewAccountEmailVerifyCommand(io ui.IO, newClient newClientFunc) *AccountEma // Register registers the command, arguments and flags on the provided Registerer. func (cmd *AccountEmailVerifyCommand) Register(r command.Registerer) { - clause := r.Command("verify-email", "Resend verification email to the registered email address.") + clause := r.CreateCommand("verify-email", "Resend verification email to the registered email address.") clause.HelpLong("When you create your account, a verification email is automatically sent to the email address you used to sign up. " + "In case anything goes wrong (e.g. the email ended up in your junk folder), this command lets you resend the verification email. " + "Once received, click the link in the verification email to verify your email address.") - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run handles the command with the options as specified in the command. diff --git a/internals/secrethub/account_init.go b/internals/secrethub/account_init.go index 7b187b12..4f972d25 100644 --- a/internals/secrethub/account_init.go +++ b/internals/secrethub/account_init.go @@ -59,13 +59,13 @@ func NewAccountInitCommand(io ui.IO, newClient newClientFunc, credentialStore Cr // Register registers the command, arguments and flags on the provided Registerer. func (cmd *AccountInitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Connect a first device to your SecretHub account.") + clause := r.CreateCommand("init", "Connect a first device to your SecretHub account.") clause.Flag("clip", "Copy the credential's public component to the clipboard instead of printing it to stdout.").Short('c').BoolVar(&cmd.useClipboard) clause.Flag("no-wait", "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.").BoolVar(&cmd.noWait) clause.Flag("continue", "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.").BoolVar(&cmd.isContinue) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run creates a credential for this CLI and an account key for the credential. diff --git a/internals/secrethub/account_inspect.go b/internals/secrethub/account_inspect.go index bb81543c..cafc2da1 100644 --- a/internals/secrethub/account_inspect.go +++ b/internals/secrethub/account_inspect.go @@ -28,9 +28,9 @@ func NewAccountInspectCommand(io ui.IO, newClient newClientFunc) *AccountInspect // Register registers the command, arguments and flags on the provided Registerer. func (cmd *AccountInspectCommand) Register(r command.Registerer) { - clause := r.Command("inspect", "Show the details of your SecretHub account.") + clause := r.CreateCommand("inspect", "Show the details of your SecretHub account.") - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run handles the command with the options as specified in the command. diff --git a/internals/secrethub/acl.go b/internals/secrethub/acl.go index 94d9d8fa..508f9328 100644 --- a/internals/secrethub/acl.go +++ b/internals/secrethub/acl.go @@ -21,7 +21,7 @@ func NewACLCommand(io ui.IO, newClient newClientFunc) *ACLCommand { // Register registers the command and its sub-commands on the provided Registerer. func (cmd *ACLCommand) Register(r command.Registerer) { - clause := r.Command("acl", "Manage access rules on directories.") + clause := r.CreateCommand("acl", "Manage access rules on directories.") NewACLCheckCommand(cmd.io, cmd.newClient).Register(clause) NewACLListCommand(cmd.io, cmd.newClient).Register(clause) NewACLRmCommand(cmd.io, cmd.newClient).Register(clause) diff --git a/internals/secrethub/acl_check.go b/internals/secrethub/acl_check.go index 0e9df30a..5cce53cc 100644 --- a/internals/secrethub/acl_check.go +++ b/internals/secrethub/acl_check.go @@ -11,6 +11,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // ACLCheckCommand prints the access level(s) on a given directory. @@ -31,11 +33,12 @@ func NewACLCheckCommand(io ui.IO, newClient newClientFunc) *ACLCheckCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ACLCheckCommand) Register(r command.Registerer) { - clause := r.Command("check", "Checks the effective permission of accounts on a path.") - clause.Arg("dir-path", "The path of the directory to check the effective permission for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Arg("account-name", "Check permissions of a specific account name (username or service name). When left empty, all accounts with permission on the path are printed out.").SetValue(&cmd.accountName) + clause := r.CreateCommand("check", "Checks the effective permission of accounts on a path.") + clause.Args = cobra.RangeArgs(1, 2) + //clause.Arg("dir-path", "The path of the directory to check the effective permission for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) + //clause.Arg("account-name", "Check permissions of a specific account name (username or service name). When left empty, all accounts with permission on the path are printed out.").SetValue(&cmd.accountName) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run prints the access level(s) on the given directory. @@ -106,3 +109,18 @@ func (cmd *ACLCheckCommand) listLevels() ([]*api.AccessLevel, error) { } return nil, listLevelsErr } + +func (cmd *ACLCheckCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewDirPath(args[0]) + if err != nil { + return err + } + if len(args) == 2 { + cmd.accountName, err = api.NewAccountName(args[1]) + if err != nil { + return err + } + } + return nil +} diff --git a/internals/secrethub/acl_list.go b/internals/secrethub/acl_list.go index 76f8ee8a..79d3ee9d 100644 --- a/internals/secrethub/acl_list.go +++ b/internals/secrethub/acl_list.go @@ -5,12 +5,13 @@ import ( "sort" "text/tabwriter" + "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/internals/api/uuid" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" - "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // ACLListCommand prints access rules for the given directory. @@ -34,14 +35,15 @@ func NewACLListCommand(io ui.IO, newClient newClientFunc) *ACLListCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ACLListCommand) Register(r command.Registerer) { - clause := r.Command("ls", "List access rules of a directory and its children.") + clause := r.CreateCommand("ls", "List access rules of a directory and its children.") clause.Alias("list") - clause.Arg("dir-path", "The path of the directory to list the access rules for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("dir-path", "The path of the directory to list the access rules for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) clause.Flag("depth", "The maximum depth to which the rules of child directories should be displayed. Defaults to -1 (no limit).").Short('d').Default("-1").IntVar(&cmd.depth) clause.Flag("all", "List all rules that apply on the directory, including rules on parent directories.").Short('a').BoolVar(&cmd.ancestors) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run prints access rules for the given directory. @@ -50,6 +52,15 @@ func (cmd *ACLListCommand) Run() error { return cmd.run() } +func (cmd *ACLListCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewDirPath(args[0]) + if err != nil { + return err + } + return nil +} + // beforeRun configures the command using the flag values. func (cmd *ACLListCommand) beforeRun() { cmd.timeFormatter = NewTimeFormatter(cmd.useTimestamps) diff --git a/internals/secrethub/acl_rm.go b/internals/secrethub/acl_rm.go index 675eec7a..a470600a 100644 --- a/internals/secrethub/acl_rm.go +++ b/internals/secrethub/acl_rm.go @@ -5,8 +5,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" - "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // ACLRmCommand handles removing an access rule. @@ -28,13 +28,14 @@ func NewACLRmCommand(io ui.IO, newClient newClientFunc) *ACLRmCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ACLRmCommand) Register(r command.Registerer) { - clause := r.Command("rm", "Remove an account's access rules on a given directory. Although the server will deny the account access afterwards, note that removing an access rule does not actually revoke an account and does NOT trigger secret rotation.") + clause := r.CreateCommand("rm", "Remove an account's access rules on a given directory. Although the server will deny the account access afterwards, note that removing an access rule does not actually revoke an account and does NOT trigger secret rotation.") clause.Alias("remove") - clause.Arg("dir-path", "The path of the directory to remove the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) + clause.Args = cobra.ExactValidArgs(2) + //clause.Arg("dir-path", "The path of the directory to remove the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) + //clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run removes the access rule. @@ -75,3 +76,16 @@ func (cmd *ACLRmCommand) Run() error { return nil } + +func (cmd *ACLRmCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewDirPath(args[0]) + if err != nil { + return err + } + cmd.accountName, err = api.NewAccountName(args[1]) + if err != nil { + return err + } + return nil +} diff --git a/internals/secrethub/acl_set.go b/internals/secrethub/acl_set.go index 7d68866e..af491ba2 100644 --- a/internals/secrethub/acl_set.go +++ b/internals/secrethub/acl_set.go @@ -5,8 +5,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" - "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // ACLSetCommand is a command to set access rules. @@ -30,13 +30,14 @@ func NewACLSetCommand(io ui.IO, newClient newClientFunc) *ACLSetCommand { // Register adds a CommandClause and it's args and flags to a Registerer. // Register adds args and flags. func (cmd *ACLSetCommand) Register(r command.Registerer) { - clause := r.Command("set", "Set access rule for an user or service on a path.") - clause.Arg("dir-path", "The path of the directory to set the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Arg("account-name", "The account name (username or service name) to set the access rule for").Required().SetValue(&cmd.accountName) - clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) + clause := r.CreateCommand("set", "Set access rule for an user or service on a path.") + clause.Args = cobra.ExactValidArgs(3) + //clause.Arg("dir-path", "The path of the directory to set the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) + //clause.Arg("account-name", "The account name (username or service name) to set the access rule for").Required().SetValue(&cmd.accountName) + //clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run handles the command with the options as specified in the command. @@ -78,5 +79,22 @@ func (cmd *ACLSetCommand) Run() error { fmt.Fprintln(cmd.io.Output(), "Access rule set!") return nil +} +func (cmd *ACLSetCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewDirPath(args[0]) + if err != nil { + return err + } + cmd.accountName, err = api.NewAccountName(args[1]) + if err != nil { + return err + } + cmd.permission = api.PermissionNone + err = cmd.permission.Set(args[2]) + if err != nil { + return err + } + return nil } diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index d89d369a..029474e7 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -2,11 +2,10 @@ package secrethub import ( "fmt" - "github.com/secrethub/secrethub-cli/internals/cli" - "github.com/secrethub/secrethub-cli/internals/cli/ui" - "github.com/secrethub/secrethub-cli/internals/demo" "strings" + "github.com/secrethub/secrethub-cli/internals/cli" + "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-go/internals/errio" "github.com/secrethub/secrethub-go/pkg/secrethub" ) @@ -95,9 +94,9 @@ func NewApp() *App { logger: cli.NewLogger(), } - RegisterDebugFlag(app.cli, app.logger) - RegisterMlockFlag(app.cli) - RegisterColorFlag(app.cli) + //RegisterDebugFlag(app.cli, app.logger) + //RegisterMlockFlag(app.cli) + //RegisterColorFlag(app.cli) app.credentialStore.Register(app.cli) app.clientFactory.Register(app.cli) app.registerCommands() @@ -190,5 +189,5 @@ func (app *App) registerCommands() { NewClearClipboardCommand().Register(app.cli) NewKeyringClearCommand().Register(app.cli) - demo.NewCommand(app.io, app.clientFactory.NewClient).Register(app.cli) + //demo.NewCommand(app.io, app.clientFactory.NewClient).Register(app.cli) } diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index 3871585d..aa728f63 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -18,6 +18,8 @@ import ( "github.com/secrethub/secrethub-go/pkg/secrethub" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) var ( @@ -66,14 +68,15 @@ func (cmd *AuditCommand) Register(r command.Registerer) { defaultLimit = pipedOutputLineLimit } - clause := r.Command("audit", "Show the audit log.") - clause.Arg("repo-path or secret-path", "Path to the repository or the secret to audit "+repoPathPlaceHolder+" or "+secretPathPlaceHolder).SetValue(&cmd.path) + clause := r.CreateCommand("audit", "Show the audit log.") + clause.Args = cobra.MaximumNArgs(1) + //clause.Arg("repo-path or secret-path", "Path to the repository or the secret to audit "+repoPathPlaceHolder+" or "+secretPathPlaceHolder).SetValue(&cmd.path) clause.Flag("per-page", "Number of audit events shown per page").Default("20").Hidden().IntVar(&cmd.perPage) clause.Flag("output-format", "Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.").HintOptions("table", "json").Default("table").StringVar(&cmd.format) clause.Flag("max-results", "Specify the number of entries to list. If maxResults < 0 all entries are displayed. If the output of the command is piped, maxResults defaults to 1000.").Default(strconv.Itoa(defaultLimit)).IntVar(&cmd.maxResults) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run prints all audit events for the given repository or secret. @@ -82,6 +85,17 @@ func (cmd *AuditCommand) Run() error { return cmd.run() } +func (cmd *AuditCommand) PreRun(c *cobra.Command, args []string) error { + var err error + if len(args) != 0 { + cmd.path, err = api.NewPath(args[0]) + if err != nil { + return err + } + } + return nil +} + // beforeRun configures the command using the flag values. func (cmd *AuditCommand) beforeRun() { if cmd.format == formatJSON { diff --git a/internals/secrethub/clear.go b/internals/secrethub/clear.go index 83b1c33a..633ad03b 100644 --- a/internals/secrethub/clear.go +++ b/internals/secrethub/clear.go @@ -25,10 +25,10 @@ func NewClearCommand(io ui.IO) *ClearCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ClearCommand) Register(r command.Registerer) { - clause := r.Command("clear", "Clear the secrets from your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() + clause := r.CreateCommand("clear", "Clear the secrets from your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() clause.Flag("in", "The path to a secrets.yml file to read").Short('i').Default("secrets.yml").ExistingFileVar(&cmd.in) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run clears the secrets from the system. diff --git a/internals/secrethub/clear_clipboard.go b/internals/secrethub/clear_clipboard.go index e49b4836..54576b30 100644 --- a/internals/secrethub/clear_clipboard.go +++ b/internals/secrethub/clear_clipboard.go @@ -2,13 +2,13 @@ package secrethub import ( "encoding/hex" - "github.com/spf13/cobra" "time" "github.com/secrethub/secrethub-cli/internals/cli/clip" "github.com/secrethub/secrethub-cli/internals/cli/cloneproc" "github.com/secrethub/secrethub-cli/internals/secrethub/command" + "github.com/spf13/cobra" "golang.org/x/crypto/bcrypt" ) @@ -31,15 +31,16 @@ func NewClearClipboardCommand() *ClearClipboardCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ClearClipboardCommand) Register(r command.Registerer) { - clause := r.Command("clipboard-clear", "Removes secret from clipboard.").Hidden() + clause := r.CreateCommand("clipboard-clear", "Removes secret from clipboard.").Hidden() + clause.Args = cobra.ExactValidArgs(1) //clause.Arg("hash", "Hash from the secret to be cleared").Required().HexBytesVar(&cmd.hash) clause.Flag("timeout", "Time to wait before clearing in seconds").DurationVar(&cmd.timeout) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run handles the command with the options as specified in the command. -func (cmd *ClearClipboardCommand) Run(c *cobra.Command, args []string) error { +func (cmd *ClearClipboardCommand) Run() error { if cmd.timeout > 0 { time.Sleep(cmd.timeout) } @@ -79,3 +80,7 @@ func WriteClipboardAutoClear(data []byte, timeout time.Duration, clipper clip.Cl return err } + +func (cmd *ClearClipboardCommand) PreRun(c *cobra.Command, args []string) error { + return nil +} diff --git a/internals/secrethub/command/command.go b/internals/secrethub/command/command.go index 8c883621..54464c93 100644 --- a/internals/secrethub/command/command.go +++ b/internals/secrethub/command/command.go @@ -8,11 +8,16 @@ import ( // Registerer allows others to register commands on it. type Registerer interface { - Command(cmd string, help string) *cli.CommandClause + CreateCommand(cmd string, help string) *cli.CommandClause } // BindAction binds a function to a command clause, so that // it is executed when the command is parsed. -func BindAction(clause *cli.CommandClause, fn func(cmd *cobra.Command, args []string) error) { - clause.RunE = fn +func BindAction(clause *cli.CommandClause, prefn func(c *cobra.Command, args []string) error, fn func() error) { + if prefn != nil { + clause.Command.RunE = prefn + } + clause.Command.PostRunE = func(cmd *cobra.Command, args []string) error { + return fn() + } } diff --git a/internals/secrethub/config.go b/internals/secrethub/config.go index 8b3e790f..13cb3b0f 100644 --- a/internals/secrethub/config.go +++ b/internals/secrethub/config.go @@ -21,7 +21,7 @@ func NewConfigCommand(io ui.IO, store CredentialConfig) *ConfigCommand { // Register registers the command and its sub-commands on the provided Registerer. func (cmd *ConfigCommand) Register(r command.Registerer) { - clause := r.Command("config", "Manage your local configuration.") + clause := r.CreateCommand("config", "Manage your local configuration.") NewConfigUpdatePassphraseCommand(cmd.io, cmd.credentialStore).Register(clause) NewConfigUpgradeCommand().Register(clause) } diff --git a/internals/secrethub/config_update_passphrase.go b/internals/secrethub/config_update_passphrase.go index c890b715..245650e9 100644 --- a/internals/secrethub/config_update_passphrase.go +++ b/internals/secrethub/config_update_passphrase.go @@ -24,9 +24,9 @@ func NewConfigUpdatePassphraseCommand(io ui.IO, credentialStore CredentialConfig // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ConfigUpdatePassphraseCommand) Register(r command.Registerer) { - clause := r.Command("update-passphrase", "Update the passphrase of your local key credential file.") + clause := r.CreateCommand("update-passphrase", "Update the passphrase of your local key credential file.") - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run upgrades the configuration in the profile directory to the new version. diff --git a/internals/secrethub/config_upgrade.go b/internals/secrethub/config_upgrade.go index d2a98ada..2606c4bc 100644 --- a/internals/secrethub/config_upgrade.go +++ b/internals/secrethub/config_upgrade.go @@ -14,8 +14,8 @@ func NewConfigUpgradeCommand() *ConfigUpgradeCommand { } func (cmd *ConfigUpgradeCommand) Register(r command.Registerer) { - clause := r.Command("upgrade", "Upgrade your .secrethub configuration directory. This can be useful to migrate to a newer version of the configuration files.").Hidden() - command.BindAction(clause, cmd.Run) + clause := r.CreateCommand("upgrade", "Upgrade your .secrethub configuration directory. This can be useful to migrate to a newer version of the configuration files.").Hidden() + command.BindAction(clause, nil, cmd.Run) } func (cmd *ConfigUpgradeCommand) Run() error { diff --git a/internals/secrethub/credential.go b/internals/secrethub/credential.go index d0fc14d7..83de3507 100644 --- a/internals/secrethub/credential.go +++ b/internals/secrethub/credential.go @@ -23,7 +23,7 @@ func NewCredentialCommand(io ui.IO, clientFactory ClientFactory, credentialStore // Register registers the command and its sub-commands on the provided Registerer. func (cmd *CredentialCommand) Register(r command.Registerer) { - clause := r.Command("credential", "Manage your credentials.") + clause := r.CreateCommand("credential", "Manage your credentials.") NewCredentialListCommand(cmd.io, cmd.clientFactory.NewClient).Register(clause) NewCredentialBackupCommand(cmd.io, cmd.clientFactory.NewClient).Register(clause) NewCredentialDisableCommand(cmd.io, cmd.clientFactory.NewClient).Register(clause) diff --git a/internals/secrethub/credential_backup.go b/internals/secrethub/credential_backup.go index d4673edd..4bf620ab 100644 --- a/internals/secrethub/credential_backup.go +++ b/internals/secrethub/credential_backup.go @@ -24,9 +24,9 @@ func NewCredentialBackupCommand(io ui.IO, newClient newClientFunc) *CredentialBa // Register registers the command, arguments and flags on the provided Registerer. func (cmd *CredentialBackupCommand) Register(r command.Registerer) { - clause := r.Command("backup", "Create a backup code for restoring your account.") + clause := r.CreateCommand("backup", "Create a backup code for restoring your account.") - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run creates a backup code for the currently authenticated account. diff --git a/internals/secrethub/credential_disable.go b/internals/secrethub/credential_disable.go index dfc6b247..0f272649 100644 --- a/internals/secrethub/credential_disable.go +++ b/internals/secrethub/credential_disable.go @@ -7,6 +7,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // CredentialDisableCommand is a command that allows to disable an existing credential. @@ -27,14 +28,15 @@ func NewCredentialDisableCommand(io ui.IO, newClient newClientFunc) *CredentialD // Register registers the command, arguments and flags on the provided Registerer. func (cmd *CredentialDisableCommand) Register(r command.Registerer) { - clause := r.Command("disable", "Disable a credential for usage on SecretHub.") + clause := r.CreateCommand("disable", "Disable a credential for usage on SecretHub.") + clause.Args = cobra.MaximumNArgs(1) - fingerprintHelp := fmt.Sprintf("Fingerprint of the credential to disable. At least the first %d characters must be entered.", api.ShortCredentialFingerprintMinimumLength) - clause.Arg("fingerprint", fingerprintHelp).StringVar(&cmd.fingerprint) + //fingerprintHelp := fmt.Sprintf("Fingerprint of the credential to disable. At least the first %d characters must be entered.", api.ShortCredentialFingerprintMinimumLength) + //clause.Arg("fingerprint", fingerprintHelp).StringVar(&cmd.fingerprint) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run disables an existing credential. @@ -84,3 +86,10 @@ func (cmd *CredentialDisableCommand) Run() error { return nil } + +func (cmd *CredentialDisableCommand) PreRun(c *cobra.Command, args []string) error { + if len(args) != 0 { + cmd.fingerprint = args[0] + } + return nil +} diff --git a/internals/secrethub/credential_list.go b/internals/secrethub/credential_list.go index 31801f11..ca7437a5 100644 --- a/internals/secrethub/credential_list.go +++ b/internals/secrethub/credential_list.go @@ -29,12 +29,12 @@ func NewCredentialListCommand(io ui.IO, newClient newClientFunc) *CredentialList // Register registers the command, arguments and flags on the provided Registerer. func (cmd *CredentialListCommand) Register(r command.Registerer) { - clause := r.Command("ls", "List all your credentials.") + clause := r.CreateCommand("ls", "List all your credentials.") clause.Alias("list") registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run lists all the currently authenticated account's credentials. diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 09f2ccf2..09163572 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -27,8 +27,11 @@ type CredentialConfig interface { // NewCredentialConfig creates a new CredentialConfig. func NewCredentialConfig(io ui.IO) CredentialConfig { + dir, _ := configdir.Default() + c := ConfigDir{Dir: *dir} return &credentialConfig{ - io: io, + configDir: c, + io: io, } } diff --git a/internals/secrethub/env.go b/internals/secrethub/env.go index 5e653311..8c9fdd50 100644 --- a/internals/secrethub/env.go +++ b/internals/secrethub/env.go @@ -21,7 +21,7 @@ func NewEnvCommand(io ui.IO, newClient newClientFunc) *EnvCommand { // Register registers the command and its sub-commands on the provided Registerer. func (cmd *EnvCommand) Register(r command.Registerer) { - clause := r.Command("env", "[BETA] Manage environment variables.").Hidden() + clause := r.CreateCommand("env", "[BETA] Manage environment variables.").Hidden() clause.HelpLong("This command is hidden because it is still in beta. Future versions may break.") NewEnvReadCommand(cmd.io, cmd.newClient).Register(clause) NewEnvListCommand(cmd.io, cmd.newClient).Register(clause) diff --git a/internals/secrethub/env_ls.go b/internals/secrethub/env_ls.go index c1cac212..8fcb7b87 100644 --- a/internals/secrethub/env_ls.go +++ b/internals/secrethub/env_ls.go @@ -23,13 +23,13 @@ func NewEnvListCommand(io ui.IO, newClient newClientFunc) *EnvListCommand { // Register adds a CommandClause and it's args and flags to a Registerer. func (cmd *EnvListCommand) Register(r command.Registerer) { - clause := r.Command("ls", "[BETA] List environment variable names that will be populated with secrets.") + clause := r.CreateCommand("ls", "[BETA] List environment variable names that will be populated with secrets.") clause.HelpLong("This command is hidden because it is still in beta. Future versions may break.") clause.Alias("list") cmd.environment.register(clause) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run executes the command. diff --git a/internals/secrethub/env_read.go b/internals/secrethub/env_read.go index af216e25..0fbdf2ec 100644 --- a/internals/secrethub/env_read.go +++ b/internals/secrethub/env_read.go @@ -5,6 +5,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" + "github.com/spf13/cobra" ) // EnvReadCommand is a command to read the value of a single environment variable. @@ -26,13 +27,14 @@ func NewEnvReadCommand(io ui.IO, newClient newClientFunc) *EnvReadCommand { // Register adds a CommandClause and it's args and flags to a Registerer. func (cmd *EnvReadCommand) Register(r command.Registerer) { - clause := r.Command("read", "[BETA] Read the value of a single environment variable.") + clause := r.CreateCommand("read", "[BETA] Read the value of a single environment variable.") clause.HelpLong("This command is hidden because it is still in beta. Future versions may break.") - clause.Arg("key", "the key of the environment variable to read").StringVar(&cmd.key) + clause.Args = cobra.MaximumNArgs(1) + //clause.Arg("key", "the key of the environment variable to read").StringVar(&cmd.key) cmd.environment.register(clause) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run executes the command. @@ -58,3 +60,10 @@ func (cmd *EnvReadCommand) Run() error { return nil } + +func (cmd *EnvReadCommand) PreRun(c *cobra.Command, args []string) error { + if len(args) != 0 { + cmd.key = args[0] + } + return nil +} diff --git a/internals/secrethub/generate.go b/internals/secrethub/generate.go index 67fa949e..e1d7a6cc 100644 --- a/internals/secrethub/generate.go +++ b/internals/secrethub/generate.go @@ -16,6 +16,8 @@ import ( "github.com/secrethub/secrethub-go/pkg/randchar" "github.com/docker/go-units" + + "github.com/spf13/cobra" ) var ( @@ -60,17 +62,18 @@ func NewGenerateSecretCommand(io ui.IO, newClient newClientFunc) *GenerateSecret // Register registers the command, arguments and flags on the provided Registerer. func (cmd *GenerateSecretCommand) Register(r command.Registerer) { - clause := r.Command("generate", "Generate a random secret.") - clause.Arg("secret-path", "The path to write the generated secret to").Required().PlaceHolder(secretPathPlaceHolder).StringVar(&cmd.firstArg) + clause := r.CreateCommand("generate", "Generate a random secret.") + clause.Args = cobra.RangeArgs(1, 3) + //clause.Arg("secret-path", "The path to write the generated secret to").Required().PlaceHolder(secretPathPlaceHolder).StringVar(&cmd.firstArg) clause.Flag("length", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)).PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) clause.Flag("min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.").SetValue(&cmd.mins) clause.Flag("clip", "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".").Short('c').BoolVar(&cmd.copyToClipboard) clause.Flag("charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.").Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable").SetValue(&cmd.charsetFlag) clause.Flag("symbols", "Include symbols in secret.").Short('s').Hidden().SetValue(&cmd.symbolsFlag) - clause.Arg("rand-command", "").Hidden().StringVar(&cmd.secondArg) - clause.Arg("length", "").Hidden().SetValue(&cmd.lengthArg) + //clause.Arg("rand-command", "").Hidden().StringVar(&cmd.secondArg) + //clause.Arg("length", "").Hidden().SetValue(&cmd.lengthArg) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // before configures the command using the flag values. @@ -102,6 +105,21 @@ func (cmd *GenerateSecretCommand) Run() error { return cmd.run() } +func (cmd *GenerateSecretCommand) PreRun(c *cobra.Command, args []string) error { + cmd.firstArg = args[0] + if len(args) >= 2 { + cmd.secondArg = args[1] + } + if len(args) == 3 { + len, err := strconv.Atoi(args[2]) + if err != nil { + return err + } + cmd.lengthArg = intValue{v: &len} + } + return nil +} + // run generates a new secret and writes to the output path. func (cmd *GenerateSecretCommand) run() error { length, err := cmd.length() diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index dce0c9ac..b0fa42db 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -38,11 +38,11 @@ func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentia // Register registers the command, arguments and flags on the provided Registerer. func (cmd *InitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Initialize the SecretHub client for first use on this device.") + clause := r.CreateCommand("init", "Initialize the SecretHub client for first use on this device.") clause.Flag("backup-code", "The backup code used to restore an existing account to this device.").StringVar(&cmd.backupCode) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } type InitMode int diff --git a/internals/secrethub/inject.go b/internals/secrethub/inject.go index e8718bd9..7602f622 100644 --- a/internals/secrethub/inject.go +++ b/internals/secrethub/inject.go @@ -56,7 +56,7 @@ func NewInjectCommand(io ui.IO, newClient newClientFunc) *InjectCommand { // Register adds a CommandClause and it's args and flags to a cli.App. // Register adds args and flags. func (cmd *InjectCommand) Register(r command.Registerer) { - clause := r.Command("inject", "Inject secrets into a template.") + clause := r.CreateCommand("inject", "Inject secrets into a template.") clause.Flag( "clip", fmt.Sprintf( @@ -73,7 +73,7 @@ func (cmd *InjectCommand) Register(r command.Registerer) { clause.Flag("no-prompt", "Do not prompt when a template variable is missing and return an error instead.").BoolVar(&cmd.dontPromptMissingTemplateVars) clause.Flag("force", "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.").Short('f').BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run handles the command with the options as specified in the command. diff --git a/internals/secrethub/inspect.go b/internals/secrethub/inspect.go index 22ff1ad1..9ef97399 100644 --- a/internals/secrethub/inspect.go +++ b/internals/secrethub/inspect.go @@ -3,6 +3,7 @@ package secrethub import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" + "github.com/spf13/cobra" "github.com/secrethub/secrethub-go/internals/api" ) @@ -30,10 +31,11 @@ func NewInspectCommand(io ui.IO, newClient newClientFunc) *InspectCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *InspectCommand) Register(r command.Registerer) { - clause := r.Command("inspect", "Print details of a resource.") - clause.Arg("repo or secret-path", "Path to the repository or the secret to inspect "+repoPathPlaceHolder+" or "+secretPathOptionalVersionPlaceHolder).Required().SetValue(&cmd.path) + clause := r.CreateCommand("inspect", "Print details of a resource.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo or secret-path", "Path to the repository or the secret to inspect "+repoPathPlaceHolder+" or "+secretPathOptionalVersionPlaceHolder).Required().SetValue(&cmd.path) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run inspects a repository or a secret @@ -67,3 +69,12 @@ func (cmd *InspectCommand) Run() error { return ErrInspectResourceNotSupported } + +func (cmd *InspectCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewPath(args[0]) + if err != nil { + return err + } + return nil +} diff --git a/internals/secrethub/keyring_clear.go b/internals/secrethub/keyring_clear.go index 40edb8cc..93e7f447 100644 --- a/internals/secrethub/keyring_clear.go +++ b/internals/secrethub/keyring_clear.go @@ -21,12 +21,12 @@ func NewKeyringClearCommand() *KeyringClearCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *KeyringClearCommand) Register(r command.Registerer) { - clause := r.Command("keyring-clear", "Clear the key passphrase from the keyring.").Hidden() + clause := r.CreateCommand("keyring-clear", "Clear the key passphrase from the keyring.").Hidden() // Alias for backwards compatibility with old name of command. clause.Alias("key-passphrase-clear") - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run waits for the keyringItem store to expire and clears it. diff --git a/internals/secrethub/list.go b/internals/secrethub/list.go index 8a51f99e..3fd5a3e6 100644 --- a/internals/secrethub/list.go +++ b/internals/secrethub/list.go @@ -9,9 +9,9 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" - "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/internals/errio" + "github.com/spf13/cobra" ) // LsCommand lists a repo, secret or namespace. @@ -33,13 +33,14 @@ func NewLsCommand(io ui.IO, newClient newClientFunc) *LsCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *LsCommand) Register(r command.Registerer) { - clause := r.Command("ls", "List contents of a path.") + clause := r.CreateCommand("ls", "List contents of a path.") clause.Alias("list") - clause.Arg("path", "The path to list contents of").SetValue(&cmd.path) + clause.Args = cobra.MaximumNArgs(1) + //clause.Arg("path", "The path to list contents of").SetValue(&cmd.path) clause.Flag("quiet", "Only print paths.").Short('q').BoolVar(&cmd.quiet) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run lists a repo, secret or namespace. @@ -132,6 +133,17 @@ func (cmd *LsCommand) Run() error { return errio.UnexpectedError(errors.New("invalid path argument")) } +func (cmd *LsCommand) PreRun(c *cobra.Command, args []string) error { + var err error + if len(args) != 0 { + cmd.path, err = api.NewPath(args[0]) + if err != nil { + return err + } + } + return nil +} + // printVersions prints out secret versions in long or short format. func printVersions(w io.Writer, quiet bool, timeFormatter TimeFormatter, versions ...*api.SecretVersion) error { if quiet { diff --git a/internals/secrethub/mkdir.go b/internals/secrethub/mkdir.go index 37e94438..2200aa54 100644 --- a/internals/secrethub/mkdir.go +++ b/internals/secrethub/mkdir.go @@ -9,6 +9,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" + + "github.com/spf13/cobra" ) // Errors @@ -34,11 +36,12 @@ func NewMkDirCommand(io ui.IO, newClient newClientFunc) *MkDirCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *MkDirCommand) Register(r command.Registerer) { - clause := r.Command("mkdir", "Create a new directory.") - clause.Arg("dir-paths", "The paths to the directories").Required().PlaceHolder(dirPathsPlaceHolder).SetValue(&cmd.paths) + clause := r.CreateCommand("mkdir", "Create a new directory.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("dir-paths", "The paths to the directories").Required().PlaceHolder(dirPathsPlaceHolder).SetValue(&cmd.paths) clause.Flag("parents", "Create parent directories if needed. Does not error when directories already exist.").BoolVar(&cmd.parents) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run executes the command. @@ -59,6 +62,15 @@ func (cmd *MkDirCommand) Run() error { return nil } +func (cmd *MkDirCommand) PreRun(c *cobra.Command, args []string) error { + var list dirPathList + for _, arg := range args { + list = append(list, arg) + } + cmd.paths = list + return nil +} + // createDirectory validates the given path and creates a directory on it. func (cmd *MkDirCommand) createDirectory(client secrethub.ClientInterface, path string) error { dirPath, err := api.NewDirPath(path) diff --git a/internals/secrethub/org.go b/internals/secrethub/org.go index 49637400..94bcf89e 100644 --- a/internals/secrethub/org.go +++ b/internals/secrethub/org.go @@ -21,7 +21,7 @@ func NewOrgCommand(io ui.IO, newClient newClientFunc) *OrgCommand { // Register registers the command and its sub-commands on the provided Registerer. func (cmd *OrgCommand) Register(r command.Registerer) { - clause := r.Command("org", "Manage shared organization workspaces.") + clause := r.CreateCommand("org", "Manage shared organization workspaces.") clause.Alias("organization") clause.Alias("organisation") clause.Alias("orgs") diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index b936b906..8cbbc943 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -28,14 +28,14 @@ func NewOrgInitCommand(io ui.IO, newClient newClientFunc) *OrgInitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Initialize a new organization account.") + clause := r.CreateCommand("init", "Initialize a new organization account.") clause.Flag("name", "The name you would like to use for your organization. If not set, you will be asked for it.").SetValue(&cmd.name) clause.Flag("description", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.").StringVar(&cmd.description) clause.Flag("descr", "").Hidden().StringVar(&cmd.description) clause.Flag("desc", "").Hidden().StringVar(&cmd.description) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run creates an organization. diff --git a/internals/secrethub/org_inspect.go b/internals/secrethub/org_inspect.go index 123d2df6..c0c8e6b8 100644 --- a/internals/secrethub/org_inspect.go +++ b/internals/secrethub/org_inspect.go @@ -8,6 +8,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // OrgInspectCommand handles printing out the details of an organization in a JSON format. @@ -29,10 +31,11 @@ func NewOrgInspectCommand(io ui.IO, newClient newClientFunc) *OrgInspectCommand // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInspectCommand) Register(r command.Registerer) { - clause := r.Command("inspect", "Show the details of an organization.") - clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) + clause := r.CreateCommand("inspect", "Show the details of an organization.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run prints out the details of an organization. @@ -67,6 +70,15 @@ func (cmd *OrgInspectCommand) Run() error { return nil } +func (cmd *OrgInspectCommand) PreRun(c *cobra.Command, args []string) error { + err := api.ValidateOrgName(args[0]) + if err != nil { + return err + } + cmd.name = api.OrgName(args[0]) + return nil +} + // OrgInspectOutput is the json format to print out with all the details of an organization. type OrgInspectOutput struct { Name string diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index 459193ce..63dae484 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -7,6 +7,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // OrgInviteCommand handles inviting a user to an organization. @@ -29,13 +31,14 @@ func NewOrgInviteCommand(io ui.IO, newClient newClientFunc) *OrgInviteCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInviteCommand) Register(r command.Registerer) { - clause := r.Command("invite", "Invite a user to join an organization.") - clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) - clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) + clause := r.CreateCommand("invite", "Invite a user to join an organization.") + clause.Args = cobra.ExactValidArgs(2) + //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) + //clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) clause.Flag("role", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.").Default("member").StringVar(&cmd.role) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run invites a user to an organization and gives them a certain role. @@ -72,3 +75,13 @@ func (cmd *OrgInviteCommand) Run() error { return nil } + +func (cmd *OrgInviteCommand) PreRun(c *cobra.Command, args []string) error { + err := api.ValidateOrgName(args[0]) + if err != nil { + return err + } + cmd.orgName = api.OrgName(args[0]) + cmd.username = args[1] + return nil +} diff --git a/internals/secrethub/org_list_users.go b/internals/secrethub/org_list_users.go index 7bfbedc7..bb4978a9 100644 --- a/internals/secrethub/org_list_users.go +++ b/internals/secrethub/org_list_users.go @@ -9,6 +9,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // OrgListUsersCommand handles listing the users of an organization. @@ -30,12 +32,13 @@ func NewOrgListUsersCommand(io ui.IO, newClient newClientFunc) *OrgListUsersComm // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgListUsersCommand) Register(r command.Registerer) { - clause := r.Command("list-users", "List all members of an organization.") + clause := r.CreateCommand("list-users", "List all members of an organization.") clause.Alias("list-members") - clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run lists the users of an organization. @@ -44,6 +47,15 @@ func (cmd *OrgListUsersCommand) Run() error { return cmd.run() } +func (cmd *OrgListUsersCommand) PreRun(c *cobra.Command, args []string) error { + err := api.ValidateOrgName(args[0]) + if err != nil { + return err + } + cmd.orgName = api.OrgName(args[0]) + return nil +} + // beforeRun configures the command using the flag values. func (cmd *OrgListUsersCommand) beforeRun() { cmd.timeFormatter = NewTimeFormatter(cmd.useTimestamps) diff --git a/internals/secrethub/org_ls.go b/internals/secrethub/org_ls.go index fccc24b4..90e1848f 100644 --- a/internals/secrethub/org_ls.go +++ b/internals/secrethub/org_ls.go @@ -30,12 +30,12 @@ func NewOrgLsCommand(io ui.IO, newClient newClientFunc) *OrgLsCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgLsCommand) Register(r command.Registerer) { - clause := r.Command("ls", "List all organizations you are a member of.") + clause := r.CreateCommand("ls", "List all organizations you are a member of.") clause.Alias("list") clause.Flag("quiet", "Only print organization names.").Short('q').BoolVar(&cmd.quiet) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run lists all organizations a user is a member of. diff --git a/internals/secrethub/org_purchase.go b/internals/secrethub/org_purchase.go index a7da9083..b2d2fbfc 100644 --- a/internals/secrethub/org_purchase.go +++ b/internals/secrethub/org_purchase.go @@ -21,9 +21,9 @@ func NewOrgPurchaseCommand(io ui.IO) *OrgPurchaseCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgPurchaseCommand) Register(r command.Registerer) { - clause := r.Command("purchase", "Purchase a SecretHub subscription.") + clause := r.CreateCommand("purchase", "Purchase a SecretHub subscription.") - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run prints instructions on purchasing a SecretHub subscription. diff --git a/internals/secrethub/org_revoke.go b/internals/secrethub/org_revoke.go index dccfc0bf..4f6e9b5e 100644 --- a/internals/secrethub/org_revoke.go +++ b/internals/secrethub/org_revoke.go @@ -9,6 +9,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // OrgRevokeCommand handles revoking a member from an organization. @@ -29,11 +31,12 @@ func NewOrgRevokeCommand(io ui.IO, newClient newClientFunc) *OrgRevokeCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgRevokeCommand) Register(r command.Registerer) { - clause := r.Command("revoke", "Revoke a user from an organization. This automatically revokes the user from all of the organization's repositories. A list of repositories containing secrets that should be rotated will be printed out.") - clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) - clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) + clause := r.CreateCommand("revoke", "Revoke a user from an organization. This automatically revokes the user from all of the organization's repositories. A list of repositories containing secrets that should be rotated will be printed out.") + clause.Args = cobra.ExactValidArgs(2) + //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) + //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run revokes an organization member. @@ -130,6 +133,16 @@ func (cmd *OrgRevokeCommand) Run() error { return nil } +func (cmd *OrgRevokeCommand) PreRun(c *cobra.Command, args []string) error { + err := api.ValidateOrgName(args[0]) + if err != nil { + return err + } + cmd.orgName = api.OrgName(args[0]) + cmd.username = args[1] + return nil +} + // writeOrgRevokeRepoList is a helper function that writes repos with a status. func writeOrgRevokeRepoList(w io.Writer, repos ...*api.RevokeRepoResponse) error { tw := tabwriter.NewWriter(w, 0, 2, 2, ' ', 0) diff --git a/internals/secrethub/org_rm.go b/internals/secrethub/org_rm.go index 12a651b0..8495dbb9 100644 --- a/internals/secrethub/org_rm.go +++ b/internals/secrethub/org_rm.go @@ -7,6 +7,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // OrgRmCommand deletes an organization, prompting the user for confirmation. @@ -27,11 +29,12 @@ func NewOrgRmCommand(io ui.IO, newClient newClientFunc) *OrgRmCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgRmCommand) Register(r command.Registerer) { - clause := r.Command("rm", "Permanently delete an organization and all the repositories it owns.") + clause := r.CreateCommand("rm", "Permanently delete an organization and all the repositories it owns.") clause.Alias("remove") - clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run deletes an organization, prompting the user for confirmation. @@ -71,3 +74,12 @@ func (cmd *OrgRmCommand) Run() error { return nil } + +func (cmd *OrgRmCommand) PreRun(c *cobra.Command, args []string) error { + err := api.ValidateOrgName(args[0]) + if err != nil { + return err + } + cmd.name = api.OrgName(args[0]) + return nil +} diff --git a/internals/secrethub/org_set_role.go b/internals/secrethub/org_set_role.go index 65286a31..d223f573 100644 --- a/internals/secrethub/org_set_role.go +++ b/internals/secrethub/org_set_role.go @@ -7,6 +7,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // OrgSetRoleCommand handles updating the role of an organization member. @@ -28,12 +30,13 @@ func NewOrgSetRoleCommand(io ui.IO, newClient newClientFunc) *OrgSetRoleCommand // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgSetRoleCommand) Register(r command.Registerer) { - clause := r.Command("set-role", "Set a user's organization role.") - clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) - clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) - clause.Arg("role", "The role to assign to the user. Can be either `admin` or `member`.").Required().StringVar(&cmd.role) + clause := r.CreateCommand("set-role", "Set a user's organization role.") + clause.Args = cobra.ExactValidArgs(3) + //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) + //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) + //clause.Arg("role", "The role to assign to the user. Can be either `admin` or `member`.").Required().StringVar(&cmd.role) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run updates the role of an organization member. @@ -54,3 +57,14 @@ func (cmd *OrgSetRoleCommand) Run() error { return nil } + +func (cmd *OrgSetRoleCommand) PreRun(c *cobra.Command, args []string) error { + err := api.ValidateOrgName(args[0]) + if err != nil { + return err + } + cmd.orgName = api.OrgName(args[0]) + cmd.username = args[1] + cmd.role = args[2] + return nil +} diff --git a/internals/secrethub/path_placeholders.go b/internals/secrethub/path_placeholders.go index 1aead2d7..94dcdcab 100644 --- a/internals/secrethub/path_placeholders.go +++ b/internals/secrethub/path_placeholders.go @@ -1,10 +1,10 @@ package secrethub -const ( - repoPathPlaceHolder = "/" - dirPathPlaceHolder = repoPathPlaceHolder + "/[/ ...]" - dirPathsPlaceHolder = dirPathPlaceHolder + "..." - optionalDirPathPlaceHolder = repoPathPlaceHolder + "[/ ...]" - secretPathPlaceHolder = optionalDirPathPlaceHolder + "/" - secretPathOptionalVersionPlaceHolder = secretPathPlaceHolder + "[:]" -) +//const ( +// repoPathPlaceHolder = "/" +// dirPathPlaceHolder = repoPathPlaceHolder + "/[/ ...]" +// dirPathsPlaceHolder = dirPathPlaceHolder + "..." +// optionalDirPathPlaceHolder = repoPathPlaceHolder + "[/ ...]" +// secretPathPlaceHolder = optionalDirPathPlaceHolder + "/" +// secretPathOptionalVersionPlaceHolder = secretPathPlaceHolder + "[:]" +//) diff --git a/internals/secrethub/printenv.go b/internals/secrethub/printenv.go index 44f597d9..1033103a 100644 --- a/internals/secrethub/printenv.go +++ b/internals/secrethub/printenv.go @@ -36,8 +36,8 @@ func (cmd *PrintEnvCommand) Run() error { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *PrintEnvCommand) Register(r command.Registerer) { - clause := r.Command("printenv", "Print environment variables.") + clause := r.CreateCommand("printenv", "Print environment variables.") clause.Flag("verbose", "Show all possible environment variables.").Short('v').BoolVar(&cmd.verbose) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index a57b8e41..9d50d982 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -2,7 +2,6 @@ package secrethub import ( "fmt" - "github.com/spf13/cobra" "io/ioutil" "time" @@ -15,6 +14,8 @@ import ( "github.com/secrethub/secrethub-go/internals/api" "github.com/docker/go-units" + + "github.com/spf13/cobra" ) // ReadCommand is a command to read a secret. @@ -42,7 +43,8 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ReadCommand) Register(r command.Registerer) { - clause := r.Command("read", "Read a secret.") + clause := r.CreateCommand("read", "Read a secret.") + clause.Args = cobra.ExactValidArgs(1) //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathOptionalVersionPlaceHolder).SetValue(&cmd.path) clause.Flag( "clip", @@ -52,15 +54,14 @@ func (cmd *ReadCommand) Register(r command.Registerer) { ), ).Short('c').BoolVar(&cmd.useClipboard) clause.Flag("out-file", "Write the secret value to this file.").Short('o').StringVar(&cmd.outFile) - clause.Flag("file-mode", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) + //clause.Flag("file-mode", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) clause.Flag("no-newline", "Do not print a new line after the secret.").Short('n').BoolVar(&cmd.noNewLine) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run handles the command with the options as specified in the command. -func (cmd *ReadCommand) Run(c *cobra.Command, args []string) error { - cmd.path = api.SecretPath(args[0]) +func (cmd *ReadCommand) Run() error { client, err := cmd.newClient() if err != nil { return err @@ -103,3 +104,12 @@ func (cmd *ReadCommand) Run(c *cobra.Command, args []string) error { return nil } + +func (cmd *ReadCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewSecretPath(args[0]) + if err != nil { + return err + } + return nil +} diff --git a/internals/secrethub/repo.go b/internals/secrethub/repo.go index 463d9e19..c5db46b2 100644 --- a/internals/secrethub/repo.go +++ b/internals/secrethub/repo.go @@ -21,7 +21,7 @@ func NewRepoCommand(io ui.IO, newClient newClientFunc) *RepoCommand { // Register registers the command and its sub-commands on the provided Registerer. func (cmd *RepoCommand) Register(r command.Registerer) { - clause := r.Command("repo", "Manage repositories.") + clause := r.CreateCommand("repo", "Manage repositories.") clause.Alias("repository") clause.Alias("repos") clause.Alias("repositories") diff --git a/internals/secrethub/repo_export.go b/internals/secrethub/repo_export.go index 23ffe444..0141fdac 100644 --- a/internals/secrethub/repo_export.go +++ b/internals/secrethub/repo_export.go @@ -12,6 +12,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // Error @@ -37,11 +39,12 @@ func NewRepoExportCommand(io ui.IO, newClient newClientFunc) *RepoExportCommand // Register registers the command, arguments and flags on the provided Registerer. func (cmd *RepoExportCommand) Register(r command.Registerer) { - clause := r.Command("export", "Export the repository to a zip file.") - clause.Arg("repo-path", "The repository to export").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - clause.Arg("zip-file-name", "The file name to assign to the exported .zip file. Defaults to secrethub_export___.zip with the timestamp formatted as YYYYMMDD_HHMMSS").StringVar(&cmd.zipName) + clause := r.CreateCommand("export", "Export the repository to a zip file.") + clause.Args = cobra.RangeArgs(1, 2) + //clause.Arg("repo-path", "The repository to export").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) + //clause.Arg("zip-file-name", "The file name to assign to the exported .zip file. Defaults to secrethub_export___.zip with the timestamp formatted as YYYYMMDD_HHMMSS").StringVar(&cmd.zipName) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run exports a repo to a zip file @@ -139,3 +142,15 @@ func (cmd *RepoExportCommand) Run() error { return nil } + +func (cmd *RepoExportCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + if len(args) == 2 { + cmd.zipName = args[1] + } + return nil +} diff --git a/internals/secrethub/repo_init.go b/internals/secrethub/repo_init.go index df801140..4d98b6b8 100644 --- a/internals/secrethub/repo_init.go +++ b/internals/secrethub/repo_init.go @@ -7,6 +7,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // RepoInitCommand handles creating new repositories. @@ -26,10 +28,11 @@ func NewRepoInitCommand(io ui.IO, newClient newClientFunc) *RepoInitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *RepoInitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Initialize a new repository.") - clause.Arg("repo-path", "Path to the new repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) + clause := r.CreateCommand("init", "Initialize a new repository.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo-path", "Path to the new repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run creates a new repository. @@ -50,3 +53,12 @@ func (cmd *RepoInitCommand) Run() error { return nil } + +func (cmd *RepoInitCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + return nil +} diff --git a/internals/secrethub/repo_inspect.go b/internals/secrethub/repo_inspect.go index 66165648..7481b150 100644 --- a/internals/secrethub/repo_inspect.go +++ b/internals/secrethub/repo_inspect.go @@ -8,6 +8,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // RepoInspectCommand handles printing out the details of a repo in a JSON format. @@ -29,10 +31,11 @@ func NewRepoInspectCommand(io ui.IO, newClient newClientFunc) *RepoInspectComman // Register registers the command, args, and flags on the provided registerer. func (cmd *RepoInspectCommand) Register(r command.Registerer) { - clause := r.Command("inspect", "Show the details of a repository.") - clause.Arg("repo-path", "Path to the repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) + clause := r.CreateCommand("inspect", "Show the details of a repository.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo-path", "Path to the repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run prints out the details of a repo. @@ -67,6 +70,15 @@ func (cmd *RepoInspectCommand) Run() error { return nil } +func (cmd *RepoInspectCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + return nil +} + func newInspectRepoOutput(repo *api.Repo, users []*api.User, services []*api.Service, timeFormatter TimeFormatter) inspectRepoOutput { out := inspectRepoOutput{ Name: repo.Name, diff --git a/internals/secrethub/repo_invite.go b/internals/secrethub/repo_invite.go index 317a86d3..c6527f35 100644 --- a/internals/secrethub/repo_invite.go +++ b/internals/secrethub/repo_invite.go @@ -7,6 +7,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // RepoInviteCommand handles inviting a user to collaborate on a repository. @@ -28,12 +30,13 @@ func NewRepoInviteCommand(io ui.IO, newClient newClientFunc) *RepoInviteCommand // Register registers the command, arguments and flags on the provided Registerer. func (cmd *RepoInviteCommand) Register(r command.Registerer) { - clause := r.Command("invite", "Invite a user to collaborate on a repository.") - clause.Arg("repo-path", "The repository to invite the user to").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - clause.Arg("username", "username of the user").Required().StringVar(&cmd.username) + clause := r.CreateCommand("invite", "Invite a user to collaborate on a repository.") + clause.Args = cobra.ExactValidArgs(2) + //clause.Arg("repo-path", "The repository to invite the user to").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) + //clause.Arg("username", "username of the user").Required().StringVar(&cmd.username) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run invites the configured user to collaborate on the repo. @@ -74,3 +77,13 @@ func (cmd *RepoInviteCommand) Run() error { return nil } + +func (cmd *RepoInviteCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + cmd.username = args[1] + return nil +} diff --git a/internals/secrethub/repo_ls.go b/internals/secrethub/repo_ls.go index f13ae0b2..8fc413f5 100644 --- a/internals/secrethub/repo_ls.go +++ b/internals/secrethub/repo_ls.go @@ -9,6 +9,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // RepoLSCommand lists repositories. @@ -31,13 +32,14 @@ func NewRepoLSCommand(io ui.IO, newClient newClientFunc) *RepoLSCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *RepoLSCommand) Register(r command.Registerer) { - clause := r.Command("ls", "List all repositories you have access to.") + clause := r.CreateCommand("ls", "List all repositories you have access to.") clause.Alias("list") + clause.Args = cobra.MaximumNArgs(1) clause.Flag("quiet", "Only print paths.").Short('q').BoolVar(&cmd.quiet) - clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) + //clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run lists the repositories a user has access to. @@ -46,6 +48,18 @@ func (cmd *RepoLSCommand) Run() error { return cmd.run() } +func (cmd *RepoLSCommand) PreRun(c *cobra.Command, args []string) error { + var err error + if len(args) != 0 { + err = api.ValidateNamespace(args[0]) + if err != nil { + return err + } + cmd.workspace = api.Namespace(args[0]) + } + return nil +} + // beforeRun configures the command using the flag values. func (cmd *RepoLSCommand) beforeRun() { cmd.timeFormatter = NewTimeFormatter(cmd.useTimestamps) diff --git a/internals/secrethub/repo_revoke.go b/internals/secrethub/repo_revoke.go index 02b2f5cf..073033b5 100644 --- a/internals/secrethub/repo_revoke.go +++ b/internals/secrethub/repo_revoke.go @@ -9,6 +9,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // RepoRevokeCommand handles revoking an account access to a repository. @@ -30,12 +31,13 @@ func NewRepoRevokeCommand(io ui.IO, newClient newClientFunc) *RepoRevokeCommand // Register registers the command, arguments and flags on the provided Registerer. func (cmd *RepoRevokeCommand) Register(r command.Registerer) { - clause := r.Command("revoke", "Revoke an account's access to a repository. A list of secrets that should be rotated will be printed out.") - clause.Arg("repo-path", "The repository to revoke the account from").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) + clause := r.CreateCommand("revoke", "Revoke an account's access to a repository. A list of secrets that should be rotated will be printed out.") + clause.Args = cobra.ExactValidArgs(2) + //clause.Arg("repo-path", "The repository to revoke the account from").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) + //clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run removes and revokes access to an account from a repo if possible. @@ -126,6 +128,19 @@ func (cmd *RepoRevokeCommand) Run() error { return nil } +func (cmd *RepoRevokeCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + cmd.accountName, err = api.NewAccountName(args[0]) + if err != nil { + return err + } + return nil +} + func printFlaggedSecrets(w io.Writer, dir *api.Dir, prePath string) (int, int) { var countUnaffected, countFlagged int if prePath != "" { diff --git a/internals/secrethub/repo_rm.go b/internals/secrethub/repo_rm.go index 9c33eef8..f59c5171 100644 --- a/internals/secrethub/repo_rm.go +++ b/internals/secrethub/repo_rm.go @@ -7,6 +7,8 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + + "github.com/spf13/cobra" ) // RepoRmCommand handles removing a repo. @@ -26,11 +28,12 @@ func NewRepoRmCommand(io ui.IO, newClient newClientFunc) *RepoRmCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *RepoRmCommand) Register(r command.Registerer) { - clause := r.Command("rm", "Permanently delete a repository.") + clause := r.CreateCommand("rm", "Permanently delete a repository.") clause.Alias("remove") - clause.Arg("repo-path", "The repository to delete").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo-path", "The repository to delete").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run removes the repository. @@ -75,3 +78,12 @@ func (cmd *RepoRmCommand) Run() error { return nil } + +func (cmd *RepoRmCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + return nil +} diff --git a/internals/secrethub/rm.go b/internals/secrethub/rm.go index 21b0c1d6..03dc9de7 100644 --- a/internals/secrethub/rm.go +++ b/internals/secrethub/rm.go @@ -8,6 +8,7 @@ import ( "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/pkg/secrethub" + "github.com/spf13/cobra" ) // Errors @@ -37,13 +38,14 @@ func NewRmCommand(io ui.IO, newClient newClientFunc) *RmCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *RmCommand) Register(r command.Registerer) { - clause := r.Command("rm", "Remove a directory, secret or version.") + clause := r.CreateCommand("rm", "Remove a directory, secret or version.") clause.Alias("remove") - clause.Arg("path", "The path to the resource to remove (/[/])").Required().SetValue(&cmd.path) + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("path", "The path to the resource to remove (/[/])").Required().SetValue(&cmd.path) clause.Flag("recursive", "Remove directories and their contents recursively.").Short('r').BoolVar(&cmd.recursive) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run removes the resource at the given path. @@ -94,6 +96,15 @@ func (cmd *RmCommand) Run() error { return rmSecret(client, secretPath, cmd.force, cmd.io) } +func (cmd *RmCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewPath(args[0]) + if err != nil { + return err + } + return nil +} + func rmSecretVersion(client secrethub.ClientInterface, secretPath api.SecretPath, force bool, io ui.IO) error { version, err := secretPath.GetVersion() if err != nil { diff --git a/internals/secrethub/run.go b/internals/secrethub/run.go index db770e20..30a2b571 100644 --- a/internals/secrethub/run.go +++ b/internals/secrethub/run.go @@ -17,6 +17,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/validation" "github.com/secrethub/secrethub-cli/internals/secrethub/command" + "github.com/spf13/cobra" ) // Errors @@ -75,16 +76,17 @@ func (cmd *RunCommand) Register(r command.Registerer) { "The output is buffered to scan for secrets and can be adjusted using the masking-buffer-period flag. " + "You should regard the masking as a best effort attempt and should always prevent secrets ending up on stdout and stderr in the first place." - clause := r.Command("run", helpShort) + clause := r.CreateCommand("run", helpShort) clause.HelpLong(helpLong) clause.Alias("exec") - clause.Arg("command", "The command to execute").Required().StringsVar(&cmd.command) + clause.Args = cobra.MinimumNArgs(1) + //clause.Arg("command", "The command to execute").Required().StringsVar(&cmd.command) clause.Flag("no-masking", "Disable masking of secrets on stdout and stderr").BoolVar(&cmd.noMasking) clause.Flag("no-output-buffering", "Disable output buffering. This increases output responsiveness, but decreases the probability that secrets get masked.").BoolVar(&cmd.maskerOptions.DisableBuffer) clause.Flag("masking-buffer-period", "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.").Default("50ms").DurationVar(&cmd.maskerOptions.BufferDelay) clause.Flag("ignore-missing-secrets", "Do not return an error when a secret does not exist and use an empty value instead.").BoolVar(&cmd.ignoreMissingSecrets) cmd.environment.register(clause) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run reads files from the .secretsenv/ directory, sets them as environment variables and runs the given command. @@ -173,6 +175,14 @@ func (cmd *RunCommand) Run() error { return nil } +func (cmd *RunCommand) PreRun(c *cobra.Command, args []string) error { + cmd.command = make([]string, len(args)) + for i, arg := range args { + cmd.command[i] = arg + } + return nil +} + // sourceEnvironment returns the environment of the subcommand, with all the secrets sourced // and the secret values that need to be masked. func (cmd *RunCommand) sourceEnvironment() ([]string, []string, error) { diff --git a/internals/secrethub/service.go b/internals/secrethub/service.go index 9a8d187a..750dad5d 100644 --- a/internals/secrethub/service.go +++ b/internals/secrethub/service.go @@ -21,7 +21,7 @@ func NewServiceCommand(io ui.IO, newClient newClientFunc) *ServiceCommand { // Register registers the command and its sub-commands on the provided Registerer. func (cmd *ServiceCommand) Register(r command.Registerer) { - clause := r.Command("service", "Manage service accounts.") + clause := r.CreateCommand("service", "Manage service accounts.") NewServiceAWSCommand(cmd.io, cmd.newClient).Register(clause) NewServiceGCPCommand(cmd.io, cmd.newClient).Register(clause) NewServiceDeployCommand(cmd.io).Register(clause) diff --git a/internals/secrethub/service_aws.go b/internals/secrethub/service_aws.go index 45f5ed5d..1411b991 100644 --- a/internals/secrethub/service_aws.go +++ b/internals/secrethub/service_aws.go @@ -21,7 +21,7 @@ func NewServiceAWSCommand(io ui.IO, newClient newClientFunc) *ServiceAWSCommand // Register registers the command and its sub-commands on the provided Registerer. func (cmd *ServiceAWSCommand) Register(r command.Registerer) { - clause := r.Command("aws", "Manage AWS service accounts.") + clause := r.CreateCommand("aws", "Manage AWS service accounts.") NewServiceAWSInitCommand(cmd.io, cmd.newClient).Register(clause) NewServiceAWSLsCommand(cmd.io, cmd.newClient).Register(clause) } diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 11ac5127..9afeb515 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -21,6 +21,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/sts" + "github.com/spf13/cobra" ) // Errors @@ -152,10 +153,20 @@ func (cmd *ServiceAWSInitCommand) Run() error { return nil } +func (cmd *ServiceAWSInitCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.repo, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + return nil +} + // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Create a new service account that is tied to an AWS IAM role.") - clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) + clause := r.CreateCommand("init", "Create a new service account that is tied to an AWS IAM role.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.Flag("kms-key", "The ID or ARN of the KMS-key to be used for encrypting the service's account key.").StringVar(&cmd.kmsKeyID) clause.Flag("role", "The role name or ARN of the IAM role that should have access to this service account.").StringVar(&cmd.role) clause.Flag("region", "The AWS region that should be used for KMS.").StringVar(&cmd.region) @@ -174,7 +185,7 @@ func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { "If no system-wide default for the AWS region is provided (e.g. with $AWS_REGION), the AWS-region where the KMS key resides should be explicitly provided to this command with the --region flag.", ) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } func newKMSKeyOptionsGetter(cfg *aws.Config) kmsKeyOptionsGetter { diff --git a/internals/secrethub/service_deploy.go b/internals/secrethub/service_deploy.go index 1417a2dc..764be59b 100644 --- a/internals/secrethub/service_deploy.go +++ b/internals/secrethub/service_deploy.go @@ -19,6 +19,6 @@ func NewServiceDeployCommand(io ui.IO) *ServiceDeployCommand { // Register registers the command and its sub-commands on the provided Registerer. func (cmd *ServiceDeployCommand) Register(r command.Registerer) { - clause := r.Command("deploy", "Deploy a service account to a destination.") + clause := r.CreateCommand("deploy", "Deploy a service account to a destination.") NewServiceDeployWinRmCommand(cmd.io).Register(clause) } diff --git a/internals/secrethub/service_deploy_winrm.go b/internals/secrethub/service_deploy_winrm.go index 8c6c5d5c..16742fd3 100644 --- a/internals/secrethub/service_deploy_winrm.go +++ b/internals/secrethub/service_deploy_winrm.go @@ -13,6 +13,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-cli/internals/winrm" + "github.com/spf13/cobra" ) // DefaultServiceConfigFilemode configures the filemode used for writing service configuration files. @@ -58,8 +59,9 @@ func NewServiceDeployWinRmCommand(io ui.IO) *ServiceDeployWinRmCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ServiceDeployWinRmCommand) Register(r command.Registerer) { - clause := r.Command("winrm", "Read a service account configuration from stdin and deploy it to a running instance with WinRM. The instance needs to be reachable, have WinRM enabled, and have PowerShell installed.") - clause.Arg("resource-uri", "Hostname, optional connection protocol and port of the host ([http[s]://][:]). This defaults to https and port 5986.").Required().URLVar(&cmd.resourceURI) + clause := r.CreateCommand("winrm", "Read a service account configuration from stdin and deploy it to a running instance with WinRM. The instance needs to be reachable, have WinRM enabled, and have PowerShell installed.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("resource-uri", "Hostname, optional connection protocol and port of the host ([http[s]://][:]). This defaults to https and port 5986.").Required().URLVar(&cmd.resourceURI) clause.Flag("auth-type", "Authentication type (basic/cert)").HintOptions("basic", "cert").Default("basic").StringVar(&cmd.authType) clause.Flag("username", "The username used for logging in when authentication type is basic. Is asked if not supplied.").StringVar(&cmd.username) clause.Flag("password", "The password used for logging in when authentication type is basic. Is asked if not supplied.").StringVar(&cmd.password) @@ -68,7 +70,7 @@ func (cmd *ServiceDeployWinRmCommand) Register(r command.Registerer) { clause.Flag("ca-cert", "Path to CA certificate used to verify server TLS certificate.").ExistingFileVar(&cmd.caCert) clause.Flag("insecure-no-verify-cert", "Do not verify server TLS certificate (insecure).").BoolVar(&cmd.noVerify) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run creates a service and installs the configuration using WinRM. @@ -200,6 +202,15 @@ func (cmd *ServiceDeployWinRmCommand) Run() error { return nil } +func (cmd *ServiceDeployWinRmCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.resourceURI, err = url.Parse(args[0]) + if err != nil { + return err + } + return nil +} + // checkWinRMTLS checks if the given schema corresponds to the given CLI flags. func (cmd *ServiceDeployWinRmCommand) checkWinRMTLS() (bool, error) { if cmd.resourceURI.Scheme == "http" { diff --git a/internals/secrethub/service_gcp.go b/internals/secrethub/service_gcp.go index 67a7294b..f0ae3624 100644 --- a/internals/secrethub/service_gcp.go +++ b/internals/secrethub/service_gcp.go @@ -21,7 +21,7 @@ func NewServiceGCPCommand(io ui.IO, newClient newClientFunc) *ServiceGCPCommand // Register registers the command and its sub-commands on the provided Registerer. func (cmd *ServiceGCPCommand) Register(r command.Registerer) { - clause := r.Command("gcp", "Manage GCP service accounts.") + clause := r.CreateCommand("gcp", "Manage GCP service accounts.") NewServiceGCPInitCommand(cmd.io, cmd.newClient).Register(clause) NewServiceGCPLsCommand(cmd.io, cmd.newClient).Register(clause) NewServiceGCPLinkCommand(cmd.io, cmd.newClient).Register(clause) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index a0ca47be..d0a8fb59 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -22,6 +22,8 @@ import ( "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/pkg/secrethub/credentials" + + "github.com/spf13/cobra" ) // ServiceGCPInitCommand initializes a service for GCP. @@ -153,10 +155,20 @@ func (cmd *ServiceGCPInitCommand) Run() error { return nil } +func (cmd *ServiceGCPInitCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.repo, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + return nil +} + // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Create a new service account that is tied to a GCP Service Account.") - clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) + clause := r.CreateCommand("init", "Create a new service account that is tied to a GCP Service Account.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.Flag("kms-key", "The Resource ID of the KMS-key to be used for encrypting the service's account key.").StringVar(&cmd.kmsKeyResourceID) clause.Flag("service-account-email", "The email of the GCP Service Account that should have access to this service account.").StringVar(&cmd.serviceAccountEmail) clause.Flag("description", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.").StringVar(&cmd.description) @@ -172,7 +184,7 @@ func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { "To create a new service that uses the GCP identity provider, the CLI must have encryption access to the KMS key that will be used by the service account. Therefore GCP application default credentials should be configured on this system. To achieve this, first install the Google Cloud SDK (https://cloud.google.com/sdk/docs/quickstarts) and then run `gcloud auth application-default login`.", ) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } type gcpProjectOptionLister struct { diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 74022da3..98307a4a 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -13,6 +13,7 @@ import ( "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/pkg/secrethub" "github.com/secrethub/secrethub-go/pkg/secrethub/iterator" + "github.com/spf13/cobra" ) // ServiceGCPLinkCommand create a new link between a SecretHub namespace and a GCP project. @@ -49,10 +50,25 @@ func (cmd *ServiceGCPLinkCommand) Run() error { return createGCPLink(client, cmd.io, cmd.namespace.String(), cmd.projectID.String()) } +func (cmd *ServiceGCPLinkCommand) PreRun(c *cobra.Command, args []string) error { + var err error + err = api.ValidateOrgName(args[0]) + if err != nil { + return err + } + cmd.namespace = api.OrgName(args[0]) + err = cmd.projectID.Set(args[1]) + if err != nil { + return err + } + return nil +} + func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { - clause := r.Command("link", "Create a new link between a namespace and a GCP project to allow creating SecretHub service accounts for GCP Service Accounts in the GCP project.") - clause.Arg("namespace", "The SecretHub namespace to link.").Required().SetValue(&cmd.namespace) - clause.Arg("project-id", "The GCP project to link the namespace to.").Required().SetValue(&cmd.projectID) + clause := r.CreateCommand("link", "Create a new link between a namespace and a GCP project to allow creating SecretHub service accounts for GCP Service Accounts in the GCP project.") + clause.Args = cobra.ExactValidArgs(2) + //clause.Arg("namespace", "The SecretHub namespace to link.").Required().SetValue(&cmd.namespace) + //clause.Arg("project-id", "The GCP project to link the namespace to.").Required().SetValue(&cmd.projectID) clause.HelpLong("Linking a GCP project to a namespace is required to create SecretHub service accounts that use a GCP Service Account within the project. " + "A SecretHub namespace can be linked to multiple GCP projects and a GCP project can be linked to multiple namespaces.\n" + @@ -69,7 +85,7 @@ func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { "Any reference to SecretHub should automatically disappear within a few minutes. " + "If it does not, the access can safely be revoked manually.") - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // ServiceGCPListLinksCommand lists all existing links between the given namespace and GCP projects @@ -120,13 +136,23 @@ func (cmd *ServiceGCPListLinksCommand) Run() error { return nil } +func (cmd *ServiceGCPListLinksCommand) PreRun(c *cobra.Command, args []string) error { + err := api.ValidateNamespace(args[0]) + if err != nil { + return err + } + cmd.namespace = api.Namespace(args[0]) + return nil +} + func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { - clause := r.Command("list-links", "List all existing links between the given namespace and GCP projects.") - clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().SetValue(&cmd.namespace) + clause := r.CreateCommand("list-links", "List all existing links between the given namespace and GCP projects.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().SetValue(&cmd.namespace) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // ServiceGCPDeleteLinkCommand deletes the link between a SecretHub namespace and a GCP project. @@ -145,12 +171,13 @@ func NewServiceGCPDeleteLinkCommand(io ui.IO, newClient newClientFunc) *ServiceG } func (cmd *ServiceGCPDeleteLinkCommand) Register(r command.Registerer) { - clause := r.Command("delete-link", "Delete the link between a SecretHub namespace and a GCP project.") + clause := r.CreateCommand("delete-link", "Delete the link between a SecretHub namespace and a GCP project.") clause.HelpLong("After deleting the link you cannot create new GCP service accounts in the specified namespace and GCP project anymore. Exisiting service accounts will keep on working.") - clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().SetValue(&cmd.namespace) - clause.Arg("project-id", "The GCP project to delete the link to.").Required().SetValue(&cmd.projectID) + clause.Args = cobra.ExactValidArgs(2) + //clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().SetValue(&cmd.namespace) + //clause.Arg("project-id", "The GCP project to delete the link to.").Required().SetValue(&cmd.projectID) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } func (cmd *ServiceGCPDeleteLinkCommand) Run() error { @@ -179,6 +206,20 @@ func (cmd *ServiceGCPDeleteLinkCommand) Run() error { return client.IDPLinks().GCP().Delete(cmd.namespace.String(), cmd.projectID.String()) } +func (cmd *ServiceGCPDeleteLinkCommand) PreRun(c *cobra.Command, args []string) error { + var err error + err = api.ValidateNamespace(args[0]) + if err != nil { + return err + } + cmd.namespace = api.Namespace(args[0]) + err = cmd.projectID.Set(args[1]) + if err != nil { + return err + } + return nil +} + type gcpProjectID string func (g *gcpProjectID) String() string { diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index 3213526e..fef45992 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -15,6 +15,7 @@ import ( "github.com/secrethub/secrethub-go/internals/api" "github.com/secrethub/secrethub-go/pkg/secrethub" "github.com/secrethub/secrethub-go/pkg/secrethub/credentials" + "github.com/spf13/cobra" ) // ServiceInitCommand initializes a service and writes the generated config to stdout. @@ -104,8 +105,9 @@ func (cmd *ServiceInitCommand) Run() error { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ServiceInitCommand) Register(r command.Registerer) { - clause := r.Command("init", "Create a new service account.") - clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) + clause := r.CreateCommand("init", "Create a new service account.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.Flag("description", "A description for the service so others will recognize it.").StringVar(&cmd.description) clause.Flag("descr", "").Hidden().StringVar(&cmd.description) clause.Flag("desc", "").Hidden().StringVar(&cmd.description) @@ -116,7 +118,7 @@ func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause.Flag("out-file", "Write the service account configuration to a file instead of stdout.").StringVar(&cmd.file) clause.Flag("file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.").Default("0440").SetValue(&cmd.fileMode) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // givePermission gives the service permission on the repository as defined in the permission flag. @@ -153,6 +155,15 @@ func givePermission(service *api.Service, repo api.RepoPath, permissionFlagValue return nil } +func (cmd *ServiceInitCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.repo, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + return nil +} + // parsePermissionFlag parses a permission flag into a permission and a subdirectory to give // the permission on. func parsePermissionFlag(value string) (subdir string, permission string) { diff --git a/internals/secrethub/service_ls.go b/internals/secrethub/service_ls.go index 59bad3da..6e4bb136 100644 --- a/internals/secrethub/service_ls.go +++ b/internals/secrethub/service_ls.go @@ -9,6 +9,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // ServiceLsCommand lists all service accounts in a given repository. @@ -60,13 +61,14 @@ func NewServiceGCPLsCommand(io ui.IO, newClient newClientFunc) *ServiceLsCommand // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ServiceLsCommand) Register(r command.Registerer) { - clause := r.Command("ls", cmd.help) + clause := r.CreateCommand("ls", cmd.help) clause.Alias("list") - clause.Arg("repo-path", "The path to the repository to list services for").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repoPath) + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("repo-path", "The path to the repository to list services for").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repoPath) clause.Flag("quiet", "Only print service IDs.").Short('q').BoolVar(&cmd.quiet) registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run lists all service accounts in a given repository. @@ -116,6 +118,15 @@ outer: return nil } +func (cmd *ServiceLsCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.repoPath, err = api.NewRepoPath(args[0]) + if err != nil { + return err + } + return nil +} + type serviceTable interface { header() []string row(service *api.Service) []string diff --git a/internals/secrethub/set.go b/internals/secrethub/set.go index 73059e41..9948804d 100644 --- a/internals/secrethub/set.go +++ b/internals/secrethub/set.go @@ -37,10 +37,10 @@ func NewSetCommand(io ui.IO, newClient newClientFunc) *SetCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SetCommand) Register(r command.Registerer) { - clause := r.Command("set", "Set the secrets in your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() + clause := r.CreateCommand("set", "Set the secrets in your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() clause.Flag("in", "The path to a secrets.yml file to read").Short('i').Default("secrets.yml").ExistingFileVar(&cmd.in) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run parses a secret spec file and presents secrets on the system. diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 2d8f3eca..062fcc1d 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -44,7 +44,7 @@ func NewSignUpCommand(io ui.IO, newClient newClientFunc, credentialStore Credent // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SignUpCommand) Register(r command.Registerer) { - clause := r.Command("signup", "Create a free personal developer account.") + clause := r.CreateCommand("signup", "Create a free personal developer account.") clause.Flag("username", "The username you would like to use on SecretHub.").StringVar(&cmd.username) clause.Flag("full-name", "Your full name.").StringVar(&cmd.fullName) clause.Flag("email", "Your (work) email address we will use for all correspondence.").StringVar(&cmd.email) @@ -52,7 +52,7 @@ func (cmd *SignUpCommand) Register(r command.Registerer) { clause.Flag("org-description", "A description (max 144 chars) for your organization so others will recognize it.").StringVar(&cmd.orgDescription) registerForceFlag(clause).BoolVar(&cmd.force) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, nil, cmd.Run) } // Run signs up a new user and configures his account for use on this machine. diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index e026b27f..1b3bfbdf 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -9,6 +9,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) // TreeCommand lists the contents of a directory at a given path in a tree-like format. @@ -45,17 +46,27 @@ func (cmd *TreeCommand) Run() error { return nil } +func (cmd *TreeCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewDirPath(args[0]) + if err != nil { + return err + } + return nil +} + // Register registers the command, arguments and flags on the provided Registerer. func (cmd *TreeCommand) Register(r command.Registerer) { - clause := r.Command("tree", "List contents of a directory in a tree-like format.") - clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) + clause := r.CreateCommand("tree", "List contents of a directory in a tree-like format.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) clause.Flag("full-paths", "Print the full path of each directory and secret.").Short('f').BoolVar(&cmd.fullPaths) clause.Flag("no-indentation", "Don't print indentation lines.").Short('i').BoolVar(&cmd.noIndentation) clause.Flag("no-report", "Turn off secret/directory count at end of tree listing.").BoolVar(&cmd.noReport) clause.Flag("noreport", "Turn off secret/directory count at end of tree listing.").Hidden().BoolVar(&cmd.noReport) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // printTree recursively prints the tree's contents in a tree-like structure. diff --git a/internals/secrethub/write.go b/internals/secrethub/write.go index 316e48a6..8b57a409 100644 --- a/internals/secrethub/write.go +++ b/internals/secrethub/write.go @@ -10,6 +10,7 @@ import ( "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + "github.com/spf13/cobra" ) var ( @@ -42,14 +43,15 @@ func NewWriteCommand(io ui.IO, newClient newClientFunc) *WriteCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *WriteCommand) Register(r command.Registerer) { - clause := r.Command("write", "Write a secret.") - clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathPlaceHolder).SetValue(&cmd.path) + clause := r.CreateCommand("write", "Write a secret.") + clause.Args = cobra.ExactValidArgs(1) + //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathPlaceHolder).SetValue(&cmd.path) clause.Flag("clip", "Use clipboard content as input.").Short('c').BoolVar(&cmd.useClipboard) clause.Flag("multiline", "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.").Short('m').BoolVar(&cmd.multiline) clause.Flag("no-trim", "Do not trim leading and trailing whitespace in the secret.").BoolVar(&cmd.noTrim) clause.Flag("in-file", "Use the contents of this file as the value of the secret.").Short('i').StringVar(&cmd.inFile) - command.BindAction(clause, cmd.Run) + command.BindAction(clause, cmd.PreRun, cmd.Run) } // Run handles the command with the options as specified in the command. @@ -132,3 +134,12 @@ func (cmd *WriteCommand) Run() error { return nil } + +func (cmd *WriteCommand) PreRun(c *cobra.Command, args []string) error { + var err error + cmd.path, err = api.NewSecretPath(args[0]) + if err != nil { + return err + } + return nil +} From b78ebfed236d4f1270cf4256c791051b8e2bb33c Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Sat, 8 Aug 2020 10:37:05 +0300 Subject: [PATCH 05/41] Fix lint using copy instead of loop --- internals/secrethub/run.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/internals/secrethub/run.go b/internals/secrethub/run.go index 30a2b571..97cd3809 100644 --- a/internals/secrethub/run.go +++ b/internals/secrethub/run.go @@ -176,10 +176,7 @@ func (cmd *RunCommand) Run() error { } func (cmd *RunCommand) PreRun(c *cobra.Command, args []string) error { - cmd.command = make([]string, len(args)) - for i, arg := range args { - cmd.command[i] = arg - } + copy(cmd.command, args) return nil } From 05979855d3f53d2e03bd396949a2c7cdc79ea8a7 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Mon, 10 Aug 2020 13:57:34 +0300 Subject: [PATCH 06/41] some of the functions implemented properly. tested on secrethub read, so far so good --- go.mod | 1 + go.sum | 2 ++ internals/cli/env.go | 24 +++++++++++++++++++++--- internals/secrethub/app.go | 8 ++++---- internals/secrethub/command/command.go | 15 ++++++++++----- internals/secrethub/read.go | 15 ++++++++++----- 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index cdabf7d5..7f38623b 100644 --- a/go.mod +++ b/go.mod @@ -20,6 +20,7 @@ require ( github.com/secrethub/secrethub-go v0.30.0 github.com/spf13/cobra v1.0.0 github.com/spf13/pflag v1.0.5 + github.com/xhit/go-str2duration v1.2.0 github.com/zalando/go-keyring v0.0.0-20190208082241-fbe81aec3a07 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 golang.org/x/sys v0.0.0-20200501052902-10377860bb8e diff --git a/go.sum b/go.sum index 209c0ae5..cede34aa 100644 --- a/go.sum +++ b/go.sum @@ -241,6 +241,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/xhit/go-str2duration v1.2.0 h1:BcV5u025cITWxEQKGWr1URRzrcXtu7uk8+luz3Yuhwc= +github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/internals/cli/env.go b/internals/cli/env.go index ce0a2492..4e56363a 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -13,6 +13,7 @@ import ( "bitbucket.org/zombiezen/cardcpx/natsort" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/xhit/go-str2duration" ) var ( @@ -291,9 +292,9 @@ func (f *Flag) HintOptions(options ...string) *Flag { // TODO Implement it properly func (f *Flag) SetValue(location interface{}) *Flag { - //if f.Value != nil { - // location = &f.Value - //} + if f.Value != nil { + location = &f.Value + } return f } @@ -320,14 +321,31 @@ func (f *Flag) StringVar(location *string) *Flag { // TODO Implement the following functions properly func (f *Flag) DurationVar(location *time.Duration) *Flag { + if f.Value != nil { + *location, _ = str2duration.Str2Duration(f.Value.String()) + } else { + *location, _ = str2duration.Str2Duration(f.DefValue) + } return f } func (f *Flag) URLVar(location **url.URL) *Flag { + if f.Value != nil { + parsedURL, _ := url.Parse(f.Value.String()) + *location = parsedURL + } else { + parsedURL, _ := url.Parse(f.DefValue) + location = &parsedURL + } return f } func (f *Flag) IntVar(location *int) *Flag { + if f.Value != nil { + *location, _ = strconv.Atoi(f.Value.String()) + } else { + *location, _ = strconv.Atoi(f.DefValue) + } return f } diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index 029474e7..c2fbc459 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -94,9 +94,9 @@ func NewApp() *App { logger: cli.NewLogger(), } - //RegisterDebugFlag(app.cli, app.logger) - //RegisterMlockFlag(app.cli) - //RegisterColorFlag(app.cli) + RegisterDebugFlag(app.cli, app.logger) + RegisterMlockFlag(app.cli) + RegisterColorFlag(app.cli) app.credentialStore.Register(app.cli) app.clientFactory.Register(app.cli) app.registerCommands() @@ -190,4 +190,4 @@ func (app *App) registerCommands() { NewKeyringClearCommand().Register(app.cli) //demo.NewCommand(app.io, app.clientFactory.NewClient).Register(app.cli) -} +} \ No newline at end of file diff --git a/internals/secrethub/command/command.go b/internals/secrethub/command/command.go index 54464c93..0fb4db89 100644 --- a/internals/secrethub/command/command.go +++ b/internals/secrethub/command/command.go @@ -1,3 +1,6 @@ + + + package command import ( @@ -13,11 +16,13 @@ type Registerer interface { // BindAction binds a function to a command clause, so that // it is executed when the command is parsed. -func BindAction(clause *cli.CommandClause, prefn func(c *cobra.Command, args []string) error, fn func() error) { - if prefn != nil { - clause.Command.RunE = prefn +func BindAction(clause *cli.CommandClause, argumentRegister func(c *cobra.Command, args []string) error, fn func() error) { + if argumentRegister != nil { + clause.RunE = argumentRegister } - clause.Command.PostRunE = func(cmd *cobra.Command, args []string) error { - return fn() + if fn != nil { + clause.PostRunE = func(cmd *cobra.Command, args []string) error { + return fn() + } } } diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index 9d50d982..76603eb9 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -44,7 +44,8 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") - clause.Args = cobra.ExactValidArgs(1) + + cmd.argumentConstraint(clause.Command) //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathOptionalVersionPlaceHolder).SetValue(&cmd.path) clause.Flag( "clip", @@ -54,10 +55,10 @@ func (cmd *ReadCommand) Register(r command.Registerer) { ), ).Short('c').BoolVar(&cmd.useClipboard) clause.Flag("out-file", "Write the secret value to this file.").Short('o').StringVar(&cmd.outFile) - //clause.Flag("file-mode", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) + clause.Flag("file-mode", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) clause.Flag("no-newline", "Do not print a new line after the secret.").Short('n').BoolVar(&cmd.noNewLine) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run handles the command with the options as specified in the command. @@ -105,11 +106,15 @@ func (cmd *ReadCommand) Run() error { return nil } -func (cmd *ReadCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ReadCommand) argumentConstraint(c *cobra.Command) { + c.Args = cobra.ExactValidArgs(1) +} + +func (cmd *ReadCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewSecretPath(args[0]) if err != nil { return err } return nil -} +} \ No newline at end of file From b9699bfe56cc1b4a33a5812382226566d8173044 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Mon, 10 Aug 2020 14:43:40 +0300 Subject: [PATCH 07/41] implemented existing file var in progress and stringmapvar --- internals/cli/env.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/internals/cli/env.go b/internals/cli/env.go index 4e56363a..a715a9ae 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -350,10 +350,21 @@ func (f *Flag) IntVar(location *int) *Flag { } func (f *Flag) ExistingFileVar(location *string) *Flag { + if f.Value != nil { + *location = f.Value.String() + } else { + *location = f.DefValue + } return f + } func (f *Flag) StringMapVar(location *map[string]string) *Flag { + if f.Value != nil { + newVar := f.Value.String() + arr := strings.Split(newVar, "=") + (*location)[arr[0]] = arr[1] + } return f } From ba69bc7f6b8bfae17b1aebaf5057f7357a49cdd8 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Tue, 11 Aug 2020 12:59:48 +0300 Subject: [PATCH 08/41] changed to another flag structure --- internals/secrethub/read.go | 38 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index 76603eb9..ba42bbe6 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -2,19 +2,18 @@ package secrethub import ( "fmt" + "github.com/docker/go-units" + "github.com/secrethub/secrethub-cli/internals/cli/posix" "io/ioutil" "time" "github.com/secrethub/secrethub-cli/internals/cli/clip" "github.com/secrethub/secrethub-cli/internals/cli/filemode" - "github.com/secrethub/secrethub-cli/internals/cli/posix" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" - "github.com/docker/go-units" - "github.com/spf13/cobra" ) @@ -22,12 +21,12 @@ import ( type ReadCommand struct { io ui.IO path api.SecretPath - useClipboard bool + useClipboard *bool clearClipboardAfter time.Duration clipper clip.Clipper - outFile string + outFile *string fileMode filemode.FileMode - noNewLine bool + noNewLine *bool newClient newClientFunc } @@ -44,20 +43,17 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") - cmd.argumentConstraint(clause.Command) - //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathOptionalVersionPlaceHolder).SetValue(&cmd.path) - clause.Flag( - "clip", + cmd.useClipboard = clause.Flags().BoolP( + "clip", "c", false, fmt.Sprintf( "Copy the secret value to the clipboard. The clipboard is automatically cleared after %s.", units.HumanDuration(cmd.clearClipboardAfter), ), - ).Short('c').BoolVar(&cmd.useClipboard) - clause.Flag("out-file", "Write the secret value to this file.").Short('o').StringVar(&cmd.outFile) - clause.Flag("file-mode", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) - clause.Flag("no-newline", "Do not print a new line after the secret.").Short('n').BoolVar(&cmd.noNewLine) - + ) + cmd.outFile = clause.Flags().StringP("out-file", "o", "", "Write the secret value to this file.") + cmd.fileMode = ("file-mode", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) + cmd.noNewLine = clause.Flags().BoolP("no-newline", "n", false, "Do not print a new line after the secret") command.BindAction(clause, cmd.argumentRegister, cmd.Run) } @@ -73,7 +69,7 @@ func (cmd *ReadCommand) Run() error { return err } - if cmd.useClipboard { + if *cmd.useClipboard { err = WriteClipboardAutoClear(secret.Data, cmd.clearClipboardAfter, cmd.clipper) if err != nil { return err @@ -88,18 +84,18 @@ func (cmd *ReadCommand) Run() error { } secretData := secret.Data - if !cmd.noNewLine { + if !*cmd.noNewLine { secretData = posix.AddNewLine(secretData) } - if cmd.outFile != "" { - err = ioutil.WriteFile(cmd.outFile, secretData, cmd.fileMode.FileMode()) + if *cmd.outFile != "" { + err = ioutil.WriteFile(*cmd.outFile, secretData, cmd.fileMode.FileMode()) if err != nil { return ErrCannotWrite(cmd.outFile, err) } } - if cmd.outFile == "" && !cmd.useClipboard { + if *cmd.outFile == "" && !*cmd.useClipboard { fmt.Fprintf(cmd.io.Output(), "%s", string(secretData)) } @@ -117,4 +113,4 @@ func (cmd *ReadCommand) argumentRegister(c *cobra.Command, args []string) error return err } return nil -} \ No newline at end of file +} From 7f24ee389a513f605c2c8bfb7a08bd75c7c7e6ce Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Wed, 12 Aug 2020 13:00:09 +0300 Subject: [PATCH 09/41] the transition began. --- internals/cli/env.go | 111 ----------------------------- internals/cli/filemode/filemode.go | 4 ++ internals/secrethub/read.go | 33 +++++---- 3 files changed, 22 insertions(+), 126 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index a715a9ae..40a84f8a 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -3,17 +3,13 @@ package cli import ( "fmt" "io" - "net/url" "os" - "strconv" "strings" "text/tabwriter" - "time" "bitbucket.org/zombiezen/cardcpx/natsort" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/xhit/go-str2duration" ) var ( @@ -262,113 +258,6 @@ func (f *Flag) NoEnvar() *Flag { return f } -// Hidden hides the flag in help texts. -func (f *Flag) Hidden() *Flag { - f.Flag.Hidden = true - return f -} - -// Short puts the shorthand of the flag. -func (f *Flag) Short(s rune) *Flag { - f.Flag.Shorthand = string(s) - return f -} - -func (f *Flag) Default(val string) *Flag { - if f.Flag.DefValue == "" { - f.Flag.DefValue = val - } - return f -} - -func (f *Flag) PlaceHolder(val string) *Flag { - return f -} - -// TODO Implement it properly -func (f *Flag) HintOptions(options ...string) *Flag { - return f -} - -// TODO Implement it properly -func (f *Flag) SetValue(location interface{}) *Flag { - if f.Value != nil { - location = &f.Value - } - return f -} - -// Hidden hides the command in help texts. -func (f *Flag) BoolVar(location *bool) *Flag { - if f.Value != nil { - intermediary, _ := strconv.ParseBool(f.Value.String()) - *location = intermediary - } else { - *location = false - } - - return f -} - -func (f *Flag) StringVar(location *string) *Flag { - if f.Value != nil { - *location = f.Value.String() - } else { - *location = f.DefValue - } - return f -} - -// TODO Implement the following functions properly -func (f *Flag) DurationVar(location *time.Duration) *Flag { - if f.Value != nil { - *location, _ = str2duration.Str2Duration(f.Value.String()) - } else { - *location, _ = str2duration.Str2Duration(f.DefValue) - } - return f -} - -func (f *Flag) URLVar(location **url.URL) *Flag { - if f.Value != nil { - parsedURL, _ := url.Parse(f.Value.String()) - *location = parsedURL - } else { - parsedURL, _ := url.Parse(f.DefValue) - location = &parsedURL - } - return f -} - -func (f *Flag) IntVar(location *int) *Flag { - if f.Value != nil { - *location, _ = strconv.Atoi(f.Value.String()) - } else { - *location, _ = strconv.Atoi(f.DefValue) - } - return f -} - -func (f *Flag) ExistingFileVar(location *string) *Flag { - if f.Value != nil { - *location = f.Value.String() - } else { - *location = f.DefValue - } - return f - -} - -func (f *Flag) StringMapVar(location *map[string]string) *Flag { - if f.Value != nil { - newVar := f.Value.String() - arr := strings.Split(newVar, "=") - (*location)[arr[0]] = arr[1] - } - return f -} - -// End of TODO // formatName takes a name and converts it to an uppercased name, // joined by the given separator and prefixed with the given prefix. diff --git a/internals/cli/filemode/filemode.go b/internals/cli/filemode/filemode.go index c293405d..588907f9 100644 --- a/internals/cli/filemode/filemode.go +++ b/internals/cli/filemode/filemode.go @@ -17,6 +17,10 @@ var ( // so that the file mode can be parsed from a flag. type FileMode os.FileMode +func (m *FileMode) Type() string { + return "filemode" +} + // New creates a new FileMode. func New(fileMode os.FileMode) FileMode { return FileMode(fileMode) diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index ba42bbe6..e6b54eca 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -21,12 +21,12 @@ import ( type ReadCommand struct { io ui.IO path api.SecretPath - useClipboard *bool + useClipboard bool clearClipboardAfter time.Duration clipper clip.Clipper - outFile *string + outFile string fileMode filemode.FileMode - noNewLine *bool + noNewLine bool newClient newClientFunc } @@ -44,16 +44,19 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") cmd.argumentConstraint(clause.Command) - cmd.useClipboard = clause.Flags().BoolP( + clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, fmt.Sprintf( "Copy the secret value to the clipboard. The clipboard is automatically cleared after %s.", units.HumanDuration(cmd.clearClipboardAfter), ), ) - cmd.outFile = clause.Flags().StringP("out-file", "o", "", "Write the secret value to this file.") - cmd.fileMode = ("file-mode", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) - cmd.noNewLine = clause.Flags().BoolP("no-newline", "n", false, "Do not print a new line after the secret") + clause.Flags().StringVarP(&cmd.outFile, "out-file", "o", "", "Write the secret value to this file.") + clause.Flags().BoolVarP(&cmd.noNewLine, "no-newline", "n",false, "Do not print a new line after the secret") + + fileModeFlag := clause.Flags().VarPF(&cmd.fileMode, "file-mode", "","Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") + fileModeFlag.DefValue = "0600" + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } @@ -69,13 +72,13 @@ func (cmd *ReadCommand) Run() error { return err } - if *cmd.useClipboard { + if cmd.useClipboard { err = WriteClipboardAutoClear(secret.Data, cmd.clearClipboardAfter, cmd.clipper) if err != nil { return err } - fmt.Fprintf( + _, _ = fmt.Fprintf( cmd.io.Output(), "Copied %s to clipboard. It will be cleared after %s.\n", cmd.path, @@ -84,19 +87,19 @@ func (cmd *ReadCommand) Run() error { } secretData := secret.Data - if !*cmd.noNewLine { + if !cmd.noNewLine { secretData = posix.AddNewLine(secretData) } - if *cmd.outFile != "" { - err = ioutil.WriteFile(*cmd.outFile, secretData, cmd.fileMode.FileMode()) + if cmd.outFile != "" { + err = ioutil.WriteFile(cmd.outFile, secretData, cmd.fileMode.FileMode()) if err != nil { return ErrCannotWrite(cmd.outFile, err) } } - if *cmd.outFile == "" && !*cmd.useClipboard { - fmt.Fprintf(cmd.io.Output(), "%s", string(secretData)) + if cmd.outFile == "" && !cmd.useClipboard { + _, _ = fmt.Fprintf(cmd.io.Output(), "%s", string(secretData)) } return nil @@ -106,7 +109,7 @@ func (cmd *ReadCommand) argumentConstraint(c *cobra.Command) { c.Args = cobra.ExactValidArgs(1) } -func (cmd *ReadCommand) argumentRegister(c *cobra.Command, args []string) error { +func (cmd *ReadCommand) argumentRegister(_ *cobra.Command, args []string) error { var err error cmd.path, err = api.NewSecretPath(args[0]) if err != nil { From 365d03d41154b959005f3c7b7c62326f5782df4a Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Wed, 12 Aug 2020 13:42:51 +0300 Subject: [PATCH 10/41] formatted around a quarter of the files --- internals/cli/env.go | 26 +++++++++++------------ internals/secrethub/account_init.go | 9 ++++---- internals/secrethub/acl_list.go | 7 +++--- internals/secrethub/acl_rm.go | 3 ++- internals/secrethub/acl_set.go | 3 ++- internals/secrethub/clear.go | 2 +- internals/secrethub/clear_clipboard.go | 2 +- internals/secrethub/color.go | 5 +++-- internals/secrethub/credential_disable.go | 4 ++-- internals/secrethub/credential_list.go | 3 ++- internals/secrethub/service_gcp_link.go | 3 ++- internals/secrethub/service_ls.go | 5 +++-- internals/secrethub/set.go | 2 +- internals/secrethub/signup.go | 14 ++++++------ internals/secrethub/tree.go | 10 +++++---- internals/secrethub/write.go | 7 +++--- 16 files changed, 58 insertions(+), 47 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 40a84f8a..2d9bab04 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -213,19 +213,19 @@ func (cmd *CommandClause) Alias(alias string) { // Flag defines a new flag with the given long name and help text, // adding an environment variable default configurable by APP_COMMAND_FLAG_NAME. // The help text is suffixed with a description of secrthe environment variable default. -func (cmd *CommandClause) Flag(name, help string) *Flag { - fullCmd := strings.Replace(cmd.FullCommand(), " ", cmd.app.separator, -1) - prefix := formatName(fullCmd, cmd.app.name, cmd.app.separator, cmd.app.delimiters...) - envVar := formatName(name, prefix, cmd.app.separator, cmd.app.delimiters...) - - cmd.app.registerEnvVar(envVar) - flag := &pflag.Flag{Name: name, Usage: help} - return &Flag{ - Flag: flag, - app: cmd.app, - envVar: envVar, - } -} +//func (cmd *CommandClause) Flag(name, help string) *Flag { +// fullCmd := strings.Replace(cmd.FullCommand(), " ", cmd.app.separator, -1) +// prefix := formatName(fullCmd, cmd.app.name, cmd.app.separator, cmd.app.delimiters...) +// envVar := formatName(name, prefix, cmd.app.separator, cmd.app.delimiters...) +// +// cmd.app.registerEnvVar(envVar) +// flag := &pflag.Flag{Name: name, Usage: help} +// return &Flag{ +// Flag: flag, +// app: cmd.app, +// envVar: envVar, +// } +//} // Flag represents a command-line flag. type Flag struct { diff --git a/internals/secrethub/account_init.go b/internals/secrethub/account_init.go index 4f972d25..31a3fa90 100644 --- a/internals/secrethub/account_init.go +++ b/internals/secrethub/account_init.go @@ -60,10 +60,11 @@ func NewAccountInitCommand(io ui.IO, newClient newClientFunc, credentialStore Cr // Register registers the command, arguments and flags on the provided Registerer. func (cmd *AccountInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Connect a first device to your SecretHub account.") - clause.Flag("clip", "Copy the credential's public component to the clipboard instead of printing it to stdout.").Short('c').BoolVar(&cmd.useClipboard) - clause.Flag("no-wait", "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.").BoolVar(&cmd.noWait) - clause.Flag("continue", "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.").BoolVar(&cmd.isContinue) - registerForceFlag(clause).BoolVar(&cmd.force) + clause.Flags().BoolVarP(&cmd.useClipboard, "clip","c", false, "Copy the credential's public component to the clipboard instead of printing it to stdout.") + clause.Flags().BoolVar(&cmd.noWait,"no-wait", false, "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.") + clause.Flags().BoolVar(&cmd.isContinue, "continue", false, "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.") + // TODO force flags!!!! + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/acl_list.go b/internals/secrethub/acl_list.go index 79d3ee9d..c5e0c558 100644 --- a/internals/secrethub/acl_list.go +++ b/internals/secrethub/acl_list.go @@ -39,9 +39,10 @@ func (cmd *ACLListCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-path", "The path of the directory to list the access rules for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Flag("depth", "The maximum depth to which the rules of child directories should be displayed. Defaults to -1 (no limit).").Short('d').Default("-1").IntVar(&cmd.depth) - clause.Flag("all", "List all rules that apply on the directory, including rules on parent directories.").Short('a').BoolVar(&cmd.ancestors) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + clause.Flags().IntVarP(&cmd.depth, "depth", "d", -1, "The maximum depth to which the rules of child directories should be displayed. Defaults to -1 (no limit).") + clause.Flags().BoolVarP(&cmd.ancestors, "all", "a", false, "List all rules that apply on the directory, including rules on parent directories.") + //TODO timestamps!!! + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/acl_rm.go b/internals/secrethub/acl_rm.go index a470600a..d0a85d92 100644 --- a/internals/secrethub/acl_rm.go +++ b/internals/secrethub/acl_rm.go @@ -33,7 +33,8 @@ func (cmd *ACLRmCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("dir-path", "The path of the directory to remove the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) - registerForceFlag(clause).BoolVar(&cmd.force) + //TODO FORCE!! + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/acl_set.go b/internals/secrethub/acl_set.go index af491ba2..3418b58a 100644 --- a/internals/secrethub/acl_set.go +++ b/internals/secrethub/acl_set.go @@ -35,7 +35,8 @@ func (cmd *ACLSetCommand) Register(r command.Registerer) { //clause.Arg("dir-path", "The path of the directory to set the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to set the access rule for").Required().SetValue(&cmd.accountName) //clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) - registerForceFlag(clause).BoolVar(&cmd.force) + //TODO FORCE!!! + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/clear.go b/internals/secrethub/clear.go index 633ad03b..16c2affe 100644 --- a/internals/secrethub/clear.go +++ b/internals/secrethub/clear.go @@ -26,7 +26,7 @@ func NewClearCommand(io ui.IO) *ClearCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ClearCommand) Register(r command.Registerer) { clause := r.CreateCommand("clear", "Clear the secrets from your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() - clause.Flag("in", "The path to a secrets.yml file to read").Short('i').Default("secrets.yml").ExistingFileVar(&cmd.in) + clause.Flags().StringVarP(&cmd.in,"in", "i", "secrets.yml", "The path to a secrets.yml file to read") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/clear_clipboard.go b/internals/secrethub/clear_clipboard.go index 54576b30..16e9e889 100644 --- a/internals/secrethub/clear_clipboard.go +++ b/internals/secrethub/clear_clipboard.go @@ -34,7 +34,7 @@ func (cmd *ClearClipboardCommand) Register(r command.Registerer) { clause := r.CreateCommand("clipboard-clear", "Removes secret from clipboard.").Hidden() clause.Args = cobra.ExactValidArgs(1) //clause.Arg("hash", "Hash from the secret to be cleared").Required().HexBytesVar(&cmd.hash) - clause.Flag("timeout", "Time to wait before clearing in seconds").DurationVar(&cmd.timeout) + clause.Flags().DurationVar(&cmd.timeout, "timeout",0, "Time to wait before clearing in seconds") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/color.go b/internals/secrethub/color.go index 2d36fbf8..48a5f39e 100644 --- a/internals/secrethub/color.go +++ b/internals/secrethub/color.go @@ -16,8 +16,9 @@ func (f noColorFlag) init() { // RegisterColorFlag registers a color flag that configures whether colored output is used. func RegisterColorFlag(r FlagRegisterer) { - flag := noColorFlag(false) - r.Flag("no-color", "Disable colored output.").SetValue(&flag) + //TODO + //flag := noColorFlag(false) + //r.Flag("no-color", "Disable colored output.").SetValue(&flag) } // String implements the flag.Value interface. diff --git a/internals/secrethub/credential_disable.go b/internals/secrethub/credential_disable.go index 0f272649..6f1e8199 100644 --- a/internals/secrethub/credential_disable.go +++ b/internals/secrethub/credential_disable.go @@ -33,8 +33,8 @@ func (cmd *CredentialDisableCommand) Register(r command.Registerer) { //fingerprintHelp := fmt.Sprintf("Fingerprint of the credential to disable. At least the first %d characters must be entered.", api.ShortCredentialFingerprintMinimumLength) //clause.Arg("fingerprint", fingerprintHelp).StringVar(&cmd.fingerprint) - - registerForceFlag(clause).BoolVar(&cmd.force) +//TODO + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/credential_list.go b/internals/secrethub/credential_list.go index ca7437a5..7cef3f10 100644 --- a/internals/secrethub/credential_list.go +++ b/internals/secrethub/credential_list.go @@ -32,7 +32,8 @@ func (cmd *CredentialListCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all your credentials.") clause.Alias("list") - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + //TODO + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 98307a4a..3cf74e66 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -150,7 +150,8 @@ func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().SetValue(&cmd.namespace) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + //TODO + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_ls.go b/internals/secrethub/service_ls.go index 6e4bb136..4ef036d5 100644 --- a/internals/secrethub/service_ls.go +++ b/internals/secrethub/service_ls.go @@ -65,8 +65,9 @@ func (cmd *ServiceLsCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo-path", "The path to the repository to list services for").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repoPath) - clause.Flag("quiet", "Only print service IDs.").Short('q').BoolVar(&cmd.quiet) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + clause.Flags().BoolVarP(&cmd.quiet,"quiet","q",false, "Only print service IDs.") + //TODO + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/set.go b/internals/secrethub/set.go index 9948804d..163a5dec 100644 --- a/internals/secrethub/set.go +++ b/internals/secrethub/set.go @@ -38,7 +38,7 @@ func NewSetCommand(io ui.IO, newClient newClientFunc) *SetCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SetCommand) Register(r command.Registerer) { clause := r.CreateCommand("set", "Set the secrets in your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() - clause.Flag("in", "The path to a secrets.yml file to read").Short('i').Default("secrets.yml").ExistingFileVar(&cmd.in) + clause.Flags().StringVarP(&cmd.in, "in","i", "secrets.yml", "The path to a secrets.yml file to read") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 062fcc1d..d810ea7a 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -45,12 +45,14 @@ func NewSignUpCommand(io ui.IO, newClient newClientFunc, credentialStore Credent // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SignUpCommand) Register(r command.Registerer) { clause := r.CreateCommand("signup", "Create a free personal developer account.") - clause.Flag("username", "The username you would like to use on SecretHub.").StringVar(&cmd.username) - clause.Flag("full-name", "Your full name.").StringVar(&cmd.fullName) - clause.Flag("email", "Your (work) email address we will use for all correspondence.").StringVar(&cmd.email) - clause.Flag("org", "The name of your organization.").StringVar(&cmd.org) - clause.Flag("org-description", "A description (max 144 chars) for your organization so others will recognize it.").StringVar(&cmd.orgDescription) - registerForceFlag(clause).BoolVar(&cmd.force) + clause.Flags().StringVar(&cmd.username,"username", "","The username you would like to use on SecretHub.") + clause.Flags().StringVar(&cmd.fullName,"full-name", "","Your full name.") + clause.Flags().StringVar(&cmd.email,"email", "","Your (work) email address we will use for all correspondence.") + clause.Flags().StringVar(&cmd.org,"org", "","The name of your organization.") + clause.Flags().StringVar(&cmd.orgDescription,"org-description", "","A description (max 144 chars) for your organization so others will recognize it.") + + //TODO + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 1b3bfbdf..5bbf6b3a 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -61,10 +61,12 @@ func (cmd *TreeCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Flag("full-paths", "Print the full path of each directory and secret.").Short('f').BoolVar(&cmd.fullPaths) - clause.Flag("no-indentation", "Don't print indentation lines.").Short('i').BoolVar(&cmd.noIndentation) - clause.Flag("no-report", "Turn off secret/directory count at end of tree listing.").BoolVar(&cmd.noReport) - clause.Flag("noreport", "Turn off secret/directory count at end of tree listing.").Hidden().BoolVar(&cmd.noReport) + clause.Flags().BoolVarP(&cmd.fullPaths, "full-paths", "f",false, "Print the full path of each directory and secret.") + clause.Flags().BoolVarP(&cmd.noIndentation, "no-indentation", "n",false, "Do not use the standard indentation.") + clause.Flags().BoolVar(&cmd.noReport, "no-report", false,"Turn off secret/directory count at end of tree listing.") + clause.Flags().BoolVar(&cmd.noReport, "noreport", false,"Turn off secret/directory count at end of tree listing.") + + clause.Flag("noreport").Hidden = true command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/write.go b/internals/secrethub/write.go index 8b57a409..0b94bedb 100644 --- a/internals/secrethub/write.go +++ b/internals/secrethub/write.go @@ -46,10 +46,9 @@ func (cmd *WriteCommand) Register(r command.Registerer) { clause := r.CreateCommand("write", "Write a secret.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathPlaceHolder).SetValue(&cmd.path) - clause.Flag("clip", "Use clipboard content as input.").Short('c').BoolVar(&cmd.useClipboard) - clause.Flag("multiline", "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.").Short('m').BoolVar(&cmd.multiline) - clause.Flag("no-trim", "Do not trim leading and trailing whitespace in the secret.").BoolVar(&cmd.noTrim) - clause.Flag("in-file", "Use the contents of this file as the value of the secret.").Short('i').StringVar(&cmd.inFile) + clause.Flags().BoolVarP(&cmd.useClipboard,"clip","c", false, "Use clipboard content as input.") + clause.Flags().BoolVarP(&cmd.multiline,"multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.") + clause.Flags().StringVarP(&cmd.inFile, "in-file", "i", "", "Use the contents of this file as the value of the secret.") command.BindAction(clause, cmd.PreRun, cmd.Run) } From 69fb50d1cf3eb8dbbf604d44f5bc0b88a3724e8a Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Wed, 12 Aug 2020 13:43:39 +0300 Subject: [PATCH 11/41] linter, not that it isn't my last concern --- internals/cli/env.go | 1 - internals/secrethub/account_init.go | 4 ++-- internals/secrethub/app.go | 2 +- internals/secrethub/clear.go | 2 +- internals/secrethub/clear_clipboard.go | 2 +- internals/secrethub/command/command.go | 3 --- internals/secrethub/credential_disable.go | 2 +- internals/secrethub/read.go | 6 +++--- internals/secrethub/service_ls.go | 2 +- internals/secrethub/set.go | 2 +- internals/secrethub/signup.go | 10 +++++----- internals/secrethub/tree.go | 8 ++++---- internals/secrethub/write.go | 4 ++-- 13 files changed, 22 insertions(+), 26 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 2d9bab04..0f46ec47 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -258,7 +258,6 @@ func (f *Flag) NoEnvar() *Flag { return f } - // formatName takes a name and converts it to an uppercased name, // joined by the given separator and prefixed with the given prefix. func formatName(name, prefix, separator string, delimiters ...string) string { diff --git a/internals/secrethub/account_init.go b/internals/secrethub/account_init.go index 31a3fa90..09b74858 100644 --- a/internals/secrethub/account_init.go +++ b/internals/secrethub/account_init.go @@ -60,8 +60,8 @@ func NewAccountInitCommand(io ui.IO, newClient newClientFunc, credentialStore Cr // Register registers the command, arguments and flags on the provided Registerer. func (cmd *AccountInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Connect a first device to your SecretHub account.") - clause.Flags().BoolVarP(&cmd.useClipboard, "clip","c", false, "Copy the credential's public component to the clipboard instead of printing it to stdout.") - clause.Flags().BoolVar(&cmd.noWait,"no-wait", false, "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.") + clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, "Copy the credential's public component to the clipboard instead of printing it to stdout.") + clause.Flags().BoolVar(&cmd.noWait, "no-wait", false, "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.") clause.Flags().BoolVar(&cmd.isContinue, "continue", false, "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.") // TODO force flags!!!! //registerForceFlag(clause).BoolVar(&cmd.force) diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index c2fbc459..01cd421c 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -190,4 +190,4 @@ func (app *App) registerCommands() { NewKeyringClearCommand().Register(app.cli) //demo.NewCommand(app.io, app.clientFactory.NewClient).Register(app.cli) -} \ No newline at end of file +} diff --git a/internals/secrethub/clear.go b/internals/secrethub/clear.go index 16c2affe..b5b7707e 100644 --- a/internals/secrethub/clear.go +++ b/internals/secrethub/clear.go @@ -26,7 +26,7 @@ func NewClearCommand(io ui.IO) *ClearCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ClearCommand) Register(r command.Registerer) { clause := r.CreateCommand("clear", "Clear the secrets from your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() - clause.Flags().StringVarP(&cmd.in,"in", "i", "secrets.yml", "The path to a secrets.yml file to read") + clause.Flags().StringVarP(&cmd.in, "in", "i", "secrets.yml", "The path to a secrets.yml file to read") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/clear_clipboard.go b/internals/secrethub/clear_clipboard.go index 16e9e889..aaf8226d 100644 --- a/internals/secrethub/clear_clipboard.go +++ b/internals/secrethub/clear_clipboard.go @@ -34,7 +34,7 @@ func (cmd *ClearClipboardCommand) Register(r command.Registerer) { clause := r.CreateCommand("clipboard-clear", "Removes secret from clipboard.").Hidden() clause.Args = cobra.ExactValidArgs(1) //clause.Arg("hash", "Hash from the secret to be cleared").Required().HexBytesVar(&cmd.hash) - clause.Flags().DurationVar(&cmd.timeout, "timeout",0, "Time to wait before clearing in seconds") + clause.Flags().DurationVar(&cmd.timeout, "timeout", 0, "Time to wait before clearing in seconds") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/command/command.go b/internals/secrethub/command/command.go index 0fb4db89..aa664904 100644 --- a/internals/secrethub/command/command.go +++ b/internals/secrethub/command/command.go @@ -1,6 +1,3 @@ - - - package command import ( diff --git a/internals/secrethub/credential_disable.go b/internals/secrethub/credential_disable.go index 6f1e8199..6acc2441 100644 --- a/internals/secrethub/credential_disable.go +++ b/internals/secrethub/credential_disable.go @@ -33,7 +33,7 @@ func (cmd *CredentialDisableCommand) Register(r command.Registerer) { //fingerprintHelp := fmt.Sprintf("Fingerprint of the credential to disable. At least the first %d characters must be entered.", api.ShortCredentialFingerprintMinimumLength) //clause.Arg("fingerprint", fingerprintHelp).StringVar(&cmd.fingerprint) -//TODO + //TODO //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index e6b54eca..d249b513 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -51,10 +51,10 @@ func (cmd *ReadCommand) Register(r command.Registerer) { units.HumanDuration(cmd.clearClipboardAfter), ), ) - clause.Flags().StringVarP(&cmd.outFile, "out-file", "o", "", "Write the secret value to this file.") - clause.Flags().BoolVarP(&cmd.noNewLine, "no-newline", "n",false, "Do not print a new line after the secret") + clause.Flags().StringVarP(&cmd.outFile, "out-file", "o", "", "Write the secret value to this file.") + clause.Flags().BoolVarP(&cmd.noNewLine, "no-newline", "n", false, "Do not print a new line after the secret") - fileModeFlag := clause.Flags().VarPF(&cmd.fileMode, "file-mode", "","Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") + fileModeFlag := clause.Flags().VarPF(&cmd.fileMode, "file-mode", "", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") fileModeFlag.DefValue = "0600" command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/service_ls.go b/internals/secrethub/service_ls.go index 4ef036d5..a45c811a 100644 --- a/internals/secrethub/service_ls.go +++ b/internals/secrethub/service_ls.go @@ -65,7 +65,7 @@ func (cmd *ServiceLsCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo-path", "The path to the repository to list services for").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repoPath) - clause.Flags().BoolVarP(&cmd.quiet,"quiet","q",false, "Only print service IDs.") + clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print service IDs.") //TODO //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) diff --git a/internals/secrethub/set.go b/internals/secrethub/set.go index 163a5dec..78c4b347 100644 --- a/internals/secrethub/set.go +++ b/internals/secrethub/set.go @@ -38,7 +38,7 @@ func NewSetCommand(io ui.IO, newClient newClientFunc) *SetCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SetCommand) Register(r command.Registerer) { clause := r.CreateCommand("set", "Set the secrets in your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() - clause.Flags().StringVarP(&cmd.in, "in","i", "secrets.yml", "The path to a secrets.yml file to read") + clause.Flags().StringVarP(&cmd.in, "in", "i", "secrets.yml", "The path to a secrets.yml file to read") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index d810ea7a..64064468 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -45,11 +45,11 @@ func NewSignUpCommand(io ui.IO, newClient newClientFunc, credentialStore Credent // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SignUpCommand) Register(r command.Registerer) { clause := r.CreateCommand("signup", "Create a free personal developer account.") - clause.Flags().StringVar(&cmd.username,"username", "","The username you would like to use on SecretHub.") - clause.Flags().StringVar(&cmd.fullName,"full-name", "","Your full name.") - clause.Flags().StringVar(&cmd.email,"email", "","Your (work) email address we will use for all correspondence.") - clause.Flags().StringVar(&cmd.org,"org", "","The name of your organization.") - clause.Flags().StringVar(&cmd.orgDescription,"org-description", "","A description (max 144 chars) for your organization so others will recognize it.") + clause.Flags().StringVar(&cmd.username, "username", "", "The username you would like to use on SecretHub.") + clause.Flags().StringVar(&cmd.fullName, "full-name", "", "Your full name.") + clause.Flags().StringVar(&cmd.email, "email", "", "Your (work) email address we will use for all correspondence.") + clause.Flags().StringVar(&cmd.org, "org", "", "The name of your organization.") + clause.Flags().StringVar(&cmd.orgDescription, "org-description", "", "A description (max 144 chars) for your organization so others will recognize it.") //TODO //registerForceFlag(clause).BoolVar(&cmd.force) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 5bbf6b3a..40c954db 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -61,10 +61,10 @@ func (cmd *TreeCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Flags().BoolVarP(&cmd.fullPaths, "full-paths", "f",false, "Print the full path of each directory and secret.") - clause.Flags().BoolVarP(&cmd.noIndentation, "no-indentation", "n",false, "Do not use the standard indentation.") - clause.Flags().BoolVar(&cmd.noReport, "no-report", false,"Turn off secret/directory count at end of tree listing.") - clause.Flags().BoolVar(&cmd.noReport, "noreport", false,"Turn off secret/directory count at end of tree listing.") + clause.Flags().BoolVarP(&cmd.fullPaths, "full-paths", "f", false, "Print the full path of each directory and secret.") + clause.Flags().BoolVarP(&cmd.noIndentation, "no-indentation", "n", false, "Do not use the standard indentation.") + clause.Flags().BoolVar(&cmd.noReport, "no-report", false, "Turn off secret/directory count at end of tree listing.") + clause.Flags().BoolVar(&cmd.noReport, "noreport", false, "Turn off secret/directory count at end of tree listing.") clause.Flag("noreport").Hidden = true diff --git a/internals/secrethub/write.go b/internals/secrethub/write.go index 0b94bedb..b23d4e62 100644 --- a/internals/secrethub/write.go +++ b/internals/secrethub/write.go @@ -46,8 +46,8 @@ func (cmd *WriteCommand) Register(r command.Registerer) { clause := r.CreateCommand("write", "Write a secret.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathPlaceHolder).SetValue(&cmd.path) - clause.Flags().BoolVarP(&cmd.useClipboard,"clip","c", false, "Use clipboard content as input.") - clause.Flags().BoolVarP(&cmd.multiline,"multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.") + clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, "Use clipboard content as input.") + clause.Flags().BoolVarP(&cmd.multiline, "multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.") clause.Flags().StringVarP(&cmd.inFile, "in-file", "i", "", "Use the contents of this file as the value of the secret.") command.BindAction(clause, cmd.PreRun, cmd.Run) From f12f3a309b6ed2e488851f380b0f327006112702 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Wed, 12 Aug 2020 14:18:04 +0300 Subject: [PATCH 12/41] about 12 files left to modify --- internals/secrethub/init.go | 5 +++-- internals/secrethub/kingpin.go | 1 - internals/secrethub/list.go | 5 +++-- internals/secrethub/mkdir.go | 2 +- internals/secrethub/org_invite.go | 5 +++-- internals/secrethub/org_list_users.go | 3 ++- internals/secrethub/org_ls.go | 5 +++-- internals/secrethub/printenv.go | 2 +- internals/secrethub/repo_invite.go | 3 ++- internals/secrethub/repo_ls.go | 5 +++-- internals/secrethub/repo_revoke.go | 3 ++- internals/secrethub/rm.go | 5 +++-- internals/secrethub/service_aws_init.go | 16 +++++++++------- internals/secrethub/service_gcp_init.go | 15 +++++++++------ internals/secrethub/service_init.go | 20 ++++++++++++-------- 15 files changed, 56 insertions(+), 39 deletions(-) delete mode 100644 internals/secrethub/kingpin.go diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index b0fa42db..9f011ed2 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -39,8 +39,9 @@ func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentia // Register registers the command, arguments and flags on the provided Registerer. func (cmd *InitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize the SecretHub client for first use on this device.") - clause.Flag("backup-code", "The backup code used to restore an existing account to this device.").StringVar(&cmd.backupCode) - registerForceFlag(clause).BoolVar(&cmd.force) + clause.Flags().StringVar(&cmd.backupCode,"backup-code", "","The backup code used to restore an existing account to this device.") + //TODO + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/kingpin.go b/internals/secrethub/kingpin.go deleted file mode 100644 index 40f7fcdd..00000000 --- a/internals/secrethub/kingpin.go +++ /dev/null @@ -1 +0,0 @@ -package secrethub diff --git a/internals/secrethub/list.go b/internals/secrethub/list.go index 3fd5a3e6..5e0be699 100644 --- a/internals/secrethub/list.go +++ b/internals/secrethub/list.go @@ -37,8 +37,9 @@ func (cmd *LsCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) //clause.Arg("path", "The path to list contents of").SetValue(&cmd.path) - clause.Flag("quiet", "Only print paths.").Short('q').BoolVar(&cmd.quiet) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + clause.Flags().BoolVarP(&cmd.quiet,"quiet", "q", false,"Only print paths.") + //TODO + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/mkdir.go b/internals/secrethub/mkdir.go index 2200aa54..259c763d 100644 --- a/internals/secrethub/mkdir.go +++ b/internals/secrethub/mkdir.go @@ -39,7 +39,7 @@ func (cmd *MkDirCommand) Register(r command.Registerer) { clause := r.CreateCommand("mkdir", "Create a new directory.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-paths", "The paths to the directories").Required().PlaceHolder(dirPathsPlaceHolder).SetValue(&cmd.paths) - clause.Flag("parents", "Create parent directories if needed. Does not error when directories already exist.").BoolVar(&cmd.parents) + clause.Flags().BoolVar(&cmd.parents, "parents", false,"Create parent directories if needed. Does not error when directories already exist.") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index 63dae484..1bcdd1c7 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -35,8 +35,9 @@ func (cmd *OrgInviteCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) - clause.Flag("role", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.").Default("member").StringVar(&cmd.role) - registerForceFlag(clause).BoolVar(&cmd.force) + clause.Flags().StringVar(&cmd.role, "role", "member","Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.") + //TODO + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_list_users.go b/internals/secrethub/org_list_users.go index bb4978a9..ff51a940 100644 --- a/internals/secrethub/org_list_users.go +++ b/internals/secrethub/org_list_users.go @@ -36,7 +36,8 @@ func (cmd *OrgListUsersCommand) Register(r command.Registerer) { clause.Alias("list-members") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + //TODO + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_ls.go b/internals/secrethub/org_ls.go index 90e1848f..f8939ac7 100644 --- a/internals/secrethub/org_ls.go +++ b/internals/secrethub/org_ls.go @@ -32,8 +32,9 @@ func NewOrgLsCommand(io ui.IO, newClient newClientFunc) *OrgLsCommand { func (cmd *OrgLsCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all organizations you are a member of.") clause.Alias("list") - clause.Flag("quiet", "Only print organization names.").Short('q').BoolVar(&cmd.quiet) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false,"Only print organization names.") + //TODO + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/printenv.go b/internals/secrethub/printenv.go index 1033103a..beda7bec 100644 --- a/internals/secrethub/printenv.go +++ b/internals/secrethub/printenv.go @@ -37,7 +37,7 @@ func (cmd *PrintEnvCommand) Run() error { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *PrintEnvCommand) Register(r command.Registerer) { clause := r.CreateCommand("printenv", "Print environment variables.") - clause.Flag("verbose", "Show all possible environment variables.").Short('v').BoolVar(&cmd.verbose) + clause.Flags().BoolVarP(&cmd.verbose,"verbose", "v", false,"Show all possible environment variables.") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/repo_invite.go b/internals/secrethub/repo_invite.go index c6527f35..9d2f5a51 100644 --- a/internals/secrethub/repo_invite.go +++ b/internals/secrethub/repo_invite.go @@ -34,7 +34,8 @@ func (cmd *RepoInviteCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("repo-path", "The repository to invite the user to").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("username", "username of the user").Required().StringVar(&cmd.username) - registerForceFlag(clause).BoolVar(&cmd.force) + //TODO + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/repo_ls.go b/internals/secrethub/repo_ls.go index 8fc413f5..e9337927 100644 --- a/internals/secrethub/repo_ls.go +++ b/internals/secrethub/repo_ls.go @@ -35,9 +35,10 @@ func (cmd *RepoLSCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all repositories you have access to.") clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) - clause.Flag("quiet", "Only print paths.").Short('q').BoolVar(&cmd.quiet) + clause.Flags().BoolVarP(&cmd.quiet,"quiet", "q",false, "Only print paths.") //clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + //TODO + //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/repo_revoke.go b/internals/secrethub/repo_revoke.go index 073033b5..8aac4651 100644 --- a/internals/secrethub/repo_revoke.go +++ b/internals/secrethub/repo_revoke.go @@ -35,7 +35,8 @@ func (cmd *RepoRevokeCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("repo-path", "The repository to revoke the account from").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) - registerForceFlag(clause).BoolVar(&cmd.force) + //TODO + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/rm.go b/internals/secrethub/rm.go index 03dc9de7..51197d05 100644 --- a/internals/secrethub/rm.go +++ b/internals/secrethub/rm.go @@ -42,8 +42,9 @@ func (cmd *RmCommand) Register(r command.Registerer) { clause.Alias("remove") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("path", "The path to the resource to remove (/[/])").Required().SetValue(&cmd.path) - clause.Flag("recursive", "Remove directories and their contents recursively.").Short('r').BoolVar(&cmd.recursive) - registerForceFlag(clause).BoolVar(&cmd.force) + clause.Flags().BoolVarP(&cmd.recursive, "recursive", "r", false, "Remove directories and their contents recursively.") + //TODO + //registerForceFlag(clause).BoolVar(&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 9afeb515..c72b97a0 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -167,13 +167,15 @@ func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to an AWS IAM role.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flag("kms-key", "The ID or ARN of the KMS-key to be used for encrypting the service's account key.").StringVar(&cmd.kmsKeyID) - clause.Flag("role", "The role name or ARN of the IAM role that should have access to this service account.").StringVar(&cmd.role) - clause.Flag("region", "The AWS region that should be used for KMS.").StringVar(&cmd.region) - clause.Flag("description", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.").StringVar(&cmd.description) - clause.Flag("descr", "").Hidden().StringVar(&cmd.description) - clause.Flag("desc", "").Hidden().StringVar(&cmd.description) - clause.Flag("permission", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.").StringVar(&cmd.permission) + clause.Flags().StringVar(&cmd.kmsKeyID, "kms-key", "","The ID or ARN of the KMS-key to be used for encrypting the service's account key.") + clause.Flags().StringVar(&cmd.role,"role", "","The role name or ARN of the IAM role that should have access to this service account.") + clause.Flags().StringVar(&cmd.region, "region", "","The AWS region that should be used for KMS.") + clause.Flags().StringVar(&cmd.description, "description", "","A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") + clause.Flags().StringVar(&cmd.description,"descr", "", "") + clause.Flag("desc").Hidden = true + clause.Flag("descr").Hidden = true + clause.Flags().StringVar(&cmd.description,"desc", "", "") + clause.Flags().StringVar(&cmd.permission, "permission", "","Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") clause.HelpLong("The native AWS identity provider uses a combination of AWS IAM and AWS KMS to provide access to SecretHub for any service running on AWS (e.g. EC2, Lambda or ECS). For this to work, an IAM role and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index d0a8fb59..37fd92b2 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -169,12 +169,15 @@ func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to a GCP Service Account.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flag("kms-key", "The Resource ID of the KMS-key to be used for encrypting the service's account key.").StringVar(&cmd.kmsKeyResourceID) - clause.Flag("service-account-email", "The email of the GCP Service Account that should have access to this service account.").StringVar(&cmd.serviceAccountEmail) - clause.Flag("description", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.").StringVar(&cmd.description) - clause.Flag("descr", "").Hidden().StringVar(&cmd.description) - clause.Flag("desc", "").Hidden().StringVar(&cmd.description) - clause.Flag("permission", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.").StringVar(&cmd.permission) + clause.Flags().StringVar(&cmd.kmsKeyResourceID,"kms-key", "","The Resource ID of the KMS-key to be used for encrypting the service's account key.") + clause.Flags().StringVar(&cmd.serviceAccountEmail, "service-account-email","", "The email of the GCP Service Account that should have access to this service account.") + clause.Flags().StringVar(&cmd.description,"description", "","A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") + clause.Flags().StringVar(&cmd.description,"descr", "", "") + clause.Flag("desc").Hidden = true + clause.Flag("descr").Hidden = true + clause.Flags().StringVar(&cmd.description,"desc", "", "") + clause.Flags().StringVar(&cmd.permission,"permission","", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") + clause.HelpLong("The native GCP identity provider uses a combination of GCP IAM and GCP KMS to provide access to SecretHub for any service running on GCP. For this to work, a GCP Service Account and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index fef45992..f76e921e 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -108,15 +108,19 @@ func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flag("description", "A description for the service so others will recognize it.").StringVar(&cmd.description) - clause.Flag("descr", "").Hidden().StringVar(&cmd.description) - clause.Flag("desc", "").Hidden().StringVar(&cmd.description) - clause.Flag("permission", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.").StringVar(&cmd.permission) + clause.Flags().StringVar(&cmd.description,"description", "","A description for the service so others will recognize it.") + clause.Flags().StringVar(&cmd.description,"descr", "", "") + clause.Flags().StringVar(&cmd.description,"desc", "", "") + clause.Flag("desc").Hidden = true + clause.Flag("descr").Hidden = true + clause.Flags().StringVar(&cmd.permission, "permission", "","Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") // TODO make 45 sec configurable - clause.Flag("clip", "Write the service account configuration to the clipboard instead of stdout. The clipboard is automatically cleared after 45 seconds.").Short('c').BoolVar(&cmd.clip) - clause.Flag("file", "Write the service account configuration to a file instead of stdout.").Hidden().StringVar(&cmd.file) - clause.Flag("out-file", "Write the service account configuration to a file instead of stdout.").StringVar(&cmd.file) - clause.Flag("file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.").Default("0440").SetValue(&cmd.fileMode) + clause.Flags().BoolVarP(&cmd.clip,"clip","c", false, "Write the service account configuration to the clipboard instead of stdout. The clipboard is automatically cleared after 45 seconds.") + clause.Flags().StringVar(&cmd.file,"file", "", "Write the service account configuration to a file instead of stdout.") + clause.Flag("file").Hidden = true + clause.Flags().StringVar(&cmd.file,"out-file", "", "Write the service account configuration to a file instead of stdout.") + clause.Flags().Var(&cmd.fileMode,"file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.") + clause.Flag("file-mode").DefValue = "0440" command.BindAction(clause, cmd.PreRun, cmd.Run) } From 47b91b6ca93bc46e1912809daf81485769f3e6b1 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Wed, 12 Aug 2020 14:46:46 +0300 Subject: [PATCH 13/41] force flag and timestamp flag --- internals/secrethub/account_init.go | 3 +-- internals/secrethub/acl_list.go | 3 +-- internals/secrethub/acl_rm.go | 3 +-- internals/secrethub/acl_set.go | 3 +-- internals/secrethub/audit.go | 14 +++++++++----- internals/secrethub/credential_disable.go | 3 +-- internals/secrethub/credential_list.go | 3 +-- internals/secrethub/flags.go | 8 ++++---- internals/secrethub/init.go | 3 +-- internals/secrethub/list.go | 3 +-- internals/secrethub/org_init.go | 2 +- internals/secrethub/org_invite.go | 3 +-- internals/secrethub/org_list_users.go | 3 +-- internals/secrethub/org_ls.go | 4 ++-- internals/secrethub/repo_invite.go | 3 +-- internals/secrethub/repo_ls.go | 3 +-- internals/secrethub/repo_revoke.go | 3 +-- internals/secrethub/rm.go | 3 +-- internals/secrethub/service_gcp_link.go | 4 +--- internals/secrethub/service_ls.go | 3 +-- internals/secrethub/signup.go | 4 +--- 21 files changed, 33 insertions(+), 48 deletions(-) diff --git a/internals/secrethub/account_init.go b/internals/secrethub/account_init.go index 09b74858..6c9056f7 100644 --- a/internals/secrethub/account_init.go +++ b/internals/secrethub/account_init.go @@ -63,8 +63,7 @@ func (cmd *AccountInitCommand) Register(r command.Registerer) { clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, "Copy the credential's public component to the clipboard instead of printing it to stdout.") clause.Flags().BoolVar(&cmd.noWait, "no-wait", false, "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.") clause.Flags().BoolVar(&cmd.isContinue, "continue", false, "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.") - // TODO force flags!!!! - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/acl_list.go b/internals/secrethub/acl_list.go index c5e0c558..32d72de1 100644 --- a/internals/secrethub/acl_list.go +++ b/internals/secrethub/acl_list.go @@ -41,8 +41,7 @@ func (cmd *ACLListCommand) Register(r command.Registerer) { //clause.Arg("dir-path", "The path of the directory to list the access rules for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) clause.Flags().IntVarP(&cmd.depth, "depth", "d", -1, "The maximum depth to which the rules of child directories should be displayed. Defaults to -1 (no limit).") clause.Flags().BoolVarP(&cmd.ancestors, "all", "a", false, "List all rules that apply on the directory, including rules on parent directories.") - //TODO timestamps!!! - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/acl_rm.go b/internals/secrethub/acl_rm.go index d0a85d92..40c0cf0d 100644 --- a/internals/secrethub/acl_rm.go +++ b/internals/secrethub/acl_rm.go @@ -33,8 +33,7 @@ func (cmd *ACLRmCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("dir-path", "The path of the directory to remove the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) - //TODO FORCE!! - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/acl_set.go b/internals/secrethub/acl_set.go index 3418b58a..456213ee 100644 --- a/internals/secrethub/acl_set.go +++ b/internals/secrethub/acl_set.go @@ -35,8 +35,7 @@ func (cmd *ACLSetCommand) Register(r command.Registerer) { //clause.Arg("dir-path", "The path of the directory to set the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to set the access rule for").Required().SetValue(&cmd.accountName) //clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) - //TODO FORCE!!! - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index aa728f63..80b37dd1 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -3,7 +3,6 @@ package secrethub import ( "fmt" "io" - "strconv" "github.com/secrethub/secrethub-go/internals/errio" @@ -71,10 +70,15 @@ func (cmd *AuditCommand) Register(r command.Registerer) { clause := r.CreateCommand("audit", "Show the audit log.") clause.Args = cobra.MaximumNArgs(1) //clause.Arg("repo-path or secret-path", "Path to the repository or the secret to audit "+repoPathPlaceHolder+" or "+secretPathPlaceHolder).SetValue(&cmd.path) - clause.Flag("per-page", "Number of audit events shown per page").Default("20").Hidden().IntVar(&cmd.perPage) - clause.Flag("output-format", "Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.").HintOptions("table", "json").Default("table").StringVar(&cmd.format) - clause.Flag("max-results", "Specify the number of entries to list. If maxResults < 0 all entries are displayed. If the output of the command is piped, maxResults defaults to 1000.").Default(strconv.Itoa(defaultLimit)).IntVar(&cmd.maxResults) - registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + clause.Flags().IntVar(&cmd.perPage, "per-page", 20, "Number of audit events shown per page") + clause.Flag("per-page").Hidden = true + //clause.Flag("output-format", "Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.").HintOptions("table", "json").Default("table").StringVar(&cmd.format) + clause.Flags().StringVar(&cmd.format, "output-format", "table","Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.") + _ = clause.RegisterFlagCompletionFunc("output-format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"table", "json"}, cobra.ShellCompDirectiveDefault + }) + clause.Flags().IntVar(&cmd.maxResults, "max-results", defaultLimit, "Specify the number of entries to list. If maxResults < 0 all entries are displayed. If the output of the command is piped, maxResults defaults to 1000.") + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/credential_disable.go b/internals/secrethub/credential_disable.go index 6acc2441..8df95007 100644 --- a/internals/secrethub/credential_disable.go +++ b/internals/secrethub/credential_disable.go @@ -33,8 +33,7 @@ func (cmd *CredentialDisableCommand) Register(r command.Registerer) { //fingerprintHelp := fmt.Sprintf("Fingerprint of the credential to disable. At least the first %d characters must be entered.", api.ShortCredentialFingerprintMinimumLength) //clause.Arg("fingerprint", fingerprintHelp).StringVar(&cmd.fingerprint) - //TODO - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/credential_list.go b/internals/secrethub/credential_list.go index 7cef3f10..f8adcf05 100644 --- a/internals/secrethub/credential_list.go +++ b/internals/secrethub/credential_list.go @@ -32,8 +32,7 @@ func (cmd *CredentialListCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all your credentials.") clause.Alias("list") - //TODO - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/flags.go b/internals/secrethub/flags.go index 32629632..43417517 100644 --- a/internals/secrethub/flags.go +++ b/internals/secrethub/flags.go @@ -9,10 +9,10 @@ type FlagRegisterer interface { Flag(name, help string) *cli.Flag } -func registerTimestampFlag(r FlagRegisterer) *cli.Flag { - return r.Flag("timestamp", "Show timestamps formatted to RFC3339 instead of human readable durations.").Short('T') +func registerTimestampFlag(r *cli.CommandClause, p *bool) { + r.Flags().BoolVarP(p,"timestamp", "T", false, "Show timestamps formatted to RFC3339 instead of human readable durations.") } -func registerForceFlag(r FlagRegisterer) *cli.Flag { - return r.Flag("force", "Ignore confirmation and fail instead of prompt for missing arguments.").Short('f') +func registerForceFlag(r *cli.CommandClause, p *bool) { + r.Flags().BoolVarP(p, "force", "f", false,"Ignore confirmation and fail instead of prompt for missing arguments.") } diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 9f011ed2..f2a241f7 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -40,8 +40,7 @@ func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentia func (cmd *InitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize the SecretHub client for first use on this device.") clause.Flags().StringVar(&cmd.backupCode,"backup-code", "","The backup code used to restore an existing account to this device.") - //TODO - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/list.go b/internals/secrethub/list.go index 5e0be699..3762ae7a 100644 --- a/internals/secrethub/list.go +++ b/internals/secrethub/list.go @@ -38,8 +38,7 @@ func (cmd *LsCommand) Register(r command.Registerer) { clause.Args = cobra.MaximumNArgs(1) //clause.Arg("path", "The path to list contents of").SetValue(&cmd.path) clause.Flags().BoolVarP(&cmd.quiet,"quiet", "q", false,"Only print paths.") - //TODO - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index 8cbbc943..8826fe9a 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -33,7 +33,7 @@ func (cmd *OrgInitCommand) Register(r command.Registerer) { clause.Flag("description", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.").StringVar(&cmd.description) clause.Flag("descr", "").Hidden().StringVar(&cmd.description) clause.Flag("desc", "").Hidden().StringVar(&cmd.description) - registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index 1bcdd1c7..189f547e 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -36,8 +36,7 @@ func (cmd *OrgInviteCommand) Register(r command.Registerer) { //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) clause.Flags().StringVar(&cmd.role, "role", "member","Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.") - //TODO - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_list_users.go b/internals/secrethub/org_list_users.go index ff51a940..5aa087c0 100644 --- a/internals/secrethub/org_list_users.go +++ b/internals/secrethub/org_list_users.go @@ -36,8 +36,7 @@ func (cmd *OrgListUsersCommand) Register(r command.Registerer) { clause.Alias("list-members") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) - //TODO - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_ls.go b/internals/secrethub/org_ls.go index f8939ac7..e57b680b 100644 --- a/internals/secrethub/org_ls.go +++ b/internals/secrethub/org_ls.go @@ -33,8 +33,8 @@ func (cmd *OrgLsCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all organizations you are a member of.") clause.Alias("list") clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false,"Only print organization names.") - //TODO - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/repo_invite.go b/internals/secrethub/repo_invite.go index 9d2f5a51..844c77a5 100644 --- a/internals/secrethub/repo_invite.go +++ b/internals/secrethub/repo_invite.go @@ -34,8 +34,7 @@ func (cmd *RepoInviteCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("repo-path", "The repository to invite the user to").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("username", "username of the user").Required().StringVar(&cmd.username) - //TODO - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/repo_ls.go b/internals/secrethub/repo_ls.go index e9337927..ff314269 100644 --- a/internals/secrethub/repo_ls.go +++ b/internals/secrethub/repo_ls.go @@ -37,8 +37,7 @@ func (cmd *RepoLSCommand) Register(r command.Registerer) { clause.Args = cobra.MaximumNArgs(1) clause.Flags().BoolVarP(&cmd.quiet,"quiet", "q",false, "Only print paths.") //clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) - //TODO - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/repo_revoke.go b/internals/secrethub/repo_revoke.go index 8aac4651..f04403df 100644 --- a/internals/secrethub/repo_revoke.go +++ b/internals/secrethub/repo_revoke.go @@ -35,8 +35,7 @@ func (cmd *RepoRevokeCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("repo-path", "The repository to revoke the account from").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) - //TODO - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/rm.go b/internals/secrethub/rm.go index 51197d05..d340d53b 100644 --- a/internals/secrethub/rm.go +++ b/internals/secrethub/rm.go @@ -43,8 +43,7 @@ func (cmd *RmCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("path", "The path to the resource to remove (/[/])").Required().SetValue(&cmd.path) clause.Flags().BoolVarP(&cmd.recursive, "recursive", "r", false, "Remove directories and their contents recursively.") - //TODO - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 3cf74e66..b6b5453c 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -149,9 +149,7 @@ func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { clause := r.CreateCommand("list-links", "List all existing links between the given namespace and GCP projects.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().SetValue(&cmd.namespace) - - //TODO - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_ls.go b/internals/secrethub/service_ls.go index a45c811a..2e387e93 100644 --- a/internals/secrethub/service_ls.go +++ b/internals/secrethub/service_ls.go @@ -66,8 +66,7 @@ func (cmd *ServiceLsCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo-path", "The path to the repository to list services for").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repoPath) clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print service IDs.") - //TODO - //registerTimestampFlag(clause).BoolVar(&cmd.useTimestamps) + registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 64064468..18cfaa89 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -50,9 +50,7 @@ func (cmd *SignUpCommand) Register(r command.Registerer) { clause.Flags().StringVar(&cmd.email, "email", "", "Your (work) email address we will use for all correspondence.") clause.Flags().StringVar(&cmd.org, "org", "", "The name of your organization.") clause.Flags().StringVar(&cmd.orgDescription, "org-description", "", "A description (max 144 chars) for your organization so others will recognize it.") - - //TODO - //registerForceFlag(clause).BoolVar(&cmd.force) + registerForceFlag(clause,&cmd.force) command.BindAction(clause, nil, cmd.Run) } From 663810232e6a5644524f2a2ee086a9de68eedcd3 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Wed, 12 Aug 2020 15:08:23 +0300 Subject: [PATCH 14/41] 2 more fixed files, 8 more to go --- internals/secrethub/org_init.go | 10 ++++++---- internals/secrethub/run.go | 9 +++++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index 8826fe9a..47f415b5 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -29,10 +29,12 @@ func NewOrgInitCommand(io ui.IO, newClient newClientFunc) *OrgInitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize a new organization account.") - clause.Flag("name", "The name you would like to use for your organization. If not set, you will be asked for it.").SetValue(&cmd.name) - clause.Flag("description", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.").StringVar(&cmd.description) - clause.Flag("descr", "").Hidden().StringVar(&cmd.description) - clause.Flag("desc", "").Hidden().StringVar(&cmd.description) + clause.Flags().Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") + clause.Flags().StringVar(&cmd.description,"description", "","A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.") + clause.Flags().StringVar(&cmd.description,"descr", "","") + clause.Flag("descr").Hidden = true + clause.Flags().StringVar(&cmd.description,"desc", "","") + clause.Flag("desc").Hidden = true registerForceFlag(clause,&cmd.force) command.BindAction(clause, nil, cmd.Run) diff --git a/internals/secrethub/run.go b/internals/secrethub/run.go index 97cd3809..f2638c91 100644 --- a/internals/secrethub/run.go +++ b/internals/secrethub/run.go @@ -7,6 +7,7 @@ import ( "os/signal" "strings" "syscall" + "time" "github.com/secrethub/secrethub-cli/internals/cli/masker" "github.com/secrethub/secrethub-cli/internals/secrethub/tpl" @@ -81,10 +82,10 @@ func (cmd *RunCommand) Register(r command.Registerer) { clause.Alias("exec") clause.Args = cobra.MinimumNArgs(1) //clause.Arg("command", "The command to execute").Required().StringsVar(&cmd.command) - clause.Flag("no-masking", "Disable masking of secrets on stdout and stderr").BoolVar(&cmd.noMasking) - clause.Flag("no-output-buffering", "Disable output buffering. This increases output responsiveness, but decreases the probability that secrets get masked.").BoolVar(&cmd.maskerOptions.DisableBuffer) - clause.Flag("masking-buffer-period", "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.").Default("50ms").DurationVar(&cmd.maskerOptions.BufferDelay) - clause.Flag("ignore-missing-secrets", "Do not return an error when a secret does not exist and use an empty value instead.").BoolVar(&cmd.ignoreMissingSecrets) + clause.Flags().BoolVar(&cmd.noMasking, "no-masking", false,"Disable masking of secrets on stdout and stderr") + clause.Flags().BoolVar(&cmd.maskerOptions.DisableBuffer, "no-output-buffering", false, "Disable output buffering. This increases output responsiveness, but decreases the probability that secrets get masked.") + clause.Flags().DurationVar(&cmd.maskerOptions.BufferDelay, "masking-buffer-period", time.Millisecond * 50, "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.") + clause.Flags().BoolVar(&cmd.ignoreMissingSecrets,"ignore-missing-secrets", false,"Do not return an error when a secret does not exist and use an empty value instead.") cmd.environment.register(clause) command.BindAction(clause, cmd.PreRun, cmd.Run) } From 1486edaa2913da86ba64fb2e81777f303587c8f9 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Thu, 13 Aug 2020 12:24:06 +0300 Subject: [PATCH 15/41] something i did yesterday --- internals/secrethub/client_factory.go | 1 + internals/secrethub/inject.go | 26 +++++++++++---------- internals/secrethub/service_deploy_winrm.go | 17 ++++++++------ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index bd50bad2..be438aad 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -41,6 +41,7 @@ type clientFactory struct { // Register the flags for configuration on a cli application. func (f *clientFactory) Register(r FlagRegisterer) { + r.Flag("api-remote", "The SecretHub API address, don't set this unless you know what you're doing.").Hidden().URLVar(&f.ServerURL) r.Flag("identity-provider", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ").Default("key").StringVar(&f.identityProvider) r.Flag("proxy-address", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`").URLVar(&f.proxyAddress) diff --git a/internals/secrethub/inject.go b/internals/secrethub/inject.go index 7602f622..c4ac1172 100644 --- a/internals/secrethub/inject.go +++ b/internals/secrethub/inject.go @@ -57,21 +57,23 @@ func NewInjectCommand(io ui.IO, newClient newClientFunc) *InjectCommand { // Register adds args and flags. func (cmd *InjectCommand) Register(r command.Registerer) { clause := r.CreateCommand("inject", "Inject secrets into a template.") - clause.Flag( - "clip", + clause.Flags().BoolVarP(&cmd.useClipboard, + "clip", "c", false, fmt.Sprintf( "Copy the injected template to the clipboard instead of stdout. The clipboard is automatically cleared after %s.", units.HumanDuration(cmd.clearClipboardAfter), - ), - ).Short('c').BoolVar(&cmd.useClipboard) - clause.Flag("in-file", "The filename of a template file to inject.").Short('i').StringVar(&cmd.inFile) - clause.Flag("out-file", "Write the injected template to a file instead of stdout.").Short('o').StringVar(&cmd.outFile) - clause.Flag("file", "").Hidden().StringVar(&cmd.outFile) // Alias of --out-file (for backwards compatibility) - clause.Flag("file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.").Default("0600").SetValue(&cmd.fileMode) - clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&cmd.templateVars) - clause.Flag("template-version", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.").Default("auto").StringVar(&cmd.templateVersion) - clause.Flag("no-prompt", "Do not prompt when a template variable is missing and return an error instead.").BoolVar(&cmd.dontPromptMissingTemplateVars) - clause.Flag("force", "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.").Short('f').BoolVar(&cmd.force) + )) + clause.Flags().StringVarP(&cmd.inFile,"in-file", "i", "","The filename of a template file to inject.") + clause.Flags().StringVarP(&cmd.outFile,"out-file", "i", "", "Write the injected template to a file instead of stdout.") + clause.Flags().StringVar(&cmd.outFile, "file", "", "") // Alias of --out-file (for backwards compatibility) + clause.Flag("file").Hidden = true + clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") + clause.Flag("file-mode").DefValue = "0600" + //TODO + //clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&cmd.templateVars) + clause.Flags().StringVar(&cmd.templateVersion,"template-version", "auto","Do not prompt when a template variable is missing and return an error instead.") + clause.Flags().BoolVar(&cmd.dontPromptMissingTemplateVars, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") + clause.Flags().BoolVarP(&cmd.force, "force","f",false, "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/service_deploy_winrm.go b/internals/secrethub/service_deploy_winrm.go index 16742fd3..ca3d2258 100644 --- a/internals/secrethub/service_deploy_winrm.go +++ b/internals/secrethub/service_deploy_winrm.go @@ -62,13 +62,16 @@ func (cmd *ServiceDeployWinRmCommand) Register(r command.Registerer) { clause := r.CreateCommand("winrm", "Read a service account configuration from stdin and deploy it to a running instance with WinRM. The instance needs to be reachable, have WinRM enabled, and have PowerShell installed.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("resource-uri", "Hostname, optional connection protocol and port of the host ([http[s]://][:]). This defaults to https and port 5986.").Required().URLVar(&cmd.resourceURI) - clause.Flag("auth-type", "Authentication type (basic/cert)").HintOptions("basic", "cert").Default("basic").StringVar(&cmd.authType) - clause.Flag("username", "The username used for logging in when authentication type is basic. Is asked if not supplied.").StringVar(&cmd.username) - clause.Flag("password", "The password used for logging in when authentication type is basic. Is asked if not supplied.").StringVar(&cmd.password) - clause.Flag("client-cert", "Path to client certificate used for certificate authentication.").ExistingFileVar(&cmd.clientCert) - clause.Flag("client-key", "Path to client key used for certificate authentication.").ExistingFileVar(&cmd.clientKey) - clause.Flag("ca-cert", "Path to CA certificate used to verify server TLS certificate.").ExistingFileVar(&cmd.caCert) - clause.Flag("insecure-no-verify-cert", "Do not verify server TLS certificate (insecure).").BoolVar(&cmd.noVerify) + clause.Flags().StringVar(&cmd.authType,"auth-type", "basic","Authentication type (basic/cert)") + _ = clause.RegisterFlagCompletionFunc("auth-type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"basic", "cert"}, cobra.ShellCompDirectiveDefault + }) + clause.Flags().StringVar(&cmd.username,"username", "","The username used for logging in when authentication type is basic. Is asked if not supplied.") + clause.Flags().StringVar(&cmd.password, "password", "","The password used for logging in when authentication type is basic. Is asked if not supplied.") + clause.Flags().StringVar(&cmd.clientCert,"client-cert", "","Path to client certificate used for certificate authentication.") + clause.Flags().StringVar(&cmd.clientKey,"client-key", "","Path to client key used for certificate authentication.") + clause.Flags().StringVar(&cmd.caCert,"ca-cert", "","Path to CA certificate used to verify server TLS certificate.") + clause.Flags().BoolVar(&cmd.noVerify, "insecure-no-verify-cert", false,"Do not verify server TLS certificate (insecure).") command.BindAction(clause, cmd.PreRun, cmd.Run) } From aeea1c6a260a8ab2bb82d83897393e08a5d943cf Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Thu, 13 Aug 2020 13:54:10 +0300 Subject: [PATCH 16/41] something's compiling --- internals/secrethub/app.go | 10 +++--- internals/secrethub/client_factory.go | 43 +++++++++++++++++++------ internals/secrethub/color.go | 12 ++++--- internals/secrethub/config_dir.go | 4 +++ internals/secrethub/credential_store.go | 17 ++++++---- internals/secrethub/debug.go | 9 ++++-- internals/secrethub/env_source.go | 16 ++++----- internals/secrethub/flags.go | 5 --- internals/secrethub/generate.go | 10 +++--- internals/secrethub/inject.go | 2 +- internals/secrethub/mlock.go | 9 ++++-- internals/secrethub/org_init.go | 2 +- internals/secrethub/service_aws_init.go | 2 +- internals/secrethub/service_gcp_init.go | 2 +- 14 files changed, 91 insertions(+), 52 deletions(-) diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index 01cd421c..4e6200ef 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -94,11 +94,11 @@ func NewApp() *App { logger: cli.NewLogger(), } - RegisterDebugFlag(app.cli, app.logger) - RegisterMlockFlag(app.cli) - RegisterColorFlag(app.cli) - app.credentialStore.Register(app.cli) - app.clientFactory.Register(app.cli) + RegisterDebugFlag(&app.cli.Application, app.logger) + RegisterMlockFlag(&app.cli.Application) + RegisterColorFlag(&app.cli.Application) + app.credentialStore.Register(&app.cli.Application) + app.clientFactory.Register(&app.cli.Application) app.registerCommands() //app.cli.UsageTemplate(DefaultUsageTemplate) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index be438aad..ebf40cd0 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/spf13/cobra" "net/http" "net/url" "strings" @@ -21,7 +22,7 @@ type ClientFactory interface { NewClient() (secrethub.ClientInterface, error) NewClientWithCredentials(credentials.Provider) (secrethub.ClientInterface, error) NewUnauthenticatedClient() (secrethub.ClientInterface, error) - Register(FlagRegisterer) + Register(command *cobra.Command) } // NewClientFactory creates a new ClientFactory. @@ -33,18 +34,18 @@ func NewClientFactory(store CredentialConfig) ClientFactory { type clientFactory struct { client *secrethub.Client - ServerURL *url.URL + ServerURL urlValue identityProvider string - proxyAddress *url.URL + proxyAddress urlValue store CredentialConfig } // Register the flags for configuration on a cli application. -func (f *clientFactory) Register(r FlagRegisterer) { +func (f *clientFactory) Register(r *cobra.Command) { - r.Flag("api-remote", "The SecretHub API address, don't set this unless you know what you're doing.").Hidden().URLVar(&f.ServerURL) - r.Flag("identity-provider", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ").Default("key").StringVar(&f.identityProvider) - r.Flag("proxy-address", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`").URLVar(&f.proxyAddress) + r.PersistentFlags().Var(&f.ServerURL, "api-remote", "The SecretHub API address, don't set this unless you know what you're doing.") + r.PersistentFlags().StringVar(&f.identityProvider,"identity-provider", "key","Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ") + r.PersistentFlags().Var(&f.proxyAddress,"proxy-address", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`") } // NewClient returns a new client that is configured to use the remote that @@ -109,17 +110,39 @@ func (f *clientFactory) baseClientOptions() []secrethub.ClientOption { }), } - if f.proxyAddress != nil { + if f.proxyAddress.u != nil { transport := http.DefaultTransport.(*http.Transport) transport.Proxy = func(request *http.Request) (*url.URL, error) { - return f.proxyAddress, nil + return f.proxyAddress.u, nil } options = append(options, secrethub.WithTransport(transport)) } - if f.ServerURL != nil { + if &f.ServerURL != nil { options = append(options, secrethub.WithServerURL(f.ServerURL.String())) } return options } + +type urlValue struct { + u *url.URL +} + +func (u *urlValue) String() string { + return u.u.String() +} + +func (u *urlValue) Set(s string) error { + parsed, err := url.Parse(s) + u.u = parsed + if err != nil { + return err + } + return nil +} + +func (u *urlValue) Type() string { + return "urlValue" +} + diff --git a/internals/secrethub/color.go b/internals/secrethub/color.go index 48a5f39e..b954c954 100644 --- a/internals/secrethub/color.go +++ b/internals/secrethub/color.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/spf13/cobra" "strconv" "github.com/fatih/color" @@ -9,16 +10,19 @@ import ( // noColorFlag configures the global behaviour to disable colored output. type noColorFlag bool +func (f noColorFlag) Type() string { + return "noColorFlag" +} + // init disables colored output based on the value of the flag. func (f noColorFlag) init() { color.NoColor = bool(f) } // RegisterColorFlag registers a color flag that configures whether colored output is used. -func RegisterColorFlag(r FlagRegisterer) { - //TODO - //flag := noColorFlag(false) - //r.Flag("no-color", "Disable colored output.").SetValue(&flag) +func RegisterColorFlag(r *cobra.Command) { + flag := noColorFlag(false) + r.PersistentFlags().Var(&flag, "no-color", "Disable colored output.") } // String implements the flag.Value interface. diff --git a/internals/secrethub/config_dir.go b/internals/secrethub/config_dir.go index 22694ef2..fa8d9110 100644 --- a/internals/secrethub/config_dir.go +++ b/internals/secrethub/config_dir.go @@ -6,6 +6,10 @@ type ConfigDir struct { configdir.Dir } +func (c *ConfigDir) Type() string { + panic("configDir") +} + func (c *ConfigDir) String() string { return c.Dir.Path() } diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 09163572..2838e32a 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/spf13/cobra" "time" "github.com/secrethub/secrethub-go/pkg/secrethub/configdir" @@ -22,7 +23,7 @@ type CredentialConfig interface { ConfigDir() configdir.Dir PassphraseReader() credentials.Reader - Register(FlagRegisterer) + Register(command *cobra.Command) } // NewCredentialConfig creates a new CredentialConfig. @@ -52,12 +53,14 @@ func (store *credentialConfig) IsPassphraseSet() bool { } // Register registers the flags for configuring the store on the provided Registerer. -func (store *credentialConfig) Register(r FlagRegisterer) { - r.Flag("config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub").Default("").PlaceHolder("CONFIG-DIR").SetValue(&store.configDir) - r.Flag("credential", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.").StringVar(&store.AccountCredential) - r.Flag("p", "").Short('p').Hidden().NoEnvar().StringVar(&store.credentialPassphrase) // Shorthand -p is deprecated. Use --credential-passphrase instead. - r.Flag("credential-passphrase", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.").StringVar(&store.credentialPassphrase) - r.Flag("credential-passphrase-cache-ttl", "Cache the credential passphrase in the OS keyring for this duration. The cache is automatically cleared after the timer runs out. Each time the passphrase is read from the cache the timer is reset. Passphrase caching is turned on by default for 5 minutes. Turn it off by setting the duration to 0.").Default("5m").DurationVar(&store.CredentialPassphraseCacheTTL) +func (store *credentialConfig) Register(r *cobra.Command) { + r.PersistentFlags().Var(&store.configDir,"config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub") + r.PersistentFlags().StringVar(&store.AccountCredential, "credential", "", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.") + //TODO NoEnvVar + r.PersistentFlags().StringVarP(&store.credentialPassphrase, "p", "p", "", "") // Shorthand -p is deprecated. Use --credential-passphrase instead. + r.Flag("p").Hidden = true + r.PersistentFlags().StringVar(&store.credentialPassphrase, "credential-passphrase", "", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.") + r.PersistentFlags().DurationVar(&store.CredentialPassphraseCacheTTL, "credential-passphrase-cache-ttl", 5*time.Minute, "Cache the credential passphrase in the OS keyring for this duration. The cache is automatically cleared after the timer runs out. Each time the passphrase is read from the cache the timer is reset. Passphrase caching is turned on by default for 5 minutes. Turn it off by setting the duration to 0.") } // Provider retrieves a credential from the store. diff --git a/internals/secrethub/debug.go b/internals/secrethub/debug.go index e85aa9c1..95fb9e87 100644 --- a/internals/secrethub/debug.go +++ b/internals/secrethub/debug.go @@ -1,17 +1,18 @@ package secrethub import ( + "github.com/spf13/cobra" "strconv" "github.com/secrethub/secrethub-cli/internals/cli" ) // RegisterDebugFlag registers a debug flag that changes the log level of the given logger to DEBUG. -func RegisterDebugFlag(r FlagRegisterer, logger cli.Logger) { +func RegisterDebugFlag(r *cobra.Command, logger cli.Logger) { flag := debugFlag{ logger: logger, } - r.Flag("debug", "Enable debug mode.").Short('D').SetValue(&flag) + r.PersistentFlags().VarP(&flag, "debug", "D", "Enable debug mode.") } // debugFlag configures the debug level of a logger. @@ -20,6 +21,10 @@ type debugFlag struct { logger cli.Logger } +func (f debugFlag) Type() string { + return "debugFlag" +} + func (f debugFlag) init() { if f.debug { f.logger.EnableDebug() diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 242d4f59..7bed34c1 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -61,14 +61,14 @@ func newEnvironment(io ui.IO, newClient newClientFunc) *environment { } func (env *environment) register(clause *cli.CommandClause) { - clause.Flag("envar", "Source an environment variable from a secret at a given path with `NAME=`").Short('e').StringMapVar(&env.envar) - clause.Flag("env-file", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.").StringVar(&env.envFile) - clause.Flag("template", "").Hidden().StringVar(&env.envFile) - clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&env.templateVars) - clause.Flag("template-version", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.").Default("auto").StringVar(&env.templateVersion) - clause.Flag("no-prompt", "Do not prompt when a template variable is missing and return an error instead.").BoolVar(&env.dontPromptMissingTemplateVar) - clause.Flag("secrets-dir", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.").StringVar(&env.secretsDir) - clause.Flag("env", "The name of the environment prepared by the set command (default is `default`)").Default("default").Hidden().StringVar(&env.secretsEnvDir) + //clause.Flag("envar", "Source an environment variable from a secret at a given path with `NAME=`").Short('e').StringMapVar(&env.envar) + //clause.Flag("env-file", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.").StringVar(&env.envFile) + //clause.Flag("template", "").Hidden().StringVar(&env.envFile) + //clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&env.templateVars) + //clause.Flag("template-version", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.").Default("auto").StringVar(&env.templateVersion) + //clause.Flag("no-prompt", "Do not prompt when a template variable is missing and return an error instead.").BoolVar(&env.dontPromptMissingTemplateVar) + //clause.Flag("secrets-dir", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.").StringVar(&env.secretsDir) + //clause.Flag("env", "The name of the environment prepared by the set command (default is `default`)").Default("default").Hidden().StringVar(&env.secretsEnvDir) } func (env *environment) env() (map[string]value, error) { diff --git a/internals/secrethub/flags.go b/internals/secrethub/flags.go index 43417517..86151265 100644 --- a/internals/secrethub/flags.go +++ b/internals/secrethub/flags.go @@ -4,11 +4,6 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli" ) -// FlagRegisterer allows others to register flags on it. -type FlagRegisterer interface { - Flag(name, help string) *cli.Flag -} - func registerTimestampFlag(r *cli.CommandClause, p *bool) { r.Flags().BoolVarP(p,"timestamp", "T", false, "Show timestamps formatted to RFC3339 instead of human readable durations.") } diff --git a/internals/secrethub/generate.go b/internals/secrethub/generate.go index e1d7a6cc..621c2802 100644 --- a/internals/secrethub/generate.go +++ b/internals/secrethub/generate.go @@ -65,11 +65,11 @@ func (cmd *GenerateSecretCommand) Register(r command.Registerer) { clause := r.CreateCommand("generate", "Generate a random secret.") clause.Args = cobra.RangeArgs(1, 3) //clause.Arg("secret-path", "The path to write the generated secret to").Required().PlaceHolder(secretPathPlaceHolder).StringVar(&cmd.firstArg) - clause.Flag("length", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)).PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) - clause.Flag("min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.").SetValue(&cmd.mins) - clause.Flag("clip", "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".").Short('c').BoolVar(&cmd.copyToClipboard) - clause.Flag("charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.").Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable").SetValue(&cmd.charsetFlag) - clause.Flag("symbols", "Include symbols in secret.").Short('s').Hidden().SetValue(&cmd.symbolsFlag) + //clause.Flag("length", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)).PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) + //clause.Flag("min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.").SetValue(&cmd.mins) + //clause.Flag("clip", "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".").Short('c').BoolVar(&cmd.copyToClipboard) + //clause.Flag("charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.").Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable").SetValue(&cmd.charsetFlag) + //clause.Flag("symbols", "Include symbols in secret.").Short('s').Hidden().SetValue(&cmd.symbolsFlag) //clause.Arg("rand-command", "").Hidden().StringVar(&cmd.secondArg) //clause.Arg("length", "").Hidden().SetValue(&cmd.lengthArg) diff --git a/internals/secrethub/inject.go b/internals/secrethub/inject.go index c4ac1172..d39d7416 100644 --- a/internals/secrethub/inject.go +++ b/internals/secrethub/inject.go @@ -64,7 +64,7 @@ func (cmd *InjectCommand) Register(r command.Registerer) { units.HumanDuration(cmd.clearClipboardAfter), )) clause.Flags().StringVarP(&cmd.inFile,"in-file", "i", "","The filename of a template file to inject.") - clause.Flags().StringVarP(&cmd.outFile,"out-file", "i", "", "Write the injected template to a file instead of stdout.") + clause.Flags().StringVarP(&cmd.outFile,"out-file", "o", "", "Write the injected template to a file instead of stdout.") clause.Flags().StringVar(&cmd.outFile, "file", "", "") // Alias of --out-file (for backwards compatibility) clause.Flag("file").Hidden = true clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") diff --git a/internals/secrethub/mlock.go b/internals/secrethub/mlock.go index 153f3a07..6c8b1e57 100644 --- a/internals/secrethub/mlock.go +++ b/internals/secrethub/mlock.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/spf13/cobra" "strconv" "github.com/secrethub/secrethub-cli/internals/cli/mlock" @@ -9,6 +10,10 @@ import ( // mlockFlag configures locking memory. type mlockFlag bool +func (f mlockFlag) Type() string { + panic("mlockFlag") +} + // init locks the memory based on the flag value if supported. func (f mlockFlag) init() error { if f { @@ -23,9 +28,9 @@ func (f mlockFlag) init() error { } // RegisterMlockFlag registers a mlock flag that enables memory locking when set to true. -func RegisterMlockFlag(r FlagRegisterer) { +func RegisterMlockFlag(r *cobra.Command) { flag := mlockFlag(false) - r.Flag("mlock", "Enable memory locking").SetValue(&flag) + r.PersistentFlags().Var(&flag, "mlock", "Enable memory locking") } // String implements the flag.Value interface. diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index 47f415b5..3311b9bc 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -29,7 +29,7 @@ func NewOrgInitCommand(io ui.IO, newClient newClientFunc) *OrgInitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize a new organization account.") - clause.Flags().Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") + //clause.Flags().Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") clause.Flags().StringVar(&cmd.description,"description", "","A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.") clause.Flags().StringVar(&cmd.description,"descr", "","") clause.Flag("descr").Hidden = true diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index c72b97a0..0efe3d1d 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -172,9 +172,9 @@ func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { clause.Flags().StringVar(&cmd.region, "region", "","The AWS region that should be used for KMS.") clause.Flags().StringVar(&cmd.description, "description", "","A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") clause.Flags().StringVar(&cmd.description,"descr", "", "") + clause.Flags().StringVar(&cmd.description,"desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.description,"desc", "", "") clause.Flags().StringVar(&cmd.permission, "permission", "","Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") clause.HelpLong("The native AWS identity provider uses a combination of AWS IAM and AWS KMS to provide access to SecretHub for any service running on AWS (e.g. EC2, Lambda or ECS). For this to work, an IAM role and a KMS key are needed.\n" + diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 37fd92b2..191c48b8 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -173,9 +173,9 @@ func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { clause.Flags().StringVar(&cmd.serviceAccountEmail, "service-account-email","", "The email of the GCP Service Account that should have access to this service account.") clause.Flags().StringVar(&cmd.description,"description", "","A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") clause.Flags().StringVar(&cmd.description,"descr", "", "") + clause.Flags().StringVar(&cmd.description,"desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.description,"desc", "", "") clause.Flags().StringVar(&cmd.permission,"permission","", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") From 306d7f2727f7b49f674cbe3f9dc229b6ae0fff30 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Thu, 13 Aug 2020 14:53:01 +0300 Subject: [PATCH 17/41] something working --- internals/secrethub/client_factory.go | 21 +++++++++++---------- internals/secrethub/config_dir.go | 2 +- internals/secrethub/mlock.go | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index ebf40cd0..e5a9dd8c 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -2,6 +2,7 @@ package secrethub import ( "github.com/spf13/cobra" + "github.com/spf13/pflag" "net/http" "net/url" "strings" @@ -35,17 +36,18 @@ func NewClientFactory(store CredentialConfig) ClientFactory { type clientFactory struct { client *secrethub.Client ServerURL urlValue + serverURLFlag *pflag.Flag identityProvider string proxyAddress urlValue + proxyAddressFlag *pflag.Flag store CredentialConfig } // Register the flags for configuration on a cli application. func (f *clientFactory) Register(r *cobra.Command) { - - r.PersistentFlags().Var(&f.ServerURL, "api-remote", "The SecretHub API address, don't set this unless you know what you're doing.") - r.PersistentFlags().StringVar(&f.identityProvider,"identity-provider", "key","Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ") - r.PersistentFlags().Var(&f.proxyAddress,"proxy-address", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`") + f.serverURLFlag = r.PersistentFlags().VarPF(&f.ServerURL, "api-remote", "", "The SecretHub API address, don't set this unless you know what you're doing.") + r.PersistentFlags().StringVar(&f.identityProvider, "identity-provider", "key", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ") + f.proxyAddressFlag = r.PersistentFlags().VarPF(&f.proxyAddress, "proxy-address", "", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`") } // NewClient returns a new client that is configured to use the remote that @@ -110,15 +112,15 @@ func (f *clientFactory) baseClientOptions() []secrethub.ClientOption { }), } - if f.proxyAddress.u != nil { + if f.proxyAddressFlag.Changed { transport := http.DefaultTransport.(*http.Transport) transport.Proxy = func(request *http.Request) (*url.URL, error) { - return f.proxyAddress.u, nil + return &f.proxyAddress.u, nil } options = append(options, secrethub.WithTransport(transport)) } - if &f.ServerURL != nil { + if f.serverURLFlag.Changed { options = append(options, secrethub.WithServerURL(f.ServerURL.String())) } @@ -126,7 +128,7 @@ func (f *clientFactory) baseClientOptions() []secrethub.ClientOption { } type urlValue struct { - u *url.URL + u url.URL } func (u *urlValue) String() string { @@ -135,7 +137,7 @@ func (u *urlValue) String() string { func (u *urlValue) Set(s string) error { parsed, err := url.Parse(s) - u.u = parsed + u.u = *parsed if err != nil { return err } @@ -145,4 +147,3 @@ func (u *urlValue) Set(s string) error { func (u *urlValue) Type() string { return "urlValue" } - diff --git a/internals/secrethub/config_dir.go b/internals/secrethub/config_dir.go index fa8d9110..4764a73f 100644 --- a/internals/secrethub/config_dir.go +++ b/internals/secrethub/config_dir.go @@ -7,7 +7,7 @@ type ConfigDir struct { } func (c *ConfigDir) Type() string { - panic("configDir") + return "configDir" } func (c *ConfigDir) String() string { diff --git a/internals/secrethub/mlock.go b/internals/secrethub/mlock.go index 6c8b1e57..4c52b7ae 100644 --- a/internals/secrethub/mlock.go +++ b/internals/secrethub/mlock.go @@ -11,7 +11,7 @@ import ( type mlockFlag bool func (f mlockFlag) Type() string { - panic("mlockFlag") + return "mlockFlag" } // init locks the memory based on the flag value if supported. From f0d79d7d10a42a71fa737b7be3930a26bc97a0e0 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Thu, 13 Aug 2020 15:22:35 +0300 Subject: [PATCH 18/41] last 2 commands --- internals/secrethub/audit.go | 1 - internals/secrethub/env_source.go | 14 ++++++++------ internals/secrethub/generate.go | 32 ++++++++++++++++++++++++++----- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index 80b37dd1..5a73a8d9 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -72,7 +72,6 @@ func (cmd *AuditCommand) Register(r command.Registerer) { //clause.Arg("repo-path or secret-path", "Path to the repository or the secret to audit "+repoPathPlaceHolder+" or "+secretPathPlaceHolder).SetValue(&cmd.path) clause.Flags().IntVar(&cmd.perPage, "per-page", 20, "Number of audit events shown per page") clause.Flag("per-page").Hidden = true - //clause.Flag("output-format", "Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.").HintOptions("table", "json").Default("table").StringVar(&cmd.format) clause.Flags().StringVar(&cmd.format, "output-format", "table","Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.") _ = clause.RegisterFlagCompletionFunc("output-format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"table", "json"}, cobra.ShellCompDirectiveDefault diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 7bed34c1..f99576d8 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -62,13 +62,15 @@ func newEnvironment(io ui.IO, newClient newClientFunc) *environment { func (env *environment) register(clause *cli.CommandClause) { //clause.Flag("envar", "Source an environment variable from a secret at a given path with `NAME=`").Short('e').StringMapVar(&env.envar) - //clause.Flag("env-file", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.").StringVar(&env.envFile) - //clause.Flag("template", "").Hidden().StringVar(&env.envFile) + clause.Flags().StringVar(&env.envFile,"env-file", "","The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.") + clause.Flags().StringVar(&env.envFile,"template", "","") + clause.Flag("template").Hidden = true //clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&env.templateVars) - //clause.Flag("template-version", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.").Default("auto").StringVar(&env.templateVersion) - //clause.Flag("no-prompt", "Do not prompt when a template variable is missing and return an error instead.").BoolVar(&env.dontPromptMissingTemplateVar) - //clause.Flag("secrets-dir", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.").StringVar(&env.secretsDir) - //clause.Flag("env", "The name of the environment prepared by the set command (default is `default`)").Default("default").Hidden().StringVar(&env.secretsEnvDir) + clause.Flags().StringVar(&env.templateVersion, "template-version", "auto", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.") + clause.Flags().BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false,"Do not prompt when a template variable is missing and return an error instead.") + clause.Flags().StringVar(&env.secretsDir,"secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") + clause.Flags().StringVar(&env.secretsEnvDir, "env", "default","The name of the environment prepared by the set command (default is `default`)") + clause.Flag("env").Hidden = true } func (env *environment) env() (map[string]value, error) { diff --git a/internals/secrethub/generate.go b/internals/secrethub/generate.go index 621c2802..1e0b6aeb 100644 --- a/internals/secrethub/generate.go +++ b/internals/secrethub/generate.go @@ -65,11 +65,17 @@ func (cmd *GenerateSecretCommand) Register(r command.Registerer) { clause := r.CreateCommand("generate", "Generate a random secret.") clause.Args = cobra.RangeArgs(1, 3) //clause.Arg("secret-path", "The path to write the generated secret to").Required().PlaceHolder(secretPathPlaceHolder).StringVar(&cmd.firstArg) - //clause.Flag("length", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)).PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) - //clause.Flag("min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.").SetValue(&cmd.mins) - //clause.Flag("clip", "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".").Short('c').BoolVar(&cmd.copyToClipboard) - //clause.Flag("charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.").Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable").SetValue(&cmd.charsetFlag) - //clause.Flag("symbols", "Include symbols in secret.").Short('s').Hidden().SetValue(&cmd.symbolsFlag) + clause.Flags().VarP(&cmd.lengthFlag, "length", "l", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)) //.PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) + clause.Flag("length").DefValue = strconv.Itoa(defaultLength) + clause.Flags().Var(&cmd.mins,"min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.") + clause.Flags().BoolVarP(&cmd.copyToClipboard,"clip", "c", false,"Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".") + clause.Flags().Var(&cmd.charsetFlag, "charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.")//Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable") + clause.Flag("charset").DefValue = "alphanumeric" + _ = clause.RegisterFlagCompletionFunc("charset", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable"}, cobra.ShellCompDirectiveDefault + }) + clause.Flags().VarP(&cmd.symbolsFlag, "symbols", "s","Include symbols in secret.")//Short('s').Hidden().SetValue(&cmd.symbolsFlag) + clause.Flag("symbols").Hidden = true //clause.Arg("rand-command", "").Hidden().StringVar(&cmd.secondArg) //clause.Arg("length", "").Hidden().SetValue(&cmd.lengthArg) @@ -216,6 +222,10 @@ type minRuleValue struct { v []randchar.Option } +func (ov *minRuleValue) Type() string { + return "minRuleValue" +} + func (ov *minRuleValue) String() string { return "" } @@ -248,6 +258,10 @@ type charsetValue struct { v randchar.Charset } +func (cv *charsetValue) Type() string { + return "charsetValue" +} + func (cv *charsetValue) String() string { return "" } @@ -272,6 +286,10 @@ type intValue struct { v *int } +func (iv *intValue) Type() string { + return "intValue" +} + func (iv *intValue) Get() int { if iv.v == nil { return 0 @@ -300,6 +318,10 @@ type boolValue struct { v *bool } +func (iv *boolValue) Type() string { + panic("boolValue") +} + func (iv *boolValue) Get() bool { if iv.v == nil { return false From 0ddb22184e201a5f1c0029e39d7c830b75906c90 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 13 Aug 2020 14:56:15 +0200 Subject: [PATCH 19/41] Small changes to make tests work again --- internals/demo/init.go | 33 +++++++++++++++++----- internals/secrethub/client_factory_test.go | 6 ++-- internals/secrethub/read.go | 6 +--- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/internals/demo/init.go b/internals/demo/init.go index 183d9475..43b6082d 100644 --- a/internals/demo/init.go +++ b/internals/demo/init.go @@ -5,7 +5,6 @@ import ( "crypto/sha256" "encoding/base64" "fmt" - "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" @@ -19,8 +18,7 @@ type newClientFunc func() (secrethub.ClientInterface, error) const defaultDemoRepo = "demo" type InitCommand struct { - repo api.RepoPath - + repo pathValue io ui.IO newClient newClientFunc } @@ -37,7 +35,7 @@ func (cmd *InitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create the secrets necessary to connect with the demo application.") clause.HelpLong("demo init creates a repository with the username and password needed to connect to the demo API.") - clause.Flag("repo", "The path of the repository to create. Defaults to a "+defaultDemoRepo+" repo in your personal namespace.").SetValue(&cmd.repo) + clause.Flags().VarPF(&cmd.repo, "repo", "", "The path of the repository to create. Defaults to a "+defaultDemoRepo+" repo in your personal namespace.") command.BindAction(clause, nil, cmd.Run) } @@ -51,7 +49,7 @@ func (cmd *InitCommand) Run() error { var repoPath string var username string - if cmd.repo == "" { + if cmd.repo.path == "" { me, err := client.Me().GetUser() if err != nil { return err @@ -59,8 +57,8 @@ func (cmd *InitCommand) Run() error { username = me.Username repoPath = secretpath.Join(me.Username, defaultDemoRepo) } else { - username = secretpath.Namespace(cmd.repo.Value()) - repoPath = cmd.repo.Value() + username = secretpath.Namespace(cmd.repo.path.Value()) + repoPath = cmd.repo.path.Value() } _, err = client.Repos().Create(repoPath) @@ -127,3 +125,24 @@ func (cmd *InitCommand) isDemoRepo(client secrethub.ClientInterface, repoPath st } return true, nil } + +type pathValue struct { + path api.RepoPath +} + +func (u *pathValue) String() string { + return u.path.String() +} + +func (u *pathValue) Set(s string) error { + var err error + u.path, err = api.NewRepoPath(s) + if err != nil { + return err + } + return nil +} + +func (u *pathValue) Type() string { + return "pathValue" +} diff --git a/internals/secrethub/client_factory_test.go b/internals/secrethub/client_factory_test.go index b4899d91..3560616d 100644 --- a/internals/secrethub/client_factory_test.go +++ b/internals/secrethub/client_factory_test.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/spf13/cobra" "net/http" "net/url" "os" @@ -38,10 +39,11 @@ func TestNewClientFactory_ProxyAddress(t *testing.T) { factory := clientFactory{ identityProvider: "key", store: store, - ServerURL: serverAddress, - proxyAddress: proxyAddress, + ServerURL: urlValue{*serverAddress}, + proxyAddress: urlValue{*proxyAddress}, } + factory.Register(&cobra.Command{}) client, err := factory.NewUnauthenticatedClient() assert.OK(t, err) diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index d249b513..1b3f57c8 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -43,7 +43,7 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") - cmd.argumentConstraint(clause.Command) + clause.Args = cobra.ExactValidArgs(1) clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, fmt.Sprintf( @@ -105,10 +105,6 @@ func (cmd *ReadCommand) Run() error { return nil } -func (cmd *ReadCommand) argumentConstraint(c *cobra.Command) { - c.Args = cobra.ExactValidArgs(1) -} - func (cmd *ReadCommand) argumentRegister(_ *cobra.Command, args []string) error { var err error cmd.path, err = api.NewSecretPath(args[0]) From 1058d4ee073d60df8d81c3e1d9c4976688e3b53e Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 13 Aug 2020 15:31:32 +0200 Subject: [PATCH 20/41] Make tests work --- internals/secrethub/client_factory.go | 23 +++++++++++----------- internals/secrethub/client_factory_test.go | 8 +++----- internals/secrethub/read.go | 4 ++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index e5a9dd8c..d0b74c02 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -1,8 +1,6 @@ package secrethub import ( - "github.com/spf13/cobra" - "github.com/spf13/pflag" "net/http" "net/url" "strings" @@ -10,6 +8,8 @@ import ( "github.com/secrethub/secrethub-go/pkg/secrethub" "github.com/secrethub/secrethub-go/pkg/secrethub/configdir" "github.com/secrethub/secrethub-go/pkg/secrethub/credentials" + + "github.com/spf13/cobra" ) // Errors @@ -36,18 +36,16 @@ func NewClientFactory(store CredentialConfig) ClientFactory { type clientFactory struct { client *secrethub.Client ServerURL urlValue - serverURLFlag *pflag.Flag identityProvider string proxyAddress urlValue - proxyAddressFlag *pflag.Flag store CredentialConfig } // Register the flags for configuration on a cli application. func (f *clientFactory) Register(r *cobra.Command) { - f.serverURLFlag = r.PersistentFlags().VarPF(&f.ServerURL, "api-remote", "", "The SecretHub API address, don't set this unless you know what you're doing.") + r.PersistentFlags().VarPF(&f.ServerURL, "api-remote", "", "The SecretHub API address, don't set this unless you know what you're doing.") r.PersistentFlags().StringVar(&f.identityProvider, "identity-provider", "key", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ") - f.proxyAddressFlag = r.PersistentFlags().VarPF(&f.proxyAddress, "proxy-address", "", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`") + r.PersistentFlags().VarPF(&f.proxyAddress, "proxy-address", "", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`") } // NewClient returns a new client that is configured to use the remote that @@ -112,15 +110,15 @@ func (f *clientFactory) baseClientOptions() []secrethub.ClientOption { }), } - if f.proxyAddressFlag.Changed { + if f.proxyAddress.u != nil { transport := http.DefaultTransport.(*http.Transport) transport.Proxy = func(request *http.Request) (*url.URL, error) { - return &f.proxyAddress.u, nil + return f.proxyAddress.u, nil } options = append(options, secrethub.WithTransport(transport)) } - if f.serverURLFlag.Changed { + if f.ServerURL.u != nil { options = append(options, secrethub.WithServerURL(f.ServerURL.String())) } @@ -128,16 +126,19 @@ func (f *clientFactory) baseClientOptions() []secrethub.ClientOption { } type urlValue struct { - u url.URL + u *url.URL } func (u *urlValue) String() string { + if u.u == nil { + return "" + } return u.u.String() } func (u *urlValue) Set(s string) error { parsed, err := url.Parse(s) - u.u = *parsed + u.u = parsed if err != nil { return err } diff --git a/internals/secrethub/client_factory_test.go b/internals/secrethub/client_factory_test.go index 3560616d..e8b7c88f 100644 --- a/internals/secrethub/client_factory_test.go +++ b/internals/secrethub/client_factory_test.go @@ -1,7 +1,6 @@ package secrethub import ( - "github.com/spf13/cobra" "net/http" "net/url" "os" @@ -19,7 +18,7 @@ func TestNewClientFactory_ProxyAddress(t *testing.T) { proxyReceivedRequest := false go func() { - err := http.ListenAndServe(proxyAddress.Hostname()+":"+proxyAddress.Port(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + err = http.ListenAndServe(proxyAddress.Hostname()+":"+proxyAddress.Port(), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { proxyReceivedRequest = true })) if err != http.ErrServerClosed && err != nil { @@ -39,11 +38,10 @@ func TestNewClientFactory_ProxyAddress(t *testing.T) { factory := clientFactory{ identityProvider: "key", store: store, - ServerURL: urlValue{*serverAddress}, - proxyAddress: urlValue{*proxyAddress}, + ServerURL: urlValue{serverAddress}, + proxyAddress: urlValue{proxyAddress}, } - factory.Register(&cobra.Command{}) client, err := factory.NewUnauthenticatedClient() assert.OK(t, err) diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index 1b3f57c8..d5c57f96 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -2,18 +2,18 @@ package secrethub import ( "fmt" - "github.com/docker/go-units" - "github.com/secrethub/secrethub-cli/internals/cli/posix" "io/ioutil" "time" "github.com/secrethub/secrethub-cli/internals/cli/clip" "github.com/secrethub/secrethub-cli/internals/cli/filemode" + "github.com/secrethub/secrethub-cli/internals/cli/posix" "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" "github.com/secrethub/secrethub-go/internals/api" + "github.com/docker/go-units" "github.com/spf13/cobra" ) From 789f8849ca1304481a980ab6d19160e31f0a2ace Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 13 Aug 2020 15:42:21 +0200 Subject: [PATCH 21/41] Fix lint --- internals/demo/init.go | 1 + internals/secrethub/account_init.go | 2 +- internals/secrethub/acl_rm.go | 2 +- internals/secrethub/acl_set.go | 2 +- internals/secrethub/audit.go | 2 +- internals/secrethub/color.go | 2 +- internals/secrethub/credential_disable.go | 2 +- internals/secrethub/credential_store.go | 5 +++-- internals/secrethub/debug.go | 2 +- internals/secrethub/env_source.go | 10 +++++----- internals/secrethub/flags.go | 4 ++-- internals/secrethub/generate.go | 10 +++++----- internals/secrethub/init.go | 4 ++-- internals/secrethub/inject.go | 8 ++++---- internals/secrethub/list.go | 2 +- internals/secrethub/mkdir.go | 2 +- internals/secrethub/mlock.go | 2 +- internals/secrethub/org_init.go | 8 ++++---- internals/secrethub/org_invite.go | 4 ++-- internals/secrethub/org_ls.go | 2 +- internals/secrethub/printenv.go | 2 +- internals/secrethub/repo_ls.go | 2 +- internals/secrethub/repo_revoke.go | 2 +- internals/secrethub/rm.go | 2 +- internals/secrethub/run.go | 6 +++--- internals/secrethub/service_aws_init.go | 14 +++++++------- internals/secrethub/service_deploy_winrm.go | 14 +++++++------- internals/secrethub/service_gcp_init.go | 13 ++++++------- internals/secrethub/service_init.go | 16 ++++++++-------- internals/secrethub/signup.go | 2 +- 30 files changed, 75 insertions(+), 74 deletions(-) diff --git a/internals/demo/init.go b/internals/demo/init.go index 43b6082d..bc7c029b 100644 --- a/internals/demo/init.go +++ b/internals/demo/init.go @@ -5,6 +5,7 @@ import ( "crypto/sha256" "encoding/base64" "fmt" + "github.com/secrethub/secrethub-cli/internals/cli/ui" "github.com/secrethub/secrethub-cli/internals/secrethub/command" diff --git a/internals/secrethub/account_init.go b/internals/secrethub/account_init.go index 6c9056f7..68d49477 100644 --- a/internals/secrethub/account_init.go +++ b/internals/secrethub/account_init.go @@ -63,7 +63,7 @@ func (cmd *AccountInitCommand) Register(r command.Registerer) { clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, "Copy the credential's public component to the clipboard instead of printing it to stdout.") clause.Flags().BoolVar(&cmd.noWait, "no-wait", false, "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.") clause.Flags().BoolVar(&cmd.isContinue, "continue", false, "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.") - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/acl_rm.go b/internals/secrethub/acl_rm.go index 40c0cf0d..4ad89b4e 100644 --- a/internals/secrethub/acl_rm.go +++ b/internals/secrethub/acl_rm.go @@ -33,7 +33,7 @@ func (cmd *ACLRmCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("dir-path", "The path of the directory to remove the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/acl_set.go b/internals/secrethub/acl_set.go index 456213ee..54087574 100644 --- a/internals/secrethub/acl_set.go +++ b/internals/secrethub/acl_set.go @@ -35,7 +35,7 @@ func (cmd *ACLSetCommand) Register(r command.Registerer) { //clause.Arg("dir-path", "The path of the directory to set the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to set the access rule for").Required().SetValue(&cmd.accountName) //clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index 5a73a8d9..03fa9679 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -72,7 +72,7 @@ func (cmd *AuditCommand) Register(r command.Registerer) { //clause.Arg("repo-path or secret-path", "Path to the repository or the secret to audit "+repoPathPlaceHolder+" or "+secretPathPlaceHolder).SetValue(&cmd.path) clause.Flags().IntVar(&cmd.perPage, "per-page", 20, "Number of audit events shown per page") clause.Flag("per-page").Hidden = true - clause.Flags().StringVar(&cmd.format, "output-format", "table","Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.") + clause.Flags().StringVar(&cmd.format, "output-format", "table", "Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.") _ = clause.RegisterFlagCompletionFunc("output-format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"table", "json"}, cobra.ShellCompDirectiveDefault }) diff --git a/internals/secrethub/color.go b/internals/secrethub/color.go index b954c954..416debb3 100644 --- a/internals/secrethub/color.go +++ b/internals/secrethub/color.go @@ -1,10 +1,10 @@ package secrethub import ( - "github.com/spf13/cobra" "strconv" "github.com/fatih/color" + "github.com/spf13/cobra" ) // noColorFlag configures the global behaviour to disable colored output. diff --git a/internals/secrethub/credential_disable.go b/internals/secrethub/credential_disable.go index 8df95007..32fa9876 100644 --- a/internals/secrethub/credential_disable.go +++ b/internals/secrethub/credential_disable.go @@ -33,7 +33,7 @@ func (cmd *CredentialDisableCommand) Register(r command.Registerer) { //fingerprintHelp := fmt.Sprintf("Fingerprint of the credential to disable. At least the first %d characters must be entered.", api.ShortCredentialFingerprintMinimumLength) //clause.Arg("fingerprint", fingerprintHelp).StringVar(&cmd.fingerprint) - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 2838e32a..8c7be9e5 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -1,13 +1,14 @@ package secrethub import ( - "github.com/spf13/cobra" "time" "github.com/secrethub/secrethub-go/pkg/secrethub/configdir" "github.com/secrethub/secrethub-go/pkg/secrethub/credentials" "github.com/secrethub/secrethub-cli/internals/cli/ui" + + "github.com/spf13/cobra" ) // Errors @@ -54,7 +55,7 @@ func (store *credentialConfig) IsPassphraseSet() bool { // Register registers the flags for configuring the store on the provided Registerer. func (store *credentialConfig) Register(r *cobra.Command) { - r.PersistentFlags().Var(&store.configDir,"config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub") + r.PersistentFlags().Var(&store.configDir, "config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub") r.PersistentFlags().StringVar(&store.AccountCredential, "credential", "", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.") //TODO NoEnvVar r.PersistentFlags().StringVarP(&store.credentialPassphrase, "p", "p", "", "") // Shorthand -p is deprecated. Use --credential-passphrase instead. diff --git a/internals/secrethub/debug.go b/internals/secrethub/debug.go index 95fb9e87..756e10e5 100644 --- a/internals/secrethub/debug.go +++ b/internals/secrethub/debug.go @@ -1,10 +1,10 @@ package secrethub import ( - "github.com/spf13/cobra" "strconv" "github.com/secrethub/secrethub-cli/internals/cli" + "github.com/spf13/cobra" ) // RegisterDebugFlag registers a debug flag that changes the log level of the given logger to DEBUG. diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index f99576d8..7e595c62 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -62,14 +62,14 @@ func newEnvironment(io ui.IO, newClient newClientFunc) *environment { func (env *environment) register(clause *cli.CommandClause) { //clause.Flag("envar", "Source an environment variable from a secret at a given path with `NAME=`").Short('e').StringMapVar(&env.envar) - clause.Flags().StringVar(&env.envFile,"env-file", "","The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.") - clause.Flags().StringVar(&env.envFile,"template", "","") + clause.Flags().StringVar(&env.envFile, "env-file", "", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.") + clause.Flags().StringVar(&env.envFile, "template", "", "") clause.Flag("template").Hidden = true //clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&env.templateVars) clause.Flags().StringVar(&env.templateVersion, "template-version", "auto", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.") - clause.Flags().BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false,"Do not prompt when a template variable is missing and return an error instead.") - clause.Flags().StringVar(&env.secretsDir,"secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") - clause.Flags().StringVar(&env.secretsEnvDir, "env", "default","The name of the environment prepared by the set command (default is `default`)") + clause.Flags().BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") + clause.Flags().StringVar(&env.secretsDir, "secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") + clause.Flags().StringVar(&env.secretsEnvDir, "env", "default", "The name of the environment prepared by the set command (default is `default`)") clause.Flag("env").Hidden = true } diff --git a/internals/secrethub/flags.go b/internals/secrethub/flags.go index 86151265..ecc17c25 100644 --- a/internals/secrethub/flags.go +++ b/internals/secrethub/flags.go @@ -5,9 +5,9 @@ import ( ) func registerTimestampFlag(r *cli.CommandClause, p *bool) { - r.Flags().BoolVarP(p,"timestamp", "T", false, "Show timestamps formatted to RFC3339 instead of human readable durations.") + r.Flags().BoolVarP(p, "timestamp", "T", false, "Show timestamps formatted to RFC3339 instead of human readable durations.") } func registerForceFlag(r *cli.CommandClause, p *bool) { - r.Flags().BoolVarP(p, "force", "f", false,"Ignore confirmation and fail instead of prompt for missing arguments.") + r.Flags().BoolVarP(p, "force", "f", false, "Ignore confirmation and fail instead of prompt for missing arguments.") } diff --git a/internals/secrethub/generate.go b/internals/secrethub/generate.go index 1e0b6aeb..02f7fa55 100644 --- a/internals/secrethub/generate.go +++ b/internals/secrethub/generate.go @@ -65,16 +65,16 @@ func (cmd *GenerateSecretCommand) Register(r command.Registerer) { clause := r.CreateCommand("generate", "Generate a random secret.") clause.Args = cobra.RangeArgs(1, 3) //clause.Arg("secret-path", "The path to write the generated secret to").Required().PlaceHolder(secretPathPlaceHolder).StringVar(&cmd.firstArg) - clause.Flags().VarP(&cmd.lengthFlag, "length", "l", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)) //.PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) + clause.Flags().VarP(&cmd.lengthFlag, "length", "l", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)) //.PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) clause.Flag("length").DefValue = strconv.Itoa(defaultLength) - clause.Flags().Var(&cmd.mins,"min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.") - clause.Flags().BoolVarP(&cmd.copyToClipboard,"clip", "c", false,"Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".") - clause.Flags().Var(&cmd.charsetFlag, "charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.")//Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable") + clause.Flags().Var(&cmd.mins, "min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.") + clause.Flags().BoolVarP(&cmd.copyToClipboard, "clip", "c", false, "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".") + clause.Flags().Var(&cmd.charsetFlag, "charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.") //Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable") clause.Flag("charset").DefValue = "alphanumeric" _ = clause.RegisterFlagCompletionFunc("charset", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable"}, cobra.ShellCompDirectiveDefault }) - clause.Flags().VarP(&cmd.symbolsFlag, "symbols", "s","Include symbols in secret.")//Short('s').Hidden().SetValue(&cmd.symbolsFlag) + clause.Flags().VarP(&cmd.symbolsFlag, "symbols", "s", "Include symbols in secret.") //Short('s').Hidden().SetValue(&cmd.symbolsFlag) clause.Flag("symbols").Hidden = true //clause.Arg("rand-command", "").Hidden().StringVar(&cmd.secondArg) //clause.Arg("length", "").Hidden().SetValue(&cmd.lengthArg) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index f2a241f7..1b6e3710 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -39,8 +39,8 @@ func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentia // Register registers the command, arguments and flags on the provided Registerer. func (cmd *InitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize the SecretHub client for first use on this device.") - clause.Flags().StringVar(&cmd.backupCode,"backup-code", "","The backup code used to restore an existing account to this device.") - registerForceFlag(clause,&cmd.force) + clause.Flags().StringVar(&cmd.backupCode, "backup-code", "", "The backup code used to restore an existing account to this device.") + registerForceFlag(clause, &cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/inject.go b/internals/secrethub/inject.go index d39d7416..162b346c 100644 --- a/internals/secrethub/inject.go +++ b/internals/secrethub/inject.go @@ -63,17 +63,17 @@ func (cmd *InjectCommand) Register(r command.Registerer) { "Copy the injected template to the clipboard instead of stdout. The clipboard is automatically cleared after %s.", units.HumanDuration(cmd.clearClipboardAfter), )) - clause.Flags().StringVarP(&cmd.inFile,"in-file", "i", "","The filename of a template file to inject.") - clause.Flags().StringVarP(&cmd.outFile,"out-file", "o", "", "Write the injected template to a file instead of stdout.") + clause.Flags().StringVarP(&cmd.inFile, "in-file", "i", "", "The filename of a template file to inject.") + clause.Flags().StringVarP(&cmd.outFile, "out-file", "o", "", "Write the injected template to a file instead of stdout.") clause.Flags().StringVar(&cmd.outFile, "file", "", "") // Alias of --out-file (for backwards compatibility) clause.Flag("file").Hidden = true clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") clause.Flag("file-mode").DefValue = "0600" //TODO //clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&cmd.templateVars) - clause.Flags().StringVar(&cmd.templateVersion,"template-version", "auto","Do not prompt when a template variable is missing and return an error instead.") + clause.Flags().StringVar(&cmd.templateVersion, "template-version", "auto", "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().BoolVar(&cmd.dontPromptMissingTemplateVars, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") - clause.Flags().BoolVarP(&cmd.force, "force","f",false, "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.") + clause.Flags().BoolVarP(&cmd.force, "force", "f", false, "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/list.go b/internals/secrethub/list.go index 3762ae7a..b21e4358 100644 --- a/internals/secrethub/list.go +++ b/internals/secrethub/list.go @@ -37,7 +37,7 @@ func (cmd *LsCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) //clause.Arg("path", "The path to list contents of").SetValue(&cmd.path) - clause.Flags().BoolVarP(&cmd.quiet,"quiet", "q", false,"Only print paths.") + clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.") registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/mkdir.go b/internals/secrethub/mkdir.go index 259c763d..f5ea731e 100644 --- a/internals/secrethub/mkdir.go +++ b/internals/secrethub/mkdir.go @@ -39,7 +39,7 @@ func (cmd *MkDirCommand) Register(r command.Registerer) { clause := r.CreateCommand("mkdir", "Create a new directory.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-paths", "The paths to the directories").Required().PlaceHolder(dirPathsPlaceHolder).SetValue(&cmd.paths) - clause.Flags().BoolVar(&cmd.parents, "parents", false,"Create parent directories if needed. Does not error when directories already exist.") + clause.Flags().BoolVar(&cmd.parents, "parents", false, "Create parent directories if needed. Does not error when directories already exist.") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/mlock.go b/internals/secrethub/mlock.go index 4c52b7ae..ad2fe975 100644 --- a/internals/secrethub/mlock.go +++ b/internals/secrethub/mlock.go @@ -1,10 +1,10 @@ package secrethub import ( - "github.com/spf13/cobra" "strconv" "github.com/secrethub/secrethub-cli/internals/cli/mlock" + "github.com/spf13/cobra" ) // mlockFlag configures locking memory. diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index 3311b9bc..aeba018e 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -30,12 +30,12 @@ func NewOrgInitCommand(io ui.IO, newClient newClientFunc) *OrgInitCommand { func (cmd *OrgInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize a new organization account.") //clause.Flags().Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") - clause.Flags().StringVar(&cmd.description,"description", "","A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.") - clause.Flags().StringVar(&cmd.description,"descr", "","") + clause.Flags().StringVar(&cmd.description, "description", "", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.") + clause.Flags().StringVar(&cmd.description, "descr", "", "") clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.description,"desc", "","") + clause.Flags().StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index 189f547e..f3f668f8 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -35,8 +35,8 @@ func (cmd *OrgInviteCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) - clause.Flags().StringVar(&cmd.role, "role", "member","Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.") - registerForceFlag(clause,&cmd.force) + clause.Flags().StringVar(&cmd.role, "role", "member", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.") + registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_ls.go b/internals/secrethub/org_ls.go index e57b680b..41bf3294 100644 --- a/internals/secrethub/org_ls.go +++ b/internals/secrethub/org_ls.go @@ -32,7 +32,7 @@ func NewOrgLsCommand(io ui.IO, newClient newClientFunc) *OrgLsCommand { func (cmd *OrgLsCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all organizations you are a member of.") clause.Alias("list") - clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false,"Only print organization names.") + clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print organization names.") registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/printenv.go b/internals/secrethub/printenv.go index beda7bec..fdbf929c 100644 --- a/internals/secrethub/printenv.go +++ b/internals/secrethub/printenv.go @@ -37,7 +37,7 @@ func (cmd *PrintEnvCommand) Run() error { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *PrintEnvCommand) Register(r command.Registerer) { clause := r.CreateCommand("printenv", "Print environment variables.") - clause.Flags().BoolVarP(&cmd.verbose,"verbose", "v", false,"Show all possible environment variables.") + clause.Flags().BoolVarP(&cmd.verbose, "verbose", "v", false, "Show all possible environment variables.") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/repo_ls.go b/internals/secrethub/repo_ls.go index ff314269..dbfb9494 100644 --- a/internals/secrethub/repo_ls.go +++ b/internals/secrethub/repo_ls.go @@ -35,7 +35,7 @@ func (cmd *RepoLSCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all repositories you have access to.") clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) - clause.Flags().BoolVarP(&cmd.quiet,"quiet", "q",false, "Only print paths.") + clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.") //clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/repo_revoke.go b/internals/secrethub/repo_revoke.go index f04403df..6e11e992 100644 --- a/internals/secrethub/repo_revoke.go +++ b/internals/secrethub/repo_revoke.go @@ -35,7 +35,7 @@ func (cmd *RepoRevokeCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("repo-path", "The repository to revoke the account from").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/rm.go b/internals/secrethub/rm.go index d340d53b..040caaa4 100644 --- a/internals/secrethub/rm.go +++ b/internals/secrethub/rm.go @@ -43,7 +43,7 @@ func (cmd *RmCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("path", "The path to the resource to remove (/[/])").Required().SetValue(&cmd.path) clause.Flags().BoolVarP(&cmd.recursive, "recursive", "r", false, "Remove directories and their contents recursively.") - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/run.go b/internals/secrethub/run.go index f2638c91..303498b9 100644 --- a/internals/secrethub/run.go +++ b/internals/secrethub/run.go @@ -82,10 +82,10 @@ func (cmd *RunCommand) Register(r command.Registerer) { clause.Alias("exec") clause.Args = cobra.MinimumNArgs(1) //clause.Arg("command", "The command to execute").Required().StringsVar(&cmd.command) - clause.Flags().BoolVar(&cmd.noMasking, "no-masking", false,"Disable masking of secrets on stdout and stderr") + clause.Flags().BoolVar(&cmd.noMasking, "no-masking", false, "Disable masking of secrets on stdout and stderr") clause.Flags().BoolVar(&cmd.maskerOptions.DisableBuffer, "no-output-buffering", false, "Disable output buffering. This increases output responsiveness, but decreases the probability that secrets get masked.") - clause.Flags().DurationVar(&cmd.maskerOptions.BufferDelay, "masking-buffer-period", time.Millisecond * 50, "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.") - clause.Flags().BoolVar(&cmd.ignoreMissingSecrets,"ignore-missing-secrets", false,"Do not return an error when a secret does not exist and use an empty value instead.") + clause.Flags().DurationVar(&cmd.maskerOptions.BufferDelay, "masking-buffer-period", time.Millisecond*50, "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.") + clause.Flags().BoolVar(&cmd.ignoreMissingSecrets, "ignore-missing-secrets", false, "Do not return an error when a secret does not exist and use an empty value instead.") cmd.environment.register(clause) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 0efe3d1d..5c83a38e 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -167,15 +167,15 @@ func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to an AWS IAM role.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flags().StringVar(&cmd.kmsKeyID, "kms-key", "","The ID or ARN of the KMS-key to be used for encrypting the service's account key.") - clause.Flags().StringVar(&cmd.role,"role", "","The role name or ARN of the IAM role that should have access to this service account.") - clause.Flags().StringVar(&cmd.region, "region", "","The AWS region that should be used for KMS.") - clause.Flags().StringVar(&cmd.description, "description", "","A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") - clause.Flags().StringVar(&cmd.description,"descr", "", "") - clause.Flags().StringVar(&cmd.description,"desc", "", "") + clause.Flags().StringVar(&cmd.kmsKeyID, "kms-key", "", "The ID or ARN of the KMS-key to be used for encrypting the service's account key.") + clause.Flags().StringVar(&cmd.role, "role", "", "The role name or ARN of the IAM role that should have access to this service account.") + clause.Flags().StringVar(&cmd.region, "region", "", "The AWS region that should be used for KMS.") + clause.Flags().StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") + clause.Flags().StringVar(&cmd.description, "descr", "", "") + clause.Flags().StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.permission, "permission", "","Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") + clause.Flags().StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") clause.HelpLong("The native AWS identity provider uses a combination of AWS IAM and AWS KMS to provide access to SecretHub for any service running on AWS (e.g. EC2, Lambda or ECS). For this to work, an IAM role and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_deploy_winrm.go b/internals/secrethub/service_deploy_winrm.go index ca3d2258..7f30d871 100644 --- a/internals/secrethub/service_deploy_winrm.go +++ b/internals/secrethub/service_deploy_winrm.go @@ -62,16 +62,16 @@ func (cmd *ServiceDeployWinRmCommand) Register(r command.Registerer) { clause := r.CreateCommand("winrm", "Read a service account configuration from stdin and deploy it to a running instance with WinRM. The instance needs to be reachable, have WinRM enabled, and have PowerShell installed.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("resource-uri", "Hostname, optional connection protocol and port of the host ([http[s]://][:]). This defaults to https and port 5986.").Required().URLVar(&cmd.resourceURI) - clause.Flags().StringVar(&cmd.authType,"auth-type", "basic","Authentication type (basic/cert)") + clause.Flags().StringVar(&cmd.authType, "auth-type", "basic", "Authentication type (basic/cert)") _ = clause.RegisterFlagCompletionFunc("auth-type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"basic", "cert"}, cobra.ShellCompDirectiveDefault }) - clause.Flags().StringVar(&cmd.username,"username", "","The username used for logging in when authentication type is basic. Is asked if not supplied.") - clause.Flags().StringVar(&cmd.password, "password", "","The password used for logging in when authentication type is basic. Is asked if not supplied.") - clause.Flags().StringVar(&cmd.clientCert,"client-cert", "","Path to client certificate used for certificate authentication.") - clause.Flags().StringVar(&cmd.clientKey,"client-key", "","Path to client key used for certificate authentication.") - clause.Flags().StringVar(&cmd.caCert,"ca-cert", "","Path to CA certificate used to verify server TLS certificate.") - clause.Flags().BoolVar(&cmd.noVerify, "insecure-no-verify-cert", false,"Do not verify server TLS certificate (insecure).") + clause.Flags().StringVar(&cmd.username, "username", "", "The username used for logging in when authentication type is basic. Is asked if not supplied.") + clause.Flags().StringVar(&cmd.password, "password", "", "The password used for logging in when authentication type is basic. Is asked if not supplied.") + clause.Flags().StringVar(&cmd.clientCert, "client-cert", "", "Path to client certificate used for certificate authentication.") + clause.Flags().StringVar(&cmd.clientKey, "client-key", "", "Path to client key used for certificate authentication.") + clause.Flags().StringVar(&cmd.caCert, "ca-cert", "", "Path to CA certificate used to verify server TLS certificate.") + clause.Flags().BoolVar(&cmd.noVerify, "insecure-no-verify-cert", false, "Do not verify server TLS certificate (insecure).") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 191c48b8..b62b84f8 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -169,15 +169,14 @@ func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to a GCP Service Account.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flags().StringVar(&cmd.kmsKeyResourceID,"kms-key", "","The Resource ID of the KMS-key to be used for encrypting the service's account key.") - clause.Flags().StringVar(&cmd.serviceAccountEmail, "service-account-email","", "The email of the GCP Service Account that should have access to this service account.") - clause.Flags().StringVar(&cmd.description,"description", "","A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") - clause.Flags().StringVar(&cmd.description,"descr", "", "") - clause.Flags().StringVar(&cmd.description,"desc", "", "") + clause.Flags().StringVar(&cmd.kmsKeyResourceID, "kms-key", "", "The Resource ID of the KMS-key to be used for encrypting the service's account key.") + clause.Flags().StringVar(&cmd.serviceAccountEmail, "service-account-email", "", "The email of the GCP Service Account that should have access to this service account.") + clause.Flags().StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") + clause.Flags().StringVar(&cmd.description, "descr", "", "") + clause.Flags().StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.permission,"permission","", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") - + clause.Flags().StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") clause.HelpLong("The native GCP identity provider uses a combination of GCP IAM and GCP KMS to provide access to SecretHub for any service running on GCP. For this to work, a GCP Service Account and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index f76e921e..d3889be1 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -108,18 +108,18 @@ func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flags().StringVar(&cmd.description,"description", "","A description for the service so others will recognize it.") - clause.Flags().StringVar(&cmd.description,"descr", "", "") - clause.Flags().StringVar(&cmd.description,"desc", "", "") + clause.Flags().StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it.") + clause.Flags().StringVar(&cmd.description, "descr", "", "") + clause.Flags().StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.permission, "permission", "","Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") + clause.Flags().StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") // TODO make 45 sec configurable - clause.Flags().BoolVarP(&cmd.clip,"clip","c", false, "Write the service account configuration to the clipboard instead of stdout. The clipboard is automatically cleared after 45 seconds.") - clause.Flags().StringVar(&cmd.file,"file", "", "Write the service account configuration to a file instead of stdout.") + clause.Flags().BoolVarP(&cmd.clip, "clip", "c", false, "Write the service account configuration to the clipboard instead of stdout. The clipboard is automatically cleared after 45 seconds.") + clause.Flags().StringVar(&cmd.file, "file", "", "Write the service account configuration to a file instead of stdout.") clause.Flag("file").Hidden = true - clause.Flags().StringVar(&cmd.file,"out-file", "", "Write the service account configuration to a file instead of stdout.") - clause.Flags().Var(&cmd.fileMode,"file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.") + clause.Flags().StringVar(&cmd.file, "out-file", "", "Write the service account configuration to a file instead of stdout.") + clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.") clause.Flag("file-mode").DefValue = "0440" command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index 18cfaa89..e1a8bbf8 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -50,7 +50,7 @@ func (cmd *SignUpCommand) Register(r command.Registerer) { clause.Flags().StringVar(&cmd.email, "email", "", "Your (work) email address we will use for all correspondence.") clause.Flags().StringVar(&cmd.org, "org", "", "The name of your organization.") clause.Flags().StringVar(&cmd.orgDescription, "org-description", "", "A description (max 144 chars) for your organization so others will recognize it.") - registerForceFlag(clause,&cmd.force) + registerForceFlag(clause, &cmd.force) command.BindAction(clause, nil, cmd.Run) } From 6032908c3b3bc2b360da1ec0eb20ab5b5a273a98 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Thu, 13 Aug 2020 17:16:58 +0300 Subject: [PATCH 22/41] solved almost all todos --- internals/secrethub/env_source.go | 39 ++++++++++++++++++++++++------- internals/secrethub/inject.go | 9 ++++--- internals/secrethub/org_init.go | 28 +++++++++++++++++----- 3 files changed, 57 insertions(+), 19 deletions(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 7e595c62..46d64752 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -39,9 +39,9 @@ type environment struct { osEnv []string readFile func(filename string) ([]byte, error) osStat func(filename string) (os.FileInfo, error) - envar map[string]string + envar MapValue envFile string - templateVars map[string]string + templateVars MapValue templateVersion string dontPromptMissingTemplateVar bool secretsDir string @@ -55,17 +55,17 @@ func newEnvironment(io ui.IO, newClient newClientFunc) *environment { osEnv: os.Environ(), readFile: ioutil.ReadFile, osStat: os.Stat, - templateVars: make(map[string]string), - envar: make(map[string]string), + templateVars: MapValue{stringMap: make(map[string]string)}, + envar: MapValue{stringMap: make(map[string]string)}, } } func (env *environment) register(clause *cli.CommandClause) { - //clause.Flag("envar", "Source an environment variable from a secret at a given path with `NAME=`").Short('e').StringMapVar(&env.envar) + clause.Flags().VarP(&env.envar,"envar", "e","Source an environment variable from a secret at a given path with `NAME=`") clause.Flags().StringVar(&env.envFile, "env-file", "", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.") clause.Flags().StringVar(&env.envFile, "template", "", "") clause.Flag("template").Hidden = true - //clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&env.templateVars) + clause.Flags().VarP(&env.templateVars,"var","v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") clause.Flags().StringVar(&env.templateVersion, "template-version", "auto", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.") clause.Flags().BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().StringVar(&env.secretsDir, "secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") @@ -109,7 +109,7 @@ func (env *environment) env() (map[string]value, error) { } if env.envFile != "" { - templateVariableReader, err := newVariableReader(osEnvMap, env.templateVars) + templateVariableReader, err := newVariableReader(osEnvMap, env.templateVars.stringMap) if err != nil { return nil, err } @@ -141,7 +141,7 @@ func (env *environment) env() (map[string]value, error) { // --envar flag // TODO: Validate the flags when parsing by implementing the Flag interface for EnvFlags. - flagEnv, err := NewEnvFlags(env.envar) + flagEnv, err := NewEnvFlags(env.envar.stringMap) if err != nil { return nil, err } @@ -665,3 +665,26 @@ func (o *osEnv) env() (map[string]value, error) { } return res, nil } + +type MapValue struct { + stringMap map[string]string +} + +func (m MapValue) String() string { + textRepresentation := "" + for k, v :=range m.stringMap { + textRepresentation += k + "=" + v + ";" + } + return textRepresentation +} + +//TODO treat the case when the array does not contain exactly 2 elements +func (m MapValue) Set(s string) error { + arr := strings.Split(s, "=") + m.stringMap[arr[0]] = arr[1] + return nil +} + +func (m MapValue) Type() string { + return "mapValue" +} diff --git a/internals/secrethub/inject.go b/internals/secrethub/inject.go index 162b346c..db2e2f38 100644 --- a/internals/secrethub/inject.go +++ b/internals/secrethub/inject.go @@ -36,7 +36,7 @@ type InjectCommand struct { clipper clip.Clipper osEnv []string newClient newClientFunc - templateVars map[string]string + templateVars MapValue templateVersion string dontPromptMissingTemplateVars bool } @@ -49,7 +49,7 @@ func NewInjectCommand(io ui.IO, newClient newClientFunc) *InjectCommand { clearClipboardAfter: defaultClearClipboardAfter, io: io, newClient: newClient, - templateVars: make(map[string]string), + templateVars: MapValue{stringMap: make(map[string]string)}, } } @@ -69,8 +69,7 @@ func (cmd *InjectCommand) Register(r command.Registerer) { clause.Flag("file").Hidden = true clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") clause.Flag("file-mode").DefValue = "0600" - //TODO - //clause.Flag("var", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod").Short('v').StringMapVar(&cmd.templateVars) + clause.Flags().VarP(&cmd.templateVars,"var", "v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") clause.Flags().StringVar(&cmd.templateVersion, "template-version", "auto", "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().BoolVar(&cmd.dontPromptMissingTemplateVars, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().BoolVarP(&cmd.force, "force", "f", false, "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.") @@ -106,7 +105,7 @@ func (cmd *InjectCommand) Run() error { osEnv, _ := parseKeyValueStringsToMap(cmd.osEnv) var templateVariableReader tpl.VariableReader - templateVariableReader, err = newVariableReader(osEnv, cmd.templateVars) + templateVariableReader, err = newVariableReader(osEnv, cmd.templateVars.stringMap) if err != nil { return err } diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index aeba018e..83865e34 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -11,7 +11,7 @@ import ( // OrgInitCommand handles creating an organization. type OrgInitCommand struct { - name api.OrgName + name orgNameValue description string force bool io ui.IO @@ -29,7 +29,7 @@ func NewOrgInitCommand(io ui.IO, newClient newClientFunc) *OrgInitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize a new organization account.") - //clause.Flags().Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") + clause.Flags().Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") clause.Flags().StringVar(&cmd.description, "description", "", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.") clause.Flags().StringVar(&cmd.description, "descr", "", "") clause.Flag("descr").Hidden = true @@ -44,7 +44,7 @@ func (cmd *OrgInitCommand) Register(r command.Registerer) { func (cmd *OrgInitCommand) Run() error { var err error - incompleteInput := cmd.name == "" || cmd.description == "" + incompleteInput := cmd.name.orgName == "" || cmd.description == "" if cmd.force && incompleteInput { return ErrMissingFlags } else if !cmd.force && incompleteInput { @@ -54,12 +54,12 @@ func (cmd *OrgInitCommand) Run() error { "Please answer the questions below, followed by an [ENTER]\n\n", ) - if cmd.name == "" { + if cmd.name.orgName == "" { name, err := ui.AskAndValidate(cmd.io, "The name you would like to use for your organization: ", 2, api.ValidateOrgName) if err != nil { return err } - cmd.name = api.OrgName(name) + cmd.name = orgNameValue{orgName: api.OrgName(name)} } if cmd.description == "" { @@ -80,7 +80,7 @@ func (cmd *OrgInitCommand) Run() error { fmt.Fprintf(cmd.io.Output(), "Creating organization...\n") - resp, err := client.Orgs().Create(cmd.name.Value(), cmd.description) + resp, err := client.Orgs().Create(cmd.name.orgName.Value(), cmd.description) if err != nil { return err } @@ -89,3 +89,19 @@ func (cmd *OrgInitCommand) Run() error { return nil } + +type orgNameValue struct { + orgName api.OrgName +} + +func (o orgNameValue) String() string { + return o.orgName.String() +} + +func (o orgNameValue) Set(s string) error { + return o.orgName.Set(s) +} + +func (o orgNameValue) Type() string { + return "orgNameValue" +} From 6b2a9bb455d2bb757561290ac7cae6b35e1e09da Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 13 Aug 2020 16:42:27 +0200 Subject: [PATCH 23/41] Add app version --- cmd/secrethub/main.go | 2 +- internals/cli/env.go | 12 ++++++------ internals/secrethub/app.go | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cmd/secrethub/main.go b/cmd/secrethub/main.go index 5673cfe8..b25d6031 100644 --- a/cmd/secrethub/main.go +++ b/cmd/secrethub/main.go @@ -8,7 +8,7 @@ import ( ) func main() { - err := secrethub.NewApp().Run(os.Args[1:]) + err := secrethub.NewApp().Version(secrethub.Version, secrethub.Commit).Run() if err != nil { handleError(err) } diff --git a/internals/cli/env.go b/internals/cli/env.go index 0f46ec47..0514695d 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -56,12 +56,12 @@ func (a *App) CreateCommand(name, help string) *CommandClause { } // -//// Version adds a flag for displaying the application version number. -//func (a *App) Version(version string) *App { -// a.Application = a.Application.Version(version) -// return a -//} -// +// Version adds a flag for displaying the application version number. +func (a *App) Version(version string) *App { + a.Application.Version = version + return a +} + // Flag defines a new flag with the given long name and help text, // adding an environment variable default configurable by APP_FLAG_NAME. func (a *App) Flag(name, help string) *Flag { diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index 4e6200ef..9c80a5e0 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -136,14 +136,14 @@ func NewApp() *App { } // Version adds a flag for displaying the application version number. -//func (app *App) Version(version string, commit string) *App { -// app.cli = app.cli.Version(ApplicationName + " version " + version + ", build " + commit) -// return app -//} +func (app *App) Version(version string, commit string) *App { + app.cli = app.cli.Version(version + ", build " + commit) + return app +} // Run builds the command-line application, parses the arguments, // configures global behavior and executes the command given by the args. -func (app *App) Run(args []string) error { +func (app *App) Run() error { // Parse also executes the command when parsing is successful. err := app.cli.Application.Execute() return err From 382c19aed6975027c21c0b56d4e7445bb945a47f Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 13 Aug 2020 16:55:04 +0200 Subject: [PATCH 24/41] Fix tests and lint --- internals/secrethub/env_source.go | 6 ++-- internals/secrethub/inject.go | 2 +- internals/secrethub/org_init_test.go | 6 ++-- internals/secrethub/run_test.go | 46 ++++++++++++++-------------- 4 files changed, 30 insertions(+), 30 deletions(-) diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 46d64752..76836611 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -61,11 +61,11 @@ func newEnvironment(io ui.IO, newClient newClientFunc) *environment { } func (env *environment) register(clause *cli.CommandClause) { - clause.Flags().VarP(&env.envar,"envar", "e","Source an environment variable from a secret at a given path with `NAME=`") + clause.Flags().VarP(&env.envar, "envar", "e", "Source an environment variable from a secret at a given path with `NAME=`") clause.Flags().StringVar(&env.envFile, "env-file", "", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.") clause.Flags().StringVar(&env.envFile, "template", "", "") clause.Flag("template").Hidden = true - clause.Flags().VarP(&env.templateVars,"var","v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") + clause.Flags().VarP(&env.templateVars, "var", "v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") clause.Flags().StringVar(&env.templateVersion, "template-version", "auto", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.") clause.Flags().BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().StringVar(&env.secretsDir, "secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") @@ -672,7 +672,7 @@ type MapValue struct { func (m MapValue) String() string { textRepresentation := "" - for k, v :=range m.stringMap { + for k, v := range m.stringMap { textRepresentation += k + "=" + v + ";" } return textRepresentation diff --git a/internals/secrethub/inject.go b/internals/secrethub/inject.go index db2e2f38..984cf21a 100644 --- a/internals/secrethub/inject.go +++ b/internals/secrethub/inject.go @@ -69,7 +69,7 @@ func (cmd *InjectCommand) Register(r command.Registerer) { clause.Flag("file").Hidden = true clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") clause.Flag("file-mode").DefValue = "0600" - clause.Flags().VarP(&cmd.templateVars,"var", "v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") + clause.Flags().VarP(&cmd.templateVars, "var", "v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") clause.Flags().StringVar(&cmd.templateVersion, "template-version", "auto", "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().BoolVar(&cmd.dontPromptMissingTemplateVars, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().BoolVarP(&cmd.force, "force", "f", false, "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.") diff --git a/internals/secrethub/org_init_test.go b/internals/secrethub/org_init_test.go index c298d1d3..19ad5655 100644 --- a/internals/secrethub/org_init_test.go +++ b/internals/secrethub/org_init_test.go @@ -24,7 +24,7 @@ func TestOrgInitCommand_Run(t *testing.T) { }{ "success": { cmd: OrgInitCommand{ - name: "company", + name: orgNameValue{"company"}, description: "description", force: true, }, @@ -40,7 +40,7 @@ func TestOrgInitCommand_Run(t *testing.T) { }, "new client error": { cmd: OrgInitCommand{ - name: "company", + name: orgNameValue{"company"}, description: "description", force: true, }, @@ -49,7 +49,7 @@ func TestOrgInitCommand_Run(t *testing.T) { }, "create org error": { cmd: OrgInitCommand{ - name: "company", + name: orgNameValue{"company"}, description: "description", force: true, }, diff --git a/internals/secrethub/run_test.go b/internals/secrethub/run_test.go index 87ed68a0..f3eefcae 100644 --- a/internals/secrethub/run_test.go +++ b/internals/secrethub/run_test.go @@ -490,9 +490,9 @@ func TestRunCommand_Run(t *testing.T) { command: RunCommand{ command: []string{"echo", "test"}, environment: &environment{ - envar: map[string]string{ + envar: MapValue{map[string]string{ "missing": "path/to/unexisting/secret", - }, + }}, osStat: osStatNotExist, }, newClient: func() (secrethub.ClientInterface, error) { @@ -515,9 +515,9 @@ func TestRunCommand_Run(t *testing.T) { command: []string{"echo", "test"}, environment: &environment{ osStat: osStatNotExist, - envar: map[string]string{ + envar: MapValue{map[string]string{ "missing": "path/to/unexisting/secret", - }, + }}, }, io: fakeui.NewIO(t), newClient: func() (secrethub.ClientInterface, error) { @@ -539,9 +539,9 @@ func TestRunCommand_Run(t *testing.T) { command: RunCommand{ command: []string{"echo", "test"}, environment: &environment{ - envar: map[string]string{ - "missing": "unexisting/repo/secret", - }, + envar: MapValue{map[string]string{ + "missing": "path/to/unexisting/secret", + }}, osStat: osStatNotExist, }, io: fakeui.NewIO(t), @@ -565,10 +565,10 @@ func TestRunCommand_Run(t *testing.T) { environment: &environment{ osStat: osStatNotExist, envFile: "secrethub.env", - templateVars: map[string]string{ + templateVars: MapValue{map[string]string{ "0foo": "value", - }, - envar: map[string]string{}, + }}, + envar: MapValue{map[string]string{}}, }, }, err: ErrInvalidTemplateVar("0foo"), @@ -578,10 +578,10 @@ func TestRunCommand_Run(t *testing.T) { environment: &environment{ osStat: osStatNotExist, envFile: "secrethub.env", - templateVars: map[string]string{ + templateVars: MapValue{map[string]string{ "foo@bar": "value", - }, - envar: map[string]string{}, + }}, + envar: MapValue{map[string]string{}}, }, }, err: ErrInvalidTemplateVar("foo@bar"), @@ -751,9 +751,9 @@ func TestRunCommand_environment(t *testing.T) { osStat: osStatFunc("secrethub.env", nil), readFile: readFileFunc("secrethub.env", "TEST=aaa"), envFile: "secrethub.env", - envar: map[string]string{ + envar: MapValue{map[string]string{ "TEST": "test/test/test", - }, + }}, templateVersion: "2", }, newClient: func() (secrethub.ClientInterface, error) { @@ -992,9 +992,9 @@ func TestRunCommand_environment(t *testing.T) { osStat: osStatFunc("secrethub.env", nil), envFile: "secrethub.env", readFile: readFileFunc("secrethub.env", ""), - envar: map[string]string{ + envar: MapValue{map[string]string{ "TEST": "test/test/test", - }, + }}, templateVersion: "2", }, newClient: func() (secrethub.ClientInterface, error) { @@ -1068,7 +1068,7 @@ func TestRunCommand_environment(t *testing.T) { readFile: readFileFunc("secrethub.env", "TEST = {{ test/$variable/test }}"), dontPromptMissingTemplateVar: true, templateVersion: "2", - templateVars: map[string]string{"variable": "test"}, + templateVars: MapValue{map[string]string{"variable": "test"}}, }, newClient: func() (secrethub.ClientInterface, error) { return fakeclient.Client{ @@ -1093,7 +1093,7 @@ func TestRunCommand_environment(t *testing.T) { readFile: readFileFunc("secrethub.env", "TEST=$variable"), dontPromptMissingTemplateVar: true, templateVersion: "2", - templateVars: map[string]string{"variable": "foo"}, + templateVars: MapValue{map[string]string{"variable": "foo"}}, }, osEnv: []string{"SECRETHUB_VAR_VARIABLE=bar"}, newClient: func() (secrethub.ClientInterface, error) { @@ -1180,9 +1180,9 @@ func TestRunCommand_RunWithFile(t *testing.T) { osStat: osStatOnlySecretHubEnv, readFile: readFileWithContent(""), envFile: "secrethub.env", - envar: map[string]string{ + envar: MapValue{map[string]string{ "TEST": "test/test/test", - }, + }}, templateVersion: "2", }, newClient: func() (secrethub.ClientInterface, error) { @@ -1207,9 +1207,9 @@ func TestRunCommand_RunWithFile(t *testing.T) { osStat: osStatOnlySecretHubEnv, envFile: "secrethub.env", readFile: readFileWithContent(""), - envar: map[string]string{ + envar: MapValue{map[string]string{ "TEST": "test/test/test", - }, + }}, templateVersion: "2", }, newClient: func() (secrethub.ClientInterface, error) { From 1b81c0ca390940c144f8da9070190453f174b43c Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 13 Aug 2020 17:08:50 +0200 Subject: [PATCH 25/41] Rename PreRun to argumentRegister --- internals/secrethub/acl_check.go | 4 ++-- internals/secrethub/acl_list.go | 4 ++-- internals/secrethub/acl_rm.go | 4 ++-- internals/secrethub/acl_set.go | 4 ++-- internals/secrethub/audit.go | 4 ++-- internals/secrethub/clear_clipboard.go | 4 ++-- internals/secrethub/credential_disable.go | 4 ++-- internals/secrethub/env_read.go | 4 ++-- internals/secrethub/generate.go | 4 ++-- internals/secrethub/inspect.go | 4 ++-- internals/secrethub/list.go | 4 ++-- internals/secrethub/mkdir.go | 4 ++-- internals/secrethub/org_inspect.go | 4 ++-- internals/secrethub/org_invite.go | 4 ++-- internals/secrethub/org_list_users.go | 4 ++-- internals/secrethub/org_revoke.go | 4 ++-- internals/secrethub/org_rm.go | 4 ++-- internals/secrethub/org_set_role.go | 4 ++-- internals/secrethub/repo_export.go | 4 ++-- internals/secrethub/repo_init.go | 4 ++-- internals/secrethub/repo_inspect.go | 4 ++-- internals/secrethub/repo_invite.go | 4 ++-- internals/secrethub/repo_ls.go | 4 ++-- internals/secrethub/repo_revoke.go | 4 ++-- internals/secrethub/repo_rm.go | 4 ++-- internals/secrethub/rm.go | 4 ++-- internals/secrethub/run.go | 4 ++-- internals/secrethub/service_aws_init.go | 4 ++-- internals/secrethub/service_deploy_winrm.go | 4 ++-- internals/secrethub/service_gcp_init.go | 4 ++-- internals/secrethub/service_gcp_link.go | 12 ++++++------ internals/secrethub/service_init.go | 4 ++-- internals/secrethub/service_ls.go | 4 ++-- internals/secrethub/tree.go | 4 ++-- internals/secrethub/write.go | 4 ++-- 35 files changed, 74 insertions(+), 74 deletions(-) diff --git a/internals/secrethub/acl_check.go b/internals/secrethub/acl_check.go index 5cce53cc..9d144f50 100644 --- a/internals/secrethub/acl_check.go +++ b/internals/secrethub/acl_check.go @@ -38,7 +38,7 @@ func (cmd *ACLCheckCommand) Register(r command.Registerer) { //clause.Arg("dir-path", "The path of the directory to check the effective permission for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "Check permissions of a specific account name (username or service name). When left empty, all accounts with permission on the path are printed out.").SetValue(&cmd.accountName) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run prints the access level(s) on the given directory. @@ -110,7 +110,7 @@ func (cmd *ACLCheckCommand) listLevels() ([]*api.AccessLevel, error) { return nil, listLevelsErr } -func (cmd *ACLCheckCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ACLCheckCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewDirPath(args[0]) if err != nil { diff --git a/internals/secrethub/acl_list.go b/internals/secrethub/acl_list.go index 32d72de1..5bf57bed 100644 --- a/internals/secrethub/acl_list.go +++ b/internals/secrethub/acl_list.go @@ -43,7 +43,7 @@ func (cmd *ACLListCommand) Register(r command.Registerer) { clause.Flags().BoolVarP(&cmd.ancestors, "all", "a", false, "List all rules that apply on the directory, including rules on parent directories.") registerTimestampFlag(clause, &cmd.useTimestamps) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run prints access rules for the given directory. @@ -52,7 +52,7 @@ func (cmd *ACLListCommand) Run() error { return cmd.run() } -func (cmd *ACLListCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ACLListCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewDirPath(args[0]) if err != nil { diff --git a/internals/secrethub/acl_rm.go b/internals/secrethub/acl_rm.go index 4ad89b4e..fee7c127 100644 --- a/internals/secrethub/acl_rm.go +++ b/internals/secrethub/acl_rm.go @@ -35,7 +35,7 @@ func (cmd *ACLRmCommand) Register(r command.Registerer) { //clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) registerForceFlag(clause, &cmd.force) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run removes the access rule. @@ -77,7 +77,7 @@ func (cmd *ACLRmCommand) Run() error { return nil } -func (cmd *ACLRmCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ACLRmCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewDirPath(args[0]) if err != nil { diff --git a/internals/secrethub/acl_set.go b/internals/secrethub/acl_set.go index 54087574..1178cc8e 100644 --- a/internals/secrethub/acl_set.go +++ b/internals/secrethub/acl_set.go @@ -37,7 +37,7 @@ func (cmd *ACLSetCommand) Register(r command.Registerer) { //clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) registerForceFlag(clause, &cmd.force) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run handles the command with the options as specified in the command. @@ -81,7 +81,7 @@ func (cmd *ACLSetCommand) Run() error { return nil } -func (cmd *ACLSetCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ACLSetCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewDirPath(args[0]) if err != nil { diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index 03fa9679..2dc6bfbd 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -79,7 +79,7 @@ func (cmd *AuditCommand) Register(r command.Registerer) { clause.Flags().IntVar(&cmd.maxResults, "max-results", defaultLimit, "Specify the number of entries to list. If maxResults < 0 all entries are displayed. If the output of the command is piped, maxResults defaults to 1000.") registerTimestampFlag(clause, &cmd.useTimestamps) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run prints all audit events for the given repository or secret. @@ -88,7 +88,7 @@ func (cmd *AuditCommand) Run() error { return cmd.run() } -func (cmd *AuditCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *AuditCommand) argumentRegister(c *cobra.Command, args []string) error { var err error if len(args) != 0 { cmd.path, err = api.NewPath(args[0]) diff --git a/internals/secrethub/clear_clipboard.go b/internals/secrethub/clear_clipboard.go index aaf8226d..a7d79500 100644 --- a/internals/secrethub/clear_clipboard.go +++ b/internals/secrethub/clear_clipboard.go @@ -36,7 +36,7 @@ func (cmd *ClearClipboardCommand) Register(r command.Registerer) { //clause.Arg("hash", "Hash from the secret to be cleared").Required().HexBytesVar(&cmd.hash) clause.Flags().DurationVar(&cmd.timeout, "timeout", 0, "Time to wait before clearing in seconds") - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run handles the command with the options as specified in the command. @@ -81,6 +81,6 @@ func WriteClipboardAutoClear(data []byte, timeout time.Duration, clipper clip.Cl return err } -func (cmd *ClearClipboardCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ClearClipboardCommand) argumentRegister(c *cobra.Command, args []string) error { return nil } diff --git a/internals/secrethub/credential_disable.go b/internals/secrethub/credential_disable.go index 32fa9876..9788e50d 100644 --- a/internals/secrethub/credential_disable.go +++ b/internals/secrethub/credential_disable.go @@ -35,7 +35,7 @@ func (cmd *CredentialDisableCommand) Register(r command.Registerer) { //clause.Arg("fingerprint", fingerprintHelp).StringVar(&cmd.fingerprint) registerForceFlag(clause, &cmd.force) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run disables an existing credential. @@ -86,7 +86,7 @@ func (cmd *CredentialDisableCommand) Run() error { return nil } -func (cmd *CredentialDisableCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *CredentialDisableCommand) argumentRegister(c *cobra.Command, args []string) error { if len(args) != 0 { cmd.fingerprint = args[0] } diff --git a/internals/secrethub/env_read.go b/internals/secrethub/env_read.go index 0fbdf2ec..eb6c7eaa 100644 --- a/internals/secrethub/env_read.go +++ b/internals/secrethub/env_read.go @@ -34,7 +34,7 @@ func (cmd *EnvReadCommand) Register(r command.Registerer) { cmd.environment.register(clause) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run executes the command. @@ -61,7 +61,7 @@ func (cmd *EnvReadCommand) Run() error { return nil } -func (cmd *EnvReadCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *EnvReadCommand) argumentRegister(c *cobra.Command, args []string) error { if len(args) != 0 { cmd.key = args[0] } diff --git a/internals/secrethub/generate.go b/internals/secrethub/generate.go index 02f7fa55..85aec87c 100644 --- a/internals/secrethub/generate.go +++ b/internals/secrethub/generate.go @@ -79,7 +79,7 @@ func (cmd *GenerateSecretCommand) Register(r command.Registerer) { //clause.Arg("rand-command", "").Hidden().StringVar(&cmd.secondArg) //clause.Arg("length", "").Hidden().SetValue(&cmd.lengthArg) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // before configures the command using the flag values. @@ -111,7 +111,7 @@ func (cmd *GenerateSecretCommand) Run() error { return cmd.run() } -func (cmd *GenerateSecretCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *GenerateSecretCommand) argumentRegister(c *cobra.Command, args []string) error { cmd.firstArg = args[0] if len(args) >= 2 { cmd.secondArg = args[1] diff --git a/internals/secrethub/inspect.go b/internals/secrethub/inspect.go index 9ef97399..3fdc4a0c 100644 --- a/internals/secrethub/inspect.go +++ b/internals/secrethub/inspect.go @@ -35,7 +35,7 @@ func (cmd *InspectCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo or secret-path", "Path to the repository or the secret to inspect "+repoPathPlaceHolder+" or "+secretPathOptionalVersionPlaceHolder).Required().SetValue(&cmd.path) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run inspects a repository or a secret @@ -70,7 +70,7 @@ func (cmd *InspectCommand) Run() error { return ErrInspectResourceNotSupported } -func (cmd *InspectCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *InspectCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewPath(args[0]) if err != nil { diff --git a/internals/secrethub/list.go b/internals/secrethub/list.go index b21e4358..e8f0edc3 100644 --- a/internals/secrethub/list.go +++ b/internals/secrethub/list.go @@ -40,7 +40,7 @@ func (cmd *LsCommand) Register(r command.Registerer) { clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.") registerTimestampFlag(clause, &cmd.useTimestamps) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run lists a repo, secret or namespace. @@ -133,7 +133,7 @@ func (cmd *LsCommand) Run() error { return errio.UnexpectedError(errors.New("invalid path argument")) } -func (cmd *LsCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *LsCommand) argumentRegister(c *cobra.Command, args []string) error { var err error if len(args) != 0 { cmd.path, err = api.NewPath(args[0]) diff --git a/internals/secrethub/mkdir.go b/internals/secrethub/mkdir.go index f5ea731e..bb5229aa 100644 --- a/internals/secrethub/mkdir.go +++ b/internals/secrethub/mkdir.go @@ -41,7 +41,7 @@ func (cmd *MkDirCommand) Register(r command.Registerer) { //clause.Arg("dir-paths", "The paths to the directories").Required().PlaceHolder(dirPathsPlaceHolder).SetValue(&cmd.paths) clause.Flags().BoolVar(&cmd.parents, "parents", false, "Create parent directories if needed. Does not error when directories already exist.") - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run executes the command. @@ -62,7 +62,7 @@ func (cmd *MkDirCommand) Run() error { return nil } -func (cmd *MkDirCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *MkDirCommand) argumentRegister(c *cobra.Command, args []string) error { var list dirPathList for _, arg := range args { list = append(list, arg) diff --git a/internals/secrethub/org_inspect.go b/internals/secrethub/org_inspect.go index c0c8e6b8..5804de48 100644 --- a/internals/secrethub/org_inspect.go +++ b/internals/secrethub/org_inspect.go @@ -35,7 +35,7 @@ func (cmd *OrgInspectCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run prints out the details of an organization. @@ -70,7 +70,7 @@ func (cmd *OrgInspectCommand) Run() error { return nil } -func (cmd *OrgInspectCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *OrgInspectCommand) argumentRegister(c *cobra.Command, args []string) error { err := api.ValidateOrgName(args[0]) if err != nil { return err diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index f3f668f8..3f3c970c 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -38,7 +38,7 @@ func (cmd *OrgInviteCommand) Register(r command.Registerer) { clause.Flags().StringVar(&cmd.role, "role", "member", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.") registerForceFlag(clause, &cmd.force) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run invites a user to an organization and gives them a certain role. @@ -76,7 +76,7 @@ func (cmd *OrgInviteCommand) Run() error { return nil } -func (cmd *OrgInviteCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *OrgInviteCommand) argumentRegister(c *cobra.Command, args []string) error { err := api.ValidateOrgName(args[0]) if err != nil { return err diff --git a/internals/secrethub/org_list_users.go b/internals/secrethub/org_list_users.go index 5aa087c0..45a06c21 100644 --- a/internals/secrethub/org_list_users.go +++ b/internals/secrethub/org_list_users.go @@ -38,7 +38,7 @@ func (cmd *OrgListUsersCommand) Register(r command.Registerer) { //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) registerTimestampFlag(clause, &cmd.useTimestamps) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run lists the users of an organization. @@ -47,7 +47,7 @@ func (cmd *OrgListUsersCommand) Run() error { return cmd.run() } -func (cmd *OrgListUsersCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *OrgListUsersCommand) argumentRegister(c *cobra.Command, args []string) error { err := api.ValidateOrgName(args[0]) if err != nil { return err diff --git a/internals/secrethub/org_revoke.go b/internals/secrethub/org_revoke.go index 4f6e9b5e..d4c0ba2a 100644 --- a/internals/secrethub/org_revoke.go +++ b/internals/secrethub/org_revoke.go @@ -36,7 +36,7 @@ func (cmd *OrgRevokeCommand) Register(r command.Registerer) { //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run revokes an organization member. @@ -133,7 +133,7 @@ func (cmd *OrgRevokeCommand) Run() error { return nil } -func (cmd *OrgRevokeCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *OrgRevokeCommand) argumentRegister(c *cobra.Command, args []string) error { err := api.ValidateOrgName(args[0]) if err != nil { return err diff --git a/internals/secrethub/org_rm.go b/internals/secrethub/org_rm.go index 8495dbb9..52fff3a3 100644 --- a/internals/secrethub/org_rm.go +++ b/internals/secrethub/org_rm.go @@ -34,7 +34,7 @@ func (cmd *OrgRmCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run deletes an organization, prompting the user for confirmation. @@ -75,7 +75,7 @@ func (cmd *OrgRmCommand) Run() error { return nil } -func (cmd *OrgRmCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *OrgRmCommand) argumentRegister(c *cobra.Command, args []string) error { err := api.ValidateOrgName(args[0]) if err != nil { return err diff --git a/internals/secrethub/org_set_role.go b/internals/secrethub/org_set_role.go index d223f573..93642835 100644 --- a/internals/secrethub/org_set_role.go +++ b/internals/secrethub/org_set_role.go @@ -36,7 +36,7 @@ func (cmd *OrgSetRoleCommand) Register(r command.Registerer) { //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) //clause.Arg("role", "The role to assign to the user. Can be either `admin` or `member`.").Required().StringVar(&cmd.role) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run updates the role of an organization member. @@ -58,7 +58,7 @@ func (cmd *OrgSetRoleCommand) Run() error { return nil } -func (cmd *OrgSetRoleCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *OrgSetRoleCommand) argumentRegister(c *cobra.Command, args []string) error { err := api.ValidateOrgName(args[0]) if err != nil { return err diff --git a/internals/secrethub/repo_export.go b/internals/secrethub/repo_export.go index 0141fdac..dc5c2f84 100644 --- a/internals/secrethub/repo_export.go +++ b/internals/secrethub/repo_export.go @@ -44,7 +44,7 @@ func (cmd *RepoExportCommand) Register(r command.Registerer) { //clause.Arg("repo-path", "The repository to export").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("zip-file-name", "The file name to assign to the exported .zip file. Defaults to secrethub_export___.zip with the timestamp formatted as YYYYMMDD_HHMMSS").StringVar(&cmd.zipName) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run exports a repo to a zip file @@ -143,7 +143,7 @@ func (cmd *RepoExportCommand) Run() error { return nil } -func (cmd *RepoExportCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RepoExportCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/repo_init.go b/internals/secrethub/repo_init.go index 4d98b6b8..93634240 100644 --- a/internals/secrethub/repo_init.go +++ b/internals/secrethub/repo_init.go @@ -32,7 +32,7 @@ func (cmd *RepoInitCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo-path", "Path to the new repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run creates a new repository. @@ -54,7 +54,7 @@ func (cmd *RepoInitCommand) Run() error { return nil } -func (cmd *RepoInitCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RepoInitCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/repo_inspect.go b/internals/secrethub/repo_inspect.go index 7481b150..e0f63716 100644 --- a/internals/secrethub/repo_inspect.go +++ b/internals/secrethub/repo_inspect.go @@ -35,7 +35,7 @@ func (cmd *RepoInspectCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo-path", "Path to the repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run prints out the details of a repo. @@ -70,7 +70,7 @@ func (cmd *RepoInspectCommand) Run() error { return nil } -func (cmd *RepoInspectCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RepoInspectCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/repo_invite.go b/internals/secrethub/repo_invite.go index 844c77a5..21313d79 100644 --- a/internals/secrethub/repo_invite.go +++ b/internals/secrethub/repo_invite.go @@ -36,7 +36,7 @@ func (cmd *RepoInviteCommand) Register(r command.Registerer) { //clause.Arg("username", "username of the user").Required().StringVar(&cmd.username) registerForceFlag(clause, &cmd.force) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run invites the configured user to collaborate on the repo. @@ -78,7 +78,7 @@ func (cmd *RepoInviteCommand) Run() error { return nil } -func (cmd *RepoInviteCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RepoInviteCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/repo_ls.go b/internals/secrethub/repo_ls.go index dbfb9494..28cf0c23 100644 --- a/internals/secrethub/repo_ls.go +++ b/internals/secrethub/repo_ls.go @@ -39,7 +39,7 @@ func (cmd *RepoLSCommand) Register(r command.Registerer) { //clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) registerTimestampFlag(clause, &cmd.useTimestamps) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run lists the repositories a user has access to. @@ -48,7 +48,7 @@ func (cmd *RepoLSCommand) Run() error { return cmd.run() } -func (cmd *RepoLSCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RepoLSCommand) argumentRegister(c *cobra.Command, args []string) error { var err error if len(args) != 0 { err = api.ValidateNamespace(args[0]) diff --git a/internals/secrethub/repo_revoke.go b/internals/secrethub/repo_revoke.go index 6e11e992..039d694c 100644 --- a/internals/secrethub/repo_revoke.go +++ b/internals/secrethub/repo_revoke.go @@ -37,7 +37,7 @@ func (cmd *RepoRevokeCommand) Register(r command.Registerer) { //clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) registerForceFlag(clause, &cmd.force) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run removes and revokes access to an account from a repo if possible. @@ -128,7 +128,7 @@ func (cmd *RepoRevokeCommand) Run() error { return nil } -func (cmd *RepoRevokeCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RepoRevokeCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/repo_rm.go b/internals/secrethub/repo_rm.go index f59c5171..223c5af7 100644 --- a/internals/secrethub/repo_rm.go +++ b/internals/secrethub/repo_rm.go @@ -33,7 +33,7 @@ func (cmd *RepoRmCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo-path", "The repository to delete").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run removes the repository. @@ -79,7 +79,7 @@ func (cmd *RepoRmCommand) Run() error { return nil } -func (cmd *RepoRmCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RepoRmCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/rm.go b/internals/secrethub/rm.go index 040caaa4..948b3f57 100644 --- a/internals/secrethub/rm.go +++ b/internals/secrethub/rm.go @@ -45,7 +45,7 @@ func (cmd *RmCommand) Register(r command.Registerer) { clause.Flags().BoolVarP(&cmd.recursive, "recursive", "r", false, "Remove directories and their contents recursively.") registerForceFlag(clause, &cmd.force) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run removes the resource at the given path. @@ -96,7 +96,7 @@ func (cmd *RmCommand) Run() error { return rmSecret(client, secretPath, cmd.force, cmd.io) } -func (cmd *RmCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RmCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewPath(args[0]) if err != nil { diff --git a/internals/secrethub/run.go b/internals/secrethub/run.go index 303498b9..2f767acf 100644 --- a/internals/secrethub/run.go +++ b/internals/secrethub/run.go @@ -87,7 +87,7 @@ func (cmd *RunCommand) Register(r command.Registerer) { clause.Flags().DurationVar(&cmd.maskerOptions.BufferDelay, "masking-buffer-period", time.Millisecond*50, "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.") clause.Flags().BoolVar(&cmd.ignoreMissingSecrets, "ignore-missing-secrets", false, "Do not return an error when a secret does not exist and use an empty value instead.") cmd.environment.register(clause) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run reads files from the .secretsenv/ directory, sets them as environment variables and runs the given command. @@ -176,7 +176,7 @@ func (cmd *RunCommand) Run() error { return nil } -func (cmd *RunCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *RunCommand) argumentRegister(c *cobra.Command, args []string) error { copy(cmd.command, args) return nil } diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 5c83a38e..15a7b714 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -153,7 +153,7 @@ func (cmd *ServiceAWSInitCommand) Run() error { return nil } -func (cmd *ServiceAWSInitCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceAWSInitCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.repo, err = api.NewRepoPath(args[0]) if err != nil { @@ -187,7 +187,7 @@ func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { "If no system-wide default for the AWS region is provided (e.g. with $AWS_REGION), the AWS-region where the KMS key resides should be explicitly provided to this command with the --region flag.", ) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } func newKMSKeyOptionsGetter(cfg *aws.Config) kmsKeyOptionsGetter { diff --git a/internals/secrethub/service_deploy_winrm.go b/internals/secrethub/service_deploy_winrm.go index 7f30d871..620438d8 100644 --- a/internals/secrethub/service_deploy_winrm.go +++ b/internals/secrethub/service_deploy_winrm.go @@ -73,7 +73,7 @@ func (cmd *ServiceDeployWinRmCommand) Register(r command.Registerer) { clause.Flags().StringVar(&cmd.caCert, "ca-cert", "", "Path to CA certificate used to verify server TLS certificate.") clause.Flags().BoolVar(&cmd.noVerify, "insecure-no-verify-cert", false, "Do not verify server TLS certificate (insecure).") - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run creates a service and installs the configuration using WinRM. @@ -205,7 +205,7 @@ func (cmd *ServiceDeployWinRmCommand) Run() error { return nil } -func (cmd *ServiceDeployWinRmCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceDeployWinRmCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.resourceURI, err = url.Parse(args[0]) if err != nil { diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index b62b84f8..8736bf4e 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -155,7 +155,7 @@ func (cmd *ServiceGCPInitCommand) Run() error { return nil } -func (cmd *ServiceGCPInitCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceGCPInitCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.repo, err = api.NewRepoPath(args[0]) if err != nil { @@ -186,7 +186,7 @@ func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { "To create a new service that uses the GCP identity provider, the CLI must have encryption access to the KMS key that will be used by the service account. Therefore GCP application default credentials should be configured on this system. To achieve this, first install the Google Cloud SDK (https://cloud.google.com/sdk/docs/quickstarts) and then run `gcloud auth application-default login`.", ) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } type gcpProjectOptionLister struct { diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index b6b5453c..dda63b92 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -50,7 +50,7 @@ func (cmd *ServiceGCPLinkCommand) Run() error { return createGCPLink(client, cmd.io, cmd.namespace.String(), cmd.projectID.String()) } -func (cmd *ServiceGCPLinkCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceGCPLinkCommand) argumentRegister(c *cobra.Command, args []string) error { var err error err = api.ValidateOrgName(args[0]) if err != nil { @@ -85,7 +85,7 @@ func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { "Any reference to SecretHub should automatically disappear within a few minutes. " + "If it does not, the access can safely be revoked manually.") - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // ServiceGCPListLinksCommand lists all existing links between the given namespace and GCP projects @@ -136,7 +136,7 @@ func (cmd *ServiceGCPListLinksCommand) Run() error { return nil } -func (cmd *ServiceGCPListLinksCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceGCPListLinksCommand) argumentRegister(c *cobra.Command, args []string) error { err := api.ValidateNamespace(args[0]) if err != nil { return err @@ -151,7 +151,7 @@ func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { //clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().SetValue(&cmd.namespace) registerTimestampFlag(clause, &cmd.useTimestamps) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // ServiceGCPDeleteLinkCommand deletes the link between a SecretHub namespace and a GCP project. @@ -176,7 +176,7 @@ func (cmd *ServiceGCPDeleteLinkCommand) Register(r command.Registerer) { //clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().SetValue(&cmd.namespace) //clause.Arg("project-id", "The GCP project to delete the link to.").Required().SetValue(&cmd.projectID) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } func (cmd *ServiceGCPDeleteLinkCommand) Run() error { @@ -205,7 +205,7 @@ func (cmd *ServiceGCPDeleteLinkCommand) Run() error { return client.IDPLinks().GCP().Delete(cmd.namespace.String(), cmd.projectID.String()) } -func (cmd *ServiceGCPDeleteLinkCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceGCPDeleteLinkCommand) argumentRegister(c *cobra.Command, args []string) error { var err error err = api.ValidateNamespace(args[0]) if err != nil { diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index d3889be1..7b090ce5 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -122,7 +122,7 @@ func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.") clause.Flag("file-mode").DefValue = "0440" - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // givePermission gives the service permission on the repository as defined in the permission flag. @@ -159,7 +159,7 @@ func givePermission(service *api.Service, repo api.RepoPath, permissionFlagValue return nil } -func (cmd *ServiceInitCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceInitCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.repo, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/service_ls.go b/internals/secrethub/service_ls.go index 2e387e93..9c925315 100644 --- a/internals/secrethub/service_ls.go +++ b/internals/secrethub/service_ls.go @@ -68,7 +68,7 @@ func (cmd *ServiceLsCommand) Register(r command.Registerer) { clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print service IDs.") registerTimestampFlag(clause, &cmd.useTimestamps) - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run lists all service accounts in a given repository. @@ -118,7 +118,7 @@ outer: return nil } -func (cmd *ServiceLsCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *ServiceLsCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.repoPath, err = api.NewRepoPath(args[0]) if err != nil { diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 40c954db..fa537154 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -46,7 +46,7 @@ func (cmd *TreeCommand) Run() error { return nil } -func (cmd *TreeCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *TreeCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewDirPath(args[0]) if err != nil { @@ -68,7 +68,7 @@ func (cmd *TreeCommand) Register(r command.Registerer) { clause.Flag("noreport").Hidden = true - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // printTree recursively prints the tree's contents in a tree-like structure. diff --git a/internals/secrethub/write.go b/internals/secrethub/write.go index b23d4e62..baaf6d3a 100644 --- a/internals/secrethub/write.go +++ b/internals/secrethub/write.go @@ -50,7 +50,7 @@ func (cmd *WriteCommand) Register(r command.Registerer) { clause.Flags().BoolVarP(&cmd.multiline, "multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.") clause.Flags().StringVarP(&cmd.inFile, "in-file", "i", "", "Use the contents of this file as the value of the secret.") - command.BindAction(clause, cmd.PreRun, cmd.Run) + command.BindAction(clause, cmd.argumentRegister, cmd.Run) } // Run handles the command with the options as specified in the command. @@ -134,7 +134,7 @@ func (cmd *WriteCommand) Run() error { return nil } -func (cmd *WriteCommand) PreRun(c *cobra.Command, args []string) error { +func (cmd *WriteCommand) argumentRegister(c *cobra.Command, args []string) error { var err error cmd.path, err = api.NewSecretPath(args[0]) if err != nil { From 5d1cddf3f574cb69f0ce5d2c08b6f97aa2339b7c Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Thu, 13 Aug 2020 17:50:58 +0200 Subject: [PATCH 26/41] Add completion functionality into CLI --- internals/secrethub/app.go | 1 + internals/secrethub/argumentAutocompletion.go | 84 +++++++++++++++++++ internals/secrethub/completion.go | 49 +++++++++++ internals/secrethub/read.go | 1 + 4 files changed, 135 insertions(+) create mode 100644 internals/secrethub/argumentAutocompletion.go create mode 100644 internals/secrethub/completion.go diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index 9c80a5e0..904b5d25 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -188,6 +188,7 @@ func (app *App) registerCommands() { NewSetCommand(app.io, app.clientFactory.NewClient).Register(app.cli) NewClearClipboardCommand().Register(app.cli) NewKeyringClearCommand().Register(app.cli) + NewCompletionCommand().Register(app.cli) //demo.NewCommand(app.io, app.clientFactory.NewClient).Register(app.cli) } diff --git a/internals/secrethub/argumentAutocompletion.go b/internals/secrethub/argumentAutocompletion.go new file mode 100644 index 00000000..7a414e60 --- /dev/null +++ b/internals/secrethub/argumentAutocompletion.go @@ -0,0 +1,84 @@ +package secrethub + +import ( + "fmt" + "os" + "strings" + + "github.com/secrethub/secrethub-go/pkg/secrethub" + "github.com/secrethub/secrethub-go/pkg/secrethub/iterator" + "github.com/spf13/cobra" +) + +type AutoCompleter struct { + client *secrethub.Client +} + +// SecretSuggestions provides auto-completions for both arguments and flags +// that take as values paths to secrets SecretHub. +func (ac AutoCompleter) SecretSuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return getFullPaths(ac.client, toComplete, true), cobra.ShellCompDirectiveNoSpace +} + +// DirectorySuggestions provides auto-completions for both arguments and flags +// that take as values paths to directories in SecretHub. +func (ac AutoCompleter) DirectorySuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return getFullPaths(ac.client, toComplete, false), cobra.ShellCompDirectiveNoSpace +} + +func getNamespacesAndRepos(client *secrethub.Client) []string { + var suggestions []string + iter := client.Me().RepoIterator(&secrethub.RepoIteratorParams{}) + for { + repo, err := iter.Next() + if err == iterator.Done { + break + } else if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + return nil + } + suggestions = append(suggestions, string(repo.Path()+"/")) + } + return suggestions +} + +func getFullPaths(client *secrethub.Client, toComplete string, includeSecrets bool) []string { + if len(toComplete) == 0 { + return getNamespacesAndRepos(client) + } + tree, err := client.Dirs().GetTree(toComplete, 1, false) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + path := toComplete[0:strings.LastIndex(toComplete, "/")] + _, err = client.Dirs().GetTree(path, 1, false) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + return getNamespacesAndRepos(client) + } + return getFullPaths(client, path, includeSecrets) + } + if strings.LastIndex(toComplete, "/") != len(toComplete)-1 { + toComplete += "/" + } + suggestions := make([]string, tree.DirCount()+tree.SecretCount()) + + for _, dir := range tree.RootDir.SubDirs { + suggestions = append(suggestions, toComplete+dir.Name+"/") + } + + if includeSecrets { + for _, secret := range tree.RootDir.Secrets { + suggestions = append(suggestions, toComplete+secret.Name) + } + } + return suggestions +} + +// GetClient returns a new SecretHub client. +func GetClient() *secrethub.Client { + client, err := secrethub.NewClient() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + } + return client +} diff --git a/internals/secrethub/completion.go b/internals/secrethub/completion.go new file mode 100644 index 00000000..67ae237a --- /dev/null +++ b/internals/secrethub/completion.go @@ -0,0 +1,49 @@ +package secrethub + +import ( + "os" + + "github.com/secrethub/secrethub-cli/internals/cli" + "github.com/secrethub/secrethub-cli/internals/secrethub/command" + "github.com/spf13/cobra" +) + +type CompletionCommand struct { + shell string + clause *cli.CommandClause +} + +// NewCompletionCommand is a command that, when executed, generates a completion script +// for a specific shell, based on the argument it is provided with. It is able to generate +// completions for Bash, ZSh, Fish and PowerShell. +func NewCompletionCommand() *CompletionCommand { + return &CompletionCommand{} +} + +// Register registers the command, arguments and flags on the provided Registerer. +func (cmd *CompletionCommand) Register(r command.Registerer) { + cmd.clause = r.CreateCommand("completion", "Generate completion script").Hidden() + cmd.clause.DisableFlagsInUseLine = true + cmd.clause.ValidArgs = []string{"bash", "zsh", "fish", "powershell"} + cmd.clause.Args = cobra.ExactValidArgs(1) + command.BindAction(cmd.clause, cmd.argumentRegister, cmd.run) +} + +func (cmd *CompletionCommand) run() error { + switch cmd.shell { + case "bash": + _ = cmd.clause.Root().GenBashCompletion(os.Stdout) + case "zsh": + _ = cmd.clause.Root().GenZshCompletion(os.Stdout) + case "fish": + _ = cmd.clause.Root().GenFishCompletion(os.Stdout, true) + case "powershell": + _ = cmd.clause.Root().GenPowerShellCompletion(os.Stdout) + } + return nil +} + +func (cmd *CompletionCommand) argumentRegister(_ *cobra.Command, args []string) error { + cmd.shell = args[0] + return nil +} diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index d5c57f96..d544c28e 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -44,6 +44,7 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, fmt.Sprintf( From 3143890b96456d4484d933f7860a1ea578efb16a Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Thu, 13 Aug 2020 19:07:15 +0300 Subject: [PATCH 27/41] added one forgotten flag optionality --- internals/secrethub/app.go | 2 +- internals/secrethub/env_source.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index 9c80a5e0..f9782661 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -149,7 +149,7 @@ func (app *App) Run() error { return err } -// Model returns the CLI application model containing all the SecretHub CLI commands, flags, and args. +//Model returns the CLI application model containing all the SecretHub CLI commands, flags, and args. //func (app *App) Model() *kingpin.ApplicationModel { // return app.cli.Model() //} diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index 46d64752..ee5935ea 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -5,6 +5,7 @@ import ( "bytes" "errors" "fmt" + "github.com/spf13/cobra" "io" "io/ioutil" "os" @@ -67,6 +68,9 @@ func (env *environment) register(clause *cli.CommandClause) { clause.Flag("template").Hidden = true clause.Flags().VarP(&env.templateVars,"var","v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") clause.Flags().StringVar(&env.templateVersion, "template-version", "auto", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.") + _ = clause.RegisterFlagCompletionFunc("template-version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"v1", "v2", "latest", "auto"}, cobra.ShellCompDirectiveDefault + }) clause.Flags().BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") clause.Flags().StringVar(&env.secretsDir, "secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") clause.Flags().StringVar(&env.secretsEnvDir, "env", "default", "The name of the environment prepared by the set command (default is `default`)") From 0ef995ebe05d3d34823b026ab7b3e32e961e0913 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Fri, 14 Aug 2020 11:31:48 +0300 Subject: [PATCH 28/41] env.go --- internals/cli/env.go | 44 +++++++++++++++++++++ internals/demo/init.go | 2 +- internals/secrethub/account_init.go | 6 +-- internals/secrethub/acl_list.go | 4 +- internals/secrethub/audit.go | 6 +-- internals/secrethub/clear.go | 2 +- internals/secrethub/clear_clipboard.go | 2 +- internals/secrethub/env_source.go | 16 ++++---- internals/secrethub/generate.go | 10 ++--- internals/secrethub/init.go | 2 +- internals/secrethub/inject.go | 18 ++++----- internals/secrethub/list.go | 2 +- internals/secrethub/mkdir.go | 2 +- internals/secrethub/org_init.go | 8 ++-- internals/secrethub/org_invite.go | 2 +- internals/secrethub/org_ls.go | 2 +- internals/secrethub/printenv.go | 2 +- internals/secrethub/read.go | 8 ++-- internals/secrethub/repo_ls.go | 2 +- internals/secrethub/rm.go | 2 +- internals/secrethub/run.go | 8 ++-- internals/secrethub/service_aws_init.go | 14 +++---- internals/secrethub/service_deploy_winrm.go | 14 +++---- internals/secrethub/service_gcp_init.go | 12 +++--- internals/secrethub/service_init.go | 16 ++++---- internals/secrethub/service_ls.go | 2 +- internals/secrethub/set.go | 2 +- internals/secrethub/signup.go | 10 ++--- internals/secrethub/tree.go | 8 ++-- internals/secrethub/write.go | 6 +-- 30 files changed, 139 insertions(+), 95 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 0514695d..9a7ab01a 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -6,6 +6,7 @@ import ( "os" "strings" "text/tabwriter" + "time" "bitbucket.org/zombiezen/cardcpx/natsort" "github.com/spf13/cobra" @@ -176,6 +177,49 @@ type CommandClause struct { app *App } +func (cc *CommandClause) BoolVarP(reference *bool, name, shorthand string, def bool, usage string) { + cc.Flags().BoolVarP(reference, name, shorthand, def, usage) +} + +func (cc *CommandClause) IntVarP(reference *int, name, shorthand string, def int, usage string) { + cc.Flags().IntVarP(reference, name, shorthand, def, usage) +} + +func (cc *CommandClause) StringVarP(reference *string, name, shorthand string, def string, usage string) { + cc.Flags().StringVarP(reference, name, shorthand, def, usage) +} + +func (cc *CommandClause) DurationVarP(reference *time.Duration, name, shorthand string, def time.Duration, usage string) { + cc.Flags().DurationVarP(reference, name, shorthand, def, usage) +} + +func (cc *CommandClause) BoolVar(reference *bool, name string, def bool, usage string) { + cc.Flags().BoolVar(reference, name, def, usage) +} + +func (cc *CommandClause) IntVar(reference *int, name string, def int, usage string) { + cc.Flags().IntVar(reference, name, def, usage) +} + +func (cc *CommandClause) StringVar(reference *string, name string, def string, usage string) { + cc.Flags().StringVar(reference, name, def, usage) +} + +func (cc *CommandClause) DurationVar(reference *time.Duration, name string, def time.Duration, usage string) { + cc.Flags().DurationVar(reference, name, def, usage) +} + +func (cc *CommandClause) VarP(reference pflag.Value, name string, shorthand string, usage string) { + cc.Flags().VarP(reference, name, shorthand, usage) +} + +func (cc *CommandClause) Var(reference pflag.Value, name string, usage string) { + cc.Flags().Var(reference, name, usage) +} + +func (cc *CommandClause) VarPF(reference pflag.Value, name string,shorthand string, usage string) *pflag.Flag { + return cc.Flags().VarPF(reference, name, shorthand, usage) +} // Command adds a new subcommand to this command. func (cmd *CommandClause) CreateCommand(name, help string) *CommandClause { return &CommandClause{ diff --git a/internals/demo/init.go b/internals/demo/init.go index bc7c029b..179979f3 100644 --- a/internals/demo/init.go +++ b/internals/demo/init.go @@ -36,7 +36,7 @@ func (cmd *InitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create the secrets necessary to connect with the demo application.") clause.HelpLong("demo init creates a repository with the username and password needed to connect to the demo API.") - clause.Flags().VarPF(&cmd.repo, "repo", "", "The path of the repository to create. Defaults to a "+defaultDemoRepo+" repo in your personal namespace.") + clause.VarPF(&cmd.repo, "repo", "", "The path of the repository to create. Defaults to a "+defaultDemoRepo+" repo in your personal namespace.") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/account_init.go b/internals/secrethub/account_init.go index 68d49477..5a2e84a3 100644 --- a/internals/secrethub/account_init.go +++ b/internals/secrethub/account_init.go @@ -60,9 +60,9 @@ func NewAccountInitCommand(io ui.IO, newClient newClientFunc, credentialStore Cr // Register registers the command, arguments and flags on the provided Registerer. func (cmd *AccountInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Connect a first device to your SecretHub account.") - clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, "Copy the credential's public component to the clipboard instead of printing it to stdout.") - clause.Flags().BoolVar(&cmd.noWait, "no-wait", false, "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.") - clause.Flags().BoolVar(&cmd.isContinue, "continue", false, "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.") + clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, "Copy the credential's public component to the clipboard instead of printing it to stdout.") + clause.BoolVar(&cmd.noWait, "no-wait", false, "Do not hang waiting for the credential's public component to be added to the account and instead exit after outputting the credential's public component. To finish initializing the account, use the --continue flag after adding the credential to the account.") + clause.BoolVar(&cmd.isContinue, "continue", false, "Continue initializing the account. Use this when a credential has already been generated by a previous execution of the command.") registerForceFlag(clause, &cmd.force) command.BindAction(clause, nil, cmd.Run) diff --git a/internals/secrethub/acl_list.go b/internals/secrethub/acl_list.go index 32d72de1..15031f96 100644 --- a/internals/secrethub/acl_list.go +++ b/internals/secrethub/acl_list.go @@ -39,8 +39,8 @@ func (cmd *ACLListCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-path", "The path of the directory to list the access rules for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Flags().IntVarP(&cmd.depth, "depth", "d", -1, "The maximum depth to which the rules of child directories should be displayed. Defaults to -1 (no limit).") - clause.Flags().BoolVarP(&cmd.ancestors, "all", "a", false, "List all rules that apply on the directory, including rules on parent directories.") + clause.IntVarP(&cmd.depth, "depth", "d", -1, "The maximum depth to which the rules of child directories should be displayed. Defaults to -1 (no limit).") + clause.BoolVarP(&cmd.ancestors, "all", "a", false, "List all rules that apply on the directory, including rules on parent directories.") registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index 03fa9679..e35d7912 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -70,13 +70,13 @@ func (cmd *AuditCommand) Register(r command.Registerer) { clause := r.CreateCommand("audit", "Show the audit log.") clause.Args = cobra.MaximumNArgs(1) //clause.Arg("repo-path or secret-path", "Path to the repository or the secret to audit "+repoPathPlaceHolder+" or "+secretPathPlaceHolder).SetValue(&cmd.path) - clause.Flags().IntVar(&cmd.perPage, "per-page", 20, "Number of audit events shown per page") + clause.IntVar(&cmd.perPage, "per-page", 20, "Number of audit events shown per page") clause.Flag("per-page").Hidden = true - clause.Flags().StringVar(&cmd.format, "output-format", "table", "Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.") + clause.StringVar(&cmd.format, "output-format", "table", "Specify the format in which to output the log. Options are: table and json. If the output of the command is parsed by a script an alternative of the table format must be used.") _ = clause.RegisterFlagCompletionFunc("output-format", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"table", "json"}, cobra.ShellCompDirectiveDefault }) - clause.Flags().IntVar(&cmd.maxResults, "max-results", defaultLimit, "Specify the number of entries to list. If maxResults < 0 all entries are displayed. If the output of the command is piped, maxResults defaults to 1000.") + clause.IntVar(&cmd.maxResults, "max-results", defaultLimit, "Specify the number of entries to list. If maxResults < 0 all entries are displayed. If the output of the command is piped, maxResults defaults to 1000.") registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/clear.go b/internals/secrethub/clear.go index b5b7707e..969e6268 100644 --- a/internals/secrethub/clear.go +++ b/internals/secrethub/clear.go @@ -26,7 +26,7 @@ func NewClearCommand(io ui.IO) *ClearCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *ClearCommand) Register(r command.Registerer) { clause := r.CreateCommand("clear", "Clear the secrets from your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() - clause.Flags().StringVarP(&cmd.in, "in", "i", "secrets.yml", "The path to a secrets.yml file to read") + clause.StringVarP(&cmd.in, "in", "i", "secrets.yml", "The path to a secrets.yml file to read") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/clear_clipboard.go b/internals/secrethub/clear_clipboard.go index aaf8226d..5bf07902 100644 --- a/internals/secrethub/clear_clipboard.go +++ b/internals/secrethub/clear_clipboard.go @@ -34,7 +34,7 @@ func (cmd *ClearClipboardCommand) Register(r command.Registerer) { clause := r.CreateCommand("clipboard-clear", "Removes secret from clipboard.").Hidden() clause.Args = cobra.ExactValidArgs(1) //clause.Arg("hash", "Hash from the secret to be cleared").Required().HexBytesVar(&cmd.hash) - clause.Flags().DurationVar(&cmd.timeout, "timeout", 0, "Time to wait before clearing in seconds") + clause.DurationVar(&cmd.timeout, "timeout", 0, "Time to wait before clearing in seconds") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/env_source.go b/internals/secrethub/env_source.go index ee5935ea..1b936187 100644 --- a/internals/secrethub/env_source.go +++ b/internals/secrethub/env_source.go @@ -62,18 +62,18 @@ func newEnvironment(io ui.IO, newClient newClientFunc) *environment { } func (env *environment) register(clause *cli.CommandClause) { - clause.Flags().VarP(&env.envar,"envar", "e","Source an environment variable from a secret at a given path with `NAME=`") - clause.Flags().StringVar(&env.envFile, "env-file", "", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.") - clause.Flags().StringVar(&env.envFile, "template", "", "") + clause.VarP(&env.envar,"envar", "e","Source an environment variable from a secret at a given path with `NAME=`") + clause.StringVar(&env.envFile, "env-file", "", "The path to a file with environment variable mappings of the form `NAME=value`. Template syntax can be used to inject secrets.") + clause.StringVar(&env.envFile, "template", "", "") clause.Flag("template").Hidden = true - clause.Flags().VarP(&env.templateVars,"var","v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") - clause.Flags().StringVar(&env.templateVersion, "template-version", "auto", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.") + clause.VarP(&env.templateVars,"var","v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") + clause.StringVar(&env.templateVersion, "template-version", "auto", "The template syntax version to be used. The options are v1, v2, latest or auto to automatically detect the version.") _ = clause.RegisterFlagCompletionFunc("template-version", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"v1", "v2", "latest", "auto"}, cobra.ShellCompDirectiveDefault }) - clause.Flags().BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") - clause.Flags().StringVar(&env.secretsDir, "secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") - clause.Flags().StringVar(&env.secretsEnvDir, "env", "default", "The name of the environment prepared by the set command (default is `default`)") + clause.BoolVar(&env.dontPromptMissingTemplateVar, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") + clause.StringVar(&env.secretsDir, "secrets-dir", "", "Recursively include all secrets from a directory. Environment variable names are derived from the path of the secret: `/` are replaced with `_` and the name is uppercased.") + clause.StringVar(&env.secretsEnvDir, "env", "default", "The name of the environment prepared by the set command (default is `default`)") clause.Flag("env").Hidden = true } diff --git a/internals/secrethub/generate.go b/internals/secrethub/generate.go index 02f7fa55..e094cd8e 100644 --- a/internals/secrethub/generate.go +++ b/internals/secrethub/generate.go @@ -65,16 +65,16 @@ func (cmd *GenerateSecretCommand) Register(r command.Registerer) { clause := r.CreateCommand("generate", "Generate a random secret.") clause.Args = cobra.RangeArgs(1, 3) //clause.Arg("secret-path", "The path to write the generated secret to").Required().PlaceHolder(secretPathPlaceHolder).StringVar(&cmd.firstArg) - clause.Flags().VarP(&cmd.lengthFlag, "length", "l", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)) //.PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) + clause.VarP(&cmd.lengthFlag, "length", "l", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength)) //.PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) clause.Flag("length").DefValue = strconv.Itoa(defaultLength) - clause.Flags().Var(&cmd.mins, "min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.") - clause.Flags().BoolVarP(&cmd.copyToClipboard, "clip", "c", false, "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".") - clause.Flags().Var(&cmd.charsetFlag, "charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.") //Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable") + clause.Var(&cmd.mins, "min", ": Ensure that the resulting password contains at least n characters from the given character set. Note that adding constraints reduces the strength of the secret. When possible, avoid any constraints.") + clause.BoolVarP(&cmd.copyToClipboard, "clip", "c", false, "Copy the generated value to the clipboard. The clipboard is automatically cleared after "+units.HumanDuration(cmd.clearClipboardAfter)+".") + clause.Var(&cmd.charsetFlag, "charset", "Define the set of characters to randomly generate a password from. Options are all, alphanumeric, numeric, lowercase, uppercase, letters, symbols and human-readable. Multiple character sets can be combined by supplying them in a comma separated list. Defaults to alphanumeric.") //Default("alphanumeric").HintOptions("all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable") clause.Flag("charset").DefValue = "alphanumeric" _ = clause.RegisterFlagCompletionFunc("charset", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"all", "alphanumeric", "numeric", "lowercase", "uppercase", "letters", "symbols", "human-readable"}, cobra.ShellCompDirectiveDefault }) - clause.Flags().VarP(&cmd.symbolsFlag, "symbols", "s", "Include symbols in secret.") //Short('s').Hidden().SetValue(&cmd.symbolsFlag) + clause.VarP(&cmd.symbolsFlag, "symbols", "s", "Include symbols in secret.") //Short('s').Hidden().SetValue(&cmd.symbolsFlag) clause.Flag("symbols").Hidden = true //clause.Arg("rand-command", "").Hidden().StringVar(&cmd.secondArg) //clause.Arg("length", "").Hidden().SetValue(&cmd.lengthArg) diff --git a/internals/secrethub/init.go b/internals/secrethub/init.go index 1b6e3710..d4725704 100644 --- a/internals/secrethub/init.go +++ b/internals/secrethub/init.go @@ -39,7 +39,7 @@ func NewInitCommand(io ui.IO, newClient newClientFunc, newClientWithoutCredentia // Register registers the command, arguments and flags on the provided Registerer. func (cmd *InitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize the SecretHub client for first use on this device.") - clause.Flags().StringVar(&cmd.backupCode, "backup-code", "", "The backup code used to restore an existing account to this device.") + clause.StringVar(&cmd.backupCode, "backup-code", "", "The backup code used to restore an existing account to this device.") registerForceFlag(clause, &cmd.force) command.BindAction(clause, nil, cmd.Run) diff --git a/internals/secrethub/inject.go b/internals/secrethub/inject.go index db2e2f38..c9aeca69 100644 --- a/internals/secrethub/inject.go +++ b/internals/secrethub/inject.go @@ -57,22 +57,22 @@ func NewInjectCommand(io ui.IO, newClient newClientFunc) *InjectCommand { // Register adds args and flags. func (cmd *InjectCommand) Register(r command.Registerer) { clause := r.CreateCommand("inject", "Inject secrets into a template.") - clause.Flags().BoolVarP(&cmd.useClipboard, + clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, fmt.Sprintf( "Copy the injected template to the clipboard instead of stdout. The clipboard is automatically cleared after %s.", units.HumanDuration(cmd.clearClipboardAfter), )) - clause.Flags().StringVarP(&cmd.inFile, "in-file", "i", "", "The filename of a template file to inject.") - clause.Flags().StringVarP(&cmd.outFile, "out-file", "o", "", "Write the injected template to a file instead of stdout.") - clause.Flags().StringVar(&cmd.outFile, "file", "", "") // Alias of --out-file (for backwards compatibility) + clause.StringVarP(&cmd.inFile, "in-file", "i", "", "The filename of a template file to inject.") + clause.StringVarP(&cmd.outFile, "out-file", "o", "", "Write the injected template to a file instead of stdout.") + clause.StringVar(&cmd.outFile, "file", "", "") // Alias of --out-file (for backwards compatibility) clause.Flag("file").Hidden = true - clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") + clause.Var(&cmd.fileMode, "file-mode", "Set filemode for the output file if it does not yet exist. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") clause.Flag("file-mode").DefValue = "0600" - clause.Flags().VarP(&cmd.templateVars,"var", "v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") - clause.Flags().StringVar(&cmd.templateVersion, "template-version", "auto", "Do not prompt when a template variable is missing and return an error instead.") - clause.Flags().BoolVar(&cmd.dontPromptMissingTemplateVars, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") - clause.Flags().BoolVarP(&cmd.force, "force", "f", false, "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.") + clause.VarP(&cmd.templateVars,"var", "v", "Define the value for a template variable with `VAR=VALUE`, e.g. --var env=prod") + clause.StringVar(&cmd.templateVersion, "template-version", "auto", "Do not prompt when a template variable is missing and return an error instead.") + clause.BoolVar(&cmd.dontPromptMissingTemplateVars, "no-prompt", false, "Do not prompt when a template variable is missing and return an error instead.") + clause.BoolVarP(&cmd.force, "force", "f", false, "Overwrite the output file if it already exists, without prompting for confirmation. This flag is ignored if no --out-file is supplied.") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/list.go b/internals/secrethub/list.go index b21e4358..47032408 100644 --- a/internals/secrethub/list.go +++ b/internals/secrethub/list.go @@ -37,7 +37,7 @@ func (cmd *LsCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) //clause.Arg("path", "The path to list contents of").SetValue(&cmd.path) - clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.") + clause.BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.") registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/mkdir.go b/internals/secrethub/mkdir.go index f5ea731e..e9c99361 100644 --- a/internals/secrethub/mkdir.go +++ b/internals/secrethub/mkdir.go @@ -39,7 +39,7 @@ func (cmd *MkDirCommand) Register(r command.Registerer) { clause := r.CreateCommand("mkdir", "Create a new directory.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-paths", "The paths to the directories").Required().PlaceHolder(dirPathsPlaceHolder).SetValue(&cmd.paths) - clause.Flags().BoolVar(&cmd.parents, "parents", false, "Create parent directories if needed. Does not error when directories already exist.") + clause.BoolVar(&cmd.parents, "parents", false, "Create parent directories if needed. Does not error when directories already exist.") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index 83865e34..bcd97717 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -29,11 +29,11 @@ func NewOrgInitCommand(io ui.IO, newClient newClientFunc) *OrgInitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize a new organization account.") - clause.Flags().Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") - clause.Flags().StringVar(&cmd.description, "description", "", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.") - clause.Flags().StringVar(&cmd.description, "descr", "", "") + clause.Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.") + clause.StringVar(&cmd.description, "description", "", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.") + clause.StringVar(&cmd.description, "descr", "", "") clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.description, "desc", "", "") + clause.StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index f3f668f8..887e751a 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -35,7 +35,7 @@ func (cmd *OrgInviteCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(2) //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) - clause.Flags().StringVar(&cmd.role, "role", "member", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.") + clause.StringVar(&cmd.role, "role", "member", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.") registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/org_ls.go b/internals/secrethub/org_ls.go index 41bf3294..3d3e3d0e 100644 --- a/internals/secrethub/org_ls.go +++ b/internals/secrethub/org_ls.go @@ -32,7 +32,7 @@ func NewOrgLsCommand(io ui.IO, newClient newClientFunc) *OrgLsCommand { func (cmd *OrgLsCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all organizations you are a member of.") clause.Alias("list") - clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print organization names.") + clause.BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print organization names.") registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/printenv.go b/internals/secrethub/printenv.go index fdbf929c..b6e7297a 100644 --- a/internals/secrethub/printenv.go +++ b/internals/secrethub/printenv.go @@ -37,7 +37,7 @@ func (cmd *PrintEnvCommand) Run() error { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *PrintEnvCommand) Register(r command.Registerer) { clause := r.CreateCommand("printenv", "Print environment variables.") - clause.Flags().BoolVarP(&cmd.verbose, "verbose", "v", false, "Show all possible environment variables.") + clause.BoolVarP(&cmd.verbose, "verbose", "v", false, "Show all possible environment variables.") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index d5c57f96..7279456b 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -44,17 +44,17 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") clause.Args = cobra.ExactValidArgs(1) - clause.Flags().BoolVarP(&cmd.useClipboard, + clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, fmt.Sprintf( "Copy the secret value to the clipboard. The clipboard is automatically cleared after %s.", units.HumanDuration(cmd.clearClipboardAfter), ), ) - clause.Flags().StringVarP(&cmd.outFile, "out-file", "o", "", "Write the secret value to this file.") - clause.Flags().BoolVarP(&cmd.noNewLine, "no-newline", "n", false, "Do not print a new line after the secret") + clause.StringVarP(&cmd.outFile, "out-file", "o", "", "Write the secret value to this file.") + clause.BoolVarP(&cmd.noNewLine, "no-newline", "n", false, "Do not print a new line after the secret") - fileModeFlag := clause.Flags().VarPF(&cmd.fileMode, "file-mode", "", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") + fileModeFlag := clause.VarPF(&cmd.fileMode, "file-mode", "", "Set filemode for the output file. Defaults to 0600 (read and write for current user) and is ignored without the --out-file flag.") fileModeFlag.DefValue = "0600" command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/repo_ls.go b/internals/secrethub/repo_ls.go index dbfb9494..f2388b4b 100644 --- a/internals/secrethub/repo_ls.go +++ b/internals/secrethub/repo_ls.go @@ -35,7 +35,7 @@ func (cmd *RepoLSCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all repositories you have access to.") clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) - clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.") + clause.BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.") //clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/rm.go b/internals/secrethub/rm.go index 040caaa4..5fd533a6 100644 --- a/internals/secrethub/rm.go +++ b/internals/secrethub/rm.go @@ -42,7 +42,7 @@ func (cmd *RmCommand) Register(r command.Registerer) { clause.Alias("remove") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("path", "The path to the resource to remove (/[/])").Required().SetValue(&cmd.path) - clause.Flags().BoolVarP(&cmd.recursive, "recursive", "r", false, "Remove directories and their contents recursively.") + clause.BoolVarP(&cmd.recursive, "recursive", "r", false, "Remove directories and their contents recursively.") registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/run.go b/internals/secrethub/run.go index 303498b9..c2343073 100644 --- a/internals/secrethub/run.go +++ b/internals/secrethub/run.go @@ -82,10 +82,10 @@ func (cmd *RunCommand) Register(r command.Registerer) { clause.Alias("exec") clause.Args = cobra.MinimumNArgs(1) //clause.Arg("command", "The command to execute").Required().StringsVar(&cmd.command) - clause.Flags().BoolVar(&cmd.noMasking, "no-masking", false, "Disable masking of secrets on stdout and stderr") - clause.Flags().BoolVar(&cmd.maskerOptions.DisableBuffer, "no-output-buffering", false, "Disable output buffering. This increases output responsiveness, but decreases the probability that secrets get masked.") - clause.Flags().DurationVar(&cmd.maskerOptions.BufferDelay, "masking-buffer-period", time.Millisecond*50, "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.") - clause.Flags().BoolVar(&cmd.ignoreMissingSecrets, "ignore-missing-secrets", false, "Do not return an error when a secret does not exist and use an empty value instead.") + clause.BoolVar(&cmd.noMasking, "no-masking", false, "Disable masking of secrets on stdout and stderr") + clause.BoolVar(&cmd.maskerOptions.DisableBuffer, "no-output-buffering", false, "Disable output buffering. This increases output responsiveness, but decreases the probability that secrets get masked.") + clause.DurationVar(&cmd.maskerOptions.BufferDelay, "masking-buffer-period", time.Millisecond*50, "The time period for which output is buffered. A higher value increases the probability that secrets get masked but decreases output responsiveness.") + clause.BoolVar(&cmd.ignoreMissingSecrets, "ignore-missing-secrets", false, "Do not return an error when a secret does not exist and use an empty value instead.") cmd.environment.register(clause) command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 5c83a38e..e34b731f 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -167,15 +167,15 @@ func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to an AWS IAM role.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flags().StringVar(&cmd.kmsKeyID, "kms-key", "", "The ID or ARN of the KMS-key to be used for encrypting the service's account key.") - clause.Flags().StringVar(&cmd.role, "role", "", "The role name or ARN of the IAM role that should have access to this service account.") - clause.Flags().StringVar(&cmd.region, "region", "", "The AWS region that should be used for KMS.") - clause.Flags().StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") - clause.Flags().StringVar(&cmd.description, "descr", "", "") - clause.Flags().StringVar(&cmd.description, "desc", "", "") + clause.StringVar(&cmd.kmsKeyID, "kms-key", "", "The ID or ARN of the KMS-key to be used for encrypting the service's account key.") + clause.StringVar(&cmd.role, "role", "", "The role name or ARN of the IAM role that should have access to this service account.") + clause.StringVar(&cmd.region, "region", "", "The AWS region that should be used for KMS.") + clause.StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") + clause.StringVar(&cmd.description, "descr", "", "") + clause.StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") + clause.StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") clause.HelpLong("The native AWS identity provider uses a combination of AWS IAM and AWS KMS to provide access to SecretHub for any service running on AWS (e.g. EC2, Lambda or ECS). For this to work, an IAM role and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_deploy_winrm.go b/internals/secrethub/service_deploy_winrm.go index 7f30d871..5a6998d3 100644 --- a/internals/secrethub/service_deploy_winrm.go +++ b/internals/secrethub/service_deploy_winrm.go @@ -62,16 +62,16 @@ func (cmd *ServiceDeployWinRmCommand) Register(r command.Registerer) { clause := r.CreateCommand("winrm", "Read a service account configuration from stdin and deploy it to a running instance with WinRM. The instance needs to be reachable, have WinRM enabled, and have PowerShell installed.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("resource-uri", "Hostname, optional connection protocol and port of the host ([http[s]://][:]). This defaults to https and port 5986.").Required().URLVar(&cmd.resourceURI) - clause.Flags().StringVar(&cmd.authType, "auth-type", "basic", "Authentication type (basic/cert)") + clause.StringVar(&cmd.authType, "auth-type", "basic", "Authentication type (basic/cert)") _ = clause.RegisterFlagCompletionFunc("auth-type", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return []string{"basic", "cert"}, cobra.ShellCompDirectiveDefault }) - clause.Flags().StringVar(&cmd.username, "username", "", "The username used for logging in when authentication type is basic. Is asked if not supplied.") - clause.Flags().StringVar(&cmd.password, "password", "", "The password used for logging in when authentication type is basic. Is asked if not supplied.") - clause.Flags().StringVar(&cmd.clientCert, "client-cert", "", "Path to client certificate used for certificate authentication.") - clause.Flags().StringVar(&cmd.clientKey, "client-key", "", "Path to client key used for certificate authentication.") - clause.Flags().StringVar(&cmd.caCert, "ca-cert", "", "Path to CA certificate used to verify server TLS certificate.") - clause.Flags().BoolVar(&cmd.noVerify, "insecure-no-verify-cert", false, "Do not verify server TLS certificate (insecure).") + clause.StringVar(&cmd.username, "username", "", "The username used for logging in when authentication type is basic. Is asked if not supplied.") + clause.StringVar(&cmd.password, "password", "", "The password used for logging in when authentication type is basic. Is asked if not supplied.") + clause.StringVar(&cmd.clientCert, "client-cert", "", "Path to client certificate used for certificate authentication.") + clause.StringVar(&cmd.clientKey, "client-key", "", "Path to client key used for certificate authentication.") + clause.StringVar(&cmd.caCert, "ca-cert", "", "Path to CA certificate used to verify server TLS certificate.") + clause.BoolVar(&cmd.noVerify, "insecure-no-verify-cert", false, "Do not verify server TLS certificate (insecure).") command.BindAction(clause, cmd.PreRun, cmd.Run) } diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index b62b84f8..f11f42b7 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -169,14 +169,14 @@ func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to a GCP Service Account.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flags().StringVar(&cmd.kmsKeyResourceID, "kms-key", "", "The Resource ID of the KMS-key to be used for encrypting the service's account key.") - clause.Flags().StringVar(&cmd.serviceAccountEmail, "service-account-email", "", "The email of the GCP Service Account that should have access to this service account.") - clause.Flags().StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") - clause.Flags().StringVar(&cmd.description, "descr", "", "") - clause.Flags().StringVar(&cmd.description, "desc", "", "") + clause.StringVar(&cmd.kmsKeyResourceID, "kms-key", "", "The Resource ID of the KMS-key to be used for encrypting the service's account key.") + clause.StringVar(&cmd.serviceAccountEmail, "service-account-email", "", "The email of the GCP Service Account that should have access to this service account.") + clause.StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it. Defaults to the name of the role that is attached to the service.") + clause.StringVar(&cmd.description, "descr", "", "") + clause.StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") + clause.StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") clause.HelpLong("The native GCP identity provider uses a combination of GCP IAM and GCP KMS to provide access to SecretHub for any service running on GCP. For this to work, a GCP Service Account and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index d3889be1..7265718a 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -108,18 +108,18 @@ func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) - clause.Flags().StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it.") - clause.Flags().StringVar(&cmd.description, "descr", "", "") - clause.Flags().StringVar(&cmd.description, "desc", "", "") + clause.StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it.") + clause.StringVar(&cmd.description, "descr", "", "") + clause.StringVar(&cmd.description, "desc", "", "") clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true - clause.Flags().StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") + clause.StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.") // TODO make 45 sec configurable - clause.Flags().BoolVarP(&cmd.clip, "clip", "c", false, "Write the service account configuration to the clipboard instead of stdout. The clipboard is automatically cleared after 45 seconds.") - clause.Flags().StringVar(&cmd.file, "file", "", "Write the service account configuration to a file instead of stdout.") + clause.BoolVarP(&cmd.clip, "clip", "c", false, "Write the service account configuration to the clipboard instead of stdout. The clipboard is automatically cleared after 45 seconds.") + clause.StringVar(&cmd.file, "file", "", "Write the service account configuration to a file instead of stdout.") clause.Flag("file").Hidden = true - clause.Flags().StringVar(&cmd.file, "out-file", "", "Write the service account configuration to a file instead of stdout.") - clause.Flags().Var(&cmd.fileMode, "file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.") + clause.StringVar(&cmd.file, "out-file", "", "Write the service account configuration to a file instead of stdout.") + clause.Var(&cmd.fileMode, "file-mode", "Set filemode for the written file. Defaults to 0440 (read only) and is ignored without the --file flag.") clause.Flag("file-mode").DefValue = "0440" command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/service_ls.go b/internals/secrethub/service_ls.go index 2e387e93..968f5d8e 100644 --- a/internals/secrethub/service_ls.go +++ b/internals/secrethub/service_ls.go @@ -65,7 +65,7 @@ func (cmd *ServiceLsCommand) Register(r command.Registerer) { clause.Alias("list") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("repo-path", "The path to the repository to list services for").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repoPath) - clause.Flags().BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print service IDs.") + clause.BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print service IDs.") registerTimestampFlag(clause, &cmd.useTimestamps) command.BindAction(clause, cmd.PreRun, cmd.Run) diff --git a/internals/secrethub/set.go b/internals/secrethub/set.go index 78c4b347..31549a57 100644 --- a/internals/secrethub/set.go +++ b/internals/secrethub/set.go @@ -38,7 +38,7 @@ func NewSetCommand(io ui.IO, newClient newClientFunc) *SetCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SetCommand) Register(r command.Registerer) { clause := r.CreateCommand("set", "Set the secrets in your local environment. This reads and parses the secrets.yml file in the current working directory.").Hidden() - clause.Flags().StringVarP(&cmd.in, "in", "i", "secrets.yml", "The path to a secrets.yml file to read") + clause.StringVarP(&cmd.in, "in", "i", "secrets.yml", "The path to a secrets.yml file to read") command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/signup.go b/internals/secrethub/signup.go index e1a8bbf8..45c04bde 100644 --- a/internals/secrethub/signup.go +++ b/internals/secrethub/signup.go @@ -45,11 +45,11 @@ func NewSignUpCommand(io ui.IO, newClient newClientFunc, credentialStore Credent // Register registers the command, arguments and flags on the provided Registerer. func (cmd *SignUpCommand) Register(r command.Registerer) { clause := r.CreateCommand("signup", "Create a free personal developer account.") - clause.Flags().StringVar(&cmd.username, "username", "", "The username you would like to use on SecretHub.") - clause.Flags().StringVar(&cmd.fullName, "full-name", "", "Your full name.") - clause.Flags().StringVar(&cmd.email, "email", "", "Your (work) email address we will use for all correspondence.") - clause.Flags().StringVar(&cmd.org, "org", "", "The name of your organization.") - clause.Flags().StringVar(&cmd.orgDescription, "org-description", "", "A description (max 144 chars) for your organization so others will recognize it.") + clause.StringVar(&cmd.username, "username", "", "The username you would like to use on SecretHub.") + clause.StringVar(&cmd.fullName, "full-name", "", "Your full name.") + clause.StringVar(&cmd.email, "email", "", "Your (work) email address we will use for all correspondence.") + clause.StringVar(&cmd.org, "org", "", "The name of your organization.") + clause.StringVar(&cmd.orgDescription, "org-description", "", "A description (max 144 chars) for your organization so others will recognize it.") registerForceFlag(clause, &cmd.force) command.BindAction(clause, nil, cmd.Run) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index 40c954db..da22973a 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -61,10 +61,10 @@ func (cmd *TreeCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) //clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) - clause.Flags().BoolVarP(&cmd.fullPaths, "full-paths", "f", false, "Print the full path of each directory and secret.") - clause.Flags().BoolVarP(&cmd.noIndentation, "no-indentation", "n", false, "Do not use the standard indentation.") - clause.Flags().BoolVar(&cmd.noReport, "no-report", false, "Turn off secret/directory count at end of tree listing.") - clause.Flags().BoolVar(&cmd.noReport, "noreport", false, "Turn off secret/directory count at end of tree listing.") + clause.BoolVarP(&cmd.fullPaths, "full-paths", "f", false, "Print the full path of each directory and secret.") + clause.BoolVarP(&cmd.noIndentation, "no-indentation", "n", false, "Do not use the standard indentation.") + clause.BoolVar(&cmd.noReport, "no-report", false, "Turn off secret/directory count at end of tree listing.") + clause.BoolVar(&cmd.noReport, "noreport", false, "Turn off secret/directory count at end of tree listing.") clause.Flag("noreport").Hidden = true diff --git a/internals/secrethub/write.go b/internals/secrethub/write.go index b23d4e62..e9893830 100644 --- a/internals/secrethub/write.go +++ b/internals/secrethub/write.go @@ -46,9 +46,9 @@ func (cmd *WriteCommand) Register(r command.Registerer) { clause := r.CreateCommand("write", "Write a secret.") clause.Args = cobra.ExactValidArgs(1) //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathPlaceHolder).SetValue(&cmd.path) - clause.Flags().BoolVarP(&cmd.useClipboard, "clip", "c", false, "Use clipboard content as input.") - clause.Flags().BoolVarP(&cmd.multiline, "multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.") - clause.Flags().StringVarP(&cmd.inFile, "in-file", "i", "", "Use the contents of this file as the value of the secret.") + clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, "Use clipboard content as input.") + clause.BoolVarP(&cmd.multiline, "multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.") + clause.StringVarP(&cmd.inFile, "in-file", "i", "", "Use the contents of this file as the value of the secret.") command.BindAction(clause, cmd.PreRun, cmd.Run) } From 0c120145e86d7e6ee6e4909438b37636656ff79c Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Fri, 14 Aug 2020 11:44:32 +0300 Subject: [PATCH 29/41] wrapper for cobra --- internals/secrethub/client_factory.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index d0b74c02..1d1d1964 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/secrethub/secrethub-cli/internals/cli" "net/http" "net/url" "strings" @@ -43,9 +44,13 @@ type clientFactory struct { // Register the flags for configuration on a cli application. func (f *clientFactory) Register(r *cobra.Command) { - r.PersistentFlags().VarPF(&f.ServerURL, "api-remote", "", "The SecretHub API address, don't set this unless you know what you're doing.") - r.PersistentFlags().StringVar(&f.identityProvider, "identity-provider", "key", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ") - r.PersistentFlags().VarPF(&f.proxyAddress, "proxy-address", "", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`") + commandClause := cli.CommandClause{ + Command: r, + } + //TODO persistent!!! + commandClause.VarPF(&f.ServerURL, "api-remote", "", "The SecretHub API address, don't set this unless you know what you're doing.") + commandClause.StringVar(&f.identityProvider, "identity-provider", "key", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ") + commandClause.VarPF(&f.proxyAddress, "proxy-address", "", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`") } // NewClient returns a new client that is configured to use the remote that From 64d5d222b060edb2627bddd8720437f0f26b611c Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Fri, 14 Aug 2020 10:49:57 +0200 Subject: [PATCH 30/41] Remove all persistentFlag calls --- internals/cli/env.go | 44 ++++++++++++------------- internals/secrethub/color.go | 6 +++- internals/secrethub/credential_store.go | 16 +++++---- internals/secrethub/debug.go | 5 ++- internals/secrethub/mlock.go | 6 +++- 5 files changed, 46 insertions(+), 31 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 9a7ab01a..2344086c 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -177,48 +177,48 @@ type CommandClause struct { app *App } -func (cc *CommandClause) BoolVarP(reference *bool, name, shorthand string, def bool, usage string) { - cc.Flags().BoolVarP(reference, name, shorthand, def, usage) +func (cmd *CommandClause) BoolVarP(reference *bool, name, shorthand string, def bool, usage string, hasEnv bool, persistent bool) { + cmd.Flags().BoolVarP(reference, name, shorthand, def, usage) } -func (cc *CommandClause) IntVarP(reference *int, name, shorthand string, def int, usage string) { - cc.Flags().IntVarP(reference, name, shorthand, def, usage) +func (cmd *CommandClause) IntVarP(reference *int, name, shorthand string, def int, usage string, hasEnv bool, persistent bool) { + cmd.Flags().IntVarP(reference, name, shorthand, def, usage) } -func (cc *CommandClause) StringVarP(reference *string, name, shorthand string, def string, usage string) { - cc.Flags().StringVarP(reference, name, shorthand, def, usage) +func (cmd *CommandClause) StringVarP(reference *string, name, shorthand string, def string, usage string, hasEnv bool, persistent bool) { + cmd.Flags().StringVarP(reference, name, shorthand, def, usage) } -func (cc *CommandClause) DurationVarP(reference *time.Duration, name, shorthand string, def time.Duration, usage string) { - cc.Flags().DurationVarP(reference, name, shorthand, def, usage) +func (cmd *CommandClause) DurationVarP(reference *time.Duration, name, shorthand string, def time.Duration, usage string, hasEnv bool, persistent bool) { + cmd.Flags().DurationVarP(reference, name, shorthand, def, usage) } -func (cc *CommandClause) BoolVar(reference *bool, name string, def bool, usage string) { - cc.Flags().BoolVar(reference, name, def, usage) +func (cmd *CommandClause) BoolVar(reference *bool, name string, def bool, usage string, hasEnv bool, persistent bool) { + cmd.Flags().BoolVar(reference, name, def, usage) } -func (cc *CommandClause) IntVar(reference *int, name string, def int, usage string) { - cc.Flags().IntVar(reference, name, def, usage) +func (cmd *CommandClause) IntVar(reference *int, name string, def int, usage string, hasEnv bool, persistent bool) { + cmd.Flags().IntVar(reference, name, def, usage) } -func (cc *CommandClause) StringVar(reference *string, name string, def string, usage string) { - cc.Flags().StringVar(reference, name, def, usage) +func (cmd *CommandClause) StringVar(reference *string, name string, def string, usage string, hasEnv bool, persistent bool) { + cmd.Flags().StringVar(reference, name, def, usage) } -func (cc *CommandClause) DurationVar(reference *time.Duration, name string, def time.Duration, usage string) { - cc.Flags().DurationVar(reference, name, def, usage) +func (cmd *CommandClause) DurationVar(reference *time.Duration, name string, def time.Duration, usage string, hasEnv bool, persistent bool) { + cmd.Flags().DurationVar(reference, name, def, usage) } -func (cc *CommandClause) VarP(reference pflag.Value, name string, shorthand string, usage string) { - cc.Flags().VarP(reference, name, shorthand, usage) +func (cmd *CommandClause) VarP(reference pflag.Value, name string, shorthand string, usage string, hasEnv bool, persistent bool) { + cmd.Flags().VarP(reference, name, shorthand, usage) } -func (cc *CommandClause) Var(reference pflag.Value, name string, usage string) { - cc.Flags().Var(reference, name, usage) +func (cmd *CommandClause) Var(reference pflag.Value, name string, usage string, hasEnv bool, persistent bool) { + cmd.Flags().Var(reference, name, usage) } -func (cc *CommandClause) VarPF(reference pflag.Value, name string,shorthand string, usage string) *pflag.Flag { - return cc.Flags().VarPF(reference, name, shorthand, usage) +func (cmd *CommandClause) VarPF(reference pflag.Value, name string,shorthand string, usage string, hasEnv bool, persistent bool) *pflag.Flag { + return cmd.Flags().VarPF(reference, name, shorthand, usage) } // Command adds a new subcommand to this command. func (cmd *CommandClause) CreateCommand(name, help string) *CommandClause { diff --git a/internals/secrethub/color.go b/internals/secrethub/color.go index 416debb3..5009f3ef 100644 --- a/internals/secrethub/color.go +++ b/internals/secrethub/color.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/secrethub/secrethub-cli/internals/cli" "strconv" "github.com/fatih/color" @@ -21,8 +22,11 @@ func (f noColorFlag) init() { // RegisterColorFlag registers a color flag that configures whether colored output is used. func RegisterColorFlag(r *cobra.Command) { + commandClause := cli.CommandClause{ + Command: r, + } flag := noColorFlag(false) - r.PersistentFlags().Var(&flag, "no-color", "Disable colored output.") + commandClause.Var(&flag, "no-color", "Disable colored output.") } // String implements the flag.Value interface. diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 8c7be9e5..72f5b1ec 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/secrethub/secrethub-cli/internals/cli" "time" "github.com/secrethub/secrethub-go/pkg/secrethub/configdir" @@ -55,13 +56,16 @@ func (store *credentialConfig) IsPassphraseSet() bool { // Register registers the flags for configuring the store on the provided Registerer. func (store *credentialConfig) Register(r *cobra.Command) { - r.PersistentFlags().Var(&store.configDir, "config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub") - r.PersistentFlags().StringVar(&store.AccountCredential, "credential", "", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.") + commandClause := cli.CommandClause{ + Command: r, + } + commandClause.Var(&store.configDir, "config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub") + commandClause.StringVar(&store.AccountCredential, "credential", "", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.") //TODO NoEnvVar - r.PersistentFlags().StringVarP(&store.credentialPassphrase, "p", "p", "", "") // Shorthand -p is deprecated. Use --credential-passphrase instead. - r.Flag("p").Hidden = true - r.PersistentFlags().StringVar(&store.credentialPassphrase, "credential-passphrase", "", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.") - r.PersistentFlags().DurationVar(&store.CredentialPassphraseCacheTTL, "credential-passphrase-cache-ttl", 5*time.Minute, "Cache the credential passphrase in the OS keyring for this duration. The cache is automatically cleared after the timer runs out. Each time the passphrase is read from the cache the timer is reset. Passphrase caching is turned on by default for 5 minutes. Turn it off by setting the duration to 0.") + commandClause.StringVarP(&store.credentialPassphrase, "p", "p", "", "") // Shorthand -p is deprecated. Use --credential-passphrase instead. + commandClause.Flag("p").Hidden = true + commandClause.StringVar(&store.credentialPassphrase, "credential-passphrase", "", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.") + commandClause.DurationVar(&store.CredentialPassphraseCacheTTL, "credential-passphrase-cache-ttl", 5*time.Minute, "Cache the credential passphrase in the OS keyring for this duration. The cache is automatically cleared after the timer runs out. Each time the passphrase is read from the cache the timer is reset. Passphrase caching is turned on by default for 5 minutes. Turn it off by setting the duration to 0.") } // Provider retrieves a credential from the store. diff --git a/internals/secrethub/debug.go b/internals/secrethub/debug.go index 756e10e5..241d13ef 100644 --- a/internals/secrethub/debug.go +++ b/internals/secrethub/debug.go @@ -9,10 +9,13 @@ import ( // RegisterDebugFlag registers a debug flag that changes the log level of the given logger to DEBUG. func RegisterDebugFlag(r *cobra.Command, logger cli.Logger) { + commandClause := cli.CommandClause{ + Command: r, + } flag := debugFlag{ logger: logger, } - r.PersistentFlags().VarP(&flag, "debug", "D", "Enable debug mode.") + commandClause.VarP(&flag, "debug", "D", "Enable debug mode.") } // debugFlag configures the debug level of a logger. diff --git a/internals/secrethub/mlock.go b/internals/secrethub/mlock.go index ad2fe975..0bbbe835 100644 --- a/internals/secrethub/mlock.go +++ b/internals/secrethub/mlock.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/secrethub/secrethub-cli/internals/cli" "strconv" "github.com/secrethub/secrethub-cli/internals/cli/mlock" @@ -29,8 +30,11 @@ func (f mlockFlag) init() error { // RegisterMlockFlag registers a mlock flag that enables memory locking when set to true. func RegisterMlockFlag(r *cobra.Command) { + commandClause := cli.CommandClause{ + Command: r, + } flag := mlockFlag(false) - r.PersistentFlags().Var(&flag, "mlock", "Enable memory locking") + commandClause.Var(&flag, "mlock", "Enable memory locking") } // String implements the flag.Value interface. From b1381cb684847a97f055d1a933c9c943421c0c72 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Fri, 14 Aug 2020 12:03:04 +0300 Subject: [PATCH 31/41] formatted the out structure --- internals/cli/env.go | 114 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 12 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 2344086c..bbbc6175 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -178,48 +178,138 @@ type CommandClause struct { } func (cmd *CommandClause) BoolVarP(reference *bool, name, shorthand string, def bool, usage string, hasEnv bool, persistent bool) { - cmd.Flags().BoolVarP(reference, name, shorthand, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().BoolVarP(reference, name, shorthand, def, usage) + } else { + cmd.Flags().BoolVarP(reference, name, shorthand, def, usage) + } + } func (cmd *CommandClause) IntVarP(reference *int, name, shorthand string, def int, usage string, hasEnv bool, persistent bool) { - cmd.Flags().IntVarP(reference, name, shorthand, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().IntVarP(reference, name, shorthand, def, usage) + } else { + cmd.Flags().IntVarP(reference, name, shorthand, def, usage) + } } func (cmd *CommandClause) StringVarP(reference *string, name, shorthand string, def string, usage string, hasEnv bool, persistent bool) { - cmd.Flags().StringVarP(reference, name, shorthand, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().StringVarP(reference, name, shorthand, def, usage) + } else { + cmd.Flags().StringVarP(reference, name, shorthand, def, usage) + } } func (cmd *CommandClause) DurationVarP(reference *time.Duration, name, shorthand string, def time.Duration, usage string, hasEnv bool, persistent bool) { - cmd.Flags().DurationVarP(reference, name, shorthand, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().DurationVarP(reference, name, shorthand, def, usage) + } else { + cmd.Flags().DurationVarP(reference, name, shorthand, def, usage) + } } func (cmd *CommandClause) BoolVar(reference *bool, name string, def bool, usage string, hasEnv bool, persistent bool) { - cmd.Flags().BoolVar(reference, name, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().BoolVar(reference, name, def, usage) + } else { + cmd.Flags().BoolVar(reference, name, def, usage) + } } func (cmd *CommandClause) IntVar(reference *int, name string, def int, usage string, hasEnv bool, persistent bool) { - cmd.Flags().IntVar(reference, name, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().IntVar(reference, name, def, usage) + } else { + cmd.Flags().IntVar(reference, name, def, usage) + } } func (cmd *CommandClause) StringVar(reference *string, name string, def string, usage string, hasEnv bool, persistent bool) { - cmd.Flags().StringVar(reference, name, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().StringVar(reference, name, def, usage) + } else { + cmd.Flags().StringVar(reference, name, def, usage) + } } func (cmd *CommandClause) DurationVar(reference *time.Duration, name string, def time.Duration, usage string, hasEnv bool, persistent bool) { - cmd.Flags().DurationVar(reference, name, def, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().DurationVar(reference, name, def, usage) + } else { + cmd.Flags().DurationVar(reference, name, def, usage) + } } func (cmd *CommandClause) VarP(reference pflag.Value, name string, shorthand string, usage string, hasEnv bool, persistent bool) { - cmd.Flags().VarP(reference, name, shorthand, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().VarP(reference, name, shorthand, usage) + } else { + cmd.Flags().VarP(reference, name, shorthand, usage) + } } func (cmd *CommandClause) Var(reference pflag.Value, name string, usage string, hasEnv bool, persistent bool) { - cmd.Flags().Var(reference, name, usage) + if hasEnv { + //doSTH + } + + if persistent { + cmd.PersistentFlags().Var(reference, name, usage) + } else { + cmd.Flags().Var(reference, name, usage) + } } -func (cmd *CommandClause) VarPF(reference pflag.Value, name string,shorthand string, usage string, hasEnv bool, persistent bool) *pflag.Flag { - return cmd.Flags().VarPF(reference, name, shorthand, usage) +func (cmd *CommandClause) VarPF(reference pflag.Value, name string, shorthand string, usage string, hasEnv bool, persistent bool) *pflag.Flag { + if hasEnv { + //doSTH + } + + if persistent { + return cmd.PersistentFlags().VarPF(reference, name, shorthand, usage) + } else { + return cmd.Flags().VarPF(reference, name, shorthand, usage) + } } + // Command adds a new subcommand to this command. func (cmd *CommandClause) CreateCommand(name, help string) *CommandClause { return &CommandClause{ From 0e5d1ea002920105f2981ed5499ae29403ea174c Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Fri, 14 Aug 2020 11:04:21 +0200 Subject: [PATCH 32/41] Auto stash before merge of "feature/cobra-switch" and "origin/feature/cobra-switch" --- .idea/inspectionProfiles/Project_Default.xml | 6 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/secrethub-cli.iml | 8 + .idea/vcs.xml | 6 + .idea/workspace.xml | 341 +++++++++++++++++++ internals/demo/init.go | 2 +- internals/secrethub/account_init.go | 6 +- internals/secrethub/acl_list.go | 4 +- internals/secrethub/audit.go | 6 +- internals/secrethub/clear.go | 2 +- internals/secrethub/clear_clipboard.go | 2 +- internals/secrethub/client_factory.go | 9 +- internals/secrethub/color.go | 4 +- internals/secrethub/credential_store.go | 12 +- internals/secrethub/debug.go | 2 +- internals/secrethub/env_source.go | 18 +- internals/secrethub/generate.go | 10 +- internals/secrethub/init.go | 2 +- internals/secrethub/inject.go | 19 +- internals/secrethub/list.go | 2 +- internals/secrethub/mkdir.go | 2 +- internals/secrethub/mlock.go | 4 +- internals/secrethub/org_init.go | 8 +- internals/secrethub/org_invite.go | 2 +- internals/secrethub/org_ls.go | 2 +- internals/secrethub/printenv.go | 2 +- internals/secrethub/read.go | 6 +- internals/secrethub/repo_ls.go | 2 +- internals/secrethub/rm.go | 2 +- internals/secrethub/run.go | 8 +- internals/secrethub/service_aws_init.go | 14 +- internals/secrethub/service_deploy_winrm.go | 14 +- internals/secrethub/service_gcp_init.go | 12 +- internals/secrethub/service_init.go | 16 +- internals/secrethub/service_ls.go | 2 +- internals/secrethub/set.go | 2 +- internals/secrethub/signup.go | 10 +- internals/secrethub/tree.go | 8 +- internals/secrethub/write.go | 6 +- 40 files changed, 486 insertions(+), 111 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/secrethub-cli.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..54d554ec --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..28a804d8 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..7e587d45 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/secrethub-cli.iml b/.idea/secrethub-cli.iml new file mode 100644 index 00000000..c956989b --- /dev/null +++ b/.idea/secrethub-cli.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 00000000..5cce8b39 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 04b20eff..1f3a3e78 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -62,9 +62,9 @@ func (store *credentialConfig) Register(r *cobra.Command) { commandClause.Var(&store.configDir, "config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub", true, true) commandClause.StringVar(&store.AccountCredential, "credential", "", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.", true, true) //TODO NoEnvVar - commandClause.StringVarP(&store.credentialPassphrase, "p", "p", "", "", true, true) // Shorthand -p is deprecated. Use --credential-passphrase instead. + commandClause.StringVarP(&store.credentialPassphrase, "p", "p", "", "", false, true) // Shorthand -p is deprecated. Use --credential-passphrase instead. commandClause.Flag("p").Hidden = true - commandClause.StringVar(&store.credentialPassphrase, "credential-passphrase", "", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.", true, true) + commandClause.StringVar(&store.credentialPassphrase, "credential-passphrase", "", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.", false, true) commandClause.DurationVar(&store.CredentialPassphraseCacheTTL, "credential-passphrase-cache-ttl", 5*time.Minute, "Cache the credential passphrase in the OS keyring for this duration. The cache is automatically cleared after the timer runs out. Each time the passphrase is read from the cache the timer is reset. Passphrase caching is turned on by default for 5 minutes. Turn it off by setting the duration to 0.", true, true) } From 80989edf545404dafdaeab6e4d1bf0864e9741cd Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Fri, 14 Aug 2020 12:20:40 +0300 Subject: [PATCH 34/41] first try env --- internals/cli/env.go | 43 ++++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index bbbc6175..c484634d 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -178,16 +178,15 @@ type CommandClause struct { } func (cmd *CommandClause) BoolVarP(reference *bool, name, shorthand string, def bool, usage string, hasEnv bool, persistent bool) { - if hasEnv { - //doSTH - } - if persistent { cmd.PersistentFlags().BoolVarP(reference, name, shorthand, def, usage) } else { cmd.Flags().BoolVarP(reference, name, shorthand, def, usage) } + if hasEnv { + cmd.FlagRegister(name, usage) + } } func (cmd *CommandClause) IntVarP(reference *int, name, shorthand string, def int, usage string, hasEnv bool, persistent bool) { @@ -347,19 +346,19 @@ func (cmd *CommandClause) Alias(alias string) { // Flag defines a new flag with the given long name and help text, // adding an environment variable default configurable by APP_COMMAND_FLAG_NAME. // The help text is suffixed with a description of secrthe environment variable default. -//func (cmd *CommandClause) Flag(name, help string) *Flag { -// fullCmd := strings.Replace(cmd.FullCommand(), " ", cmd.app.separator, -1) -// prefix := formatName(fullCmd, cmd.app.name, cmd.app.separator, cmd.app.delimiters...) -// envVar := formatName(name, prefix, cmd.app.separator, cmd.app.delimiters...) -// -// cmd.app.registerEnvVar(envVar) -// flag := &pflag.Flag{Name: name, Usage: help} -// return &Flag{ -// Flag: flag, -// app: cmd.app, -// envVar: envVar, -// } -//} +func (cmd *CommandClause) FlagRegister(name, help string) *Flag { + fullCmd := strings.Replace(cmd.FullCommand(), " ", cmd.app.separator, -1) + prefix := formatName(fullCmd, cmd.app.name, cmd.app.separator, cmd.app.delimiters...) + envVar := formatName(name, prefix, cmd.app.separator, cmd.app.delimiters...) + + cmd.app.registerEnvVar(envVar) + flag := cmd.Flag("name") + return (&Flag{ + Flag: flag, + app: cmd.app, + envVar: envVar, + }).Envar(name) +} // Flag represents a command-line flag. type Flag struct { @@ -382,16 +381,6 @@ func (f *Flag) Envar(name string) *Flag { return f } -// NoEnvar forces environment variable defaults to be disabled for this flag. -func (f *Flag) NoEnvar() *Flag { - if f.envVar != "" { - f.app.unregisterEnvVar(f.envVar) - } - f.envVar = "" - f.Flag.DefValue = "" - return f -} - // formatName takes a name and converts it to an uppercased name, // joined by the given separator and prefixed with the given prefix. func formatName(name, prefix, separator string, delimiters ...string) string { From a2b62a8d42a17bb41f03c92661db6a9bdd1a2334 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Fri, 14 Aug 2020 13:10:20 +0200 Subject: [PATCH 35/41] Make environmental variables work --- internals/cli/env.go | 110 ++++++++++++++---------- internals/secrethub/account.go | 3 + internals/secrethub/app.go | 10 +-- internals/secrethub/client_factory.go | 9 +- internals/secrethub/color.go | 6 +- internals/secrethub/command/command.go | 4 +- internals/secrethub/credential_store.go | 11 ++- internals/secrethub/debug.go | 6 +- internals/secrethub/flags.go | 4 +- internals/secrethub/mlock.go | 6 +- internals/secrethub/read.go | 4 +- internals/secrethub/write.go | 1 + 12 files changed, 96 insertions(+), 78 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index c484634d..b71f0f31 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -52,7 +52,7 @@ func (a *App) CreateCommand(name, help string) *CommandClause { return newCommand }(), name: name, - app: a, + App: a, } } @@ -104,7 +104,7 @@ func (a *App) isExtraEnvVar(key string) bool { return false } -// PrintEnv reads all environment variables starting with the app name and writes +// PrintEnv reads all environment variables starting with the App name and writes // a table with the keys and their status: set, empty, unrecognized. The value // of environment variables are not printed out for security reasons. The list // is limited to variables that are actually set in the environment. Setting @@ -154,7 +154,7 @@ func (a *App) PrintEnv(w io.Writer, verbose bool, osEnv func() []string) error { return nil } -// CheckStrictEnv checks that every environment variable that starts with the app name is recognized by the application. +// CheckStrictEnv checks that every environment variable that starts with the App name is recognized by the application. func (a *App) CheckStrictEnv() error { for _, envVar := range os.Environ() { key, _, match := splitVar(a.name, a.separator, envVar) @@ -174,7 +174,7 @@ type CommandClause struct { *cobra.Command name string - app *App + App *App } func (cmd *CommandClause) BoolVarP(reference *bool, name, shorthand string, def bool, usage string, hasEnv bool, persistent bool) { @@ -190,135 +190,139 @@ func (cmd *CommandClause) BoolVarP(reference *bool, name, shorthand string, def } func (cmd *CommandClause) IntVarP(reference *int, name, shorthand string, def int, usage string, hasEnv bool, persistent bool) { - if hasEnv { - //doSTH - } - if persistent { cmd.PersistentFlags().IntVarP(reference, name, shorthand, def, usage) } else { cmd.Flags().IntVarP(reference, name, shorthand, def, usage) } -} -func (cmd *CommandClause) StringVarP(reference *string, name, shorthand string, def string, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) StringVarP(reference *string, name, shorthand string, def string, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().StringVarP(reference, name, shorthand, def, usage) } else { cmd.Flags().StringVarP(reference, name, shorthand, def, usage) } -} -func (cmd *CommandClause) DurationVarP(reference *time.Duration, name, shorthand string, def time.Duration, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) DurationVarP(reference *time.Duration, name, shorthand string, def time.Duration, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().DurationVarP(reference, name, shorthand, def, usage) } else { cmd.Flags().DurationVarP(reference, name, shorthand, def, usage) } -} -func (cmd *CommandClause) BoolVar(reference *bool, name string, def bool, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) BoolVar(reference *bool, name string, def bool, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().BoolVar(reference, name, def, usage) } else { cmd.Flags().BoolVar(reference, name, def, usage) } -} -func (cmd *CommandClause) IntVar(reference *int, name string, def int, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) IntVar(reference *int, name string, def int, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().IntVar(reference, name, def, usage) } else { cmd.Flags().IntVar(reference, name, def, usage) } -} -func (cmd *CommandClause) StringVar(reference *string, name string, def string, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) StringVar(reference *string, name string, def string, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().StringVar(reference, name, def, usage) } else { cmd.Flags().StringVar(reference, name, def, usage) } -} -func (cmd *CommandClause) DurationVar(reference *time.Duration, name string, def time.Duration, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) DurationVar(reference *time.Duration, name string, def time.Duration, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().DurationVar(reference, name, def, usage) } else { cmd.Flags().DurationVar(reference, name, def, usage) } -} -func (cmd *CommandClause) VarP(reference pflag.Value, name string, shorthand string, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) VarP(reference pflag.Value, name string, shorthand string, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().VarP(reference, name, shorthand, usage) } else { cmd.Flags().VarP(reference, name, shorthand, usage) } -} -func (cmd *CommandClause) Var(reference pflag.Value, name string, usage string, hasEnv bool, persistent bool) { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) Var(reference pflag.Value, name string, usage string, hasEnv bool, persistent bool) { if persistent { cmd.PersistentFlags().Var(reference, name, usage) } else { cmd.Flags().Var(reference, name, usage) } -} -func (cmd *CommandClause) VarPF(reference pflag.Value, name string, shorthand string, usage string, hasEnv bool, persistent bool) *pflag.Flag { if hasEnv { - //doSTH + cmd.FlagRegister(name, usage) } +} +func (cmd *CommandClause) VarPF(reference pflag.Value, name string, shorthand string, usage string, hasEnv bool, persistent bool) *pflag.Flag { + var flag *pflag.Flag if persistent { - return cmd.PersistentFlags().VarPF(reference, name, shorthand, usage) + flag = cmd.PersistentFlags().VarPF(reference, name, shorthand, usage) } else { - return cmd.Flags().VarPF(reference, name, shorthand, usage) + flag = cmd.Flags().VarPF(reference, name, shorthand, usage) + } + + if hasEnv { + cmd.FlagRegister(name, usage) } + return flag } // Command adds a new subcommand to this command. func (cmd *CommandClause) CreateCommand(name, help string) *CommandClause { - return &CommandClause{ + clause := &CommandClause{ Command: func() *cobra.Command { newCommand := &cobra.Command{Use: name, Short: help} return newCommand }(), name: name, - app: cmd.app, + App: cmd.App, } + cmd.AddCommand(clause.Command) + return clause } // Hidden hides the command in help texts. @@ -328,7 +332,16 @@ func (cmd *CommandClause) Hidden() *CommandClause { } func (cmd *CommandClause) FullCommand() string { - return strings.Join(os.Args[:], " ") + if cmd.Use == cmd.Root().Use { + return "" + } + out := []string{cmd.Use} + for p := cmd.Parent(); p != nil; p = p.Parent() { + if p.Use != cmd.Root().Use { + out = append([]string{p.Use}, out...) + } + } + return strings.Join(out, " ") } func (cmd *CommandClause) HelpLong(helpLong string) { @@ -347,17 +360,17 @@ func (cmd *CommandClause) Alias(alias string) { // adding an environment variable default configurable by APP_COMMAND_FLAG_NAME. // The help text is suffixed with a description of secrthe environment variable default. func (cmd *CommandClause) FlagRegister(name, help string) *Flag { - fullCmd := strings.Replace(cmd.FullCommand(), " ", cmd.app.separator, -1) - prefix := formatName(fullCmd, cmd.app.name, cmd.app.separator, cmd.app.delimiters...) - envVar := formatName(name, prefix, cmd.app.separator, cmd.app.delimiters...) + fullCmd := strings.Replace(cmd.FullCommand(), " ", cmd.App.separator, -1) + prefix := formatName(fullCmd, cmd.App.name, cmd.App.separator, cmd.App.delimiters...) + envVar := formatName(name, prefix, cmd.App.separator, cmd.App.delimiters...) - cmd.app.registerEnvVar(envVar) - flag := cmd.Flag("name") + cmd.App.registerEnvVar(envVar) + flag := cmd.Flag(name) return (&Flag{ Flag: flag, - app: cmd.app, + app: cmd.App, envVar: envVar, - }).Envar(name) + }).Envar(envVar) } // Flag represents a command-line flag. @@ -384,6 +397,9 @@ func (f *Flag) Envar(name string) *Flag { // formatName takes a name and converts it to an uppercased name, // joined by the given separator and prefixed with the given prefix. func formatName(name, prefix, separator string, delimiters ...string) string { + if name == "" { + return strings.ToUpper(prefix) + } for _, delim := range delimiters { name = strings.Replace(name, delim, separator, -1) } diff --git a/internals/secrethub/account.go b/internals/secrethub/account.go index 7fc1c89a..0614e539 100644 --- a/internals/secrethub/account.go +++ b/internals/secrethub/account.go @@ -27,4 +27,7 @@ func (cmd *AccountCommand) Register(r command.Registerer) { NewAccountInspectCommand(cmd.io, cmd.newClient).Register(clause) NewAccountInitCommand(cmd.io, cmd.newClient, cmd.credentialStore).Register(clause) NewAccountEmailVerifyCommand(cmd.io, cmd.newClient).Register(clause) + //command.BindAction(clause, nil, func() error { + // return nil + //}) } diff --git a/internals/secrethub/app.go b/internals/secrethub/app.go index ce8c80ce..1d54926a 100644 --- a/internals/secrethub/app.go +++ b/internals/secrethub/app.go @@ -94,11 +94,11 @@ func NewApp() *App { logger: cli.NewLogger(), } - RegisterDebugFlag(&app.cli.Application, app.logger) - RegisterMlockFlag(&app.cli.Application) - RegisterColorFlag(&app.cli.Application) - app.credentialStore.Register(&app.cli.Application) - app.clientFactory.Register(&app.cli.Application) + RegisterDebugFlag(app.cli, app.logger) + RegisterMlockFlag(app.cli) + RegisterColorFlag(app.cli) + app.credentialStore.Register(app.cli) + app.clientFactory.Register(app.cli) app.registerCommands() //app.cli.UsageTemplate(DefaultUsageTemplate) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index 47702690..14efdd5b 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -10,8 +10,6 @@ import ( "github.com/secrethub/secrethub-go/pkg/secrethub" "github.com/secrethub/secrethub-go/pkg/secrethub/configdir" "github.com/secrethub/secrethub-go/pkg/secrethub/credentials" - - "github.com/spf13/cobra" ) // Errors @@ -25,7 +23,7 @@ type ClientFactory interface { NewClient() (secrethub.ClientInterface, error) NewClientWithCredentials(credentials.Provider) (secrethub.ClientInterface, error) NewUnauthenticatedClient() (secrethub.ClientInterface, error) - Register(command *cobra.Command) + Register(app *cli.App) } // NewClientFactory creates a new ClientFactory. @@ -44,9 +42,10 @@ type clientFactory struct { } // Register the flags for configuration on a cli application. -func (f *clientFactory) Register(r *cobra.Command) { +func (f *clientFactory) Register(app *cli.App) { commandClause := cli.CommandClause{ - Command: r, + Command: &app.Application, + App: app, } //TODO persistent!!! commandClause.VarPF(&f.ServerURL, "api-remote", "", "The SecretHub API address, don't set this unless you know what you're doing.", true, false) diff --git a/internals/secrethub/color.go b/internals/secrethub/color.go index 6636859b..3ad66e17 100644 --- a/internals/secrethub/color.go +++ b/internals/secrethub/color.go @@ -5,7 +5,6 @@ import ( "github.com/fatih/color" "github.com/secrethub/secrethub-cli/internals/cli" - "github.com/spf13/cobra" ) // noColorFlag configures the global behaviour to disable colored output. @@ -21,9 +20,10 @@ func (f noColorFlag) init() { } // RegisterColorFlag registers a color flag that configures whether colored output is used. -func RegisterColorFlag(r *cobra.Command) { +func RegisterColorFlag(app *cli.App) { commandClause := cli.CommandClause{ - Command: r, + Command: &app.Application, + App: app, } flag := noColorFlag(false) commandClause.Var(&flag, "no-color", "Disable colored output.", true, true) diff --git a/internals/secrethub/command/command.go b/internals/secrethub/command/command.go index aa664904..5bc4bcc2 100644 --- a/internals/secrethub/command/command.go +++ b/internals/secrethub/command/command.go @@ -15,10 +15,10 @@ type Registerer interface { // it is executed when the command is parsed. func BindAction(clause *cli.CommandClause, argumentRegister func(c *cobra.Command, args []string) error, fn func() error) { if argumentRegister != nil { - clause.RunE = argumentRegister + clause.PreRunE = argumentRegister } if fn != nil { - clause.PostRunE = func(cmd *cobra.Command, args []string) error { + clause.RunE = func(cmd *cobra.Command, args []string) error { return fn() } } diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 1f3a3e78..3e402e12 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -8,8 +8,6 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli" "github.com/secrethub/secrethub-cli/internals/cli/ui" - - "github.com/spf13/cobra" ) // Errors @@ -25,7 +23,7 @@ type CredentialConfig interface { ConfigDir() configdir.Dir PassphraseReader() credentials.Reader - Register(command *cobra.Command) + Register(app *cli.App) } // NewCredentialConfig creates a new CredentialConfig. @@ -55,14 +53,15 @@ func (store *credentialConfig) IsPassphraseSet() bool { } // Register registers the flags for configuring the store on the provided Registerer. -func (store *credentialConfig) Register(r *cobra.Command) { +func (store *credentialConfig) Register(app *cli.App) { commandClause := cli.CommandClause{ - Command: r, + Command: &app.Application, + App: app, } commandClause.Var(&store.configDir, "config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub", true, true) commandClause.StringVar(&store.AccountCredential, "credential", "", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.", true, true) //TODO NoEnvVar - commandClause.StringVarP(&store.credentialPassphrase, "p", "p", "", "", false, true) // Shorthand -p is deprecated. Use --credential-passphrase instead. + commandClause.StringVarP(&store.credentialPassphrase, "p", "p", "", "", true, true) // Shorthand -p is deprecated. Use --credential-passphrase instead. commandClause.Flag("p").Hidden = true commandClause.StringVar(&store.credentialPassphrase, "credential-passphrase", "", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.", false, true) commandClause.DurationVar(&store.CredentialPassphraseCacheTTL, "credential-passphrase-cache-ttl", 5*time.Minute, "Cache the credential passphrase in the OS keyring for this duration. The cache is automatically cleared after the timer runs out. Each time the passphrase is read from the cache the timer is reset. Passphrase caching is turned on by default for 5 minutes. Turn it off by setting the duration to 0.", true, true) diff --git a/internals/secrethub/debug.go b/internals/secrethub/debug.go index 3a64b07d..f4564cf6 100644 --- a/internals/secrethub/debug.go +++ b/internals/secrethub/debug.go @@ -4,13 +4,13 @@ import ( "strconv" "github.com/secrethub/secrethub-cli/internals/cli" - "github.com/spf13/cobra" ) // RegisterDebugFlag registers a debug flag that changes the log level of the given logger to DEBUG. -func RegisterDebugFlag(r *cobra.Command, logger cli.Logger) { +func RegisterDebugFlag(app *cli.App, logger cli.Logger) { commandClause := cli.CommandClause{ - Command: r, + Command: &app.Application, + App: app, } flag := debugFlag{ logger: logger, diff --git a/internals/secrethub/flags.go b/internals/secrethub/flags.go index ecc17c25..1ae276d1 100644 --- a/internals/secrethub/flags.go +++ b/internals/secrethub/flags.go @@ -5,9 +5,9 @@ import ( ) func registerTimestampFlag(r *cli.CommandClause, p *bool) { - r.Flags().BoolVarP(p, "timestamp", "T", false, "Show timestamps formatted to RFC3339 instead of human readable durations.") + r.BoolVarP(p, "timestamp", "T", false, "Show timestamps formatted to RFC3339 instead of human readable durations.", true, false) } func registerForceFlag(r *cli.CommandClause, p *bool) { - r.Flags().BoolVarP(p, "force", "f", false, "Ignore confirmation and fail instead of prompt for missing arguments.") + r.BoolVarP(p, "force", "f", false, "Ignore confirmation and fail instead of prompt for missing arguments.", true, false) } diff --git a/internals/secrethub/mlock.go b/internals/secrethub/mlock.go index 168730e2..494518e9 100644 --- a/internals/secrethub/mlock.go +++ b/internals/secrethub/mlock.go @@ -5,7 +5,6 @@ import ( "github.com/secrethub/secrethub-cli/internals/cli" "github.com/secrethub/secrethub-cli/internals/cli/mlock" - "github.com/spf13/cobra" ) // mlockFlag configures locking memory. @@ -29,9 +28,10 @@ func (f mlockFlag) init() error { } // RegisterMlockFlag registers a mlock flag that enables memory locking when set to true. -func RegisterMlockFlag(r *cobra.Command) { +func RegisterMlockFlag(app *cli.App) { commandClause := cli.CommandClause{ - Command: r, + Command: &app.Application, + App: app, } flag := mlockFlag(false) commandClause.Var(&flag, "mlock", "Enable memory locking", true, true) diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index 91044ad8..8ce2f97c 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -46,12 +46,12 @@ func (cmd *ReadCommand) Register(r command.Registerer) { clause.Args = cobra.ExactValidArgs(1) clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions - clause.Flags().BoolVarP(&cmd.useClipboard, + clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, fmt.Sprintf( "Copy the secret value to the clipboard. The clipboard is automatically cleared after %s.", units.HumanDuration(cmd.clearClipboardAfter), - ), + ), true, false, ) clause.StringVarP(&cmd.outFile, "out-file", "o", "", "Write the secret value to this file.", true, false) clause.BoolVarP(&cmd.noNewLine, "no-newline", "n", false, "Do not print a new line after the secret", true, false) diff --git a/internals/secrethub/write.go b/internals/secrethub/write.go index ea5e32e2..d1b96082 100644 --- a/internals/secrethub/write.go +++ b/internals/secrethub/write.go @@ -48,6 +48,7 @@ func (cmd *WriteCommand) Register(r command.Registerer) { //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathPlaceHolder).SetValue(&cmd.path) clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, "Use clipboard content as input.", true, false) clause.BoolVarP(&cmd.multiline, "multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.", true, false) + clause.BoolVar(&cmd.noTrim, "no-trim", false, "Do not trim leading and trailing whitespace in the secret.", true, false) clause.StringVarP(&cmd.inFile, "in-file", "i", "", "Use the contents of this file as the value of the secret.", true, false) command.BindAction(clause, cmd.argumentRegister, cmd.Run) From de0a964677d38f45685c2ac886cd09887832b42c Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Fri, 14 Aug 2020 14:14:42 +0300 Subject: [PATCH 36/41] some cleanup --- internals/cli/env.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index b71f0f31..2d5d0815 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -63,19 +63,6 @@ func (a *App) Version(version string) *App { return a } -// Flag defines a new flag with the given long name and help text, -// adding an environment variable default configurable by APP_FLAG_NAME. -func (a *App) Flag(name, help string) *Flag { - envVar := formatName(name, a.name, a.separator, a.delimiters...) - a.registerEnvVar(envVar) - flag := Flag{ - Flag: &pflag.Flag{Name: name, Usage: help}, - envVar: envVar, - app: a, - } - return flag.Envar(envVar) -} - // registerEnvVar ensures the App recognizes an environment variable. func (a *App) registerEnvVar(name string) { a.knownEnvVars[strings.ToUpper(name)] = struct{}{} From c16cb7cdf8d7785cb25f6d0973316686bec162c0 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Fri, 14 Aug 2020 14:09:25 +0200 Subject: [PATCH 37/41] Remove dynamic path autocompletion --- internals/secrethub/argumentAutocompletion.go | 84 ------------------- internals/secrethub/read.go | 1 - 2 files changed, 85 deletions(-) delete mode 100644 internals/secrethub/argumentAutocompletion.go diff --git a/internals/secrethub/argumentAutocompletion.go b/internals/secrethub/argumentAutocompletion.go deleted file mode 100644 index 7a414e60..00000000 --- a/internals/secrethub/argumentAutocompletion.go +++ /dev/null @@ -1,84 +0,0 @@ -package secrethub - -import ( - "fmt" - "os" - "strings" - - "github.com/secrethub/secrethub-go/pkg/secrethub" - "github.com/secrethub/secrethub-go/pkg/secrethub/iterator" - "github.com/spf13/cobra" -) - -type AutoCompleter struct { - client *secrethub.Client -} - -// SecretSuggestions provides auto-completions for both arguments and flags -// that take as values paths to secrets SecretHub. -func (ac AutoCompleter) SecretSuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getFullPaths(ac.client, toComplete, true), cobra.ShellCompDirectiveNoSpace -} - -// DirectorySuggestions provides auto-completions for both arguments and flags -// that take as values paths to directories in SecretHub. -func (ac AutoCompleter) DirectorySuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { - return getFullPaths(ac.client, toComplete, false), cobra.ShellCompDirectiveNoSpace -} - -func getNamespacesAndRepos(client *secrethub.Client) []string { - var suggestions []string - iter := client.Me().RepoIterator(&secrethub.RepoIteratorParams{}) - for { - repo, err := iter.Next() - if err == iterator.Done { - break - } else if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err.Error()) - return nil - } - suggestions = append(suggestions, string(repo.Path()+"/")) - } - return suggestions -} - -func getFullPaths(client *secrethub.Client, toComplete string, includeSecrets bool) []string { - if len(toComplete) == 0 { - return getNamespacesAndRepos(client) - } - tree, err := client.Dirs().GetTree(toComplete, 1, false) - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err.Error()) - path := toComplete[0:strings.LastIndex(toComplete, "/")] - _, err = client.Dirs().GetTree(path, 1, false) - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err.Error()) - return getNamespacesAndRepos(client) - } - return getFullPaths(client, path, includeSecrets) - } - if strings.LastIndex(toComplete, "/") != len(toComplete)-1 { - toComplete += "/" - } - suggestions := make([]string, tree.DirCount()+tree.SecretCount()) - - for _, dir := range tree.RootDir.SubDirs { - suggestions = append(suggestions, toComplete+dir.Name+"/") - } - - if includeSecrets { - for _, secret := range tree.RootDir.Secrets { - suggestions = append(suggestions, toComplete+secret.Name) - } - } - return suggestions -} - -// GetClient returns a new SecretHub client. -func GetClient() *secrethub.Client { - client, err := secrethub.NewClient() - if err != nil { - _, _ = fmt.Fprintln(os.Stderr, err.Error()) - } - return client -} diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index 8ce2f97c..ad15eedd 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -45,7 +45,6 @@ func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") clause.Args = cobra.ExactValidArgs(1) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, fmt.Sprintf( From 41e74c3e536b8039ffad4bbba4763a4156160fc5 Mon Sep 17 00:00:00 2001 From: Horia Culea Date: Fri, 14 Aug 2020 16:18:22 +0300 Subject: [PATCH 38/41] added autocompletion script --- internals/secrethub/audit.go | 2 +- internals/secrethub/path_autocompletion.go | 128 +++++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 internals/secrethub/path_autocompletion.go diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index b655d7f8..a1b303d5 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -23,7 +23,7 @@ import ( var ( errAudit = errio.Namespace("audit") - errNoSuchFormat = errAudit.Code("invalid_format").ErrorPref("invalid format: %s") + errNoSuchFormat = errAudit.Code("invalid_format").ErrorPref("invalid se: %s") ) const ( diff --git a/internals/secrethub/path_autocompletion.go b/internals/secrethub/path_autocompletion.go new file mode 100644 index 00000000..d413a5e4 --- /dev/null +++ b/internals/secrethub/path_autocompletion.go @@ -0,0 +1,128 @@ +package secrethub + +import ( + "fmt" + "os" + "strings" + + "github.com/secrethub/secrethub-go/pkg/secrethub" + "github.com/secrethub/secrethub-go/pkg/secrethub/iterator" + "github.com/spf13/cobra" +) + +type AutoCompleter struct { + client *secrethub.Client +} + +// SecretSuggestions provides auto-completions for both arguments and flags +// that take as values paths to secrets SecretHub. +func (ac AutoCompleter) SecretSuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return getFullPaths(ac.client, toComplete, true), cobra.ShellCompDirectiveNoSpace +} + +// DirectorySuggestions provides auto-completions for both arguments and flags +// that take as values paths to directories in SecretHub. +func (ac AutoCompleter) DirectorySuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return getFullPaths(ac.client, toComplete, false), cobra.ShellCompDirectiveNoSpace +} + +// RepositorySuggestions provides auto-completions for both arguments and flags +// that take as values paths to repositories in SecretHub. +func (ac AutoCompleter) RepositorySuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return getNamespacesAndRepos(ac.client), cobra.ShellCompDirectiveNoSpace +} + +// NamespaceSuggestions provides auto-completions for both arguments and flags +// that take as values namespaces in SecretHub. +func (ac AutoCompleter) NamespaceSuggestions(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return getNamespaces(ac.client), cobra.ShellCompDirectiveNoSpace +} + +func getNamespaces(client *secrethub.Client) []string { + var suggestions []string + iter := client.Orgs().Iterator(&secrethub.OrgIteratorParams{}) + for { + org, err := iter.Next() + if err == iterator.Done { + break + } else if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + return nil + } + suggestions = append(suggestions, org.Name) + } + me := client.Me() + user, _ := me.GetUser() + suggestions = append(suggestions, user.Username) + + return suggestions +} + +func getNamespacesAndRepos(client *secrethub.Client) []string { + var suggestions []string + iter := client.Me().RepoIterator(&secrethub.RepoIteratorParams{}) + for { + repo, err := iter.Next() + if err == iterator.Done { + break + } else if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + return nil + } + suggestions = append(suggestions, string(repo.Path()+"/")) + } + //TAKE PATHS FROM ORGS + //iter2 := client.Orgs().Iterator(&secrethub.OrgIteratorParams{}) + //for { + // org, err := iter2.Next() + // if err == iterator.Done { + // break + // } else if err != nil { + // _, _ = fmt.Fprintln(os.Stderr, err.Error()) + // return nil + // } + // suggestions = append(suggestions, org.) + //} + return suggestions +} + +func getFullPaths(client *secrethub.Client, toComplete string, includeSecrets bool) []string { + if len(toComplete) == 0 { + return getNamespacesAndRepos(client) + } + tree, err := client.Dirs().GetTree(toComplete, 1, false) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + path := toComplete[0:strings.LastIndex(toComplete, "/")] + _, err = client.Dirs().GetTree(path, 1, false) + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + return getNamespacesAndRepos(client) + } + return getFullPaths(client, path, includeSecrets) + } + if strings.LastIndex(toComplete, "/") != len(toComplete)-1 { + toComplete += "/" + } + suggestions := make([]string, tree.DirCount()+tree.SecretCount()) + + for _, dir := range tree.RootDir.SubDirs { + suggestions = append(suggestions, toComplete+dir.Name+"/") + } + + if includeSecrets { + for _, secret := range tree.RootDir.Secrets { + suggestions = append(suggestions, toComplete+secret.Name) + } + } + return suggestions +} + +// GetClient returns a new SecretHub client. +func GetClient() *secrethub.Client { + client, err := secrethub.NewClient() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err.Error()) + } + return client +} From f897ea3a2afd14b3a48986e515d0a89ccd60aaf4 Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Fri, 14 Aug 2020 16:15:29 +0200 Subject: [PATCH 39/41] Autocompletion for paths Autocompletion for all arguments that require a secret, dir, repo, org or namespace paths --- internals/demo/init.go | 1 - internals/secrethub/acl_check.go | 1 + internals/secrethub/acl_list.go | 1 + internals/secrethub/acl_rm.go | 1 + internals/secrethub/acl_set.go | 1 + internals/secrethub/audit.go | 1 + internals/secrethub/client_factory.go | 5 ++++- internals/secrethub/credential_store.go | 1 - internals/secrethub/inspect.go | 1 + internals/secrethub/list.go | 1 + internals/secrethub/mkdir.go | 1 + internals/secrethub/org_init.go | 1 + internals/secrethub/org_inspect.go | 1 + internals/secrethub/org_invite.go | 1 + internals/secrethub/org_list_users.go | 1 + internals/secrethub/org_revoke.go | 1 + internals/secrethub/org_rm.go | 1 + internals/secrethub/org_set_role.go | 6 ++++++ internals/secrethub/read.go | 1 + internals/secrethub/repo_export.go | 1 + internals/secrethub/repo_init.go | 1 + internals/secrethub/repo_inspect.go | 1 + internals/secrethub/repo_invite.go | 1 + internals/secrethub/repo_ls.go | 1 + internals/secrethub/repo_revoke.go | 1 + internals/secrethub/repo_rm.go | 1 + internals/secrethub/rm.go | 1 + internals/secrethub/service_aws_init.go | 1 + internals/secrethub/service_gcp_init.go | 1 + internals/secrethub/service_gcp_link.go | 3 +++ internals/secrethub/service_init.go | 1 + internals/secrethub/service_ls.go | 1 + internals/secrethub/tree.go | 1 + internals/secrethub/write.go | 1 + 34 files changed, 42 insertions(+), 3 deletions(-) diff --git a/internals/demo/init.go b/internals/demo/init.go index 9dc62bc8..14969374 100644 --- a/internals/demo/init.go +++ b/internals/demo/init.go @@ -37,7 +37,6 @@ func (cmd *InitCommand) Register(r command.Registerer) { clause.HelpLong("demo init creates a repository with the username and password needed to connect to the demo API.") clause.VarPF(&cmd.repo, "repo", "", "The path of the repository to create. Defaults to a "+defaultDemoRepo+" repo in your personal namespace.", true, false) - command.BindAction(clause, nil, cmd.Run) } diff --git a/internals/secrethub/acl_check.go b/internals/secrethub/acl_check.go index 9d144f50..3a0f4c0f 100644 --- a/internals/secrethub/acl_check.go +++ b/internals/secrethub/acl_check.go @@ -35,6 +35,7 @@ func NewACLCheckCommand(io ui.IO, newClient newClientFunc) *ACLCheckCommand { func (cmd *ACLCheckCommand) Register(r command.Registerer) { clause := r.CreateCommand("check", "Checks the effective permission of accounts on a path.") clause.Args = cobra.RangeArgs(1, 2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions //clause.Arg("dir-path", "The path of the directory to check the effective permission for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "Check permissions of a specific account name (username or service name). When left empty, all accounts with permission on the path are printed out.").SetValue(&cmd.accountName) diff --git a/internals/secrethub/acl_list.go b/internals/secrethub/acl_list.go index 3ffb4ce5..6e9f2ef5 100644 --- a/internals/secrethub/acl_list.go +++ b/internals/secrethub/acl_list.go @@ -38,6 +38,7 @@ func (cmd *ACLListCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List access rules of a directory and its children.") clause.Alias("list") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions //clause.Arg("dir-path", "The path of the directory to list the access rules for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) clause.IntVarP(&cmd.depth, "depth", "d", -1, "The maximum depth to which the rules of child directories should be displayed. Defaults to -1 (no limit).", true, false) clause.BoolVarP(&cmd.ancestors, "all", "a", false, "List all rules that apply on the directory, including rules on parent directories.", true, false) diff --git a/internals/secrethub/acl_rm.go b/internals/secrethub/acl_rm.go index fee7c127..f5f07d12 100644 --- a/internals/secrethub/acl_rm.go +++ b/internals/secrethub/acl_rm.go @@ -31,6 +31,7 @@ func (cmd *ACLRmCommand) Register(r command.Registerer) { clause := r.CreateCommand("rm", "Remove an account's access rules on a given directory. Although the server will deny the account access afterwards, note that removing an access rule does not actually revoke an account and does NOT trigger secret rotation.") clause.Alias("remove") clause.Args = cobra.ExactValidArgs(2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions //clause.Arg("dir-path", "The path of the directory to remove the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/acl_set.go b/internals/secrethub/acl_set.go index 1178cc8e..0dd027b5 100644 --- a/internals/secrethub/acl_set.go +++ b/internals/secrethub/acl_set.go @@ -32,6 +32,7 @@ func NewACLSetCommand(io ui.IO, newClient newClientFunc) *ACLSetCommand { func (cmd *ACLSetCommand) Register(r command.Registerer) { clause := r.CreateCommand("set", "Set access rule for an user or service on a path.") clause.Args = cobra.ExactValidArgs(3) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions //clause.Arg("dir-path", "The path of the directory to set the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to set the access rule for").Required().SetValue(&cmd.accountName) //clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) diff --git a/internals/secrethub/audit.go b/internals/secrethub/audit.go index a1b303d5..b0ec1071 100644 --- a/internals/secrethub/audit.go +++ b/internals/secrethub/audit.go @@ -69,6 +69,7 @@ func (cmd *AuditCommand) Register(r command.Registerer) { clause := r.CreateCommand("audit", "Show the audit log.") clause.Args = cobra.MaximumNArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions //clause.Arg("repo-path or secret-path", "Path to the repository or the secret to audit "+repoPathPlaceHolder+" or "+secretPathPlaceHolder).SetValue(&cmd.path) clause.IntVar(&cmd.perPage, "per-page", 20, "Number of audit events shown per page", true, false) clause.Flag("per-page").Hidden = true diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index 14efdd5b..a460c5ab 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -1,6 +1,7 @@ package secrethub import ( + "github.com/spf13/cobra" "net/http" "net/url" "strings" @@ -47,9 +48,11 @@ func (f *clientFactory) Register(app *cli.App) { Command: &app.Application, App: app, } - //TODO persistent!!! commandClause.VarPF(&f.ServerURL, "api-remote", "", "The SecretHub API address, don't set this unless you know what you're doing.", true, false) commandClause.StringVar(&f.identityProvider, "identity-provider", "key", "Enable native authentication with a trusted identity provider. Options are `aws` (IAM + KMS), `gcp` (IAM + KMS) and `key`. When you run the CLI on one of the platforms, you can leverage their respective identity providers to do native keyless authentication. Defaults to key, which uses the default credential sourced from a file, command-line flag, or environment variable. ", true, false) + _ = commandClause.RegisterFlagCompletionFunc("identity-provider", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"aws", "gcp", "key"}, cobra.ShellCompDirectiveDefault + }) commandClause.VarPF(&f.proxyAddress, "proxy-address", "", "Set to the address of a proxy to connect to the API through a proxy. The prepended scheme determines the proxy type (http, https and socks5 are supported). For example: `--proxy-address http://my-proxy:1234`", true, false) } diff --git a/internals/secrethub/credential_store.go b/internals/secrethub/credential_store.go index 3e402e12..cb415b62 100644 --- a/internals/secrethub/credential_store.go +++ b/internals/secrethub/credential_store.go @@ -60,7 +60,6 @@ func (store *credentialConfig) Register(app *cli.App) { } commandClause.Var(&store.configDir, "config-dir", "The absolute path to a custom configuration directory. Defaults to $HOME/.secrethub", true, true) commandClause.StringVar(&store.AccountCredential, "credential", "", "Use a specific account credential to authenticate to the API. This overrides the credential stored in the configuration directory.", true, true) - //TODO NoEnvVar commandClause.StringVarP(&store.credentialPassphrase, "p", "p", "", "", true, true) // Shorthand -p is deprecated. Use --credential-passphrase instead. commandClause.Flag("p").Hidden = true commandClause.StringVar(&store.credentialPassphrase, "credential-passphrase", "", "The passphrase to unlock your credential file. When set, it will not prompt for the passphrase, nor cache it in the OS keyring. Please only use this if you know what you're doing and ensure your passphrase doesn't end up in bash history.", false, true) diff --git a/internals/secrethub/inspect.go b/internals/secrethub/inspect.go index 3fdc4a0c..6a357951 100644 --- a/internals/secrethub/inspect.go +++ b/internals/secrethub/inspect.go @@ -33,6 +33,7 @@ func NewInspectCommand(io ui.IO, newClient newClientFunc) *InspectCommand { func (cmd *InspectCommand) Register(r command.Registerer) { clause := r.CreateCommand("inspect", "Print details of a resource.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions //clause.Arg("repo or secret-path", "Path to the repository or the secret to inspect "+repoPathPlaceHolder+" or "+secretPathOptionalVersionPlaceHolder).Required().SetValue(&cmd.path) command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/list.go b/internals/secrethub/list.go index 7e4ca7d9..44d3cd40 100644 --- a/internals/secrethub/list.go +++ b/internals/secrethub/list.go @@ -36,6 +36,7 @@ func (cmd *LsCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List contents of a path.") clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions //clause.Arg("path", "The path to list contents of").SetValue(&cmd.path) clause.BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.", true, false) registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/mkdir.go b/internals/secrethub/mkdir.go index 6e020210..f7e3a6d4 100644 --- a/internals/secrethub/mkdir.go +++ b/internals/secrethub/mkdir.go @@ -38,6 +38,7 @@ func NewMkDirCommand(io ui.IO, newClient newClientFunc) *MkDirCommand { func (cmd *MkDirCommand) Register(r command.Registerer) { clause := r.CreateCommand("mkdir", "Create a new directory.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions //clause.Arg("dir-paths", "The paths to the directories").Required().PlaceHolder(dirPathsPlaceHolder).SetValue(&cmd.paths) clause.BoolVar(&cmd.parents, "parents", false, "Create parent directories if needed. Does not error when directories already exist.", true, false) diff --git a/internals/secrethub/org_init.go b/internals/secrethub/org_init.go index 22464bb9..3e7db36b 100644 --- a/internals/secrethub/org_init.go +++ b/internals/secrethub/org_init.go @@ -29,6 +29,7 @@ func NewOrgInitCommand(io ui.IO, newClient newClientFunc) *OrgInitCommand { // Register registers the command, arguments and flags on the provided Registerer. func (cmd *OrgInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize a new organization account.") + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions clause.Var(&cmd.name, "name", "The name you would like to use for your organization. If not set, you will be asked for it.", true, false) clause.StringVar(&cmd.description, "description", "", "A description (max 144 chars) for your organization so others will recognize it. If not set, you will be asked for it.", true, false) clause.StringVar(&cmd.description, "descr", "", "", true, false) diff --git a/internals/secrethub/org_inspect.go b/internals/secrethub/org_inspect.go index 5804de48..7c68f913 100644 --- a/internals/secrethub/org_inspect.go +++ b/internals/secrethub/org_inspect.go @@ -33,6 +33,7 @@ func NewOrgInspectCommand(io ui.IO, newClient newClientFunc) *OrgInspectCommand func (cmd *OrgInspectCommand) Register(r command.Registerer) { clause := r.CreateCommand("inspect", "Show the details of an organization.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index 8dcbd2aa..601fdd72 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -33,6 +33,7 @@ func NewOrgInviteCommand(io ui.IO, newClient newClientFunc) *OrgInviteCommand { func (cmd *OrgInviteCommand) Register(r command.Registerer) { clause := r.CreateCommand("invite", "Invite a user to join an organization.") clause.Args = cobra.ExactValidArgs(2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) clause.StringVar(&cmd.role, "role", "member", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.", true, false) diff --git a/internals/secrethub/org_list_users.go b/internals/secrethub/org_list_users.go index 45a06c21..08198c78 100644 --- a/internals/secrethub/org_list_users.go +++ b/internals/secrethub/org_list_users.go @@ -35,6 +35,7 @@ func (cmd *OrgListUsersCommand) Register(r command.Registerer) { clause := r.CreateCommand("list-users", "List all members of an organization.") clause.Alias("list-members") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/org_revoke.go b/internals/secrethub/org_revoke.go index d4c0ba2a..c17c2aee 100644 --- a/internals/secrethub/org_revoke.go +++ b/internals/secrethub/org_revoke.go @@ -33,6 +33,7 @@ func NewOrgRevokeCommand(io ui.IO, newClient newClientFunc) *OrgRevokeCommand { func (cmd *OrgRevokeCommand) Register(r command.Registerer) { clause := r.CreateCommand("revoke", "Revoke a user from an organization. This automatically revokes the user from all of the organization's repositories. A list of repositories containing secrets that should be rotated will be printed out.") clause.Args = cobra.ExactValidArgs(2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) diff --git a/internals/secrethub/org_rm.go b/internals/secrethub/org_rm.go index 52fff3a3..31d55e54 100644 --- a/internals/secrethub/org_rm.go +++ b/internals/secrethub/org_rm.go @@ -32,6 +32,7 @@ func (cmd *OrgRmCommand) Register(r command.Registerer) { clause := r.CreateCommand("rm", "Permanently delete an organization and all the repositories it owns.") clause.Alias("remove") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.name) command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/org_set_role.go b/internals/secrethub/org_set_role.go index 93642835..c216f988 100644 --- a/internals/secrethub/org_set_role.go +++ b/internals/secrethub/org_set_role.go @@ -32,6 +32,12 @@ func NewOrgSetRoleCommand(io ui.IO, newClient newClientFunc) *OrgSetRoleCommand func (cmd *OrgSetRoleCommand) Register(r command.Registerer) { clause := r.CreateCommand("set-role", "Set a user's organization role.") clause.Args = cobra.ExactValidArgs(3) + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.RepositorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) //clause.Arg("role", "The role to assign to the user. Can be either `admin` or `member`.").Required().StringVar(&cmd.role) diff --git a/internals/secrethub/read.go b/internals/secrethub/read.go index ad15eedd..41497fee 100644 --- a/internals/secrethub/read.go +++ b/internals/secrethub/read.go @@ -44,6 +44,7 @@ func NewReadCommand(io ui.IO, newClient newClientFunc) *ReadCommand { func (cmd *ReadCommand) Register(r command.Registerer) { clause := r.CreateCommand("read", "Read a secret.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, diff --git a/internals/secrethub/repo_export.go b/internals/secrethub/repo_export.go index dc5c2f84..5d86df27 100644 --- a/internals/secrethub/repo_export.go +++ b/internals/secrethub/repo_export.go @@ -41,6 +41,7 @@ func NewRepoExportCommand(io ui.IO, newClient newClientFunc) *RepoExportCommand func (cmd *RepoExportCommand) Register(r command.Registerer) { clause := r.CreateCommand("export", "Export the repository to a zip file.") clause.Args = cobra.RangeArgs(1, 2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo-path", "The repository to export").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("zip-file-name", "The file name to assign to the exported .zip file. Defaults to secrethub_export___.zip with the timestamp formatted as YYYYMMDD_HHMMSS").StringVar(&cmd.zipName) diff --git a/internals/secrethub/repo_init.go b/internals/secrethub/repo_init.go index 93634240..cbe39509 100644 --- a/internals/secrethub/repo_init.go +++ b/internals/secrethub/repo_init.go @@ -30,6 +30,7 @@ func NewRepoInitCommand(io ui.IO, newClient newClientFunc) *RepoInitCommand { func (cmd *RepoInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Initialize a new repository.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo-path", "Path to the new repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/repo_inspect.go b/internals/secrethub/repo_inspect.go index e0f63716..82d2a69b 100644 --- a/internals/secrethub/repo_inspect.go +++ b/internals/secrethub/repo_inspect.go @@ -33,6 +33,7 @@ func NewRepoInspectCommand(io ui.IO, newClient newClientFunc) *RepoInspectComman func (cmd *RepoInspectCommand) Register(r command.Registerer) { clause := r.CreateCommand("inspect", "Show the details of a repository.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo-path", "Path to the repository").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/repo_invite.go b/internals/secrethub/repo_invite.go index 21313d79..83479539 100644 --- a/internals/secrethub/repo_invite.go +++ b/internals/secrethub/repo_invite.go @@ -32,6 +32,7 @@ func NewRepoInviteCommand(io ui.IO, newClient newClientFunc) *RepoInviteCommand func (cmd *RepoInviteCommand) Register(r command.Registerer) { clause := r.CreateCommand("invite", "Invite a user to collaborate on a repository.") clause.Args = cobra.ExactValidArgs(2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo-path", "The repository to invite the user to").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("username", "username of the user").Required().StringVar(&cmd.username) registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/repo_ls.go b/internals/secrethub/repo_ls.go index de69feb5..b4508c0c 100644 --- a/internals/secrethub/repo_ls.go +++ b/internals/secrethub/repo_ls.go @@ -35,6 +35,7 @@ func (cmd *RepoLSCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", "List all repositories you have access to.") clause.Alias("list") clause.Args = cobra.MaximumNArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.NamespaceSuggestions clause.BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print paths.", true, false) //clause.Arg("workspace", "When supplied, results are limited to repositories in this workspace.").SetValue(&cmd.workspace) registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/repo_revoke.go b/internals/secrethub/repo_revoke.go index 039d694c..8edffb25 100644 --- a/internals/secrethub/repo_revoke.go +++ b/internals/secrethub/repo_revoke.go @@ -33,6 +33,7 @@ func NewRepoRevokeCommand(io ui.IO, newClient newClientFunc) *RepoRevokeCommand func (cmd *RepoRevokeCommand) Register(r command.Registerer) { clause := r.CreateCommand("revoke", "Revoke an account's access to a repository. A list of secrets that should be rotated will be printed out.") clause.Args = cobra.ExactValidArgs(2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo-path", "The repository to revoke the account from").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/repo_rm.go b/internals/secrethub/repo_rm.go index 223c5af7..95008207 100644 --- a/internals/secrethub/repo_rm.go +++ b/internals/secrethub/repo_rm.go @@ -31,6 +31,7 @@ func (cmd *RepoRmCommand) Register(r command.Registerer) { clause := r.CreateCommand("rm", "Permanently delete a repository.") clause.Alias("remove") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo-path", "The repository to delete").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/rm.go b/internals/secrethub/rm.go index 949c34cd..7cb6f59e 100644 --- a/internals/secrethub/rm.go +++ b/internals/secrethub/rm.go @@ -41,6 +41,7 @@ func (cmd *RmCommand) Register(r command.Registerer) { clause := r.CreateCommand("rm", "Remove a directory, secret or version.") clause.Alias("remove") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions //clause.Arg("path", "The path to the resource to remove (/[/])").Required().SetValue(&cmd.path) clause.BoolVarP(&cmd.recursive, "recursive", "r", false, "Remove directories and their contents recursively.", true, false) registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 59575581..0018b437 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -166,6 +166,7 @@ func (cmd *ServiceAWSInitCommand) argumentRegister(c *cobra.Command, args []stri func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to an AWS IAM role.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.StringVar(&cmd.kmsKeyID, "kms-key", "", "The ID or ARN of the KMS-key to be used for encrypting the service's account key.", true, false) clause.StringVar(&cmd.role, "role", "", "The role name or ARN of the IAM role that should have access to this service account.", true, false) diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index 33104bbd..da798fdd 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -168,6 +168,7 @@ func (cmd *ServiceGCPInitCommand) argumentRegister(c *cobra.Command, args []stri func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account that is tied to a GCP Service Account.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.StringVar(&cmd.kmsKeyResourceID, "kms-key", "", "The Resource ID of the KMS-key to be used for encrypting the service's account key.", true, false) clause.StringVar(&cmd.serviceAccountEmail, "service-account-email", "", "The email of the GCP Service Account that should have access to this service account.", true, false) diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index dda63b92..113cfcdf 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -67,6 +67,7 @@ func (cmd *ServiceGCPLinkCommand) argumentRegister(c *cobra.Command, args []stri func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { clause := r.CreateCommand("link", "Create a new link between a namespace and a GCP project to allow creating SecretHub service accounts for GCP Service Accounts in the GCP project.") clause.Args = cobra.ExactValidArgs(2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.NamespaceSuggestions //clause.Arg("namespace", "The SecretHub namespace to link.").Required().SetValue(&cmd.namespace) //clause.Arg("project-id", "The GCP project to link the namespace to.").Required().SetValue(&cmd.projectID) @@ -148,6 +149,7 @@ func (cmd *ServiceGCPListLinksCommand) argumentRegister(c *cobra.Command, args [ func (cmd *ServiceGCPListLinksCommand) Register(r command.Registerer) { clause := r.CreateCommand("list-links", "List all existing links between the given namespace and GCP projects.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.NamespaceSuggestions //clause.Arg("namespace", "The namespace for which to list all existing links to GCP projects.").Required().SetValue(&cmd.namespace) registerTimestampFlag(clause, &cmd.useTimestamps) @@ -173,6 +175,7 @@ func (cmd *ServiceGCPDeleteLinkCommand) Register(r command.Registerer) { clause := r.CreateCommand("delete-link", "Delete the link between a SecretHub namespace and a GCP project.") clause.HelpLong("After deleting the link you cannot create new GCP service accounts in the specified namespace and GCP project anymore. Exisiting service accounts will keep on working.") clause.Args = cobra.ExactValidArgs(2) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.NamespaceSuggestions //clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().SetValue(&cmd.namespace) //clause.Arg("project-id", "The GCP project to delete the link to.").Required().SetValue(&cmd.projectID) diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index e3b135d4..d082e7df 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -107,6 +107,7 @@ func (cmd *ServiceInitCommand) Run() error { func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause := r.CreateCommand("init", "Create a new service account.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo", "The service account is attached to the repository in this path.").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repo) clause.StringVar(&cmd.description, "description", "", "A description for the service so others will recognize it.", true, false) clause.StringVar(&cmd.description, "descr", "", "", true, false) diff --git a/internals/secrethub/service_ls.go b/internals/secrethub/service_ls.go index cda5d85c..e226683b 100644 --- a/internals/secrethub/service_ls.go +++ b/internals/secrethub/service_ls.go @@ -64,6 +64,7 @@ func (cmd *ServiceLsCommand) Register(r command.Registerer) { clause := r.CreateCommand("ls", cmd.help) clause.Alias("list") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions //clause.Arg("repo-path", "The path to the repository to list services for").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.repoPath) clause.BoolVarP(&cmd.quiet, "quiet", "q", false, "Only print service IDs.", true, false) registerTimestampFlag(clause, &cmd.useTimestamps) diff --git a/internals/secrethub/tree.go b/internals/secrethub/tree.go index aa1f90fb..6bff8bed 100644 --- a/internals/secrethub/tree.go +++ b/internals/secrethub/tree.go @@ -59,6 +59,7 @@ func (cmd *TreeCommand) argumentRegister(c *cobra.Command, args []string) error func (cmd *TreeCommand) Register(r command.Registerer) { clause := r.CreateCommand("tree", "List contents of a directory in a tree-like format.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions //clause.Arg("dir-path", "The path to to show contents for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) clause.BoolVarP(&cmd.fullPaths, "full-paths", "f", false, "Print the full path of each directory and secret.", true, false) diff --git a/internals/secrethub/write.go b/internals/secrethub/write.go index d1b96082..52041255 100644 --- a/internals/secrethub/write.go +++ b/internals/secrethub/write.go @@ -45,6 +45,7 @@ func NewWriteCommand(io ui.IO, newClient newClientFunc) *WriteCommand { func (cmd *WriteCommand) Register(r command.Registerer) { clause := r.CreateCommand("write", "Write a secret.") clause.Args = cobra.ExactValidArgs(1) + clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.SecretSuggestions //clause.Arg("secret-path", "The path to the secret").Required().PlaceHolder(secretPathPlaceHolder).SetValue(&cmd.path) clause.BoolVarP(&cmd.useClipboard, "clip", "c", false, "Use clipboard content as input.", true, false) clause.BoolVarP(&cmd.multiline, "multiline", "m", false, "Prompt for multiple lines of input, until an EOF is reached. On Linux/Mac, press CTRL-D to end input. On Windows, press CTRL-Z and then ENTER to end input.", true, false) From 024bcbe1b0740c90fffdca2b19736907152b026d Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Fri, 14 Aug 2020 16:39:54 +0200 Subject: [PATCH 40/41] Fix lint --- internals/secrethub/client_factory.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internals/secrethub/client_factory.go b/internals/secrethub/client_factory.go index a460c5ab..eee3332c 100644 --- a/internals/secrethub/client_factory.go +++ b/internals/secrethub/client_factory.go @@ -1,7 +1,6 @@ package secrethub import ( - "github.com/spf13/cobra" "net/http" "net/url" "strings" @@ -11,6 +10,8 @@ import ( "github.com/secrethub/secrethub-go/pkg/secrethub" "github.com/secrethub/secrethub-go/pkg/secrethub/configdir" "github.com/secrethub/secrethub-go/pkg/secrethub/credentials" + + "github.com/spf13/cobra" ) // Errors From 331105d5fe838e5ce1a1e8f11989b950838eefdc Mon Sep 17 00:00:00 2001 From: Eduard Filip Date: Fri, 14 Aug 2020 17:59:03 +0200 Subject: [PATCH 41/41] Enhance autocompletion for commands with multiple arguments --- internals/cli/env.go | 4 ++-- internals/secrethub/acl_check.go | 7 ++++++- internals/secrethub/acl_rm.go | 7 ++++++- internals/secrethub/acl_set.go | 9 ++++++++- internals/secrethub/generate.go | 6 ++++++ internals/secrethub/org_invite.go | 10 +++++++++- internals/secrethub/org_revoke.go | 7 ++++++- internals/secrethub/org_set_role.go | 4 +++- internals/secrethub/repo_export.go | 7 ++++++- internals/secrethub/repo_invite.go | 7 ++++++- internals/secrethub/repo_revoke.go | 7 ++++++- internals/secrethub/service_aws_init.go | 3 +++ internals/secrethub/service_gcp_init.go | 3 +++ internals/secrethub/service_gcp_link.go | 14 ++++++++++++-- internals/secrethub/service_init.go | 3 +++ 15 files changed, 85 insertions(+), 13 deletions(-) diff --git a/internals/cli/env.go b/internals/cli/env.go index 2d5d0815..fdeae306 100644 --- a/internals/cli/env.go +++ b/internals/cli/env.go @@ -34,7 +34,7 @@ type App struct { // NewApp defines a new command-line application. func NewApp(name, help string) *App { return &App{ - Application: cobra.Command{Use: name, Short: help}, + Application: cobra.Command{Use: name, Short: help, SilenceErrors: true, SilenceUsage: true}, name: formatName(name, "", DefaultEnvSeparator, DefaultCommandDelimiters...), delimiters: DefaultCommandDelimiters, separator: DefaultEnvSeparator, @@ -47,7 +47,7 @@ func NewApp(name, help string) *App { func (a *App) CreateCommand(name, help string) *CommandClause { return &CommandClause{ Command: func() *cobra.Command { - newCommand := &cobra.Command{Use: name, Short: help} + newCommand := &cobra.Command{Use: name, Short: help, SilenceErrors: true, SilenceUsage: true} a.Application.AddCommand(newCommand) return newCommand }(), diff --git a/internals/secrethub/acl_check.go b/internals/secrethub/acl_check.go index 3a0f4c0f..d2298bf1 100644 --- a/internals/secrethub/acl_check.go +++ b/internals/secrethub/acl_check.go @@ -35,7 +35,12 @@ func NewACLCheckCommand(io ui.IO, newClient newClientFunc) *ACLCheckCommand { func (cmd *ACLCheckCommand) Register(r command.Registerer) { clause := r.CreateCommand("check", "Checks the effective permission of accounts on a path.") clause.Args = cobra.RangeArgs(1, 2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.DirectorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("dir-path", "The path of the directory to check the effective permission for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "Check permissions of a specific account name (username or service name). When left empty, all accounts with permission on the path are printed out.").SetValue(&cmd.accountName) diff --git a/internals/secrethub/acl_rm.go b/internals/secrethub/acl_rm.go index f5f07d12..ecba4b4a 100644 --- a/internals/secrethub/acl_rm.go +++ b/internals/secrethub/acl_rm.go @@ -31,7 +31,12 @@ func (cmd *ACLRmCommand) Register(r command.Registerer) { clause := r.CreateCommand("rm", "Remove an account's access rules on a given directory. Although the server will deny the account access afterwards, note that removing an access rule does not actually revoke an account and does NOT trigger secret rotation.") clause.Alias("remove") clause.Args = cobra.ExactValidArgs(2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.DirectorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("dir-path", "The path of the directory to remove the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) whose rule to remove").Required().SetValue(&cmd.accountName) registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/acl_set.go b/internals/secrethub/acl_set.go index 0dd027b5..b8a28cfc 100644 --- a/internals/secrethub/acl_set.go +++ b/internals/secrethub/acl_set.go @@ -32,7 +32,14 @@ func NewACLSetCommand(io ui.IO, newClient newClientFunc) *ACLSetCommand { func (cmd *ACLSetCommand) Register(r command.Registerer) { clause := r.CreateCommand("set", "Set access rule for an user or service on a path.") clause.Args = cobra.ExactValidArgs(3) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.DirectorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.DirectorySuggestions(cmd, args, toComplete) + } else if len(args) == 1 { + return []string{}, cobra.ShellCompDirectiveDefault + } + return []string{"read", "write", "admin"}, cobra.ShellCompDirectiveDefault + } //clause.Arg("dir-path", "The path of the directory to set the access rule for").Required().PlaceHolder(optionalDirPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to set the access rule for").Required().SetValue(&cmd.accountName) //clause.Arg("permission", "The permission to set in the access rule.").Required().SetValue(&cmd.permission) diff --git a/internals/secrethub/generate.go b/internals/secrethub/generate.go index 6a8db4c0..d734730b 100644 --- a/internals/secrethub/generate.go +++ b/internals/secrethub/generate.go @@ -64,6 +64,12 @@ func NewGenerateSecretCommand(io ui.IO, newClient newClientFunc) *GenerateSecret func (cmd *GenerateSecretCommand) Register(r command.Registerer) { clause := r.CreateCommand("generate", "Generate a random secret.") clause.Args = cobra.RangeArgs(1, 3) + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.SecretSuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("secret-path", "The path to write the generated secret to").Required().PlaceHolder(secretPathPlaceHolder).StringVar(&cmd.firstArg) clause.VarP(&cmd.lengthFlag, "length", "l", "The length of the generated secret. Defaults to "+strconv.Itoa(defaultLength), true, false) //.PlaceHolder(strconv.Itoa(defaultLength)).Short('l').SetValue(&cmd.lengthFlag) clause.Flag("length").DefValue = strconv.Itoa(defaultLength) diff --git a/internals/secrethub/org_invite.go b/internals/secrethub/org_invite.go index 601fdd72..582d711b 100644 --- a/internals/secrethub/org_invite.go +++ b/internals/secrethub/org_invite.go @@ -33,10 +33,18 @@ func NewOrgInviteCommand(io ui.IO, newClient newClientFunc) *OrgInviteCommand { func (cmd *OrgInviteCommand) Register(r command.Registerer) { clause := r.CreateCommand("invite", "Invite a user to join an organization.") clause.Args = cobra.ExactValidArgs(2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.RepositorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user to invite").Required().StringVar(&cmd.username) clause.StringVar(&cmd.role, "role", "member", "Assign a role to the invited member. This can be either `admin` or `member`. It defaults to `member`.", true, false) + _ = clause.RegisterFlagCompletionFunc("role", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"admin", "member"}, cobra.ShellCompDirectiveDefault + }) registerForceFlag(clause, &cmd.force) command.BindAction(clause, cmd.argumentRegister, cmd.Run) diff --git a/internals/secrethub/org_revoke.go b/internals/secrethub/org_revoke.go index c17c2aee..cc504cdd 100644 --- a/internals/secrethub/org_revoke.go +++ b/internals/secrethub/org_revoke.go @@ -33,7 +33,12 @@ func NewOrgRevokeCommand(io ui.IO, newClient newClientFunc) *OrgRevokeCommand { func (cmd *OrgRevokeCommand) Register(r command.Registerer) { clause := r.CreateCommand("revoke", "Revoke a user from an organization. This automatically revokes the user from all of the organization's repositories. A list of repositories containing secrets that should be rotated will be printed out.") clause.Args = cobra.ExactValidArgs(2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.RepositorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) diff --git a/internals/secrethub/org_set_role.go b/internals/secrethub/org_set_role.go index c216f988..d0e5d66a 100644 --- a/internals/secrethub/org_set_role.go +++ b/internals/secrethub/org_set_role.go @@ -35,8 +35,10 @@ func (cmd *OrgSetRoleCommand) Register(r command.Registerer) { clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { return AutoCompleter{client: GetClient()}.RepositorySuggestions(cmd, args, toComplete) + } else if len(args) == 1 { + return []string{}, cobra.ShellCompDirectiveDefault } - return []string{}, cobra.ShellCompDirectiveDefault + return []string{"admin", "member"}, cobra.ShellCompDirectiveDefault } //clause.Arg("org-name", "The organization name").Required().SetValue(&cmd.orgName) //clause.Arg("username", "The username of the user").Required().StringVar(&cmd.username) diff --git a/internals/secrethub/repo_export.go b/internals/secrethub/repo_export.go index 5d86df27..69ef32fc 100644 --- a/internals/secrethub/repo_export.go +++ b/internals/secrethub/repo_export.go @@ -41,7 +41,12 @@ func NewRepoExportCommand(io ui.IO, newClient newClientFunc) *RepoExportCommand func (cmd *RepoExportCommand) Register(r command.Registerer) { clause := r.CreateCommand("export", "Export the repository to a zip file.") clause.Args = cobra.RangeArgs(1, 2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.RepositorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("repo-path", "The repository to export").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("zip-file-name", "The file name to assign to the exported .zip file. Defaults to secrethub_export___.zip with the timestamp formatted as YYYYMMDD_HHMMSS").StringVar(&cmd.zipName) diff --git a/internals/secrethub/repo_invite.go b/internals/secrethub/repo_invite.go index 83479539..2905fdfa 100644 --- a/internals/secrethub/repo_invite.go +++ b/internals/secrethub/repo_invite.go @@ -32,7 +32,12 @@ func NewRepoInviteCommand(io ui.IO, newClient newClientFunc) *RepoInviteCommand func (cmd *RepoInviteCommand) Register(r command.Registerer) { clause := r.CreateCommand("invite", "Invite a user to collaborate on a repository.") clause.Args = cobra.ExactValidArgs(2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.RepositorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("repo-path", "The repository to invite the user to").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("username", "username of the user").Required().StringVar(&cmd.username) registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/repo_revoke.go b/internals/secrethub/repo_revoke.go index 8edffb25..8488e69b 100644 --- a/internals/secrethub/repo_revoke.go +++ b/internals/secrethub/repo_revoke.go @@ -33,7 +33,12 @@ func NewRepoRevokeCommand(io ui.IO, newClient newClientFunc) *RepoRevokeCommand func (cmd *RepoRevokeCommand) Register(r command.Registerer) { clause := r.CreateCommand("revoke", "Revoke an account's access to a repository. A list of secrets that should be rotated will be printed out.") clause.Args = cobra.ExactValidArgs(2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.RepositorySuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.RepositorySuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("repo-path", "The repository to revoke the account from").Required().PlaceHolder(repoPathPlaceHolder).SetValue(&cmd.path) //clause.Arg("account-name", "The account name (username or service name) to revoke access for").Required().SetValue(&cmd.accountName) registerForceFlag(clause, &cmd.force) diff --git a/internals/secrethub/service_aws_init.go b/internals/secrethub/service_aws_init.go index 0018b437..b0f09525 100644 --- a/internals/secrethub/service_aws_init.go +++ b/internals/secrethub/service_aws_init.go @@ -177,6 +177,9 @@ func (cmd *ServiceAWSInitCommand) Register(r command.Registerer) { clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true clause.StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.", true, false) + _ = clause.RegisterFlagCompletionFunc("permission", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"read", "write", "admin"}, cobra.ShellCompDirectiveDefault + }) clause.HelpLong("The native AWS identity provider uses a combination of AWS IAM and AWS KMS to provide access to SecretHub for any service running on AWS (e.g. EC2, Lambda or ECS). For this to work, an IAM role and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_gcp_init.go b/internals/secrethub/service_gcp_init.go index da798fdd..c2be0952 100644 --- a/internals/secrethub/service_gcp_init.go +++ b/internals/secrethub/service_gcp_init.go @@ -178,6 +178,9 @@ func (cmd *ServiceGCPInitCommand) Register(r command.Registerer) { clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true clause.StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.", true, false) + _ = clause.RegisterFlagCompletionFunc("permission", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"read", "write", "admin"}, cobra.ShellCompDirectiveDefault + }) clause.HelpLong("The native GCP identity provider uses a combination of GCP IAM and GCP KMS to provide access to SecretHub for any service running on GCP. For this to work, a GCP Service Account and a KMS key are needed.\n" + "\n" + diff --git a/internals/secrethub/service_gcp_link.go b/internals/secrethub/service_gcp_link.go index 113cfcdf..420059b3 100644 --- a/internals/secrethub/service_gcp_link.go +++ b/internals/secrethub/service_gcp_link.go @@ -67,7 +67,12 @@ func (cmd *ServiceGCPLinkCommand) argumentRegister(c *cobra.Command, args []stri func (cmd *ServiceGCPLinkCommand) Register(r command.Registerer) { clause := r.CreateCommand("link", "Create a new link between a namespace and a GCP project to allow creating SecretHub service accounts for GCP Service Accounts in the GCP project.") clause.Args = cobra.ExactValidArgs(2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.NamespaceSuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.NamespaceSuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("namespace", "The SecretHub namespace to link.").Required().SetValue(&cmd.namespace) //clause.Arg("project-id", "The GCP project to link the namespace to.").Required().SetValue(&cmd.projectID) @@ -175,7 +180,12 @@ func (cmd *ServiceGCPDeleteLinkCommand) Register(r command.Registerer) { clause := r.CreateCommand("delete-link", "Delete the link between a SecretHub namespace and a GCP project.") clause.HelpLong("After deleting the link you cannot create new GCP service accounts in the specified namespace and GCP project anymore. Exisiting service accounts will keep on working.") clause.Args = cobra.ExactValidArgs(2) - clause.ValidArgsFunction = AutoCompleter{client: GetClient()}.NamespaceSuggestions + clause.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return AutoCompleter{client: GetClient()}.NamespaceSuggestions(cmd, args, toComplete) + } + return []string{}, cobra.ShellCompDirectiveDefault + } //clause.Arg("namespace", "The SecretHub namespace to delete the link from.").Required().SetValue(&cmd.namespace) //clause.Arg("project-id", "The GCP project to delete the link to.").Required().SetValue(&cmd.projectID) diff --git a/internals/secrethub/service_init.go b/internals/secrethub/service_init.go index d082e7df..8987c22c 100644 --- a/internals/secrethub/service_init.go +++ b/internals/secrethub/service_init.go @@ -115,6 +115,9 @@ func (cmd *ServiceInitCommand) Register(r command.Registerer) { clause.Flag("desc").Hidden = true clause.Flag("descr").Hidden = true clause.StringVar(&cmd.permission, "permission", "", "Create an access rule giving the service account permission on a directory. Accepted permissions are `read`, `write` and `admin`. Use `--permission ` to give permission on the root of the repo and `--permission [/ ...]:` to give permission on a subdirectory.", true, false) + _ = clause.RegisterFlagCompletionFunc("permission", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return []string{"read", "write", "admin"}, cobra.ShellCompDirectiveDefault + }) // TODO make 45 sec configurable clause.BoolVarP(&cmd.clip, "clip", "c", false, "Write the service account configuration to the clipboard instead of stdout. The clipboard is automatically cleared after 45 seconds.", true, false) clause.StringVar(&cmd.file, "file", "", "Write the service account configuration to a file instead of stdout.", true, false)