diff --git a/cmd/agent/main.go b/cmd/agent/main.go index 9d9049bcb1..f4911a15f3 100644 --- a/cmd/agent/main.go +++ b/cmd/agent/main.go @@ -5,8 +5,8 @@ import ( "github.com/rancher/k3s/pkg/cli/agent" "github.com/rancher/k3s/pkg/cli/cmds" + "github.com/rancher/spur/cli" "github.com/sirupsen/logrus" - "github.com/urfave/cli" ) func main() { diff --git a/cmd/k3s/main.go b/cmd/k3s/main.go index 5c1bbc33b4..c2dfe775cb 100644 --- a/cmd/k3s/main.go +++ b/cmd/k3s/main.go @@ -14,8 +14,8 @@ import ( "github.com/rancher/k3s/pkg/datadir" "github.com/rancher/k3s/pkg/untar" "github.com/rancher/k3s/pkg/version" + "github.com/rancher/spur/cli" "github.com/sirupsen/logrus" - "github.com/urfave/cli" ) func main() { @@ -24,7 +24,7 @@ func main() { } app := cmds.NewApp() - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ cmds.NewServerCommand(wrap(version.Program+"-server", os.Args)), cmds.NewAgentCommand(wrap(version.Program+"-agent", os.Args)), cmds.NewKubectlCommand(externalCLIAction("kubectl")), @@ -56,7 +56,7 @@ func runCLIs() bool { func externalCLIAction(cmd string) func(cli *cli.Context) error { return func(cli *cli.Context) error { - return externalCLI(cmd, cli.String("data-dir"), cli.Args()) + return externalCLI(cmd, cli.String("data-dir"), cli.Args().Slice()) } } @@ -100,7 +100,6 @@ func stageAndRun(dataDir string, cmd string, args []string) error { if err != nil { return err } - logrus.Debugf("Running %s %v", cmd, args) return syscall.Exec(cmd, args, os.Environ()) } diff --git a/cmd/server/main.go b/cmd/server/main.go index 7fcd6e047b..386231610b 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -15,8 +15,8 @@ import ( "github.com/rancher/k3s/pkg/containerd" ctr2 "github.com/rancher/k3s/pkg/ctr" kubectl2 "github.com/rancher/k3s/pkg/kubectl" + "github.com/rancher/spur/cli" "github.com/sirupsen/logrus" - "github.com/urfave/cli" ) func init() { @@ -35,7 +35,7 @@ func main() { os.Args[0] = cmd app := cmds.NewApp() - app.Commands = []cli.Command{ + app.Commands = []*cli.Command{ cmds.NewServerCommand(server.Run), cmds.NewAgentCommand(agent.Run), cmds.NewKubectlCommand(kubectl.Run), diff --git a/go.mod b/go.mod index 2af70dfa83..177ae88595 100644 --- a/go.mod +++ b/go.mod @@ -100,6 +100,7 @@ require ( github.com/rancher/helm-controller v0.6.3 github.com/rancher/kine v0.4.0 github.com/rancher/remotedialer v0.2.0 + github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a github.com/rancher/wrangler v0.6.1 github.com/rancher/wrangler-api v0.6.0 github.com/rootless-containers/rootlesskit v0.7.2 @@ -113,7 +114,7 @@ require ( golang.org/x/net v0.0.0-20191204025024-5ee1b9f4859a golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e google.golang.org/grpc v1.26.0 - gopkg.in/yaml.v2 v2.2.8 + gopkg.in/yaml.v2 v2.3.0 k8s.io/api v0.18.0 k8s.io/apimachinery v0.18.0 k8s.io/apiserver v0.0.0 diff --git a/go.sum b/go.sum index e0976d4ff6..aa368e2129 100644 --- a/go.sum +++ b/go.sum @@ -150,8 +150,9 @@ github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea h1:n2Ltr3SrfQlf/9nOna1D github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= @@ -307,7 +308,6 @@ github.com/gogo/googleapis v1.3.0 h1:M695OaDJ5ipWvDPcoAg/YL9c3uORAegkEfBqTQF/fTQ github.com/gogo/googleapis v1.3.0/go.mod h1:d+q1s/xVJxZGKWwC/6UfPIF33J+G1Tq4GYv9Y+Tg/EU= 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/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE= github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -364,7 +364,6 @@ github.com/google/go-containerregistry v0.0.0-20190617215043-876b8855d23c/go.mod github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= -github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -418,7 +417,6 @@ github.com/heketi/heketi v9.0.1-0.20190917153846-c2e2a4ab7ab9+incompatible/go.mo github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7UkZt1i4FQeQy0R2T8GLUwQhOP5M1gBhy4= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -535,7 +533,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 h1:7InQ7/zrOh6SlFjaXFubv0xX0HsuC9qJsdqm7bNQpYM= @@ -557,7 +554,6 @@ github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -588,7 +584,6 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/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= @@ -673,8 +668,9 @@ github.com/rancher/nocode v0.0.0-20200630202308-cb097102c09f h1:mX6kuT3Ah9v1iEO3 github.com/rancher/nocode v0.0.0-20200630202308-cb097102c09f/go.mod h1:iAAt6Amgbysi6srDJs9SxGSbG2j/JSRb/xCrnEtA69g= github.com/rancher/remotedialer v0.2.0 h1:xD7t3K6JYwTdAsxmGtTHQMkEkFgKouQ1foLxVW424Dc= github.com/rancher/remotedialer v0.2.0/go.mod h1:tkU8ZvrR5lRgaKWaX71nAy6daeqvPFx/lJEnbW7tXSI= +github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a h1:MIWeFYPZ/XXnskvcUqV8W89PFs+n/mr4YWMHeZuMpYs= +github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a/go.mod h1:Q6L6c+4FRxY5CF1xG3oEAfH3tSQDf0NAZes7q7wRyPE= github.com/rancher/wrangler v0.1.4/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE= -github.com/rancher/wrangler v0.4.0 h1:iLvuJcZkd38E3RGG74dFMMNEju0PeTzfT1PQiv5okVU= github.com/rancher/wrangler v0.4.0/go.mod h1:1cR91WLhZgkZ+U4fV9nVuXqKurWbgXcIReU4wnQvTN8= github.com/rancher/wrangler v0.6.0/go.mod h1:L4HtjPeX8iqLgsxfJgz+JjKMcX2q3qbRXSeTlC/CSd4= github.com/rancher/wrangler v0.6.1 h1:7tyLk/FV2zCQkYg5SEtT4lSlsHNwa5yMOa797/VJhiQ= @@ -800,7 +796,6 @@ github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSf github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= go.etcd.io/etcd v0.5.0-alpha.5.0.20200520232829-54ba9589114f h1:pBCD+Z7cy5WPTq+R6MmJJvDRpn88cp7bmTypBsn91g4= go.etcd.io/etcd v0.5.0-alpha.5.0.20200520232829-54ba9589114f/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8= @@ -965,7 +960,6 @@ golang.org/x/tools v0.0.0-20191017205301-920acffc3e65 h1:GwXwgmbrvlcHLDsENMqrQTT golang.org/x/tools v0.0.0-20191017205301-920acffc3e65/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/gonum v0.6.2 h1:4r+yNT0+8SWcOkXP+63H2zQbN+USnC73cjGUxnDF94Q= gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= @@ -992,7 +986,6 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0 h1:2dTRdpdFEEhJYQD8EMLB61nnrzSCTbG38PhqdhvOltg= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1025,8 +1018,9 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= @@ -1039,7 +1033,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e h1:HqlU9dKk5YVs7R84jmq6U3Wo/XslpkxHpBv2iWHLtLc= k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120 h1:RPscN6KhmG54S33L+lr3GS+oD1jmchIU0ll519K6FA4= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= @@ -1075,7 +1068,6 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:w sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/main.go b/main.go index 62908bb7bb..58b47855d8 100644 --- a/main.go +++ b/main.go @@ -14,8 +14,8 @@ import ( "github.com/rancher/k3s/pkg/cli/crictl" "github.com/rancher/k3s/pkg/cli/kubectl" "github.com/rancher/k3s/pkg/cli/server" + "github.com/rancher/spur/cli" "github.com/sirupsen/logrus" - "github.com/urfave/cli" ) func main() { diff --git a/pkg/cli/agent/agent.go b/pkg/cli/agent/agent.go index 0d6c48caca..a4520ac5dd 100644 --- a/pkg/cli/agent/agent.go +++ b/pkg/cli/agent/agent.go @@ -12,15 +12,12 @@ import ( "github.com/rancher/k3s/pkg/netutil" "github.com/rancher/k3s/pkg/token" "github.com/rancher/k3s/pkg/version" + "github.com/rancher/spur/cli" "github.com/rancher/wrangler/pkg/signals" "github.com/sirupsen/logrus" - "github.com/urfave/cli" ) func Run(ctx *cli.Context) error { - if err := cmds.InitLogging(); err != nil { - return err - } if os.Getuid() != 0 && runtime.GOOS != "windows" { return fmt.Errorf("agent must be ran as root") } @@ -57,7 +54,7 @@ func Run(ctx *cli.Context) error { } cfg := cmds.AgentConfig - cfg.Debug = ctx.GlobalBool("debug") + cfg.Debug = ctx.Bool("debug") cfg.DataDir = dataDir contextCtx := signals.SetupSignalHandler(context.Background()) diff --git a/pkg/cli/cmds/agent.go b/pkg/cli/cmds/agent.go index 86fb35f3de..a234d6ea2f 100644 --- a/pkg/cli/cmds/agent.go +++ b/pkg/cli/cmds/agent.go @@ -5,7 +5,8 @@ import ( "path/filepath" "github.com/rancher/k3s/pkg/version" - "github.com/urfave/cli" + "github.com/rancher/spur/cli" + "github.com/rancher/spur/cli/altsrc" ) type Agent struct { @@ -30,12 +31,12 @@ type Agent struct { RootlessAlreadyUnshared bool WithNodeID bool DisableSELinux bool + ExtraKubeletArgs []string + ExtraKubeProxyArgs []string + Labels []string + Taints []string + PrivateRegistry string AgentShared - ExtraKubeletArgs cli.StringSlice - ExtraKubeProxyArgs cli.StringSlice - Labels cli.StringSlice - Taints cli.StringSlice - PrivateRegistry string } type AgentShared struct { @@ -58,7 +59,7 @@ var ( NodeNameFlag = cli.StringFlag{ Name: "node-name", Usage: "(agent/node) Node name", - EnvVar: version.ProgramUpper + "_NODE_NAME", + EnvVars: []string{version.ProgramUpper + "_NODE_NAME"}, Destination: &AgentConfig.NodeName, } WithNodeIDFlag = cli.BoolFlag{ @@ -106,28 +107,28 @@ var ( ResolvConfFlag = cli.StringFlag{ Name: "resolv-conf", Usage: "(agent/networking) Kubelet resolv.conf file", - EnvVar: version.ProgramUpper + "_RESOLV_CONF", + EnvVars: []string{version.ProgramUpper + "_RESOLV_CONF"}, Destination: &AgentConfig.ResolvConf, } ExtraKubeletArgs = cli.StringSliceFlag{ - Name: "kubelet-arg", - Usage: "(agent/flags) Customized flag for kubelet process", - Value: &AgentConfig.ExtraKubeletArgs, + Name: "kubelet-arg", + Usage: "(agent/flags) Customized flag for kubelet process", + Destination: &AgentConfig.ExtraKubeletArgs, } ExtraKubeProxyArgs = cli.StringSliceFlag{ - Name: "kube-proxy-arg", - Usage: "(agent/flags) Customized flag for kube-proxy process", - Value: &AgentConfig.ExtraKubeProxyArgs, + Name: "kube-proxy-arg", + Usage: "(agent/flags) Customized flag for kube-proxy process", + Destination: &AgentConfig.ExtraKubeProxyArgs, } NodeTaints = cli.StringSliceFlag{ - Name: "node-taint", - Usage: "(agent/node) Registering kubelet with set of taints", - Value: &AgentConfig.Taints, + Name: "node-taint", + Usage: "(agent/node) Registering kubelet with set of taints", + Destination: &AgentConfig.Taints, } NodeLabels = cli.StringSliceFlag{ - Name: "node-label", - Usage: "(agent/node) Registering and starting kubelet with set of labels", - Value: &AgentConfig.Labels, + Name: "node-label", + Usage: "(agent/node) Registering and starting kubelet with set of labels", + Destination: &AgentConfig.Labels, } DisableSELinuxFlag = cli.BoolFlag{ Name: "disable-selinux", @@ -137,58 +138,61 @@ var ( } ) -func NewAgentCommand(action func(ctx *cli.Context) error) cli.Command { - return cli.Command{ +func NewAgentCommand(action func(ctx *cli.Context) error) *cli.Command { + return &cli.Command{ Name: "agent", Usage: "Run node agent", UsageText: appName + " agent [OPTIONS]", - Action: action, + Before: DebugContext(cli.InitAllInputSource(altsrc.NewConfigFromFlag(ConfigFlag.Name))), + Action: InitLogging(action), Flags: []cli.Flag{ - VLevel, - VModule, - LogFile, - AlsoLogToStderr, - cli.StringFlag{ + &ConfigFlag, + &DebugFlag, + &VLevel, + &VModule, + &LogFile, + &AlsoLogToStderr, + &cli.StringFlag{ Name: "token,t", Usage: "(cluster) Token to use for authentication", - EnvVar: version.ProgramUpper + "_TOKEN", + EnvVars: []string{version.ProgramUpper + "_TOKEN"}, Destination: &AgentConfig.Token, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "token-file", Usage: "(cluster) Token file to use for authentication", - EnvVar: version.ProgramUpper + "_TOKEN_FILE", + EnvVars: []string{version.ProgramUpper + "_TOKEN_FILE"}, Destination: &AgentConfig.TokenFile, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "server,s", Usage: "(cluster) Server to connect to", - EnvVar: version.ProgramUpper + "_URL", + EnvVars: []string{version.ProgramUpper + "_URL"}, Destination: &AgentConfig.ServerURL, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "data-dir,d", Usage: "(agent/data) Folder to hold state", Destination: &AgentConfig.DataDir, Value: "/var/lib/rancher/" + version.Program + "", }, - NodeNameFlag, - WithNodeIDFlag, - NodeLabels, - NodeTaints, - DockerFlag, - DisableSELinuxFlag, - CRIEndpointFlag, - PauseImageFlag, - PrivateRegistryFlag, - NodeIPFlag, - NodeExternalIPFlag, - ResolvConfFlag, - FlannelIfaceFlag, - FlannelConfFlag, - ExtraKubeletArgs, - ExtraKubeProxyArgs, - cli.BoolFlag{ + &NodeNameFlag, + &WithNodeIDFlag, + &NodeLabels, + &NodeTaints, + &DockerFlag, + &DisableSELinuxFlag, + &CRIEndpointFlag, + &PauseImageFlag, + &PrivateRegistryFlag, + &NodeIPFlag, + &NodeExternalIPFlag, + &ResolvConfFlag, + &FlannelIfaceFlag, + &FlannelConfFlag, + &ExtraKubeletArgs, + &ExtraKubeProxyArgs, + &cli.BoolFlag{ Name: "rootless", Usage: "(experimental) Run rootless", Destination: &AgentConfig.Rootless, @@ -196,12 +200,12 @@ func NewAgentCommand(action func(ctx *cli.Context) error) cli.Command { // Deprecated/hidden below - FlannelFlag, - cli.StringFlag{ + &FlannelFlag, + &cli.StringFlag{ Name: "cluster-secret", Usage: "(deprecated) use --token", Destination: &AgentConfig.ClusterSecret, - EnvVar: version.ProgramUpper + "_CLUSTER_SECRET", + EnvVars: []string{version.ProgramUpper + "_CLUSTER_SECRET"}, }, }, } diff --git a/pkg/cli/cmds/check-config.go b/pkg/cli/cmds/check-config.go index ead97e47a9..71f0f009f2 100644 --- a/pkg/cli/cmds/check-config.go +++ b/pkg/cli/cmds/check-config.go @@ -1,15 +1,14 @@ package cmds import ( - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) -func NewCheckConfigCommand(action func(*cli.Context) error) cli.Command { - return cli.Command{ +func NewCheckConfigCommand(action func(*cli.Context) error) *cli.Command { + return &cli.Command{ Name: "check-config", Usage: "Run config check", SkipFlagParsing: true, - SkipArgReorder: true, Action: action, } } diff --git a/pkg/cli/cmds/config.go b/pkg/cli/cmds/config.go new file mode 100644 index 0000000000..d5e52e73cb --- /dev/null +++ b/pkg/cli/cmds/config.go @@ -0,0 +1,16 @@ +package cmds + +import ( + "github.com/rancher/spur/cli" +) + +var ( + DefaultConfig = "/etc/rancher/k3s/flags.conf" + ConfigFlag = cli.StringFlag{ + Name: "config", + Aliases: []string{"c"}, + Usage: "(config) Load configuration from `FILE`", + EnvVars: []string{"K3S_CONFIG_FILE"}, + Value: DefaultConfig, + } +) diff --git a/pkg/cli/cmds/crictl.go b/pkg/cli/cmds/crictl.go index ff1bbbbfd0..79c8a4e700 100644 --- a/pkg/cli/cmds/crictl.go +++ b/pkg/cli/cmds/crictl.go @@ -1,15 +1,14 @@ package cmds import ( - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) -func NewCRICTL(action func(*cli.Context) error) cli.Command { - return cli.Command{ +func NewCRICTL(action func(*cli.Context) error) *cli.Command { + return &cli.Command{ Name: "crictl", Usage: "Run crictl", SkipFlagParsing: true, - SkipArgReorder: true, Action: action, } } diff --git a/pkg/cli/cmds/ctr.go b/pkg/cli/cmds/ctr.go index c6a5e30ef7..3d701eaf14 100644 --- a/pkg/cli/cmds/ctr.go +++ b/pkg/cli/cmds/ctr.go @@ -1,15 +1,14 @@ package cmds import ( - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) -func NewCtrCommand(action func(*cli.Context) error) cli.Command { - return cli.Command{ +func NewCtrCommand(action func(*cli.Context) error) *cli.Command { + return &cli.Command{ Name: "ctr", Usage: "Run ctr", SkipFlagParsing: true, - SkipArgReorder: true, Action: action, } } diff --git a/pkg/cli/cmds/debug.go b/pkg/cli/cmds/debug.go new file mode 100644 index 0000000000..1290658dca --- /dev/null +++ b/pkg/cli/cmds/debug.go @@ -0,0 +1,31 @@ +package cmds + +import ( + "github.com/rancher/k3s/pkg/version" + "github.com/rancher/spur/cli" + "github.com/sirupsen/logrus" +) + +var ( + Debug = false + DebugFlag = cli.BoolFlag{ + Name: "debug", + Usage: "(logging) Turn on debug logs", + Destination: &Debug, + EnvVars: []string{version.ProgramUpper + "_DEBUG"}, + } +) + +func DebugContext(f func(*cli.Context) error) func(ctx *cli.Context) error { + return func(ctx *cli.Context) error { + if f != nil { + if err := f(ctx); err != nil { + return err + } + } + if Debug { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + } +} diff --git a/pkg/cli/cmds/kubectl.go b/pkg/cli/cmds/kubectl.go index 72bdd92371..a7338a74f9 100644 --- a/pkg/cli/cmds/kubectl.go +++ b/pkg/cli/cmds/kubectl.go @@ -1,15 +1,14 @@ package cmds import ( - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) -func NewKubectlCommand(action func(*cli.Context) error) cli.Command { - return cli.Command{ +func NewKubectlCommand(action func(*cli.Context) error) *cli.Command { + return &cli.Command{ Name: "kubectl", Usage: "Run kubectl", SkipFlagParsing: true, - SkipArgReorder: true, Action: action, } } diff --git a/pkg/cli/cmds/log.go b/pkg/cli/cmds/log.go index 44f6bd8d01..094fb488fa 100644 --- a/pkg/cli/cmds/log.go +++ b/pkg/cli/cmds/log.go @@ -12,7 +12,7 @@ import ( "github.com/docker/docker/pkg/reexec" "github.com/natefinch/lumberjack" "github.com/rancher/k3s/pkg/version" - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) type Log struct { @@ -49,22 +49,31 @@ var ( logSetupOnce sync.Once ) -func InitLogging() error { - var rErr error - logSetupOnce.Do(func() { - if LogConfig.LogFile != "" && os.Getenv("_K3S_LOG_REEXEC_") == "" { - rErr = runWithLogging() - return +func InitLogging(action func(*cli.Context) error) func(*cli.Context) error { + return func(ctx *cli.Context) error { + var ( + err error + reExec bool + ) + logSetupOnce.Do(func() { + if LogConfig.LogFile != "" && os.Getenv("_K3S_LOG_REEXEC_") == "" { + reExec = true + err = runWithLogging() + return + } + if err = checkUnixTimestamp(); err != nil { + return + } + setupLogging() + }) + if reExec || err != nil { + return err } - - if err := checkUnixTimestamp(); err != nil { - rErr = err - return + if action != nil { + return action(ctx) } - - setupLogging() - }) - return rErr + return nil + } } func checkUnixTimestamp() error { diff --git a/pkg/cli/cmds/root.go b/pkg/cli/cmds/root.go index 212ec13075..6c3da34e13 100644 --- a/pkg/cli/cmds/root.go +++ b/pkg/cli/cmds/root.go @@ -5,12 +5,7 @@ import ( "os" "github.com/rancher/k3s/pkg/version" - "github.com/sirupsen/logrus" - "github.com/urfave/cli" -) - -var ( - Debug bool + "github.com/rancher/spur/cli" ) func init() { @@ -28,21 +23,8 @@ func NewApp() *cli.App { cli.VersionPrinter = func(c *cli.Context) { fmt.Printf("%s version %s\n", app.Name, app.Version) } - app.Flags = []cli.Flag{ - cli.BoolFlag{ - Name: "debug", - Usage: "Turn on debug logs", - Destination: &Debug, - EnvVar: version.ProgramUpper + "_DEBUG", - }, - } - - app.Before = func(ctx *cli.Context) error { - if Debug { - logrus.SetLevel(logrus.DebugLevel) - } - return nil - } + app.Flags = []cli.Flag{&DebugFlag} + app.Before = DebugContext(nil) return app } diff --git a/pkg/cli/cmds/server.go b/pkg/cli/cmds/server.go index ccb7974b76..bae6bc4889 100644 --- a/pkg/cli/cmds/server.go +++ b/pkg/cli/cmds/server.go @@ -2,7 +2,8 @@ package cmds import ( "github.com/rancher/k3s/pkg/version" - "github.com/urfave/cli" + "github.com/rancher/spur/cli" + "github.com/rancher/spur/cli/altsrc" ) const ( @@ -30,12 +31,12 @@ type Server struct { DisableAgent bool KubeConfigOutput string KubeConfigMode string - TLSSan cli.StringSlice + TLSSan []string BindAddress string - ExtraAPIArgs cli.StringSlice - ExtraSchedulerArgs cli.StringSlice - ExtraControllerArgs cli.StringSlice - ExtraCloudControllerArgs cli.StringSlice + ExtraAPIArgs []string + ExtraSchedulerArgs []string + ExtraControllerArgs []string + ExtraCloudControllerArgs []string Rootless bool DatastoreEndpoint string DatastoreCAFile string @@ -57,229 +58,232 @@ type Server struct { var ServerConfig Server -func NewServerCommand(action func(*cli.Context) error) cli.Command { - return cli.Command{ +func NewServerCommand(action func(*cli.Context) error) *cli.Command { + return &cli.Command{ Name: "server", Usage: "Run management server", UsageText: appName + " server [OPTIONS]", - Action: action, + Before: DebugContext(cli.InitAllInputSource(altsrc.NewConfigFromFlag(ConfigFlag.Name))), + Action: InitLogging(action), Flags: []cli.Flag{ - VLevel, - VModule, - LogFile, - AlsoLogToStderr, - cli.StringFlag{ + &ConfigFlag, + &DebugFlag, + &VLevel, + &VModule, + &LogFile, + &AlsoLogToStderr, + &cli.StringFlag{ Name: "bind-address", Usage: "(listener) " + version.Program + " bind address (default: 0.0.0.0)", Destination: &ServerConfig.BindAddress, }, - cli.IntFlag{ + &cli.IntFlag{ Name: "https-listen-port", Usage: "(listener) HTTPS listen port", Value: 6443, Destination: &ServerConfig.HTTPSPort, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "advertise-address", Usage: "(listener) IP address that apiserver uses to advertise to members of the cluster (default: node-external-ip/node-ip)", Destination: &ServerConfig.AdvertiseIP, }, - cli.IntFlag{ + &cli.IntFlag{ Name: "advertise-port", Usage: "(listener) Port that apiserver uses to advertise to members of the cluster (default: listen-port)", Destination: &ServerConfig.AdvertisePort, }, - cli.StringSliceFlag{ - Name: "tls-san", - Usage: "(listener) Add additional hostname or IP as a Subject Alternative Name in the TLS cert", - Value: &ServerConfig.TLSSan, + &cli.StringSliceFlag{ + Name: "tls-san", + Usage: "(listener) Add additional hostname or IP as a Subject Alternative Name in the TLS cert", + Destination: &ServerConfig.TLSSan, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "data-dir,d", Usage: "(data) Folder to hold state default /var/lib/rancher/" + version.Program + " or ${HOME}/.rancher/" + version.Program + " if not root", Destination: &ServerConfig.DataDir, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "cluster-cidr", Usage: "(networking) Network CIDR to use for pod IPs", Destination: &ServerConfig.ClusterCIDR, Value: "10.42.0.0/16", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "service-cidr", Usage: "(networking) Network CIDR to use for services IPs", Destination: &ServerConfig.ServiceCIDR, Value: "10.43.0.0/16", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "cluster-dns", Usage: "(networking) Cluster IP for coredns service. Should be in your service-cidr range (default: 10.43.0.10)", Destination: &ServerConfig.ClusterDNS, Value: "", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "cluster-domain", Usage: "(networking) Cluster Domain", Destination: &ServerConfig.ClusterDomain, Value: "cluster.local", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "flannel-backend", Usage: "(networking) One of 'none', 'vxlan', 'ipsec', 'host-gw', or 'wireguard'", Destination: &ServerConfig.FlannelBackend, Value: "vxlan", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "token,t", Usage: "(cluster) Shared secret used to join a server or agent to a cluster", Destination: &ServerConfig.Token, - EnvVar: version.ProgramUpper + "_TOKEN", + EnvVars: []string{version.ProgramUpper + "_TOKEN"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "token-file", Usage: "(cluster) File containing the cluster-secret/token", Destination: &ServerConfig.TokenFile, - EnvVar: version.ProgramUpper + "_TOKEN_FILE", + EnvVars: []string{version.ProgramUpper + "_TOKEN_FILE"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "write-kubeconfig,o", Usage: "(client) Write kubeconfig for admin client to this file", Destination: &ServerConfig.KubeConfigOutput, - EnvVar: version.ProgramUpper + "_KUBECONFIG_OUTPUT", + EnvVars: []string{version.ProgramUpper + "_KUBECONFIG_OUTPUT"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "write-kubeconfig-mode", Usage: "(client) Write kubeconfig with this mode", Destination: &ServerConfig.KubeConfigMode, - EnvVar: version.ProgramUpper + "_KUBECONFIG_MODE", + EnvVars: []string{version.ProgramUpper + "_KUBECONFIG_MODE"}, }, - cli.StringSliceFlag{ - Name: "kube-apiserver-arg", - Usage: "(flags) Customized flag for kube-apiserver process", - Value: &ServerConfig.ExtraAPIArgs, + &cli.StringSliceFlag{ + Name: "kube-apiserver-arg", + Usage: "(flags) Customized flag for kube-apiserver process", + Destination: &ServerConfig.ExtraAPIArgs, }, - cli.StringSliceFlag{ - Name: "kube-scheduler-arg", - Usage: "(flags) Customized flag for kube-scheduler process", - Value: &ServerConfig.ExtraSchedulerArgs, + &cli.StringSliceFlag{ + Name: "kube-scheduler-arg", + Usage: "(flags) Customized flag for kube-scheduler process", + Destination: &ServerConfig.ExtraSchedulerArgs, }, - cli.StringSliceFlag{ - Name: "kube-controller-manager-arg", - Usage: "(flags) Customized flag for kube-controller-manager process", - Value: &ServerConfig.ExtraControllerArgs, + &cli.StringSliceFlag{ + Name: "kube-controller-manager-arg", + Usage: "(flags) Customized flag for kube-controller-manager process", + Destination: &ServerConfig.ExtraControllerArgs, }, - cli.StringSliceFlag{ - Name: "kube-cloud-controller-manager-arg", - Usage: "(flags) Customized flag for kube-cloud-controller-manager process", - Value: &ServerConfig.ExtraCloudControllerArgs, + &cli.StringSliceFlag{ + Name: "kube-cloud-controller-manager-arg", + Usage: "(flags) Customized flag for kube-cloud-controller-manager process", + Destination: &ServerConfig.ExtraCloudControllerArgs, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "datastore-endpoint", Usage: "(db) Specify etcd, Mysql, Postgres, or Sqlite (default) data source name", Destination: &ServerConfig.DatastoreEndpoint, - EnvVar: version.ProgramUpper + "_DATASTORE_ENDPOINT", + EnvVars: []string{version.ProgramUpper + "_DATASTORE_ENDPOINT"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "datastore-cafile", Usage: "(db) TLS Certificate Authority file used to secure datastore backend communication", Destination: &ServerConfig.DatastoreCAFile, - EnvVar: version.ProgramUpper + "_DATASTORE_CAFILE", + EnvVars: []string{version.ProgramUpper + "_DATASTORE_CAFILE"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "datastore-certfile", Usage: "(db) TLS certification file used to secure datastore backend communication", Destination: &ServerConfig.DatastoreCertFile, - EnvVar: version.ProgramUpper + "_DATASTORE_CERTFILE", + EnvVars: []string{version.ProgramUpper + "_DATASTORE_CERTFILE"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "datastore-keyfile", Usage: "(db) TLS key file used to secure datastore backend communication", Destination: &ServerConfig.DatastoreKeyFile, - EnvVar: version.ProgramUpper + "_DATASTORE_KEYFILE", + EnvVars: []string{version.ProgramUpper + "_DATASTORE_KEYFILE"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "default-local-storage-path", Usage: "(storage) Default local storage path for local provisioner storage class", Destination: &ServerConfig.DefaultLocalStoragePath, }, - cli.StringSliceFlag{ + &cli.StringSliceFlag{ Name: "disable", Usage: "(components) Do not deploy packaged components and delete any deployed components (valid items: " + DisableItems + ")", }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "disable-scheduler", Usage: "(components) Disable Kubernetes default scheduler", Destination: &ServerConfig.DisableScheduler, }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "disable-cloud-controller", Usage: "(components) Disable " + version.Program + " default cloud controller manager", Destination: &ServerConfig.DisableCCM, }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "disable-kube-proxy", Usage: "(components) Disable running kube-proxy", Destination: &ServerConfig.DisableKubeProxy, }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "disable-network-policy", Usage: "(components) Disable " + version.Program + " default network policy controller", Destination: &ServerConfig.DisableNPC, }, - NodeNameFlag, - WithNodeIDFlag, - NodeLabels, - NodeTaints, - DockerFlag, - DisableSELinuxFlag, - CRIEndpointFlag, - PauseImageFlag, - PrivateRegistryFlag, - NodeIPFlag, - NodeExternalIPFlag, - ResolvConfFlag, - FlannelIfaceFlag, - FlannelConfFlag, - ExtraKubeletArgs, - ExtraKubeProxyArgs, - cli.BoolFlag{ + &NodeNameFlag, + &WithNodeIDFlag, + &NodeLabels, + &NodeTaints, + &DockerFlag, + &DisableSELinuxFlag, + &CRIEndpointFlag, + &PauseImageFlag, + &PrivateRegistryFlag, + &NodeIPFlag, + &NodeExternalIPFlag, + &ResolvConfFlag, + &FlannelIfaceFlag, + &FlannelConfFlag, + &ExtraKubeletArgs, + &ExtraKubeProxyArgs, + &cli.BoolFlag{ Name: "rootless", Usage: "(experimental) Run rootless", Destination: &ServerConfig.Rootless, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "agent-token", Usage: "(experimental/cluster) Shared secret used to join agents to the cluster, but not servers", Destination: &ServerConfig.AgentToken, - EnvVar: version.ProgramUpper + "_AGENT_TOKEN", + EnvVars: []string{version.ProgramUpper + "_AGENT_TOKEN"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "agent-token-file", Usage: "(experimental/cluster) File containing the agent secret", Destination: &ServerConfig.AgentTokenFile, - EnvVar: version.ProgramUpper + "_AGENT_TOKEN_FILE", + EnvVars: []string{version.ProgramUpper + "_AGENT_TOKEN_FILE"}, }, - cli.StringFlag{ + &cli.StringFlag{ Name: "server,s", Usage: "(experimental/cluster) Server to connect to, used to join a cluster", - EnvVar: version.ProgramUpper + "_URL", + EnvVars: []string{version.ProgramUpper + "_URL"}, Destination: &ServerConfig.ServerURL, }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "cluster-init", Hidden: hideDqlite, Usage: "(experimental/cluster) Initialize new cluster master", - EnvVar: version.ProgramUpper + "_CLUSTER_INIT", + EnvVars: []string{version.ProgramUpper + "_CLUSTER_INIT"}, Destination: &ServerConfig.ClusterInit, }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "cluster-reset", Hidden: hideDqlite, Usage: "(experimental/cluster) Forget all peers and become a single cluster new cluster master", - EnvVar: version.ProgramUpper + "_CLUSTER_RESET", + EnvVars: []string{version.ProgramUpper + "_CLUSTER_RESET"}, Destination: &ServerConfig.ClusterReset, }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "secrets-encryption", Usage: "(experimental) Enable Secret encryption at rest", Destination: &ServerConfig.EncryptSecrets, @@ -287,34 +291,34 @@ func NewServerCommand(action func(*cli.Context) error) cli.Command { // Hidden/Deprecated flags below - FlannelFlag, - cli.StringSliceFlag{ + &FlannelFlag, + &cli.StringSliceFlag{ Name: "no-deploy", Usage: "(deprecated) Do not deploy packaged components (valid items: " + DisableItems + ")", }, - cli.StringFlag{ + &cli.StringFlag{ Name: "cluster-secret", Usage: "(deprecated) use --token", Destination: &ServerConfig.ClusterSecret, - EnvVar: version.ProgramUpper + "_CLUSTER_SECRET", + EnvVars: []string{version.ProgramUpper + "_CLUSTER_SECRET"}, }, - cli.BoolFlag{ + &cli.BoolFlag{ Name: "disable-agent", Usage: "Do not run a local agent and register a local kubelet", Hidden: true, Destination: &ServerConfig.DisableAgent, }, - cli.StringSliceFlag{ - Hidden: true, - Name: "kube-controller-arg", - Usage: "(flags) Customized flag for kube-controller-manager process", - Value: &ServerConfig.ExtraControllerArgs, + &cli.StringSliceFlag{ + Hidden: true, + Name: "kube-controller-arg", + Usage: "(flags) Customized flag for kube-controller-manager process", + Destination: &ServerConfig.ExtraControllerArgs, }, - cli.StringSliceFlag{ - Hidden: true, - Name: "kube-cloud-controller-arg", - Usage: "(flags) Customized flag for kube-cloud-controller-manager process", - Value: &ServerConfig.ExtraCloudControllerArgs, + &cli.StringSliceFlag{ + Hidden: true, + Name: "kube-cloud-controller-arg", + Usage: "(flags) Customized flag for kube-cloud-controller-manager process", + Destination: &ServerConfig.ExtraCloudControllerArgs, }, }, } diff --git a/pkg/cli/crictl/crictl.go b/pkg/cli/crictl/crictl.go index 03b3b5b661..951aee2521 100644 --- a/pkg/cli/crictl/crictl.go +++ b/pkg/cli/crictl/crictl.go @@ -2,7 +2,7 @@ package crictl import ( "github.com/kubernetes-sigs/cri-tools/cmd/crictl" - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) func Run(ctx *cli.Context) error { diff --git a/pkg/cli/ctr/ctr.go b/pkg/cli/ctr/ctr.go index a8aab2d60c..fefe68df27 100644 --- a/pkg/cli/ctr/ctr.go +++ b/pkg/cli/ctr/ctr.go @@ -2,7 +2,7 @@ package ctr import ( "github.com/rancher/k3s/pkg/ctr" - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) func Run(ctx *cli.Context) error { diff --git a/pkg/cli/kubectl/kubectl.go b/pkg/cli/kubectl/kubectl.go index 4c047a4c53..d9b24e97b6 100644 --- a/pkg/cli/kubectl/kubectl.go +++ b/pkg/cli/kubectl/kubectl.go @@ -2,7 +2,7 @@ package kubectl import ( "github.com/rancher/k3s/pkg/kubectl" - "github.com/urfave/cli" + "github.com/rancher/spur/cli" ) func Run(ctx *cli.Context) error { diff --git a/pkg/cli/server/server.go b/pkg/cli/server/server.go index 296fdf74fc..2fa536fd1f 100644 --- a/pkg/cli/server/server.go +++ b/pkg/cli/server/server.go @@ -18,9 +18,9 @@ import ( "github.com/rancher/k3s/pkg/server" "github.com/rancher/k3s/pkg/token" "github.com/rancher/k3s/pkg/version" + "github.com/rancher/spur/cli" "github.com/rancher/wrangler/pkg/signals" "github.com/sirupsen/logrus" - "github.com/urfave/cli" "k8s.io/apimachinery/pkg/util/net" kubeapiserverflag "k8s.io/component-base/cli/flag" "k8s.io/kubernetes/pkg/master" @@ -31,9 +31,6 @@ import ( ) func Run(app *cli.Context) error { - if err := cmds.InitLogging(); err != nil { - return err - } return run(app, &cmds.ServerConfig) } @@ -245,7 +242,7 @@ func run(app *cli.Context, cfg *cmds.Server) error { } agentConfig := cmds.AgentConfig - agentConfig.Debug = app.GlobalBool("bool") + agentConfig.Debug = app.Bool("debug") agentConfig.DataDir = filepath.Dir(serverConfig.ControlConfig.DataDir) agentConfig.ServerURL = url agentConfig.Token = token diff --git a/vendor/github.com/rancher/spur/LICENSE b/vendor/github.com/rancher/spur/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/vendor/github.com/rancher/spur/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/rancher/spur/cli/.flake8 b/vendor/github.com/rancher/spur/cli/.flake8 new file mode 100644 index 0000000000..6deafc2617 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/.flake8 @@ -0,0 +1,2 @@ +[flake8] +max-line-length = 120 diff --git a/vendor/github.com/rancher/spur/cli/.gitignore b/vendor/github.com/rancher/spur/cli/.gitignore new file mode 100644 index 0000000000..2d5e149b43 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/.gitignore @@ -0,0 +1,7 @@ +*.coverprofile +*.orig +node_modules/ +vendor +.idea +internal/*/built-example +coverage.txt diff --git a/vendor/github.com/rancher/spur/cli/LICENSE b/vendor/github.com/rancher/spur/cli/LICENSE new file mode 100644 index 0000000000..42a597e29b --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2016 Jeremy Saenz & Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/rancher/spur/cli/_flag.template.go b/vendor/github.com/rancher/spur/cli/_flag.template.go new file mode 100644 index 0000000000..eff484c1fb --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/_flag.template.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Title__ is a type alias for Type__ +type Title__ = Type__ + +// Title__Flag is a flag with type Type__ +type Title__Flag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Title__ + Destination *Title__ +} + +// Apply populates the flag given the flag set and environment +func (f *Title__Flag) Apply(set *flag.FlagSet) error { + return Apply(f, "LongName__", set) +} + +// Title__ looks up the value of a local Title__Flag, returns +// an empty value if not found +func (c *Context) Title__(name string) Type__ { + return c.Lookup(name, *new(Title__)).(Type__) +} diff --git a/vendor/github.com/rancher/spur/cli/altsrc/conf_file_loader.go b/vendor/github.com/rancher/spur/cli/altsrc/conf_file_loader.go new file mode 100644 index 0000000000..f8cc022e24 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/altsrc/conf_file_loader.go @@ -0,0 +1,23 @@ +package altsrc + +import ( + "fmt" + "os" + + "github.com/rancher/spur/cli" +) + +// NewConfigFromFlag creates a new Yaml cli.InputSourceContext from a provided flag name and source context. +// If the flag is not set and the default config does not exist then returns an empty input and no error. +func NewConfigFromFlag(flagFileName string) func(*cli.Context) (cli.InputSourceContext, error) { + return func(ctx *cli.Context) (cli.InputSourceContext, error) { + filePath := ctx.String(flagFileName) + if isc, err := NewYamlSourceFromFile(filePath); ctx.IsSet(flagFileName) || !os.IsNotExist(err) { + if err != nil { + err = fmt.Errorf("unable to load config file '%s': %s", filePath, err) + } + return isc, err + } + return &MapInputSource{}, nil + } +} diff --git a/vendor/github.com/rancher/spur/cli/altsrc/map_input_source.go b/vendor/github.com/rancher/spur/cli/altsrc/map_input_source.go new file mode 100644 index 0000000000..dca2977263 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/altsrc/map_input_source.go @@ -0,0 +1,49 @@ +package altsrc + +import ( + "strings" +) + +// MapInputSource implements InputSourceContext to return +// data from the map that is loaded. +type MapInputSource struct { + file string + valueMap map[interface{}]interface{} +} + +// nestedVal checks if the name has '.' delimiters. +// If so, it tries to traverse the tree by the '.' delimited sections to find +// a nested value for the key. +func nestedVal(name string, tree map[interface{}]interface{}) (interface{}, bool) { + if sections := strings.Split(name, "."); len(sections) > 1 { + node := tree + for _, section := range sections[:len(sections)-1] { + child, ok := node[section] + if !ok { + return nil, false + } + ctype, ok := child.(map[interface{}]interface{}) + if !ok { + return nil, false + } + node = ctype + } + if val, ok := node[sections[len(sections)-1]]; ok { + return val, true + } + } + return nil, false +} + +// Get returns the named value +func (fsm *MapInputSource) Get(name string) (interface{}, bool) { + if value, exists := fsm.valueMap[name]; exists { + return value, true + } + return nestedVal(name, fsm.valueMap) +} + +// Source returns the path of the source file +func (fsm *MapInputSource) Source() string { + return fsm.file +} diff --git a/vendor/github.com/rancher/spur/cli/altsrc/yaml_file_loader.go b/vendor/github.com/rancher/spur/cli/altsrc/yaml_file_loader.go new file mode 100644 index 0000000000..6df659f541 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/altsrc/yaml_file_loader.go @@ -0,0 +1,56 @@ +package altsrc + +import ( + "fmt" + "io/ioutil" + "net/http" + "net/url" + "os" + + "github.com/rancher/spur/cli" + "gopkg.in/yaml.v2" +) + +type yamlSourceContext struct { + FilePath string +} + +// NewYamlSourceFromFile creates a new Yaml cli.InputSourceContext from a filepath. +func NewYamlSourceFromFile(file string) (cli.InputSourceContext, error) { + ysc := &yamlSourceContext{FilePath: file} + var results map[interface{}]interface{} + err := readCommandYaml(ysc.FilePath, &results) + return &MapInputSource{file: file, valueMap: results}, err +} + +func readCommandYaml(filePath string, container interface{}) error { + b, err := loadDataFrom(filePath) + if err != nil { + return err + } + return yaml.Unmarshal(b, container) +} + +func loadDataFrom(filePath string) ([]byte, error) { + u, err := url.Parse(filePath) + if err != nil { + return nil, err + } + + if u.Host != "" { // i have a host, now do i support the scheme? + switch u.Scheme { + case "http", "https": + res, err := http.Get(filePath) + if err != nil { + return nil, err + } + return ioutil.ReadAll(res.Body) + default: + return nil, fmt.Errorf("scheme of %s is unsupported", filePath) + } + } + if _, err := os.Stat(filePath); err != nil { + return nil, os.ErrNotExist + } + return ioutil.ReadFile(filePath) +} diff --git a/vendor/github.com/rancher/spur/cli/app.go b/vendor/github.com/rancher/spur/cli/app.go new file mode 100644 index 0000000000..4966214ba7 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/app.go @@ -0,0 +1,540 @@ +package cli + +import ( + "context" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "time" + + "github.com/rancher/spur/flag" +) + +// App is the main structure of a cli application. It is recommended that +// an app be created with the cli.NewApp() function +type App struct { + // The name of the program. Defaults to path.Base(os.Args[0]) + Name string + // Full name of command for help, defaults to Name + HelpName string + // Description of the program. + Usage string + // Text to override the USAGE section of help + UsageText string + // Description of the program argument format. + ArgsUsage string + // Version of the program + Version string + // Description of the program + Description string + // List of commands to execute + Commands []*Command + // List of flags to parse + Flags []Flag + // Boolean to enable bash completion commands + EnableBashCompletion bool + // Boolean to hide built-in help command and help flag + HideHelp bool + // Boolean to hide built-in help command but keep help flag. + // Ignored if HideHelp is true. + HideHelpCommand bool + // Boolean to hide built-in version flag and the VERSION section of help + HideVersion bool + // categories contains the categorized commands and is populated on app startup + categories CommandCategories + // An action to execute when the shell completion flag is set + BashComplete BashCompleteFunc + // An action to execute before any subcommands are run, but after the context is ready + // If a non-nil error is returned, no subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The action to execute when no subcommands are specified + Action ActionFunc + // Execute this function if the proper command cannot be found + CommandNotFound CommandNotFoundFunc + // Execute this function if an usage error occurs + OnUsageError OnUsageErrorFunc + // Compilation date + Compiled time.Time + // List of all authors who contributed + Authors []*Author + // Copyright of the binary if any + Copyright string + // Writer writer to write output to + Writer io.Writer + // ErrWriter writes error output + ErrWriter io.Writer + // ExitErrHandler processes any error encountered while running an App before + // it is returned to the caller. If no function is provided, HandleExitCoder + // is used as the default behavior. + ExitErrHandler ExitErrHandlerFunc + // Other custom info + Metadata map[string]interface{} + // Carries a function which returns app specific info. + ExtraInfo func() map[string]string + // CustomAppHelpTemplate the text template for app help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomAppHelpTemplate string + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + + didSetup bool +} + +type showHelpFunc = func(context *Context) error + +type showHelpError struct { + error +} + +// ShowHelpOnError will take a BeforeFunc and show command usage on error +func ShowHelpOnError(someFunc BeforeFunc) BeforeFunc { + return func(context *Context) error { + if err := someFunc(context); err != nil { + return showHelpError{err} + } + return nil + } +} + +// Tries to find out when this binary was compiled. +// Returns the current time if it fails to find it. +func compileTime() time.Time { + info, err := os.Stat(os.Args[0]) + if err != nil { + return time.Now() + } + return info.ModTime() +} + +// NewApp creates a new cli Application with some reasonable defaults for Name, +// Usage, Version and Action. +func NewApp() *App { + return &App{ + Name: filepath.Base(os.Args[0]), + HelpName: filepath.Base(os.Args[0]), + Usage: "A new cli application", + UsageText: "", + BashComplete: DefaultAppComplete, + Action: helpCommand.Action, + Compiled: compileTime(), + Writer: os.Stdout, + ErrWriter: os.Stderr, + } +} + +// Setup runs initialization code to ensure all data structures are ready for +// `Run` or inspection prior to `Run`. It is internally called by `Run`, but +// will return early if setup has already happened. +func (a *App) Setup() { + if a.didSetup { + return + } + + a.didSetup = true + + if a.Name == "" { + a.Name = filepath.Base(os.Args[0]) + } + + if a.HelpName == "" { + a.HelpName = filepath.Base(os.Args[0]) + } + + if a.Usage == "" { + a.Usage = "A new cli application" + } + + if a.Version == "" { + a.HideVersion = true + } + + if a.BashComplete == nil { + a.BashComplete = DefaultAppComplete + } + + if a.Action == nil { + a.Action = helpCommand.Action + } + + if a.Compiled == (time.Time{}) { + a.Compiled = compileTime() + } + + if a.Writer == nil { + a.Writer = os.Stdout + } + + if a.ErrWriter == nil { + a.ErrWriter = os.Stderr + } + + var newCommands []*Command + + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + } + newCommands = append(newCommands, c) + } + a.Commands = newCommands + + if a.Command(helpCommand.Name) == nil && !a.HideHelp { + if !a.HideHelpCommand { + a.appendCommand(helpCommand) + } + + if HelpFlag != nil { + a.appendFlag(HelpFlag) + } + } + + if !a.HideVersion { + a.appendFlag(VersionFlag) + } + + a.categories = newCommandCategories() + for _, command := range a.Commands { + a.categories.AddCommand(command.Category, command) + } + sort.Sort(a.categories.(*commandCategories)) + + if a.Metadata == nil { + a.Metadata = make(map[string]interface{}) + } +} + +func (a *App) newFlagSet() (*flag.FlagSet, error) { + return flagSet(a.Name, a.Flags) +} + +func (a *App) useShortOptionHandling() bool { + return a.UseShortOptionHandling +} + +// Run is the entry point to the cli app. Parses the arguments slice and routes +// to the proper flag/args combination +func (a *App) Run(arguments []string) (err error) { + return a.RunContext(context.Background(), arguments) +} + +// RunContext is like Run except it takes a Context that will be +// passed to its commands and sub-commands. Through this, you can +// propagate timeouts and cancellation requests +func (a *App) RunContext(ctx context.Context, arguments []string) (err error) { + if len(arguments) == 0 { + return fmt.Errorf("arguments not provided") + } + a.Setup() + + // handle the completion flag separately from the flagset since + // completion could be attempted after a flag, but before its value was put + // on the command line. this causes the flagset to interpret the completion + // flag name as the value of the flag before it which is undesirable + // note that we can only do this because the shell autocomplete function + // always appends the completion flag at the end of the command + shellComplete, arguments := checkShellCompleteFlag(a, arguments) + + set, err := a.newFlagSet() + if err != nil { + return err + } + + err = parseIter(set, a, arguments[1:], shellComplete) + nerr := normalizeFlags(a.Flags, set) + context := NewContext(a, set, &Context{Context: ctx}) + if nerr != nil { + fmt.Fprintln(a.Writer, nerr) + ShowAppHelp(context) + return nerr + } + context.shellComplete = shellComplete + + if checkCompletions(context) { + return nil + } + + if err != nil { + return a.helpOnError(ShowAppHelp, context, showHelpError{err}) + } + + if !a.HideHelp && checkHelp(context) { + ShowAppHelp(context) + return nil + } + + if !a.HideVersion && checkVersion(context) { + ShowVersion(context) + return nil + } + + cerr := checkRequiredFlags(a.Flags, context) + if cerr != nil { + ShowAppHelp(context) + return cerr + } + + if a.After != nil { + defer func() { + if afterErr := a.After(context); afterErr != nil { + a.handleExitCoder(context, err) + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if a.Before != nil { + if err := a.Before(context); err != nil { + return a.helpOnError(ShowAppHelp, context, err) + } + } + + args := context.Args() + if args.Present() { + name := args.First() + c := a.Command(name) + if c != nil { + return c.Run(context) + } + } + + if a.Action == nil { + a.Action = helpCommand.Action + } + + // Run default Action + err = a.Action(context) + + a.handleExitCoder(context, err) + return err +} + +func (a *App) helpOnError(showHelp showHelpFunc, context *Context, err error) error { + if err == nil { + return nil + } + if e, ok := err.(showHelpError); ok { + err = e.error + if a.OnUsageError != nil { + err = a.OnUsageError(context, err, false) + } else { + fmt.Fprintf(a.Writer, "%s:\n %s\n\n", "Incorrect Usage", err.Error()) + showHelp(context) + } + } + a.handleExitCoder(context, err) + return err +} + +// RunAndExitOnError calls .Run() and exits non-zero if an error was returned +// +// Deprecated: instead you should return an error that fulfills cli.ExitCoder +// to cli.App.Run. This will cause the application to exit with the given error +// code in the cli.ExitCoder +func (a *App) RunAndExitOnError() { + if err := a.Run(os.Args); err != nil { + fmt.Fprintf(a.ErrWriter, "\nFatal: %s\n", err) + OsExiter(1) + } +} + +// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to +// generate command-specific flags +func (a *App) RunAsSubcommand(ctx *Context) (err error) { + // Setup also handles HideHelp and HideHelpCommand + a.Setup() + + var newCmds []*Command + for _, c := range a.Commands { + if c.HelpName == "" { + c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name) + } + newCmds = append(newCmds, c) + } + a.Commands = newCmds + + set, err := a.newFlagSet() + if err != nil { + return err + } + + err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete) + nerr := normalizeFlags(a.Flags, set) + context := NewContext(a, set, ctx) + + if nerr != nil { + fmt.Fprintln(a.Writer, nerr) + fmt.Fprintln(a.Writer) + if len(a.Commands) > 0 { + ShowSubcommandHelp(context) + } else { + ShowCommandHelp(ctx, context.Args().First()) + } + return nerr + } + + if checkCompletions(context) { + return nil + } + + if err != nil { + return a.helpOnError(ShowSubcommandHelp, context, showHelpError{err}) + } + + if len(a.Commands) > 0 { + if checkSubcommandHelp(context) { + return nil + } + } else { + if checkCommandHelp(ctx, context.Args().First()) { + return nil + } + } + + cerr := checkRequiredFlags(a.Flags, context) + if cerr != nil { + ShowSubcommandHelp(context) + return cerr + } + + if a.After != nil { + defer func() { + if afterErr := a.After(context); afterErr != nil { + a.handleExitCoder(context, err) + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if a.Before != nil { + if err := a.Before(context); err != nil { + return a.helpOnError(ShowSubcommandHelp, context, err) + } + } + + args := context.Args() + if args.Present() { + name := args.First() + c := a.Command(name) + if c != nil { + return c.Run(context) + } + } + + // Run default Action + err = a.Action(context) + + a.handleExitCoder(context, err) + return err +} + +// Command returns the named command on App. Returns nil if the command does not exist +func (a *App) Command(name string) *Command { + for _, c := range a.Commands { + if c.HasName(name) { + return c + } + } + + return nil +} + +// VisibleCategories returns a slice of categories and commands that are +// Hidden=false +func (a *App) VisibleCategories() []CommandCategory { + ret := []CommandCategory{} + for _, category := range a.categories.Categories() { + if visible := func() CommandCategory { + if len(category.VisibleCommands()) > 0 { + return category + } + return nil + }(); visible != nil { + ret = append(ret, visible) + } + } + return ret +} + +// VisibleCommands returns a slice of the Commands with Hidden=false +func (a *App) VisibleCommands() []*Command { + var ret []*Command + for _, command := range a.Commands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} + +// VisibleFlags returns a slice of the Flags with Hidden=false +func (a *App) VisibleFlags() []Flag { + return visibleFlags(a.Flags) +} + +func (a *App) appendFlag(fl Flag) { + if !hasFlag(a.Flags, fl) { + a.Flags = append(a.Flags, fl) + } +} + +func (a *App) appendCommand(c *Command) { + if !hasCommand(a.Commands, c) { + a.Commands = append(a.Commands, c) + } +} + +func (a *App) handleExitCoder(context *Context, err error) { + if a.ExitErrHandler != nil { + a.ExitErrHandler(context, err) + } else { + HandleExitCoder(err) + } +} + +// Author represents someone who has contributed to a cli project. +type Author struct { + Name string // The Authors name + Email string // The Authors email +} + +// String makes Author comply to the Stringer interface, to allow an easy print in the templating process +func (a *Author) String() string { + e := "" + if a.Email != "" { + e = " <" + a.Email + ">" + } + + return fmt.Sprintf("%v%v", a.Name, e) +} + +// HandleAction attempts to figure out which Action signature was used. If +// it's an ActionFunc or a func with the legacy signature for Action, the func +// is run! Panics on invalid function signature. +func HandleAction(action interface{}, context *Context) (err error) { + switch a := action.(type) { + case ActionFunc: + return a(context) + case func(*Context) error: + return a(context) + case func(*Context): // deprecated function signature + a(context) + return nil + } + panic(fmt.Sprintf("invalid Action type '%T', should be 'func(*Context) error'", action)) +} diff --git a/vendor/github.com/rancher/spur/cli/args.go b/vendor/github.com/rancher/spur/cli/args.go new file mode 100644 index 0000000000..bd65c17bde --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/args.go @@ -0,0 +1,54 @@ +package cli + +type Args interface { + // Get returns the nth argument, or else a blank string + Get(n int) string + // First returns the first argument, or else a blank string + First() string + // Tail returns the rest of the arguments (not the first one) + // or else an empty string slice + Tail() []string + // Len returns the length of the wrapped slice + Len() int + // Present checks if there are any arguments present + Present() bool + // Slice returns a copy of the internal slice + Slice() []string +} + +type args []string + +func (a *args) Get(n int) string { + if len(*a) > n { + return (*a)[n] + } + return "" +} + +func (a *args) First() string { + return a.Get(0) +} + +func (a *args) Tail() []string { + if a.Len() >= 2 { + tail := []string((*a)[1:]) + ret := make([]string, len(tail)) + copy(ret, tail) + return ret + } + return []string{} +} + +func (a *args) Len() int { + return len(*a) +} + +func (a *args) Present() bool { + return a.Len() != 0 +} + +func (a *args) Slice() []string { + ret := make([]string, len(*a)) + copy(ret, *a) + return ret +} diff --git a/vendor/github.com/rancher/spur/cli/category.go b/vendor/github.com/rancher/spur/cli/category.go new file mode 100644 index 0000000000..867e3908ca --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/category.go @@ -0,0 +1,79 @@ +package cli + +// CommandCategories interface allows for category manipulation +type CommandCategories interface { + // AddCommand adds a command to a category, creating a new category if necessary. + AddCommand(category string, command *Command) + // categories returns a copy of the category slice + Categories() []CommandCategory +} + +type commandCategories []*commandCategory + +func newCommandCategories() CommandCategories { + ret := commandCategories([]*commandCategory{}) + return &ret +} + +func (c *commandCategories) Less(i, j int) bool { + return lexicographicLess((*c)[i].Name(), (*c)[j].Name()) +} + +func (c *commandCategories) Len() int { + return len(*c) +} + +func (c *commandCategories) Swap(i, j int) { + (*c)[i], (*c)[j] = (*c)[j], (*c)[i] +} + +func (c *commandCategories) AddCommand(category string, command *Command) { + for _, commandCategory := range []*commandCategory(*c) { + if commandCategory.name == category { + commandCategory.commands = append(commandCategory.commands, command) + return + } + } + newVal := append(*c, + &commandCategory{name: category, commands: []*Command{command}}) + *c = newVal +} + +func (c *commandCategories) Categories() []CommandCategory { + ret := make([]CommandCategory, len(*c)) + for i, cat := range *c { + ret[i] = cat + } + return ret +} + +// CommandCategory is a category containing commands. +type CommandCategory interface { + // Name returns the category name string + Name() string + // VisibleCommands returns a slice of the Commands with Hidden=false + VisibleCommands() []*Command +} + +type commandCategory struct { + name string + commands []*Command +} + +func (c *commandCategory) Name() string { + return c.name +} + +func (c *commandCategory) VisibleCommands() []*Command { + if c.commands == nil { + c.commands = []*Command{} + } + + var ret []*Command + for _, command := range c.commands { + if !command.Hidden { + ret = append(ret, command) + } + } + return ret +} diff --git a/vendor/github.com/rancher/spur/cli/command.go b/vendor/github.com/rancher/spur/cli/command.go new file mode 100644 index 0000000000..3f0779eb96 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/command.go @@ -0,0 +1,301 @@ +package cli + +import ( + "fmt" + "sort" + "strings" + + "github.com/rancher/spur/flag" +) + +// Command is a subcommand for a cli.App. +type Command struct { + // The name of the command + Name string + // A list of aliases for the command + Aliases []string + // A short description of the usage of this command + Usage string + // Custom text to show on USAGE section of help + UsageText string + // A longer explanation of how the command works + Description string + // A short description of the arguments of this command + ArgsUsage string + // The category the command is part of + Category string + // The function to call when checking for bash command completions + BashComplete BashCompleteFunc + // An action to execute before any sub-subcommands are run, but after the context is ready + // If a non-nil error is returned, no sub-subcommands are run + Before BeforeFunc + // An action to execute after any subcommands are run, but after the subcommand has finished + // It is run even if Action() panics + After AfterFunc + // The function to call when this command is invoked + Action ActionFunc + // Execute this function if a usage error occurs. + OnUsageError OnUsageErrorFunc + // List of child commands + Subcommands []*Command + // List of flags to parse + Flags []Flag + // Treat all flags as normal arguments if true + SkipFlagParsing bool + // Boolean to hide built-in help command and help flag + HideHelp bool + // Boolean to hide built-in help command but keep help flag + // Ignored if HideHelp is true. + HideHelpCommand bool + // Boolean to hide this command from help or completion + Hidden bool + // Boolean to enable short-option handling so user can combine several + // single-character bool arguments into one + // i.e. foobar -o -v -> foobar -ov + UseShortOptionHandling bool + + // Full name of command for help, defaults to full command name, including parent commands. + HelpName string + commandNamePath []string + + // CustomHelpTemplate the text template for the command help topic. + // cli.go uses text/template to render templates. You can + // render custom help text by setting this variable. + CustomHelpTemplate string +} + +type Commands []*Command + +type CommandsByName []*Command + +func (c CommandsByName) Len() int { + return len(c) +} + +func (c CommandsByName) Less(i, j int) bool { + return lexicographicLess(c[i].Name, c[j].Name) +} + +func (c CommandsByName) Swap(i, j int) { + c[i], c[j] = c[j], c[i] +} + +// FullName returns the full name of the command. +// For subcommands this ensures that parent commands are part of the command path +func (c *Command) FullName() string { + if c.commandNamePath == nil { + return c.Name + } + return strings.Join(c.commandNamePath, " ") +} + +// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags +func (c *Command) Run(ctx *Context) (err error) { + if len(c.Subcommands) > 0 { + return c.startApp(ctx) + } + + if !c.HideHelp && HelpFlag != nil { + // append help to flags + c.appendFlag(HelpFlag) + } + + if ctx.App.UseShortOptionHandling { + c.UseShortOptionHandling = true + } + + set, err := c.parseFlags(ctx.Args(), ctx.shellComplete) + + context := NewContext(ctx.App, set, ctx) + context.Command = c + if checkCommandCompletions(context, c.Name) { + return nil + } + + if err != nil { + if c.OnUsageError != nil { + err = c.OnUsageError(context, err, false) + context.App.handleExitCoder(context, err) + return err + } + fmt.Fprintln(context.App.Writer, "Incorrect Usage:", err.Error()) + fmt.Fprintln(context.App.Writer) + ShowCommandHelp(context, c.Name) + return err + } + + if checkCommandHelp(context, c.Name) { + return nil + } + + cerr := checkRequiredFlags(c.Flags, context) + if cerr != nil { + ShowCommandHelp(context, c.Name) + return cerr + } + + if c.After != nil { + defer func() { + afterErr := c.After(context) + if afterErr != nil { + context.App.handleExitCoder(context, err) + if err != nil { + err = newMultiError(err, afterErr) + } else { + err = afterErr + } + } + }() + } + + if c.Before != nil { + err = c.Before(context) + if err != nil { + context.App.handleExitCoder(context, err) + return err + } + } + + if c.Action == nil { + c.Action = helpSubcommand.Action + } + + context.Command = c + err = c.Action(context) + + if err != nil { + context.App.handleExitCoder(context, err) + } + return err +} + +func (c *Command) newFlagSet() (*flag.FlagSet, error) { + return flagSet(c.Name, c.Flags) +} + +func (c *Command) useShortOptionHandling() bool { + return c.UseShortOptionHandling +} + +func (c *Command) parseFlags(args Args, shellComplete bool) (*flag.FlagSet, error) { + set, err := c.newFlagSet() + if err != nil { + return nil, err + } + + if c.SkipFlagParsing { + return set, set.Parse(append([]string{"--"}, args.Tail()...)) + } + + err = parseIter(set, c, args.Tail(), shellComplete) + if err != nil { + return nil, err + } + + err = normalizeFlags(c.Flags, set) + if err != nil { + return nil, err + } + + return set, nil +} + +// Names returns the names including short names and aliases. +func (c *Command) Names() []string { + return append([]string{c.Name}, c.Aliases...) +} + +// HasName returns true if Command.Name matches given name +func (c *Command) HasName(name string) bool { + for _, n := range c.Names() { + if n == name { + return true + } + } + return false +} + +func (c *Command) startApp(ctx *Context) error { + app := &App{ + Metadata: ctx.App.Metadata, + Name: fmt.Sprintf("%s %s", ctx.App.Name, c.Name), + } + + if c.HelpName == "" { + app.HelpName = c.HelpName + } else { + app.HelpName = app.Name + } + + app.Usage = c.Usage + app.Description = c.Description + app.ArgsUsage = c.ArgsUsage + + // set CommandNotFound + app.CommandNotFound = ctx.App.CommandNotFound + app.CustomAppHelpTemplate = c.CustomHelpTemplate + + // set the flags and commands + app.Commands = c.Subcommands + app.Flags = c.Flags + app.HideHelp = c.HideHelp + app.HideHelpCommand = c.HideHelpCommand + + app.Version = ctx.App.Version + app.HideVersion = ctx.App.HideVersion + app.Compiled = ctx.App.Compiled + app.Writer = ctx.App.Writer + app.ErrWriter = ctx.App.ErrWriter + app.ExitErrHandler = ctx.App.ExitErrHandler + app.UseShortOptionHandling = ctx.App.UseShortOptionHandling + + app.categories = newCommandCategories() + for _, command := range c.Subcommands { + app.categories.AddCommand(command.Category, command) + } + + sort.Sort(app.categories.(*commandCategories)) + + // bash completion + app.EnableBashCompletion = ctx.App.EnableBashCompletion + if c.BashComplete != nil { + app.BashComplete = c.BashComplete + } + + // set the actions + app.Before = c.Before + app.After = c.After + if c.Action != nil { + app.Action = c.Action + } else { + app.Action = helpSubcommand.Action + } + app.OnUsageError = c.OnUsageError + + for index, cc := range app.Commands { + app.Commands[index].commandNamePath = []string{c.Name, cc.Name} + } + + return app.RunAsSubcommand(ctx) +} + +// VisibleFlags returns a slice of the Flags with Hidden=false +func (c *Command) VisibleFlags() []Flag { + return visibleFlags(c.Flags) +} + +func (c *Command) appendFlag(fl Flag) { + if !hasFlag(c.Flags, fl) { + c.Flags = append(c.Flags, fl) + } +} + +func hasCommand(commands []*Command, command *Command) bool { + for _, existing := range commands { + if command == existing { + return true + } + } + + return false +} diff --git a/vendor/github.com/rancher/spur/cli/context.go b/vendor/github.com/rancher/spur/cli/context.go new file mode 100644 index 0000000000..8e41ce675d --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/context.go @@ -0,0 +1,275 @@ +package cli + +import ( + "context" + "fmt" + "reflect" + "strings" + + "github.com/rancher/spur/flag" +) + +// Context is a type that is passed through to +// each Handler action in a cli application. Context +// can be used to retrieve context-specific args and +// parsed command-line options. +type Context struct { + context.Context + App *App + Command *Command + shellComplete bool + flagSet *flag.FlagSet + parentContext *Context +} + +// NewContext creates a new context. For use in when invoking an App or Command action. +func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { + c := &Context{App: app, flagSet: set, parentContext: parentCtx} + if parentCtx != nil { + c.Context = parentCtx.Context + c.shellComplete = parentCtx.shellComplete + if parentCtx.flagSet == nil { + parentCtx.flagSet = &flag.FlagSet{} + } + } + + c.Command = &Command{} + + if c.Context == nil { + c.Context = context.Background() + } + + return c +} + +// NumFlags returns the number of flags set +func (c *Context) NumFlags() int { + return c.flagSet.NFlag() +} + +// Set sets a context flag to a value. +func (c *Context) Set(name string, value interface{}) error { + return c.flagSet.Set(name, value) +} + +// IsSet determines if the flag was actually set +func (c *Context) IsSet(name string) bool { + if fs := lookupFlagSet(name, c); fs != nil { + isSet := false + fs.Visit(func(f *flag.Flag) { + if f.Name == name { + isSet = true + } + }) + if isSet { + return true + } + } + return false +} + +// LocalFlagNames returns a slice of flag names used in this context. +func (c *Context) LocalFlagNames() []string { + var names []string + c.flagSet.Visit(makeFlagNameVisitor(&names)) + return names +} + +// FlagNames returns a slice of flag names used by the this context and all of +// its parent contexts. +func (c *Context) FlagNames() []string { + var names []string + for _, ctx := range c.Lineage() { + ctx.flagSet.Visit(makeFlagNameVisitor(&names)) + } + return names +} + +// Lineage returns *this* context and all of its ancestor contexts in order from +// child to parent +func (c *Context) Lineage() []*Context { + var lineage []*Context + + for cur := c; cur != nil; cur = cur.parentContext { + lineage = append(lineage, cur) + } + + return lineage +} + +// Value returns the value of the flag corresponding to `name` +func (c *Context) Value(name string) interface{} { + return c.flagSet.Lookup(name).Value.(flag.Getter).Get() +} + +// Args returns the command line arguments associated with the context. +func (c *Context) Args() Args { + ret := args(c.flagSet.Args()) + return &ret +} + +// NArg returns the number of the command line arguments. +func (c *Context) NArg() int { + return c.Args().Len() +} + +// Lookup will return the value for a flag, or the default value if +// the flag value does not exist or is not of the same type +func (c *Context) Lookup(name string, defaultVal interface{}) interface{} { + var result interface{} + if fs := lookupFlagSet(name, c); fs != nil { + if f := fs.Lookup(name); f != nil { + result = f.Value + } + } + if result == nil { + return defaultVal + } + // if we don't have a default value assume they want they flag.Value + if defaultVal != nil { + result = result.(flag.Getter).Get() + } + if defaultVal == nil || reflect.TypeOf(result) == reflect.TypeOf(defaultVal) { + return result + } + return defaultVal +} + +// GetFlags will return all of the flags found for this context +func (c *Context) GetFlags() []Flag { + flags := []Flag{} + for _, ctx := range c.Lineage() { + if ctx.Command != nil { + flags = append(flags, ctx.Command.Flags...) + } + } + if c.App != nil { + flags = append(flags, c.App.Flags...) + } + return flags +} + +func lookupFlag(name string, ctx *Context) Flag { + for _, f := range ctx.GetFlags() { + for _, n := range FlagNames(f) { + if n == name { + return f + } + } + } + return nil +} + +func lookupFlagSet(name string, ctx *Context) *flag.FlagSet { + for _, c := range ctx.Lineage() { + if f := c.flagSet.Lookup(name); f != nil { + return c.flagSet + } + } + + return nil +} + +func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { + set.Set(name, ff.Value.String()) +} + +func normalizeFlags(flags []Flag, set *flag.FlagSet) error { + visited := make(map[string]bool) + set.Visit(func(f *flag.Flag) { + visited[f.Name] = true + }) + for _, f := range flags { + parts := FlagNames(f) + if len(parts) == 1 { + continue + } + var ff *flag.Flag + for _, name := range parts { + name = strings.Trim(name, " ") + if visited[name] { + ff = set.Lookup(name) + } + } + if ff == nil { + continue + } + for _, name := range parts { + name = strings.Trim(name, " ") + if !visited[name] { + copyFlag(name, ff, set) + } + } + } + return nil +} + +func makeFlagNameVisitor(names *[]string) func(*flag.Flag) { + return func(f *flag.Flag) { + nameParts := strings.Split(f.Name, ",") + name := strings.TrimSpace(nameParts[0]) + + for _, part := range nameParts { + part = strings.TrimSpace(part) + if len(part) > len(name) { + name = part + } + } + + if name != "" { + *names = append(*names, name) + } + } +} + +type requiredFlagsErr interface { + error + getMissingFlags() []string +} + +type errRequiredFlags struct { + missingFlags []string +} + +func (e *errRequiredFlags) Error() string { + numberOfMissingFlags := len(e.missingFlags) + if numberOfMissingFlags == 1 { + return fmt.Sprintf("Required flag %q not set", e.missingFlags[0]) + } + joinedMissingFlags := strings.Join(e.missingFlags, ", ") + return fmt.Sprintf("Required flags %q not set", joinedMissingFlags) +} + +func (e *errRequiredFlags) getMissingFlags() []string { + return e.missingFlags +} + +func checkRequiredFlags(flags []Flag, context *Context) requiredFlagsErr { + var missingFlags []string + for _, f := range flags { + if required, ok := getFlagRequired(f); ok && required { + var flagPresent bool + var flagName string + + for _, key := range FlagNames(f) { + if len(key) > 1 { + flagName = key + } + + if context.IsSet(strings.TrimSpace(key)) { + flagPresent = true + } + } + + if !flagPresent && flagName != "" { + missingFlags = append(missingFlags, flagName) + } + } + } + + if len(missingFlags) != 0 { + return &errRequiredFlags{missingFlags: missingFlags} + } + + return nil +} diff --git a/vendor/github.com/rancher/spur/cli/docs.go b/vendor/github.com/rancher/spur/cli/docs.go new file mode 100644 index 0000000000..0046a3d70c --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/docs.go @@ -0,0 +1,160 @@ +// +build docgen + +package cli + +import ( + "bytes" + "fmt" + "io" + "sort" + "strings" + "text/template" + + "github.com/cpuguy83/go-md2man/v2/md2man" + "github.com/rancher/spur/flag" + "github.com/rancher/spur/generic" +) + +// ToMarkdown creates a markdown string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMarkdown() (string, error) { + var w bytes.Buffer + if err := a.writeDocTemplate(&w); err != nil { + return "", err + } + return w.String(), nil +} + +// ToMan creates a man page string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToMan() (string, error) { + var w bytes.Buffer + if err := a.writeDocTemplate(&w); err != nil { + return "", err + } + man := md2man.Render(w.Bytes()) + return string(man), nil +} + +type cliTemplate struct { + App *App + Commands []string + GlobalArgs []string + SynopsisArgs []string +} + +func (a *App) writeDocTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(MarkdownDocTemplate) + if err != nil { + return err + } + return t.ExecuteTemplate(w, name, &cliTemplate{ + App: a, + Commands: prepareCommands(a.Commands, 0), + GlobalArgs: prepareArgsWithValues(a.VisibleFlags()), + SynopsisArgs: prepareArgsSynopsis(a.VisibleFlags()), + }) +} + +func prepareCommands(commands []*Command, level int) []string { + var coms []string + for _, command := range commands { + if command.Hidden { + continue + } + usage := "" + if command.Usage != "" { + usage = command.Usage + } + + prepared := fmt.Sprintf("%s %s\n\n%s\n", + strings.Repeat("#", level+2), + strings.Join(command.Names(), ", "), + usage, + ) + + flags := prepareArgsWithValues(command.Flags) + if len(flags) > 0 { + prepared += fmt.Sprintf("\n%s", strings.Join(flags, "\n")) + } + + coms = append(coms, prepared) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + coms = append( + coms, + prepareCommands(command.Subcommands, level+1)..., + ) + } + } + + return coms +} + +func prepareArgsWithValues(flags []Flag) []string { + return prepareFlags(flags, ", ", "**", "**", `""`, true) +} + +func prepareArgsSynopsis(flags []Flag) []string { + return prepareFlags(flags, "|", "[", "]", "[value]", false) +} + +func prepareFlags( + flags []Flag, + sep, opener, closer, value string, + addDetails bool, +) []string { + args := []string{} + for _, f := range flags { + modifiedArg := opener + + for _, s := range FlagNames(f) { + trimmed := strings.TrimSpace(s) + if len(modifiedArg) > len(opener) { + modifiedArg += sep + } + if len(trimmed) > 1 { + modifiedArg += fmt.Sprintf("--%s", trimmed) + } else { + modifiedArg += fmt.Sprintf("-%s", trimmed) + } + } + modifiedArg += closer + if v, ok := getFlagValue(f); ok && !flag.IsBoolValue(v) { + modifiedArg += fmt.Sprintf("=%s", value) + } + + if addDetails { + modifiedArg += flagDetails(f) + } + + args = append(args, modifiedArg+"\n") + + } + sort.Strings(args) + return args +} + +// flagDetails returns a string containing the flags metadata +func flagDetails(f Flag) string { + description, _ := getFlagUsage(f) + value, _ := getFlagValue(f) + valStr := "" + + if !flag.IsBoolValue(value) { + if v, ok := value.(Generic); ok { + valStr = v.String() + } else if s, ok := generic.ToString(value); ok { + valStr = s + } else { + valStr = fmt.Sprintf("%v", value) + } + } + + if valStr != "" { + description += " (default: " + valStr + ")" + } + return ": " + description +} diff --git a/vendor/github.com/rancher/spur/cli/errors.go b/vendor/github.com/rancher/spur/cli/errors.go new file mode 100644 index 0000000000..f8a5c35b38 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/errors.go @@ -0,0 +1,141 @@ +package cli + +import ( + "fmt" + "io" + "os" + "strings" +) + +// OsExiter is the function used when the app exits. If not set defaults to os.Exit. +var OsExiter = os.Exit + +// ErrWriter is used to write errors to the user. This can be anything +// implementing the io.Writer interface and defaults to os.Stderr. +var ErrWriter io.Writer = os.Stderr + +// MultiError is an error that wraps multiple errors. +type MultiError interface { + error + Errors() []error +} + +// newMultiError creates a new MultiError. Pass in one or more errors. +func newMultiError(err ...error) MultiError { + ret := multiError(err) + return &ret +} + +type multiError []error + +// Error implements the error interface. +func (m *multiError) Error() string { + errs := make([]string, len(*m)) + for i, err := range *m { + errs[i] = err.Error() + } + + return strings.Join(errs, "\n") +} + +// Errors returns a copy of the errors slice +func (m *multiError) Errors() []error { + errs := make([]error, len(*m)) + for _, err := range *m { + errs = append(errs, err) + } + return errs +} + +// ErrorFormatter is the interface that will suitably format the error output +type ErrorFormatter interface { + Format(s fmt.State, verb rune) +} + +// ExitCoder is the interface checked by `App` and `Command` for a custom exit +// code +type ExitCoder interface { + error + ExitCode() int +} + +type exitError struct { + exitCode int + message interface{} +} + +// NewExitError calls Exit to create a new ExitCoder. +// +// Deprecated: This function is a duplicate of Exit and will eventually be removed. +func NewExitError(message interface{}, exitCode int) ExitCoder { + return Exit(message, exitCode) +} + +// Exit wraps a message and exit code into an error, which by default is +// handled with a call to os.Exit during default error handling. +// +// This is the simplest way to trigger a non-zero exit code for an App without +// having to call os.Exit manually. During testing, this behavior can be avoided +// by overiding the ExitErrHandler function on an App or the package-global +// OsExiter function. +func Exit(message interface{}, exitCode int) ExitCoder { + return &exitError{ + message: message, + exitCode: exitCode, + } +} + +func (ee *exitError) Error() string { + return fmt.Sprintf("%v", ee.message) +} + +func (ee *exitError) ExitCode() int { + return ee.exitCode +} + +// HandleExitCoder handles errors implementing ExitCoder by printing their +// message and calling OsExiter with the given exit code. +// +// If the given error instead implements MultiError, each error will be checked +// for the ExitCoder interface, and OsExiter will be called with the last exit +// code found, or exit code 1 if no ExitCoder is found. +// +// This function is the default error-handling behavior for an App. +func HandleExitCoder(err error) { + if err == nil { + return + } + + if exitErr, ok := err.(ExitCoder); ok { + if err.Error() != "" { + if _, ok := exitErr.(ErrorFormatter); ok { + fmt.Fprintf(ErrWriter, "%+v\n", err) + } else { + fmt.Fprintln(ErrWriter, err) + } + } + OsExiter(exitErr.ExitCode()) + return + } + + if multiErr, ok := err.(MultiError); ok { + code := handleMultiError(multiErr) + OsExiter(code) + return + } +} + +func handleMultiError(multiErr MultiError) int { + code := 1 + for _, merr := range multiErr.Errors() { + if multiErr2, ok := merr.(MultiError); ok { + code = handleMultiError(multiErr2) + } else if merr != nil { + fmt.Fprintln(ErrWriter, merr) + if exitErr, ok := merr.(ExitCoder); ok { + code = exitErr.ExitCode() + } + } + } + return code +} diff --git a/vendor/github.com/rancher/spur/cli/fish.go b/vendor/github.com/rancher/spur/cli/fish.go new file mode 100644 index 0000000000..016e484e94 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/fish.go @@ -0,0 +1,178 @@ +package cli + +import ( + "bytes" + "fmt" + "io" + "strings" + "text/template" + + "github.com/rancher/spur/flag" +) + +// ToFishCompletion creates a fish completion string for the `*App` +// The function errors if either parsing or writing of the string fails. +func (a *App) ToFishCompletion() (string, error) { + var w bytes.Buffer + if err := a.writeFishCompletionTemplate(&w); err != nil { + return "", err + } + return w.String(), nil +} + +type fishCompletionTemplate struct { + App *App + Completions []string + AllCommands []string +} + +func (a *App) writeFishCompletionTemplate(w io.Writer) error { + const name = "cli" + t, err := template.New(name).Parse(FishCompletionTemplate) + if err != nil { + return err + } + allCommands := []string{} + + // Add global flags + completions := a.prepareFishFlags(a.VisibleFlags(), allCommands) + + // Add help flag + if !a.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, allCommands)..., + ) + } + + // Add version flag + if !a.HideVersion { + completions = append( + completions, + a.prepareFishFlags([]Flag{VersionFlag}, allCommands)..., + ) + } + + // Add commands and their flags + completions = append( + completions, + a.prepareFishCommands(a.VisibleCommands(), &allCommands, []string{})..., + ) + + return t.ExecuteTemplate(w, name, &fishCompletionTemplate{ + App: a, + Completions: completions, + AllCommands: allCommands, + }) +} + +func (a *App) prepareFishCommands(commands []*Command, allCommands *[]string, previousCommands []string) []string { + completions := []string{} + for _, command := range commands { + if command.Hidden { + continue + } + + var completion strings.Builder + completion.WriteString(fmt.Sprintf( + "complete -r -c %s -n '%s' -a '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + strings.Join(command.Names(), " "), + )) + + if command.Usage != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(command.Usage))) + } + + if !command.HideHelp { + completions = append( + completions, + a.prepareFishFlags([]Flag{HelpFlag}, command.Names())..., + ) + } + + *allCommands = append(*allCommands, command.Names()...) + completions = append(completions, completion.String()) + completions = append( + completions, + a.prepareFishFlags(command.Flags, command.Names())..., + ) + + // recursevly iterate subcommands + if len(command.Subcommands) > 0 { + completions = append( + completions, + a.prepareFishCommands( + command.Subcommands, allCommands, command.Names(), + )..., + ) + } + } + + return completions +} + +func (a *App) prepareFishFlags(flags []Flag, previousCommands []string) []string { + completions := []string{} + for _, f := range flags { + completion := &strings.Builder{} + completion.WriteString(fmt.Sprintf( + "complete -c %s -n '%s'", + a.Name, + a.fishSubcommandHelper(previousCommands), + )) + + fishAddFileFlag(f, completion) + + for idx, opt := range FlagNames(f) { + if idx == 0 { + completion.WriteString(fmt.Sprintf( + " -l %s", strings.TrimSpace(opt), + )) + } else { + completion.WriteString(fmt.Sprintf( + " -s %s", strings.TrimSpace(opt), + )) + + } + } + + if v, ok := getFlagValue(f); ok && !flag.IsBoolValue(v) { + completion.WriteString(" -r") + } + + if usage, ok := getFlagUsage(f); ok && usage != "" { + completion.WriteString(fmt.Sprintf(" -d '%s'", + escapeSingleQuotes(usage))) + } + + completions = append(completions, completion.String()) + } + + return completions +} + +func fishAddFileFlag(flag Flag, completion *strings.Builder) { + if takesFile, ok := getFlagTakesFile(flag); ok && takesFile { + return + } + completion.WriteString(" -f") +} + +func (a *App) fishSubcommandHelper(allCommands []string) string { + fishHelper := fmt.Sprintf("__fish_%s_no_subcommand", a.Name) + if len(allCommands) > 0 { + fishHelper = fmt.Sprintf( + "__fish_seen_subcommand_from %s", + strings.Join(allCommands, " "), + ) + } + return fishHelper + +} + +func escapeSingleQuotes(input string) string { + return strings.Replace(input, `'`, `\'`, -1) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.go b/vendor/github.com/rancher/spur/cli/flag.go new file mode 100644 index 0000000000..ff263a103b --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.go @@ -0,0 +1,318 @@ +package cli + +import ( + "fmt" + "io/ioutil" + "reflect" + "regexp" + "runtime" + "strings" + + "github.com/rancher/spur/flag" + "github.com/rancher/spur/generic" +) + +// Flag is a common interface related to parsing flags in cli. +type Flag interface { + // Apply Flag settings to the given flag set + Apply(*flag.FlagSet) error +} + +// BashCompletionFlag enables bash-completion for all commands and subcommands +var BashCompletionFlag Flag = &BoolFlag{ + Name: "generate-bash-completion", + Hidden: true, +} + +// VersionFlag prints the version for the application +var VersionFlag Flag = &BoolFlag{ + Name: "version", + Aliases: []string{"v"}, + Usage: "print the version", +} + +// HelpFlag prints the help for all commands and subcommands. +// Set to nil to disable the flag. The subcommand +// will still be added unless HideHelp or HideHelpCommand is set to true. +var HelpFlag Flag = &BoolFlag{ + Name: "help", + Aliases: []string{"h"}, + Usage: "show help", +} + +// FlagStringer converts a flag definition to a string. This is used by help +// to display a flag. +var FlagStringer FlagStringFunc = stringifyFlag + +// FlagNamePrefixer converts a full flag name and its placeholder into the help +// message flag prefix. This is used by the default FlagStringer. +var FlagNamePrefixer FlagNamePrefixFunc = prefixedNames + +// FlagEnvHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagEnvHinter FlagEnvHintFunc = withEnvHint + +// FlagFileHinter annotates flag help message with the environment variable +// details. This is used by the default FlagStringer. +var FlagFileHinter FlagFileHintFunc = withFileHint + +// FlagsByName is a slice of Flag. +type FlagsByName []Flag + +const defaultPlaceholder = "value" + +func (f FlagsByName) Len() int { + return len(f) +} + +func (f FlagsByName) Less(i, j int) bool { + namesI := FlagNames(f[i]) + namesJ := FlagNames(f[j]) + if len(namesJ) == 0 { + return false + } else if len(namesI) == 0 { + return true + } + return lexicographicLess(namesI[0], namesJ[0]) +} + +func (f FlagsByName) Swap(i, j int) { + f[i], f[j] = f[j], f[i] +} + +func flagSet(name string, flags []Flag) (*flag.FlagSet, error) { + set := flag.NewFlagSet(name, flag.ContinueOnError) + + for _, f := range flags { + if err := f.Apply(set); err != nil { + return nil, err + } + } + set.SetOutput(ioutil.Discard) + return set, nil +} + +func visibleFlags(fl []Flag) []Flag { + var visible []Flag + for _, f := range fl { + if hidden, ok := getFlagHidden(f); !hidden || !ok { + visible = append(visible, f) + } + } + return visible +} + +func prefixFor(name string) (prefix string) { + if len(name) == 1 { + prefix = "-" + } else { + prefix = "--" + } + + return +} + +// Returns the placeholder, if any, and the unquoted usage string. +func unquoteUsage(usage string) (string, string) { + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name := usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break + } + } + return "", usage +} + +func prefixedNames(names []string, placeholder string) string { + var prefixed string + for i, name := range names { + if name == "" { + continue + } + + prefixed += prefixFor(name) + name + if placeholder != "" { + prefixed += " " + placeholder + } + if i < len(names)-1 { + prefixed += ", " + } + } + return prefixed +} + +func withEnvHint(envVars []string, str string) string { + envText := "" + if envVars != nil && len(envVars) > 0 { + prefix := "$" + suffix := "" + sep := ", $" + if runtime.GOOS == "windows" { + prefix = "%" + suffix = "%" + sep = "%, %" + } + + envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(envVars, sep), suffix) + } + return str + envText +} + +// FlagNames returns the name and aliases for a given flag, and panics +// if any of the values are invalid +func FlagNames(f Flag) []string { + name, ok := getFlagName(f) + if !ok { + panic("flag is missing name field") + } + aliases, _ := getFlagAliases(f) + + var ret []string + + for _, part := range strings.Split(name, ",") { + // urfave/cli v1 -> v2 migration warning zone: + // split name as per v1 standard + ret = append(ret, strings.TrimSpace(part)) + } + + // add the aliases to our names + ret = append(ret, aliases...) + + // validate the names and panic on failure + for _, part := range ret { + if strings.Contains(part, ",") { + panic(fmt.Errorf("flag name contains a comma: %q", part)) + } + if regexp.MustCompile(`\s`).Match([]byte(part)) { + panic(fmt.Errorf("flag name contains whitespace: %q", part)) + } + if part == "" { + panic("flag has an empty name") + } + } + + return ret +} + +func flagStringSliceField(f Flag, name string) []string { + fv := flagValue(f) + field := fv.FieldByName(name) + + if field.IsValid() { + return field.Interface().([]string) + } + + return []string{} +} + +func withFileHint(filePath, str string) string { + fileText := "" + if filePath != "" { + fileText = fmt.Sprintf(" [%s]", filePath) + } + return str + fileText +} + +func flagValue(f Flag) reflect.Value { + fv := reflect.ValueOf(f) + for fv.Kind() == reflect.Ptr { + fv = reflect.Indirect(fv) + } + return fv +} + +func formatDefault(format string) string { + return " (default: " + format + ")" +} + +func stringifyFlag(f Flag) string { + value, _ := getFlagValue(f) + usage, _ := getFlagUsage(f) + + if generic.IsSlice(value) { + return withEnvHint(flagStringSliceField(f, "EnvVars"), + stringifySlice(usage, FlagNames(f), value)) + } + + placeholder, usage := unquoteUsage(usage) + + needsPlaceholder := false + defaultValueString := "" + + var valKind reflect.Kind + + if valType := generic.TypeOf(value); valType != nil { + valKind = valType.Kind() + needsPlaceholder = valKind != reflect.Bool + } + + defaultValueString = fmt.Sprintf(formatDefault("%v"), value) + if valKind == reflect.String && value.(string) != "" { + defaultValueString = fmt.Sprintf(formatDefault("%q"), value) + } + + if helpText, ok := getFlagDefaultText(f); ok && helpText != "" { + defaultValueString = fmt.Sprintf(formatDefault("%s"), helpText) + } + + if defaultValueString == formatDefault("") { + defaultValueString = "" + } + + if needsPlaceholder && placeholder == "" { + placeholder = defaultPlaceholder + } + + usageWithDefault := strings.TrimSpace(usage + defaultValueString) + + return withEnvHint(flagStringSliceField(f, "EnvVars"), + fmt.Sprintf("%s\t%s", prefixedNames(FlagNames(f), placeholder), usageWithDefault)) +} + +func stringifySlice(usage string, names []string, value interface{}) string { + var defaults []string + for i := 0; i < generic.Len(value); i++ { + v := generic.Index(value, i) + s, ok := v.(string) + if ok && s == "" { + continue + } + if ok { + s = fmt.Sprintf("%q", s) + } else { + s, _ = generic.ToString(v) + } + defaults = append(defaults, s) + } + return stringifySliceFlag(usage, names, defaults) +} + +func stringifySliceFlag(usage string, names, defaultVals []string) string { + placeholder, usage := unquoteUsage(usage) + if placeholder == "" { + placeholder = defaultPlaceholder + } + + defaultVal := "" + if len(defaultVals) > 0 { + defaultVal = fmt.Sprintf(formatDefault("%s"), strings.Join(defaultVals, ", ")) + } + + usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal)) + return fmt.Sprintf("%s\t%s", prefixedNames(names, placeholder), usageWithDefault) +} + +func hasFlag(flags []Flag, fl Flag) bool { + for _, existing := range flags { + if fl == existing { + return true + } + } + return false +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_bool.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_bool.go new file mode 100644 index 0000000000..40cf8b7b21 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_bool.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Bool is a type alias for bool +type Bool = bool + +// BoolFlag is a flag with type bool +type BoolFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Bool + Destination *Bool +} + +// Apply populates the flag given the flag set and environment +func (f *BoolFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "bool", set) +} + +// Bool looks up the value of a local BoolFlag, returns +// an empty value if not found +func (c *Context) Bool(name string) bool { + return c.Lookup(name, *new(Bool)).(bool) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_boolSlice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_boolSlice.go new file mode 100644 index 0000000000..cb01262f13 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_boolSlice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// BoolSlice is a type alias for []bool +type BoolSlice = []bool + +// BoolSliceFlag is a flag with type []bool +type BoolSliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value BoolSlice + Destination *BoolSlice +} + +// Apply populates the flag given the flag set and environment +func (f *BoolSliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "bool slice", set) +} + +// BoolSlice looks up the value of a local BoolSliceFlag, returns +// an empty value if not found +func (c *Context) BoolSlice(name string) []bool { + return c.Lookup(name, *new(BoolSlice)).([]bool) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_duration.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_duration.go new file mode 100644 index 0000000000..6c4609a728 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_duration.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Duration is a type alias for time.Duration +type Duration = time.Duration + +// DurationFlag is a flag with type time.Duration +type DurationFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Duration + Destination *Duration +} + +// Apply populates the flag given the flag set and environment +func (f *DurationFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "duration", set) +} + +// Duration looks up the value of a local DurationFlag, returns +// an empty value if not found +func (c *Context) Duration(name string) time.Duration { + return c.Lookup(name, *new(Duration)).(time.Duration) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_durationSlice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_durationSlice.go new file mode 100644 index 0000000000..b309500cb1 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_durationSlice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// DurationSlice is a type alias for []time.Duration +type DurationSlice = []time.Duration + +// DurationSliceFlag is a flag with type []time.Duration +type DurationSliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value DurationSlice + Destination *DurationSlice +} + +// Apply populates the flag given the flag set and environment +func (f *DurationSliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "duration slice", set) +} + +// DurationSlice looks up the value of a local DurationSliceFlag, returns +// an empty value if not found +func (c *Context) DurationSlice(name string) []time.Duration { + return c.Lookup(name, *new(DurationSlice)).([]time.Duration) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_float64.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_float64.go new file mode 100644 index 0000000000..4d08689c84 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_float64.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Float64 is a type alias for float64 +type Float64 = float64 + +// Float64Flag is a flag with type float64 +type Float64Flag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Float64 + Destination *Float64 +} + +// Apply populates the flag given the flag set and environment +func (f *Float64Flag) Apply(set *flag.FlagSet) error { + return Apply(f, "float64", set) +} + +// Float64 looks up the value of a local Float64Flag, returns +// an empty value if not found +func (c *Context) Float64(name string) float64 { + return c.Lookup(name, *new(Float64)).(float64) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_float64Slice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_float64Slice.go new file mode 100644 index 0000000000..6f97ce5549 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_float64Slice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Float64Slice is a type alias for []float64 +type Float64Slice = []float64 + +// Float64SliceFlag is a flag with type []float64 +type Float64SliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Float64Slice + Destination *Float64Slice +} + +// Apply populates the flag given the flag set and environment +func (f *Float64SliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "float64 slice", set) +} + +// Float64Slice looks up the value of a local Float64SliceFlag, returns +// an empty value if not found +func (c *Context) Float64Slice(name string) []float64 { + return c.Lookup(name, *new(Float64Slice)).([]float64) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_int.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_int.go new file mode 100644 index 0000000000..864361c7b7 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_int.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Int is a type alias for int +type Int = int + +// IntFlag is a flag with type int +type IntFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Int + Destination *Int +} + +// Apply populates the flag given the flag set and environment +func (f *IntFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "int", set) +} + +// Int looks up the value of a local IntFlag, returns +// an empty value if not found +func (c *Context) Int(name string) int { + return c.Lookup(name, *new(Int)).(int) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_int64.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_int64.go new file mode 100644 index 0000000000..a7ad8bbd4a --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_int64.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Int64 is a type alias for int64 +type Int64 = int64 + +// Int64Flag is a flag with type int64 +type Int64Flag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Int64 + Destination *Int64 +} + +// Apply populates the flag given the flag set and environment +func (f *Int64Flag) Apply(set *flag.FlagSet) error { + return Apply(f, "int64", set) +} + +// Int64 looks up the value of a local Int64Flag, returns +// an empty value if not found +func (c *Context) Int64(name string) int64 { + return c.Lookup(name, *new(Int64)).(int64) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_int64Slice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_int64Slice.go new file mode 100644 index 0000000000..537e5cfb4a --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_int64Slice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Int64Slice is a type alias for []int64 +type Int64Slice = []int64 + +// Int64SliceFlag is a flag with type []int64 +type Int64SliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Int64Slice + Destination *Int64Slice +} + +// Apply populates the flag given the flag set and environment +func (f *Int64SliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "int64 slice", set) +} + +// Int64Slice looks up the value of a local Int64SliceFlag, returns +// an empty value if not found +func (c *Context) Int64Slice(name string) []int64 { + return c.Lookup(name, *new(Int64Slice)).([]int64) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_intSlice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_intSlice.go new file mode 100644 index 0000000000..9d5c63dd4d --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_intSlice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// IntSlice is a type alias for []int +type IntSlice = []int + +// IntSliceFlag is a flag with type []int +type IntSliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value IntSlice + Destination *IntSlice +} + +// Apply populates the flag given the flag set and environment +func (f *IntSliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "int slice", set) +} + +// IntSlice looks up the value of a local IntSliceFlag, returns +// an empty value if not found +func (c *Context) IntSlice(name string) []int { + return c.Lookup(name, *new(IntSlice)).([]int) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_string.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_string.go new file mode 100644 index 0000000000..d09830677d --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_string.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// String is a type alias for string +type String = string + +// StringFlag is a flag with type string +type StringFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value String + Destination *String +} + +// Apply populates the flag given the flag set and environment +func (f *StringFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "string", set) +} + +// String looks up the value of a local StringFlag, returns +// an empty value if not found +func (c *Context) String(name string) string { + return c.Lookup(name, *new(String)).(string) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_stringSlice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_stringSlice.go new file mode 100644 index 0000000000..5e52110c33 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_stringSlice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// StringSlice is a type alias for []string +type StringSlice = []string + +// StringSliceFlag is a flag with type []string +type StringSliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value StringSlice + Destination *StringSlice +} + +// Apply populates the flag given the flag set and environment +func (f *StringSliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "string slice", set) +} + +// StringSlice looks up the value of a local StringSliceFlag, returns +// an empty value if not found +func (c *Context) StringSlice(name string) []string { + return c.Lookup(name, *new(StringSlice)).([]string) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_time.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_time.go new file mode 100644 index 0000000000..60b2d861c2 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_time.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Time is a type alias for time.Time +type Time = time.Time + +// TimeFlag is a flag with type time.Time +type TimeFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Time + Destination *Time +} + +// Apply populates the flag given the flag set and environment +func (f *TimeFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "time", set) +} + +// Time looks up the value of a local TimeFlag, returns +// an empty value if not found +func (c *Context) Time(name string) time.Time { + return c.Lookup(name, *new(Time)).(time.Time) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_timeSlice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_timeSlice.go new file mode 100644 index 0000000000..abe19b154f --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_timeSlice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// TimeSlice is a type alias for []time.Time +type TimeSlice = []time.Time + +// TimeSliceFlag is a flag with type []time.Time +type TimeSliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value TimeSlice + Destination *TimeSlice +} + +// Apply populates the flag given the flag set and environment +func (f *TimeSliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "time slice", set) +} + +// TimeSlice looks up the value of a local TimeSliceFlag, returns +// an empty value if not found +func (c *Context) TimeSlice(name string) []time.Time { + return c.Lookup(name, *new(TimeSlice)).([]time.Time) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint.go new file mode 100644 index 0000000000..e9a901f96e --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Uint is a type alias for uint +type Uint = uint + +// UintFlag is a flag with type uint +type UintFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Uint + Destination *Uint +} + +// Apply populates the flag given the flag set and environment +func (f *UintFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "uint", set) +} + +// Uint looks up the value of a local UintFlag, returns +// an empty value if not found +func (c *Context) Uint(name string) uint { + return c.Lookup(name, *new(Uint)).(uint) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint64.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint64.go new file mode 100644 index 0000000000..f2d290b779 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint64.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Uint64 is a type alias for uint64 +type Uint64 = uint64 + +// Uint64Flag is a flag with type uint64 +type Uint64Flag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Uint64 + Destination *Uint64 +} + +// Apply populates the flag given the flag set and environment +func (f *Uint64Flag) Apply(set *flag.FlagSet) error { + return Apply(f, "uint64", set) +} + +// Uint64 looks up the value of a local Uint64Flag, returns +// an empty value if not found +func (c *Context) Uint64(name string) uint64 { + return c.Lookup(name, *new(Uint64)).(uint64) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint64Slice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint64Slice.go new file mode 100644 index 0000000000..07eadae801 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uint64Slice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// Uint64Slice is a type alias for []uint64 +type Uint64Slice = []uint64 + +// Uint64SliceFlag is a flag with type []uint64 +type Uint64SliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Uint64Slice + Destination *Uint64Slice +} + +// Apply populates the flag given the flag set and environment +func (f *Uint64SliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "uint64 slice", set) +} + +// Uint64Slice looks up the value of a local Uint64SliceFlag, returns +// an empty value if not found +func (c *Context) Uint64Slice(name string) []uint64 { + return c.Lookup(name, *new(Uint64Slice)).([]uint64) +} diff --git a/vendor/github.com/rancher/spur/cli/flag.zz_generated_uintSlice.go b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uintSlice.go new file mode 100644 index 0000000000..90938a0eaa --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag.zz_generated_uintSlice.go @@ -0,0 +1,40 @@ +package cli + +import ( + "time" + + "github.com/rancher/spur/flag" +) + +var _ = time.Time{} + +// UintSlice is a type alias for []uint +type UintSlice = []uint + +// UintSliceFlag is a flag with type []uint +type UintSliceFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value UintSlice + Destination *UintSlice +} + +// Apply populates the flag given the flag set and environment +func (f *UintSliceFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "uint slice", set) +} + +// UintSlice looks up the value of a local UintSliceFlag, returns +// an empty value if not found +func (c *Context) UintSlice(name string) []uint { + return c.Lookup(name, *new(UintSlice)).([]uint) +} diff --git a/vendor/github.com/rancher/spur/cli/flag_apply.go b/vendor/github.com/rancher/spur/cli/flag_apply.go new file mode 100644 index 0000000000..b33e91514f --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag_apply.go @@ -0,0 +1,105 @@ +package cli + +import ( + "fmt" + "io/ioutil" + "strings" + "syscall" + + "github.com/rancher/spur/flag" + "github.com/rancher/spur/generic" +) + +// Apply will attempt to apply generic flag values to a flagset +func Apply(f Flag, typ string, set *flag.FlagSet) error { + name := FlagNames(f)[0] + value, _ := getFlagValue(f) + usage, _ := getFlagUsage(f) + envVars, _ := getFlagEnvVars(f) + filePath, _ := getFlagFilePath(f) + // make sure we have a pointer to value (for non-generic values) + if !generic.IsPtr(value) { + value, _ = getFlagValuePtr(f) + } + destination, _ := getFlagDestination(f) + // create new destination if not defined + if destination == nil || generic.ValueOfPtr(destination) == nil { + destination = generic.New(value) + } + // create new value if not defined (for generic flag.Value) + if value == nil || generic.ValueOfPtr(value) == nil { + value = generic.New(destination) + } + wasSet := false + // load flags from environment or file + if val, ok := flagFromEnvOrFile(envVars, filePath); ok { + newValue := generic.New(value) + if err := applyValue(newValue, val); err != nil { + return fmt.Errorf("could not parse %q as %s value for flag %s: %s", val, typ, name, err) + } + value = newValue + wasSet = true + } + // copy value to destination + generic.Set(destination, generic.ValueOfPtr(value)) + dest, ok := destination.(flag.Value) + if !ok { + dest = flag.NewGenericValue(destination) + } + // for all of the names set the flag variable + for _, name := range FlagNames(f) { + set.Var(dest, name, usage) + } + // if value is not default mark as needs visit + if wasSet { + set.NeedsVisit(name) + } + return nil +} + +func applyValue(ptr interface{}, val string) error { + if !generic.IsSlice(ptr) { + // if we are a slice just return the applied elem + return applyElem(ptr, val) + } + // otherwise create a new slice and apply the split values + values := generic.Zero(ptr) + for _, val := range strings.Split(val, ",") { + value := generic.NewElem(ptr) + if err := generic.FromString(val, value); err != nil { + return err + } + values = generic.Append(values, generic.ValueOfPtr(value)) + } + generic.Set(ptr, values) + return nil +} + +func applyElem(ptr interface{}, val string) error { + if gen, ok := ptr.(flag.Value); ok { + // if we are a generic flag.Value then apply Set + return gen.Set(val) + } + // otherwise create a new value and convert it + value := generic.NewElem(ptr) + if err := generic.FromString(val, value); err != nil { + return err + } + generic.Set(ptr, generic.ValueOfPtr(value)) + return nil +} + +func flagFromEnvOrFile(envVars []string, filePath string) (val string, ok bool) { + for _, envVar := range envVars { + envVar = strings.TrimSpace(envVar) + if val, ok := syscall.Getenv(envVar); ok { + return val, true + } + } + for _, fileVar := range strings.Split(filePath, ",") { + if data, err := ioutil.ReadFile(fileVar); err == nil { + return string(data), true + } + } + return "", false +} diff --git a/vendor/github.com/rancher/spur/cli/flag_fields.go b/vendor/github.com/rancher/spur/cli/flag_fields.go new file mode 100644 index 0000000000..8d1358b336 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag_fields.go @@ -0,0 +1,92 @@ +package cli + +func getFlagName(f Flag) (result string, ok bool) { + if v := flagValue(f).FieldByName("Name"); v.IsValid() { + return v.Interface().(string), true + } + return +} + +func getFlagAliases(f Flag) (result []string, ok bool) { + if v := flagValue(f).FieldByName("Aliases"); v.IsValid() { + return v.Interface().([]string), true + } + return +} + +func getFlagEnvVars(f Flag) (result []string, ok bool) { + if v := flagValue(f).FieldByName("EnvVars"); v.IsValid() { + return v.Interface().([]string), true + } + return +} + +func getFlagUsage(f Flag) (result string, ok bool) { + if v := flagValue(f).FieldByName("Usage"); v.IsValid() { + return v.Interface().(string), true + } + return +} + +func getFlagDefaultText(f Flag) (result string, ok bool) { + if v := flagValue(f).FieldByName("DefaultText"); v.IsValid() { + return v.Interface().(string), true + } + return +} + +func getFlagFilePath(f Flag) (result string, ok bool) { + if v := flagValue(f).FieldByName("FilePath"); v.IsValid() { + return v.Interface().(string), true + } + return +} + +func getFlagRequired(f Flag) (result bool, ok bool) { + if v := flagValue(f).FieldByName("Required"); v.IsValid() { + return v.Interface().(bool), true + } + return +} + +func getFlagHidden(f Flag) (result bool, ok bool) { + if v := flagValue(f).FieldByName("Hidden"); v.IsValid() { + return v.Interface().(bool), true + } + return +} + +func getFlagTakesFile(f Flag) (result bool, ok bool) { + if v := flagValue(f).FieldByName("TakesFile"); v.IsValid() { + return v.Interface().(bool), true + } + return +} + +func getFlagSkipAltSrc(f Flag) (result bool, ok bool) { + if v := flagValue(f).FieldByName("SkipAltSrc"); v.IsValid() { + return v.Interface().(bool), true + } + return +} + +func getFlagValue(f Flag) (result interface{}, ok bool) { + if v := flagValue(f).FieldByName("Value"); v.IsValid() { + return v.Interface(), true + } + return +} + +func getFlagValuePtr(f Flag) (result interface{}, ok bool) { + if v := flagValue(f).FieldByName("Value"); v.IsValid() { + return v.Addr().Interface(), true + } + return +} + +func getFlagDestination(f Flag) (result interface{}, ok bool) { + if v := flagValue(f).FieldByName("Destination"); v.IsValid() { + return v.Interface(), true + } + return +} diff --git a/vendor/github.com/rancher/spur/cli/flag_generic.go b/vendor/github.com/rancher/spur/cli/flag_generic.go new file mode 100644 index 0000000000..cd8d66097a --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/flag_generic.go @@ -0,0 +1,36 @@ +package cli + +import ( + "github.com/rancher/spur/flag" +) + +// Generic is a type alias for flag.Value +type Generic = flag.Value + +// GenericFlag is a flag with type flag.Value +type GenericFlag struct { + Name string + Aliases []string + EnvVars []string + Usage string + DefaultText string + FilePath string + Required bool + Hidden bool + TakesFile bool + SkipAltSrc bool + + Value Generic + Destination Generic +} + +// Apply populates the flag given the flag set and environment +func (f *GenericFlag) Apply(set *flag.FlagSet) error { + return Apply(f, "generic", set) +} + +// Generic looks up the value of a local GenericFlag, returns +// an empty value if not found +func (c *Context) Generic(name string) interface{} { + return c.Lookup(name, nil) +} diff --git a/vendor/github.com/rancher/spur/cli/funcs.go b/vendor/github.com/rancher/spur/cli/funcs.go new file mode 100644 index 0000000000..474c48faf9 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/funcs.go @@ -0,0 +1,44 @@ +package cli + +// BashCompleteFunc is an action to execute when the shell completion flag is set +type BashCompleteFunc func(*Context) + +// BeforeFunc is an action to execute before any subcommands are run, but after +// the context is ready if a non-nil error is returned, no subcommands are run +type BeforeFunc func(*Context) error + +// AfterFunc is an action to execute after any subcommands are run, but after the +// subcommand has finished it is run even if Action() panics +type AfterFunc func(*Context) error + +// ActionFunc is the action to execute when no subcommands are specified +type ActionFunc func(*Context) error + +// CommandNotFoundFunc is executed if the proper command cannot be found +type CommandNotFoundFunc func(*Context, string) + +// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying +// customized usage error messages. This function is able to replace the +// original error messages. If this function is not set, the "Incorrect usage" +// is displayed and the execution is interrupted. +type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error + +// ExitErrHandlerFunc is executed if provided in order to handle exitError values +// returned by Actions and Before/After functions. +type ExitErrHandlerFunc func(context *Context, err error) + +// FlagStringFunc is used by the help generation to display a flag, which is +// expected to be a single line. +type FlagStringFunc func(Flag) string + +// FlagNamePrefixFunc is used by the default FlagStringFunc to create prefix +// text for a flag's full name. +type FlagNamePrefixFunc func(fullName []string, placeholder string) string + +// FlagEnvHintFunc is used by the default FlagStringFunc to annotate flag help +// with the environment variable details. +type FlagEnvHintFunc func(envVars []string, str string) string + +// FlagFileHintFunc is used by the default FlagStringFunc to annotate flag help +// with the file path details. +type FlagFileHintFunc func(filePath, str string) string diff --git a/vendor/github.com/rancher/spur/cli/help.go b/vendor/github.com/rancher/spur/cli/help.go new file mode 100644 index 0000000000..286fcce85c --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/help.go @@ -0,0 +1,378 @@ +package cli + +import ( + "fmt" + "io" + "os" + "strings" + "text/tabwriter" + "text/template" + "unicode/utf8" +) + +var helpCommand = &Command{ + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", + Action: func(c *Context) error { + args := c.Args() + if args.Present() { + return ShowCommandHelp(c, args.First()) + } + + ShowAppHelp(c) + return nil + }, +} + +var helpSubcommand = &Command{ + Name: "help", + Aliases: []string{"h"}, + Usage: "Shows a list of commands or help for one command", + ArgsUsage: "[command]", + Action: func(c *Context) error { + args := c.Args() + if args.Present() { + return ShowCommandHelp(c, args.First()) + } + + return ShowSubcommandHelp(c) + }, +} + +// Prints help for the App or Command +type helpPrinter func(w io.Writer, templ string, data interface{}) + +// Prints help for the App or Command with custom template function. +type helpPrinterCustom func(w io.Writer, templ string, data interface{}, customFunc map[string]interface{}) + +// HelpPrinter is a function that writes the help output. If not set explicitly, +// this calls HelpPrinterCustom using only the default template functions. +// +// If custom logic for printing help is required, this function can be +// overridden. If the ExtraInfo field is defined on an App, this function +// should not be modified, as HelpPrinterCustom will be used directly in order +// to capture the extra information. +var HelpPrinter helpPrinter = printHelp + +// HelpPrinterCustom is a function that writes the help output. It is used as +// the default implementation of HelpPrinter, and may be called directly if +// the ExtraInfo field is set on an App. +var HelpPrinterCustom helpPrinterCustom = printHelpCustom + +// VersionPrinter prints the version for the App +var VersionPrinter = printVersion + +// ShowAppHelpAndExit - Prints the list of subcommands for the app and exits with exit code. +func ShowAppHelpAndExit(c *Context, exitCode int) { + ShowAppHelp(c) + os.Exit(exitCode) +} + +// ShowAppHelp is an action that displays the help. +func ShowAppHelp(c *Context) error { + template := c.App.CustomAppHelpTemplate + if template == "" { + template = AppHelpTemplate + } + + if c.App.ExtraInfo == nil { + HelpPrinter(c.App.Writer, template, c.App) + return nil + } + + customAppData := func() map[string]interface{} { + return map[string]interface{}{ + "ExtraInfo": c.App.ExtraInfo, + } + } + HelpPrinterCustom(c.App.Writer, template, c.App, customAppData()) + + return nil +} + +// DefaultAppComplete prints the list of subcommands as the default app completion method +func DefaultAppComplete(c *Context) { + DefaultCompleteWithFlags(nil)(c) +} + +func printCommandSuggestions(commands []*Command, writer io.Writer) { + for _, command := range commands { + if command.Hidden { + continue + } + if os.Getenv("_CLI_ZSH_AUTOCOMPLETE_HACK") == "1" { + for _, name := range command.Names() { + fmt.Fprintf(writer, "%s:%s\n", name, command.Usage) + } + } else { + for _, name := range command.Names() { + fmt.Fprintf(writer, "%s\n", name) + } + } + } +} + +func cliArgContains(flagName string) bool { + for _, name := range strings.Split(flagName, ",") { + name = strings.TrimSpace(name) + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 + } + flag := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + for _, a := range os.Args { + if a == flag { + return true + } + } + } + return false +} + +func printFlagSuggestions(lastArg string, flags []Flag, writer io.Writer) { + cur := strings.TrimPrefix(lastArg, "-") + cur = strings.TrimPrefix(cur, "-") + for _, flag := range flags { + if bflag, ok := flag.(*BoolFlag); ok && bflag.Hidden { + continue + } + for _, name := range FlagNames(flag) { + name = strings.TrimSpace(name) + // this will get total count utf8 letters in flag name + count := utf8.RuneCountInString(name) + if count > 2 { + count = 2 // resuse this count to generate single - or -- in flag completion + } + // if flag name has more than one utf8 letter and last argument in cli has -- prefix then + // skip flag completion for short flags example -v or -x + if strings.HasPrefix(lastArg, "--") && count == 1 { + continue + } + // match if last argument matches this flag and it is not repeated + if strings.HasPrefix(name, cur) && cur != name && !cliArgContains(name) { + flagCompletion := fmt.Sprintf("%s%s", strings.Repeat("-", count), name) + fmt.Fprintln(writer, flagCompletion) + } + } + } +} + +func DefaultCompleteWithFlags(cmd *Command) func(c *Context) { + return func(c *Context) { + if len(os.Args) > 2 { + lastArg := os.Args[len(os.Args)-2] + if strings.HasPrefix(lastArg, "-") { + printFlagSuggestions(lastArg, c.App.Flags, c.App.Writer) + if cmd != nil { + printFlagSuggestions(lastArg, cmd.Flags, c.App.Writer) + } + return + } + } + if cmd != nil { + printCommandSuggestions(cmd.Subcommands, c.App.Writer) + } else { + printCommandSuggestions(c.App.Commands, c.App.Writer) + } + } +} + +// ShowCommandHelpAndExit - exits with code after showing help +func ShowCommandHelpAndExit(c *Context, command string, code int) { + ShowCommandHelp(c, command) + os.Exit(code) +} + +// ShowCommandHelp prints help for the given command +func ShowCommandHelp(ctx *Context, command string) error { + // show the subcommand help for a command with subcommands + if command == "" { + HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App) + return nil + } + + for _, c := range ctx.App.Commands { + if c.HasName(command) { + templ := c.CustomHelpTemplate + if templ == "" { + templ = CommandHelpTemplate + } + + HelpPrinter(ctx.App.Writer, templ, c) + + return nil + } + } + + if ctx.App.CommandNotFound == nil { + return Exit(fmt.Sprintf("No help topic for '%v'", command), 3) + } + + ctx.App.CommandNotFound(ctx, command) + return nil +} + +// ShowSubcommandHelp prints help for the given subcommand +func ShowSubcommandHelp(c *Context) error { + if c == nil { + return nil + } + + if c.Command != nil { + return ShowCommandHelp(c, c.Command.Name) + } + + return ShowCommandHelp(c, "") +} + +// ShowVersion prints the version number of the App +func ShowVersion(c *Context) { + VersionPrinter(c) +} + +func printVersion(c *Context) { + fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) +} + +// ShowCompletions prints the lists of commands within a given context +func ShowCompletions(c *Context) { + a := c.App + if a != nil && a.BashComplete != nil { + a.BashComplete(c) + } +} + +// ShowCommandCompletions prints the custom completions for a given command +func ShowCommandCompletions(ctx *Context, command string) { + c := ctx.App.Command(command) + if c != nil { + if c.BashComplete != nil { + c.BashComplete(ctx) + } else { + DefaultCompleteWithFlags(c)(ctx) + } + } + +} + +// FlagToString will convert a flag to a string, using either it's String() +// function, or FlagStringer if String() is not defined +func FlagToString(f Flag) string { + if stringer, ok := f.(fmt.Stringer); ok { + return stringer.String() + } + return FlagStringer(f) +} + +// printHelpCustom is the default implementation of HelpPrinterCustom. +// +// The customFuncs map will be combined with a default template.FuncMap to +// allow using arbitrary functions in template rendering. +func printHelpCustom(out io.Writer, templ string, data interface{}, customFuncs map[string]interface{}) { + funcMap := template.FuncMap{ + "join": strings.Join, + "FlagToString": FlagToString, + } + for key, value := range customFuncs { + funcMap[key] = value + } + + w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) + t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) + + err := t.Execute(w, data) + if err != nil { + // If the writer is closed, t.Execute will fail, and there's nothing + // we can do to recover. + if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" { + fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err) + } + return + } + w.Flush() +} + +func printHelp(out io.Writer, templ string, data interface{}) { + HelpPrinterCustom(out, templ, data, nil) +} + +func checkVersion(c *Context) bool { + found := false + for _, name := range FlagNames(VersionFlag) { + if c.Bool(name) { + found = true + } + } + return found +} + +func checkHelp(c *Context) bool { + found := false + for _, name := range FlagNames(HelpFlag) { + if c.Bool(name) { + found = true + } + } + return found +} + +func checkCommandHelp(c *Context, name string) bool { + if c.Bool("h") || c.Bool("help") { + ShowCommandHelp(c, name) + return true + } + + return false +} + +func checkSubcommandHelp(c *Context) bool { + if c.Bool("h") || c.Bool("help") { + ShowSubcommandHelp(c) + return true + } + + return false +} + +func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) { + if !a.EnableBashCompletion { + return false, arguments + } + + pos := len(arguments) - 1 + lastArg := arguments[pos] + + if lastArg != "--generate-bash-completion" { + return false, arguments + } + + return true, arguments[:pos] +} + +func checkCompletions(c *Context) bool { + if !c.shellComplete { + return false + } + + if args := c.Args(); args.Present() { + name := args.First() + if cmd := c.App.Command(name); cmd != nil { + // let the command handle the completion + return false + } + } + + ShowCompletions(c) + return true +} + +func checkCommandCompletions(c *Context, name string) bool { + if !c.shellComplete { + return false + } + + ShowCommandCompletions(c, name) + return true +} diff --git a/vendor/github.com/rancher/spur/cli/input_source.go b/vendor/github.com/rancher/spur/cli/input_source.go new file mode 100644 index 0000000000..cb179d4b93 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/input_source.go @@ -0,0 +1,79 @@ +package cli + +import ( + "fmt" + + "github.com/rancher/spur/flag" +) + +// InputSourceContext is an interface used to allow +// other input sources to be implemented as needed. +// +// Source returns an identifier for the input source. In case of file source +// it should return path to the file. +type InputSourceContext interface { + Source() string + Get(name string) (interface{}, bool) +} + +// ApplyInputSourceValue will attempt to apply an input source to a generic flag +func ApplyInputSourceValue(f Flag, context *Context, isc InputSourceContext) error { + name := FlagNames(f)[0] + skipAltSrc, _ := getFlagSkipAltSrc(f) + + if !skipAltSrc && context.flagSet != nil { + if !context.IsSet(name) { + // only checks the first name of this flag + value, ok := isc.Get(name) + if !ok || value == nil { + return nil + } + // if a generic flag.Value get the string representation + if v, ok := value.(flag.Value); ok { + value = v.String() + } + // sets the new value from some source + if err := context.Set(name, value); err != nil { + return fmt.Errorf("unable to apply input source '%s': %s", isc.Source(), err) + } + } + } + return nil +} + +// ApplyInputSourceValues iterates over all provided flags and executes ApplyInputSourceValue +// on each flag to apply an alternate input source. +func ApplyInputSourceValues(context *Context, inputSourceContext InputSourceContext, flags []Flag) (err error) { + for _, f := range flags { + if err = ApplyInputSourceValue(f, context, inputSourceContext); err != nil { + return err + } + } + return +} + +// InitInputSource is used to to setup an InputSourceContext on a Command Before method. It will create a new +// input source based on the func provided with potentially using existing Context values to initialize itself. If there is +// no error it will then apply the new input source to any flags that are supported by the input source +func InitInputSource(flags []Flag, createInputSource func(context *Context) (InputSourceContext, error)) BeforeFunc { + return func(context *Context) error { + inputSource, err := createInputSource(context) + if err != nil { + return err + } + return ApplyInputSourceValues(context, inputSource, flags) + } +} + +// InitAllInputSource is used to to setup an InputSourceContext on a Command Before method. It will create a new +// input source based on the func provided with potentially using existing Context values to initialize itself. If there is +// no error it will then apply the new input source to all flags that are supported by the input source +func InitAllInputSource(createInputSource func(context *Context) (InputSourceContext, error)) BeforeFunc { + return func(context *Context) error { + inputSource, err := createInputSource(context) + if err != nil { + return err + } + return ApplyInputSourceValues(context, inputSource, context.GetFlags()) + } +} diff --git a/vendor/github.com/rancher/spur/cli/parse.go b/vendor/github.com/rancher/spur/cli/parse.go new file mode 100644 index 0000000000..3106686bde --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/parse.go @@ -0,0 +1,95 @@ +package cli + +import ( + "strings" + + "github.com/rancher/spur/flag" +) + +type iterativeParser interface { + newFlagSet() (*flag.FlagSet, error) + useShortOptionHandling() bool +} + +// To enable short-option handling (e.g., "-it" vs "-i -t") we have to +// iteratively catch parsing errors. This way we achieve LR parsing without +// transforming any arguments. Otherwise, there is no way we can discriminate +// combined short options from common arguments that should be left untouched. +// Pass `shellComplete` to continue parsing options on failure during shell +// completion when, the user-supplied options may be incomplete. +func parseIter(set *flag.FlagSet, ip iterativeParser, args []string, shellComplete bool) error { + for { + err := set.Parse(args) + if !ip.useShortOptionHandling() || err == nil { + if shellComplete { + return nil + } + return err + } + + errStr := err.Error() + trimmed := strings.TrimPrefix(errStr, "flag provided but not defined: -") + if errStr == trimmed { + return err + } + + // regenerate the initial args with the split short opts + argsWereSplit := false + for i, arg := range args { + // skip args that are not part of the error message + if name := strings.TrimLeft(arg, "-"); name != trimmed { + continue + } + + // if we can't split, the error was accurate + shortOpts := splitShortOptions(set, arg) + if len(shortOpts) == 1 { + return err + } + + // swap current argument with the split version + args = append(args[:i], append(shortOpts, args[i+1:]...)...) + argsWereSplit = true + break + } + + // This should be an impossible to reach code path, but in case the arg + // splitting failed to happen, this will prevent infinite loops + if !argsWereSplit { + return err + } + + // Since custom parsing failed, replace the flag set before retrying + newSet, err := ip.newFlagSet() + if err != nil { + return err + } + *set = *newSet + } +} + +func splitShortOptions(set *flag.FlagSet, arg string) []string { + shortFlagsExist := func(s string) bool { + for _, c := range s[1:] { + if f := set.Lookup(string(c)); f == nil { + return false + } + } + return true + } + + if !isSplittable(arg) || !shortFlagsExist(arg) { + return []string{arg} + } + + separated := make([]string, 0, len(arg)-1) + for _, flagChar := range arg[1:] { + separated = append(separated, "-"+string(flagChar)) + } + + return separated +} + +func isSplittable(flagArg string) bool { + return strings.HasPrefix(flagArg, "-") && !strings.HasPrefix(flagArg, "--") && len(flagArg) > 2 +} diff --git a/vendor/github.com/rancher/spur/cli/sort.go b/vendor/github.com/rancher/spur/cli/sort.go new file mode 100644 index 0000000000..23d1c2f772 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/sort.go @@ -0,0 +1,29 @@ +package cli + +import "unicode" + +// lexicographicLess compares strings alphabetically considering case. +func lexicographicLess(i, j string) bool { + iRunes := []rune(i) + jRunes := []rune(j) + + lenShared := len(iRunes) + if lenShared > len(jRunes) { + lenShared = len(jRunes) + } + + for index := 0; index < lenShared; index++ { + ir := iRunes[index] + jr := jRunes[index] + + if lir, ljr := unicode.ToLower(ir), unicode.ToLower(jr); lir != ljr { + return lir < ljr + } + + if ir != jr { + return ir < jr + } + } + + return i < j +} diff --git a/vendor/github.com/rancher/spur/cli/template.go b/vendor/github.com/rancher/spur/cli/template.go new file mode 100644 index 0000000000..2d2ac300e5 --- /dev/null +++ b/vendor/github.com/rancher/spur/cli/template.go @@ -0,0 +1,120 @@ +package cli + +// AppHelpTemplate is the text template for the Default help topic. +// cli.go uses text/template to render templates. You can +// render custom help text by setting this variable. +var AppHelpTemplate = `NAME: + {{.Name}}{{if .Usage}} - {{.Usage}}{{end}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} + +VERSION: + {{.Version}}{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description}}{{end}}{{if len .Authors}} + +AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: + {{range $index, $author := .Authors}}{{if $index}} + {{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} + +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + +GLOBAL OPTIONS: + {{range $index, $option := .VisibleFlags}}{{if $index}} + {{end}}{{FlagToString $option}}{{end}}{{end}}{{if .Copyright}} + +COPYRIGHT: + {{.Copyright}}{{end}} +` + +// CommandHelpTemplate is the text template for the command help topic. +// cli.go uses text/template to render templates. You can +// render custom help text by setting this variable. +var CommandHelpTemplate = `NAME: + {{.HelpName}} - {{.Usage}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Category}} + +CATEGORY: + {{.Category}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description}}{{end}}{{if .VisibleFlags}} + +OPTIONS: + {{range .VisibleFlags}}{{FlagToString .}} + {{end}}{{end}} +` + +// SubcommandHelpTemplate is the text template for the subcommand help topic. +// cli.go uses text/template to render templates. You can +// render custom help text by setting this variable. +var SubcommandHelpTemplate = `NAME: + {{.HelpName}} - {{.Usage}} + +USAGE: + {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Description}} + +DESCRIPTION: + {{.Description}}{{end}} + +COMMANDS:{{range .VisibleCategories}}{{if .Name}} + {{.Name}}:{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{range .VisibleCommands}} + {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}} + +OPTIONS: + {{range .VisibleFlags}}{{FlagToString .}} + {{end}}{{end}} +` + +var MarkdownDocTemplate = `% {{ .App.Name }} 8 + +# NAME + +{{ .App.Name }}{{ if .App.Usage }} - {{ .App.Usage }}{{ end }} + +# SYNOPSIS + +{{ .App.Name }} +{{ if .SynopsisArgs }} +` + "```" + ` +{{ range $v := .SynopsisArgs }}{{ $v }}{{ end }}` + "```" + ` +{{ end }}{{ if .App.UsageText }} +# DESCRIPTION + +{{ .App.UsageText }} +{{ end }} +**Usage**: + +` + "```" + ` +{{ .App.Name }} [GLOBAL OPTIONS] command [COMMAND OPTIONS] [ARGUMENTS...] +` + "```" + ` +{{ if .GlobalArgs }} +# GLOBAL OPTIONS +{{ range $v := .GlobalArgs }} +{{ $v }}{{ end }} +{{ end }}{{ if .Commands }} +# COMMANDS +{{ range $v := .Commands }} +{{ $v }}{{ end }}{{ end }}` + +var FishCompletionTemplate = `# {{ .App.Name }} fish shell completion + +function __fish_{{ .App.Name }}_no_subcommand --description 'Test if there has been any subcommand yet' + for i in (commandline -opc) + if contains -- $i{{ range $v := .AllCommands }} {{ $v }}{{ end }} + return 1 + end + end + return 0 +end + +{{ range $v := .Completions }}{{ $v }} +{{ end }}` diff --git a/vendor/github.com/rancher/spur/flag/LICENSE b/vendor/github.com/rancher/spur/flag/LICENSE new file mode 100644 index 0000000000..6a66aea5ea --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/rancher/spur/flag/_flag.template.go b/vendor/github.com/rancher/spur/flag/_flag.template.go new file mode 100644 index 0000000000..88b42247e0 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/_flag.template.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// Title__Var defines a Type__ flag with specified name, default value, and usage string. +// The argument p points to a Type__ variable in which to store the value of the flag. +func (f *FlagSet) Title__Var(ptr *Type__, name string, value Type__, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Title__ defines a Type__ flag with specified name, default value, and usage string. +// The return value is the address of a Type__ variable that stores the value of the flag. +func (f *FlagSet) Title__(name string, value Type__, usage string) *Type__ { + return f.Generic(name, value, usage).(*Type__) +} + +// Title__Var defines a Type__ flag with specified name, default value, and usage string. +// The argument p points to a Type__ variable in which to store the value of the flag. +func Title__Var(ptr *Type__, name string, value Type__, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Title__ defines a Type__ flag with specified name, default value, and usage string. +// The return value is the address of a Type__ variable that stores the value of the flag. +func Title__(name string, value Type__, usage string) *Type__ { + return CommandLine.Generic(name, value, usage).(*Type__) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.go b/vendor/github.com/rancher/spur/flag/flag.go new file mode 100644 index 0000000000..c466190ab9 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.go @@ -0,0 +1,661 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + Package flag implements command-line flag parsing. + + Usage + + Define flags using flag.String(), Bool(), Int(), etc. + + This declares an integer flag, -n, stored in the pointer nFlag, with type *int: + import "flag" + var nFlag = flag.Int("n", 1234, "help message for flag n") + If you like, you can bind the flag to a variable using the Var() functions. + var flagvar int + func init() { + flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname") + } + Or you can create custom flags that satisfy the Value interface (with + pointer receivers) and couple them to flag parsing by + flag.Var(&flagVal, "name", "help message for flagname") + For such flags, the default value is just the initial value of the variable. + + After all flags are defined, call + flag.Parse() + to parse the command line into the defined flags. + + Flags may then be used directly. If you're using the flags themselves, + they are all pointers; if you bind to variables, they're values. + fmt.Println("ip has value ", *ip) + fmt.Println("flagvar has value ", flagvar) + + After parsing, the arguments following the flags are available as the + slice flag.Args() or individually as flag.Arg(i). + The arguments are indexed from 0 through flag.NArg()-1. + + Command line flag syntax + + The following forms are permitted: + + -flag + -flag=x + -flag x // non-boolean flags only + One or two minus signs may be used; they are equivalent. + The last form is not permitted for boolean flags because the + meaning of the command + cmd -x * + where * is a Unix shell wildcard, will change if there is a file + called 0, false, etc. You must use the -flag=false form to turn + off a boolean flag. + + Flag parsing stops just before the first non-flag argument + ("-" is a non-flag argument) or after the terminator "--". + + Integer flags accept 1234, 0664, 0x1234 and may be negative. + Boolean flags may be: + 1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False + Duration flags accept any input valid for time.ParseDuration. + + The default set of command-line flags is controlled by + top-level functions. The FlagSet type allows one to define + independent sets of flags, such as to implement subcommands + in a command-line interface. The methods of FlagSet are + analogous to the top-level functions for the command-line + flag set. +*/ +package flag + +import ( + "errors" + "fmt" + "io" + "os" + "reflect" + "sort" + "strings" + + "github.com/rancher/spur/generic" +) + +// ErrHelp is the error returned if the -help or -h flag is invoked +// but no such flag is defined. +var ErrHelp = errors.New("flag: help requested") + +// Value is the interface to the dynamic value stored in a flag. +// (The default value is represented as a string.) +// +// If a Value has an IsBoolFlag() bool method returning true, +// the command-line parser makes -name equivalent to -name=true +// rather than using the next command-line argument. +// +// Set is called once, in command line order, for each flag present. +// The flag package may call the String method with a zero-valued receiver, +// such as a nil pointer. +type Value interface { + String() string + Set(interface{}) error +} + +// Getter is an interface that allows the contents of a Value to be retrieved. +// It wraps the Value interface, rather than being part of it, because it +// appeared after Go 1 and its compatibility rules. All Value types provided +// by this package satisfy the Getter interface. +type Getter interface { + Value + Get() interface{} +} + +// BoolFlag is an interface for determining if the value of a flag is needed. +type BoolFlag interface { + IsBoolFlag() bool +} + +// IsBoolValue returns true for data types which don't require a flag value +func IsBoolValue(value interface{}) bool { + if v, ok := value.(BoolFlag); ok { + return v.IsBoolFlag() + } + var t reflect.Type + if v, ok := value.(Getter); ok { + t = generic.ElemTypeOf(v.Get()) + } else { + t = generic.ElemTypeOf(value) + } + return t != nil && t.String() == "bool" +} + +// ErrorHandling defines how FlagSet.Parse behaves if the parse fails. +type ErrorHandling int + +// These constants cause FlagSet.Parse to behave as described if the parse fails. +const ( + ContinueOnError ErrorHandling = iota // Return a descriptive error. + ExitOnError // Call os.Exit(2) or for -h/-help Exit(0). + PanicOnError // Call panic with a descriptive error. +) + +// A FlagSet represents a set of defined flags. The zero value of a FlagSet +// has no name and has ContinueOnError error handling. +// +// Flag names must be unique within a FlagSet. An attempt to define a flag whose +// name is already in use will cause a panic. +type FlagSet struct { + // Usage is the function called when an error occurs while parsing flags. + // The field is a function (not a method) that may be changed to point to + // a custom error handler. What happens after Usage is called depends + // on the ErrorHandling setting; for the command line, this defaults + // to ExitOnError, which exits the program after calling Usage. + Usage func() + + name string + parsed bool + actual map[string]*Flag + formal map[string]*Flag + args []string // arguments after flags + errorHandling ErrorHandling + output io.Writer // nil means stderr; use Output() accessor +} + +// A Flag represents the state of a flag. +type Flag struct { + Name string // name as it appears on command line + Usage string // help message + Value Value // value as set + DefValue string // default value (as text); for usage message +} + +// sortFlags returns the flags as a slice in lexicographical sorted order. +func sortFlags(flags map[string]*Flag) []*Flag { + result := make([]*Flag, len(flags)) + i := 0 + for _, f := range flags { + result[i] = f + i++ + } + sort.Slice(result, func(i, j int) bool { + return result[i].Name < result[j].Name + }) + return result +} + +const invalidValueTemplate = "invalid value %q for flag -%s: %v" + +func (f *FlagSet) addActual(name string, flag *Flag) { + if f.actual == nil { + f.actual = make(map[string]*Flag) + } + f.actual[name] = flag +} + +// Output returns the destination for usage and error messages. os.Stderr is returned if +// output was not set or was set to nil. +func (f *FlagSet) Output() io.Writer { + if f.output == nil { + return os.Stderr + } + return f.output +} + +// Name returns the name of the flag set. +func (f *FlagSet) Name() string { + return f.name +} + +// ErrorHandling returns the error handling behavior of the flag set. +func (f *FlagSet) ErrorHandling() ErrorHandling { + return f.errorHandling +} + +// SetOutput sets the destination for usage and error messages. +// If output is nil, os.Stderr is used. +func (f *FlagSet) SetOutput(output io.Writer) { + f.output = output +} + +// VisitAll visits the flags in lexicographical order, calling fn for each. +// It visits all flags, even those not set. +func (f *FlagSet) VisitAll(fn func(*Flag)) { + for _, flag := range sortFlags(f.formal) { + fn(flag) + } +} + +// VisitAll visits the command-line flags in lexicographical order, calling +// fn for each. It visits all flags, even those not set. +func VisitAll(fn func(*Flag)) { + CommandLine.VisitAll(fn) +} + +// Visit visits the flags in lexicographical order, calling fn for each. +// It visits only those flags that have been set. +func (f *FlagSet) Visit(fn func(*Flag)) { + for _, flag := range sortFlags(f.actual) { + fn(flag) + } +} + +// NeedsVisit marks the named flags for visit. +func (f *FlagSet) NeedsVisit(names ...string) { + for _, name := range names { + if flag := f.Lookup(name); flag != nil { + f.addActual(name, flag) + } + } +} + +// Visit visits the command-line flags in lexicographical order, calling fn +// for each. It visits only those flags that have been set. +func Visit(fn func(*Flag)) { + CommandLine.Visit(fn) +} + +// Lookup returns the Flag structure of the named flag, returning nil if none exists. +func (f *FlagSet) Lookup(name string) *Flag { + return f.formal[name] +} + +// Lookup returns the Flag structure of the named command-line flag, +// returning nil if none exists. +func Lookup(name string) *Flag { + return CommandLine.formal[name] +} + +// Set sets the value of the named flag. +func (f *FlagSet) Set(name string, value interface{}) error { + flag, ok := f.formal[name] + if !ok { + return fmt.Errorf("no such flag -%v", name) + } + err := flag.Value.Set(value) + if err != nil { + return fmt.Errorf(invalidValueTemplate, value, name, err) + } + f.addActual(name, flag) + return nil +} + +// Set sets the value of the named command-line flag. +func Set(name string, value interface{}) error { + return CommandLine.Set(name, value) +} + +// isZeroValue determines whether the string represents the zero +// value for a flag. +func isZeroValue(flag *Flag, value string) bool { + // Build a zero value of the flag's Value type, and see if the + // result of calling its String method equals the value passed in. + if val, ok := flag.Value.(Getter); ok { + if s, ok := generic.ToString(generic.Zero(val.Get())); ok { + return value == s + } + } + return false +} + +// UnquoteUsage extracts a back-quoted name from the usage +// string for a flag and returns it and the un-quoted usage. +// Given "a `name` to show" it returns ("name", "a name to show"). +// If there are no back quotes, the name is an educated guess of the +// type of the flag's value, or the empty string if the flag is boolean. +func UnquoteUsage(flag *Flag) (name string, usage string) { + // Look for a back-quoted name, but avoid the strings package. + usage = flag.Usage + for i := 0; i < len(usage); i++ { + if usage[i] == '`' { + for j := i + 1; j < len(usage); j++ { + if usage[j] == '`' { + name = usage[i+1 : j] + usage = usage[:i] + name + usage[j+1:] + return name, usage + } + } + break // Only one back quote; use type name. + } + } + // No explicit name, so use type if we can find one. + name = "value" + if v, ok := flag.Value.(Getter); ok { + name = generic.TypeOf(v.Get()).String() + } + if IsBoolValue(flag.Value) { + name = "" + } + return +} + +// PrintDefaults prints, to standard error unless configured otherwise, the +// default values of all defined command-line flags in the set. See the +// documentation for the global function PrintDefaults for more information. +func (f *FlagSet) PrintDefaults() { + f.VisitAll(func(flag *Flag) { + s := fmt.Sprintf(" -%s", flag.Name) // Two spaces before -; see next two comments. + name, usage := UnquoteUsage(flag) + if len(name) > 0 { + s += " " + name + } + // Boolean flags of one ASCII letter are so common we + // treat them specially, putting their usage on the same line. + if len(s) <= 4 { // space, space, '-', 'x'. + s += "\t" + } else { + // Four spaces before the tab triggers good alignment + // for both 4- and 8-space tab stops. + s += "\n \t" + } + s += strings.ReplaceAll(usage, "\n", "\n \t") + + if !isZeroValue(flag, flag.DefValue) { + if v, ok := flag.Value.(Getter); ok && generic.TypeOf(v.Get()).String() == "string" { + // put quotes on the value + s += fmt.Sprintf(" (default %q)", flag.DefValue) + } else { + s += fmt.Sprintf(" (default %v)", flag.DefValue) + } + } + fmt.Fprint(f.Output(), s, "\n") + }) +} + +// PrintDefaults prints, to standard error unless configured otherwise, +// a usage message showing the default settings of all defined +// command-line flags. +// For an integer valued flag x, the default output has the form +// -x int +// usage-message-for-x (default 7) +// The usage message will appear on a separate line for anything but +// a bool flag with a one-byte name. For bool flags, the type is +// omitted and if the flag name is one byte the usage message appears +// on the same line. The parenthetical default is omitted if the +// default is the zero value for the type. The listed type, here int, +// can be changed by placing a back-quoted name in the flag's usage +// string; the first such item in the message is taken to be a parameter +// name to show in the message and the back quotes are stripped from +// the message when displayed. For instance, given +// flag.String("I", "", "search `directory` for include files") +// the output will be +// -I directory +// search directory for include files. +// +// To change the destination for flag messages, call CommandLine.SetOutput. +func PrintDefaults() { + CommandLine.PrintDefaults() +} + +// defaultUsage is the default function to print a usage message. +func (f *FlagSet) defaultUsage() { + if f.name == "" { + fmt.Fprintf(f.Output(), "Usage:\n") + } else { + fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name) + } + f.PrintDefaults() +} + +// NOTE: Usage is not just defaultUsage(CommandLine) +// because it serves (via godoc flag Usage) as the example +// for how to write your own usage function. + +// Usage prints a usage message documenting all defined command-line flags +// to CommandLine's output, which by default is os.Stderr. +// It is called when an error occurs while parsing flags. +// The function is a variable that may be changed to point to a custom function. +// By default it prints a simple header and calls PrintDefaults; for details about the +// format of the output and how to control it, see the documentation for PrintDefaults. +// Custom usage functions may choose to exit the program; by default exiting +// happens anyway as the command line's error handling strategy is set to +// ExitOnError. +var Usage = func() { + fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0]) + PrintDefaults() +} + +// NFlag returns the number of flags that have been set. +func (f *FlagSet) NFlag() int { return len(f.actual) } + +// NFlag returns the number of command-line flags that have been set. +func NFlag() int { return len(CommandLine.actual) } + +// Arg returns the i'th argument. Arg(0) is the first remaining argument +// after flags have been processed. Arg returns an empty string if the +// requested element does not exist. +func (f *FlagSet) Arg(i int) string { + if i < 0 || i >= len(f.args) { + return "" + } + return f.args[i] +} + +// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument +// after flags have been processed. Arg returns an empty string if the +// requested element does not exist. +func Arg(i int) string { + return CommandLine.Arg(i) +} + +// NArg is the number of arguments remaining after flags have been processed. +func (f *FlagSet) NArg() int { return len(f.args) } + +// NArg is the number of arguments remaining after flags have been processed. +func NArg() int { return len(CommandLine.args) } + +// Args returns the non-flag arguments. +func (f *FlagSet) Args() []string { return f.args } + +// Args returns the non-flag command-line arguments. +func Args() []string { return CommandLine.args } + +// Var defines a flag with the specified name and usage string. The type and +// value of the flag are represented by the first argument, of type Value, which +// typically holds a user-defined implementation of Value. For instance, the +// caller could create a flag that turns a comma-separated string into a slice +// of strings by giving the slice the methods of Value; in particular, Set would +// decompose the comma-separated string into the slice. +func (f *FlagSet) Var(value Value, name string, usage string) { + // Remember the default value as a string; it won't change. + flag := &Flag{name, usage, value, value.String()} + _, alreadythere := f.formal[name] + if alreadythere { + var msg string + if f.name == "" { + msg = fmt.Sprintf("flag redefined: %s", name) + } else { + msg = fmt.Sprintf("%s flag redefined: %s", f.name, name) + } + fmt.Fprintln(f.Output(), msg) + panic(msg) // Happens only if flags are declared with identical names + } + if f.formal == nil { + f.formal = make(map[string]*Flag) + } + f.formal[name] = flag +} + +// Var defines a flag with the specified name and usage string. The type and +// value of the flag are represented by the first argument, of type Value, which +// typically holds a user-defined implementation of Value. For instance, the +// caller could create a flag that turns a comma-separated string into a slice +// of strings by giving the slice the methods of Value; in particular, Set would +// decompose the comma-separated string into the slice. +func Var(value Value, name string, usage string) { + CommandLine.Var(value, name, usage) +} + +// failf prints to standard error a formatted error and usage message and +// returns the error. +func (f *FlagSet) failf(format string, a ...interface{}) error { + err := fmt.Errorf(format, a...) + fmt.Fprintln(f.Output(), err) + f.usage() + return err +} + +// usage calls the Usage method for the flag set if one is specified, +// or the appropriate default usage function otherwise. +func (f *FlagSet) usage() { + if f.Usage == nil { + f.defaultUsage() + } else { + f.Usage() + } +} + +// parseOne parses one flag. It reports whether a flag was seen. +func (f *FlagSet) parseOne() (bool, error) { + if len(f.args) == 0 { + return false, nil + } + s := f.args[0] + if len(s) < 2 || s[0] != '-' { + return false, nil + } + numMinuses := 1 + if s[1] == '-' { + numMinuses++ + if len(s) == 2 { // "--" terminates the flags + f.args = f.args[1:] + return false, nil + } + } + name := s[numMinuses:] + if len(name) == 0 || name[0] == '-' || name[0] == '=' { + return false, f.failf("bad flag syntax: %s", s) + } + + // it's a flag. does it have an argument? + f.args = f.args[1:] + hasValue := false + value := "" + for i := 1; i < len(name); i++ { // equals cannot be first + if name[i] == '=' { + value = name[i+1:] + hasValue = true + name = name[0:i] + break + } + } + m := f.formal + flag, alreadythere := m[name] // BUG + if !alreadythere { + if name == "help" || name == "h" { // special case for nice help message. + f.usage() + return false, ErrHelp + } + return false, f.failf("flag provided but not defined: -%s", name) + } + + if IsBoolValue(flag.Value) { // special case: doesn't need an arg + if hasValue { + if err := flag.Value.Set(value); err != nil { + return false, f.failf(invalidValueTemplate, value, name, err) + } + } else { + if err := flag.Value.Set("true"); err != nil { + return false, f.failf("invalid boolean flag %s: %v", name, err) + } + } + } else { + // It must have a value, which might be the next argument. + if !hasValue && len(f.args) > 0 { + // value is the next arg + hasValue = true + value, f.args = f.args[0], f.args[1:] + } + if !hasValue { + return false, f.failf("flag needs an argument: -%s", name) + } + if err := flag.Value.Set(value); err != nil { + return false, f.failf(invalidValueTemplate, value, name, err) + } + } + if f.actual == nil { + f.actual = make(map[string]*Flag) + } + f.actual[name] = flag + return true, nil +} + +// Parse parses flag definitions from the argument list, which should not +// include the command name. Must be called after all flags in the FlagSet +// are defined and before flags are accessed by the program. +// The return value will be ErrHelp if -help or -h were set but not defined. +func (f *FlagSet) Parse(arguments []string) error { + f.parsed = true + f.args = arguments + for { + seen, err := f.parseOne() + if seen { + continue + } + if err == nil { + break + } + switch f.errorHandling { + case ContinueOnError: + return err + case ExitOnError: + if err == ErrHelp { + os.Exit(0) + } + os.Exit(2) + case PanicOnError: + panic(err) + } + } + return nil +} + +// Parsed reports whether f.Parse has been called. +func (f *FlagSet) Parsed() bool { + return f.parsed +} + +// Parse parses the command-line flags from os.Args[1:]. Must be called +// after all flags are defined and before flags are accessed by the program. +func Parse() { + // Ignore errors; CommandLine is set for ExitOnError. + CommandLine.Parse(os.Args[1:]) +} + +// Parsed reports whether the command-line flags have been parsed. +func Parsed() bool { + return CommandLine.Parsed() +} + +// CommandLine is the default set of command-line flags, parsed from os.Args. +// The top-level functions such as BoolVar, Arg, and so on are wrappers for the +// methods of CommandLine. +var CommandLine = NewFlagSet(os.Args[0], ExitOnError) + +func init() { + // Override generic FlagSet default Usage with call to global Usage. + // Note: This is not CommandLine.Usage = Usage, + // because we want any eventual call to use any updated value of Usage, + // not the value it has when this line is run. + CommandLine.Usage = commandLineUsage +} + +func commandLineUsage() { + Usage() +} + +// NewFlagSet returns a new, empty flag set with the specified name and +// error handling property. If the name is not empty, it will be printed +// in the default usage message and in error messages. +func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet { + f := &FlagSet{ + name: name, + errorHandling: errorHandling, + } + f.Usage = f.defaultUsage + return f +} + +// Init sets the name and error handling property for a flag set. +// By default, the zero FlagSet uses an empty name and the +// ContinueOnError error handling policy. +func (f *FlagSet) Init(name string, errorHandling ErrorHandling) { + f.name = name + f.errorHandling = errorHandling +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_bool.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_bool.go new file mode 100644 index 0000000000..692753e026 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_bool.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// BoolVar defines a bool flag with specified name, default value, and usage string. +// The argument p points to a bool variable in which to store the value of the flag. +func (f *FlagSet) BoolVar(ptr *bool, name string, value bool, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Bool defines a bool flag with specified name, default value, and usage string. +// The return value is the address of a bool variable that stores the value of the flag. +func (f *FlagSet) Bool(name string, value bool, usage string) *bool { + return f.Generic(name, value, usage).(*bool) +} + +// BoolVar defines a bool flag with specified name, default value, and usage string. +// The argument p points to a bool variable in which to store the value of the flag. +func BoolVar(ptr *bool, name string, value bool, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Bool defines a bool flag with specified name, default value, and usage string. +// The return value is the address of a bool variable that stores the value of the flag. +func Bool(name string, value bool, usage string) *bool { + return CommandLine.Generic(name, value, usage).(*bool) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_boolSlice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_boolSlice.go new file mode 100644 index 0000000000..7a7ea43a36 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_boolSlice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// BoolSliceVar defines a []bool flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func (f *FlagSet) BoolSliceVar(ptr *[]bool, name string, value []bool, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool { + return f.Generic(name, value, usage).(*[]bool) +} + +// BoolSliceVar defines a []bool flag with specified name, default value, and usage string. +// The argument p points to a []bool variable in which to store the value of the flag. +func BoolSliceVar(ptr *[]bool, name string, value []bool, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// BoolSlice defines a []bool flag with specified name, default value, and usage string. +// The return value is the address of a []bool variable that stores the value of the flag. +func BoolSlice(name string, value []bool, usage string) *[]bool { + return CommandLine.Generic(name, value, usage).(*[]bool) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_duration.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_duration.go new file mode 100644 index 0000000000..6b7a00a7d8 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_duration.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// DurationVar defines a time.Duration flag with specified name, default value, and usage string. +// The argument p points to a time.Duration variable in which to store the value of the flag. +func (f *FlagSet) DurationVar(ptr *time.Duration, name string, value time.Duration, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Duration defines a time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a time.Duration variable that stores the value of the flag. +func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration { + return f.Generic(name, value, usage).(*time.Duration) +} + +// DurationVar defines a time.Duration flag with specified name, default value, and usage string. +// The argument p points to a time.Duration variable in which to store the value of the flag. +func DurationVar(ptr *time.Duration, name string, value time.Duration, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Duration defines a time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a time.Duration variable that stores the value of the flag. +func Duration(name string, value time.Duration, usage string) *time.Duration { + return CommandLine.Generic(name, value, usage).(*time.Duration) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_durationSlice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_durationSlice.go new file mode 100644 index 0000000000..00ed6103ae --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_durationSlice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// DurationSliceVar defines a []time.Duration flag with specified name, default value, and usage string. +// The argument p points to a []time.Duration variable in which to store the value of the flag. +func (f *FlagSet) DurationSliceVar(ptr *[]time.Duration, name string, value []time.Duration, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a []time.Duration variable that stores the value of the flag. +func (f *FlagSet) DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration { + return f.Generic(name, value, usage).(*[]time.Duration) +} + +// DurationSliceVar defines a []time.Duration flag with specified name, default value, and usage string. +// The argument p points to a []time.Duration variable in which to store the value of the flag. +func DurationSliceVar(ptr *[]time.Duration, name string, value []time.Duration, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// DurationSlice defines a []time.Duration flag with specified name, default value, and usage string. +// The return value is the address of a []time.Duration variable that stores the value of the flag. +func DurationSlice(name string, value []time.Duration, usage string) *[]time.Duration { + return CommandLine.Generic(name, value, usage).(*[]time.Duration) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_float64.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_float64.go new file mode 100644 index 0000000000..bd267a647b --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_float64.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// Float64Var defines a float64 flag with specified name, default value, and usage string. +// The argument p points to a float64 variable in which to store the value of the flag. +func (f *FlagSet) Float64Var(ptr *float64, name string, value float64, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Float64 defines a float64 flag with specified name, default value, and usage string. +// The return value is the address of a float64 variable that stores the value of the flag. +func (f *FlagSet) Float64(name string, value float64, usage string) *float64 { + return f.Generic(name, value, usage).(*float64) +} + +// Float64Var defines a float64 flag with specified name, default value, and usage string. +// The argument p points to a float64 variable in which to store the value of the flag. +func Float64Var(ptr *float64, name string, value float64, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Float64 defines a float64 flag with specified name, default value, and usage string. +// The return value is the address of a float64 variable that stores the value of the flag. +func Float64(name string, value float64, usage string) *float64 { + return CommandLine.Generic(name, value, usage).(*float64) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_float64Slice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_float64Slice.go new file mode 100644 index 0000000000..81fa1ceb7e --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_float64Slice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// Float64SliceVar defines a []float64 flag with specified name, default value, and usage string. +// The argument p points to a []float64 variable in which to store the value of the flag. +func (f *FlagSet) Float64SliceVar(ptr *[]float64, name string, value []float64, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Float64Slice defines a []float64 flag with specified name, default value, and usage string. +// The return value is the address of a []float64 variable that stores the value of the flag. +func (f *FlagSet) Float64Slice(name string, value []float64, usage string) *[]float64 { + return f.Generic(name, value, usage).(*[]float64) +} + +// Float64SliceVar defines a []float64 flag with specified name, default value, and usage string. +// The argument p points to a []float64 variable in which to store the value of the flag. +func Float64SliceVar(ptr *[]float64, name string, value []float64, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Float64Slice defines a []float64 flag with specified name, default value, and usage string. +// The return value is the address of a []float64 variable that stores the value of the flag. +func Float64Slice(name string, value []float64, usage string) *[]float64 { + return CommandLine.Generic(name, value, usage).(*[]float64) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_int.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_int.go new file mode 100644 index 0000000000..f5a5d4f75a --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_int.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// IntVar defines a int flag with specified name, default value, and usage string. +// The argument p points to a int variable in which to store the value of the flag. +func (f *FlagSet) IntVar(ptr *int, name string, value int, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Int defines a int flag with specified name, default value, and usage string. +// The return value is the address of a int variable that stores the value of the flag. +func (f *FlagSet) Int(name string, value int, usage string) *int { + return f.Generic(name, value, usage).(*int) +} + +// IntVar defines a int flag with specified name, default value, and usage string. +// The argument p points to a int variable in which to store the value of the flag. +func IntVar(ptr *int, name string, value int, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Int defines a int flag with specified name, default value, and usage string. +// The return value is the address of a int variable that stores the value of the flag. +func Int(name string, value int, usage string) *int { + return CommandLine.Generic(name, value, usage).(*int) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_int64.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_int64.go new file mode 100644 index 0000000000..235ae50312 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_int64.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// Int64Var defines a int64 flag with specified name, default value, and usage string. +// The argument p points to a int64 variable in which to store the value of the flag. +func (f *FlagSet) Int64Var(ptr *int64, name string, value int64, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Int64 defines a int64 flag with specified name, default value, and usage string. +// The return value is the address of a int64 variable that stores the value of the flag. +func (f *FlagSet) Int64(name string, value int64, usage string) *int64 { + return f.Generic(name, value, usage).(*int64) +} + +// Int64Var defines a int64 flag with specified name, default value, and usage string. +// The argument p points to a int64 variable in which to store the value of the flag. +func Int64Var(ptr *int64, name string, value int64, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Int64 defines a int64 flag with specified name, default value, and usage string. +// The return value is the address of a int64 variable that stores the value of the flag. +func Int64(name string, value int64, usage string) *int64 { + return CommandLine.Generic(name, value, usage).(*int64) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_int64Slice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_int64Slice.go new file mode 100644 index 0000000000..be7d543f70 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_int64Slice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// Int64SliceVar defines a []int64 flag with specified name, default value, and usage string. +// The argument p points to a []int64 variable in which to store the value of the flag. +func (f *FlagSet) Int64SliceVar(ptr *[]int64, name string, value []int64, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Int64Slice defines a []int64 flag with specified name, default value, and usage string. +// The return value is the address of a []int64 variable that stores the value of the flag. +func (f *FlagSet) Int64Slice(name string, value []int64, usage string) *[]int64 { + return f.Generic(name, value, usage).(*[]int64) +} + +// Int64SliceVar defines a []int64 flag with specified name, default value, and usage string. +// The argument p points to a []int64 variable in which to store the value of the flag. +func Int64SliceVar(ptr *[]int64, name string, value []int64, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Int64Slice defines a []int64 flag with specified name, default value, and usage string. +// The return value is the address of a []int64 variable that stores the value of the flag. +func Int64Slice(name string, value []int64, usage string) *[]int64 { + return CommandLine.Generic(name, value, usage).(*[]int64) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_intSlice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_intSlice.go new file mode 100644 index 0000000000..f34ba31f23 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_intSlice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// IntSliceVar defines a []int flag with specified name, default value, and usage string. +// The argument p points to a []int variable in which to store the value of the flag. +func (f *FlagSet) IntSliceVar(ptr *[]int, name string, value []int, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// IntSlice defines a []int flag with specified name, default value, and usage string. +// The return value is the address of a []int variable that stores the value of the flag. +func (f *FlagSet) IntSlice(name string, value []int, usage string) *[]int { + return f.Generic(name, value, usage).(*[]int) +} + +// IntSliceVar defines a []int flag with specified name, default value, and usage string. +// The argument p points to a []int variable in which to store the value of the flag. +func IntSliceVar(ptr *[]int, name string, value []int, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// IntSlice defines a []int flag with specified name, default value, and usage string. +// The return value is the address of a []int variable that stores the value of the flag. +func IntSlice(name string, value []int, usage string) *[]int { + return CommandLine.Generic(name, value, usage).(*[]int) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_string.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_string.go new file mode 100644 index 0000000000..1abdeca846 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_string.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// StringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a string variable in which to store the value of the flag. +func (f *FlagSet) StringVar(ptr *string, name string, value string, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// String defines a string flag with specified name, default value, and usage string. +// The return value is the address of a string variable that stores the value of the flag. +func (f *FlagSet) String(name string, value string, usage string) *string { + return f.Generic(name, value, usage).(*string) +} + +// StringVar defines a string flag with specified name, default value, and usage string. +// The argument p points to a string variable in which to store the value of the flag. +func StringVar(ptr *string, name string, value string, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// String defines a string flag with specified name, default value, and usage string. +// The return value is the address of a string variable that stores the value of the flag. +func String(name string, value string, usage string) *string { + return CommandLine.Generic(name, value, usage).(*string) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_stringSlice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_stringSlice.go new file mode 100644 index 0000000000..0e336230ea --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_stringSlice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// StringSliceVar defines a []string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +func (f *FlagSet) StringSliceVar(ptr *[]string, name string, value []string, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// StringSlice defines a []string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string { + return f.Generic(name, value, usage).(*[]string) +} + +// StringSliceVar defines a []string flag with specified name, default value, and usage string. +// The argument p points to a []string variable in which to store the value of the flag. +func StringSliceVar(ptr *[]string, name string, value []string, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// StringSlice defines a []string flag with specified name, default value, and usage string. +// The return value is the address of a []string variable that stores the value of the flag. +func StringSlice(name string, value []string, usage string) *[]string { + return CommandLine.Generic(name, value, usage).(*[]string) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_time.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_time.go new file mode 100644 index 0000000000..5a4fd1acb2 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_time.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// TimeVar defines a time.Time flag with specified name, default value, and usage string. +// The argument p points to a time.Time variable in which to store the value of the flag. +func (f *FlagSet) TimeVar(ptr *time.Time, name string, value time.Time, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Time defines a time.Time flag with specified name, default value, and usage string. +// The return value is the address of a time.Time variable that stores the value of the flag. +func (f *FlagSet) Time(name string, value time.Time, usage string) *time.Time { + return f.Generic(name, value, usage).(*time.Time) +} + +// TimeVar defines a time.Time flag with specified name, default value, and usage string. +// The argument p points to a time.Time variable in which to store the value of the flag. +func TimeVar(ptr *time.Time, name string, value time.Time, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Time defines a time.Time flag with specified name, default value, and usage string. +// The return value is the address of a time.Time variable that stores the value of the flag. +func Time(name string, value time.Time, usage string) *time.Time { + return CommandLine.Generic(name, value, usage).(*time.Time) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_timeSlice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_timeSlice.go new file mode 100644 index 0000000000..9ae104c7ca --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_timeSlice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// TimeSliceVar defines a []time.Time flag with specified name, default value, and usage string. +// The argument p points to a []time.Time variable in which to store the value of the flag. +func (f *FlagSet) TimeSliceVar(ptr *[]time.Time, name string, value []time.Time, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// TimeSlice defines a []time.Time flag with specified name, default value, and usage string. +// The return value is the address of a []time.Time variable that stores the value of the flag. +func (f *FlagSet) TimeSlice(name string, value []time.Time, usage string) *[]time.Time { + return f.Generic(name, value, usage).(*[]time.Time) +} + +// TimeSliceVar defines a []time.Time flag with specified name, default value, and usage string. +// The argument p points to a []time.Time variable in which to store the value of the flag. +func TimeSliceVar(ptr *[]time.Time, name string, value []time.Time, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// TimeSlice defines a []time.Time flag with specified name, default value, and usage string. +// The return value is the address of a []time.Time variable that stores the value of the flag. +func TimeSlice(name string, value []time.Time, usage string) *[]time.Time { + return CommandLine.Generic(name, value, usage).(*[]time.Time) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint.go new file mode 100644 index 0000000000..ec2563117d --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// UintVar defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func (f *FlagSet) UintVar(ptr *uint, name string, value uint, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Uint defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func (f *FlagSet) Uint(name string, value uint, usage string) *uint { + return f.Generic(name, value, usage).(*uint) +} + +// UintVar defines a uint flag with specified name, default value, and usage string. +// The argument p points to a uint variable in which to store the value of the flag. +func UintVar(ptr *uint, name string, value uint, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Uint defines a uint flag with specified name, default value, and usage string. +// The return value is the address of a uint variable that stores the value of the flag. +func Uint(name string, value uint, usage string) *uint { + return CommandLine.Generic(name, value, usage).(*uint) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint64.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint64.go new file mode 100644 index 0000000000..7aefd26981 --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint64.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// Uint64Var defines a uint64 flag with specified name, default value, and usage string. +// The argument p points to a uint64 variable in which to store the value of the flag. +func (f *FlagSet) Uint64Var(ptr *uint64, name string, value uint64, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Uint64 defines a uint64 flag with specified name, default value, and usage string. +// The return value is the address of a uint64 variable that stores the value of the flag. +func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 { + return f.Generic(name, value, usage).(*uint64) +} + +// Uint64Var defines a uint64 flag with specified name, default value, and usage string. +// The argument p points to a uint64 variable in which to store the value of the flag. +func Uint64Var(ptr *uint64, name string, value uint64, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Uint64 defines a uint64 flag with specified name, default value, and usage string. +// The return value is the address of a uint64 variable that stores the value of the flag. +func Uint64(name string, value uint64, usage string) *uint64 { + return CommandLine.Generic(name, value, usage).(*uint64) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint64Slice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint64Slice.go new file mode 100644 index 0000000000..f2cd099adc --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uint64Slice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// Uint64SliceVar defines a []uint64 flag with specified name, default value, and usage string. +// The argument p points to a []uint64 variable in which to store the value of the flag. +func (f *FlagSet) Uint64SliceVar(ptr *[]uint64, name string, value []uint64, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// Uint64Slice defines a []uint64 flag with specified name, default value, and usage string. +// The return value is the address of a []uint64 variable that stores the value of the flag. +func (f *FlagSet) Uint64Slice(name string, value []uint64, usage string) *[]uint64 { + return f.Generic(name, value, usage).(*[]uint64) +} + +// Uint64SliceVar defines a []uint64 flag with specified name, default value, and usage string. +// The argument p points to a []uint64 variable in which to store the value of the flag. +func Uint64SliceVar(ptr *[]uint64, name string, value []uint64, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Uint64Slice defines a []uint64 flag with specified name, default value, and usage string. +// The return value is the address of a []uint64 variable that stores the value of the flag. +func Uint64Slice(name string, value []uint64, usage string) *[]uint64 { + return CommandLine.Generic(name, value, usage).(*[]uint64) +} diff --git a/vendor/github.com/rancher/spur/flag/flag.zz_generated_uintSlice.go b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uintSlice.go new file mode 100644 index 0000000000..5fd690766a --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag.zz_generated_uintSlice.go @@ -0,0 +1,35 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "time" +) + +var _ = time.Time{} + +// UintSliceVar defines a []uint flag with specified name, default value, and usage string. +// The argument p points to a []uint variable in which to store the value of the flag. +func (f *FlagSet) UintSliceVar(ptr *[]uint, name string, value []uint, usage string) { + f.GenericVar(ptr, name, value, usage) +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint { + return f.Generic(name, value, usage).(*[]uint) +} + +// UintSliceVar defines a []uint flag with specified name, default value, and usage string. +// The argument p points to a []uint variable in which to store the value of the flag. +func UintSliceVar(ptr *[]uint, name string, value []uint, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// UintSlice defines a []uint flag with specified name, default value, and usage string. +// The return value is the address of a []uint variable that stores the value of the flag. +func UintSlice(name string, value []uint, usage string) *[]uint { + return CommandLine.Generic(name, value, usage).(*[]uint) +} diff --git a/vendor/github.com/rancher/spur/flag/flag_generic.go b/vendor/github.com/rancher/spur/flag/flag_generic.go new file mode 100644 index 0000000000..0f70f83d9b --- /dev/null +++ b/vendor/github.com/rancher/spur/flag/flag_generic.go @@ -0,0 +1,83 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package flag + +import ( + "fmt" + "time" + + "github.com/rancher/spur/generic" +) + +var _ = time.Time{} + +// GenericValue takes a pointer to a generic type +type GenericValue struct { + ptr interface{} + set bool +} + +// NewGenericValue returns a flag.Value given a pointer +func NewGenericValue(ptr interface{}) Value { + generic.PtrPanic(ptr) + return &GenericValue{ptr: ptr} +} + +// Get returns the contents of the stored pointer +func (v *GenericValue) Get() interface{} { + return generic.ValueOfPtr(v.ptr) +} + +// Set will convert a given value to the type of our pointer +// and store the new value +func (v *GenericValue) Set(value interface{}) error { + if generic.IsSlice(v.Get()) && !v.set { + // If this is a slice and has not already been set then + // clear any existing value + generic.Set(v.ptr, generic.Zero(v.Get())) + v.set = true + } + val, err := generic.Convert(v.Get(), value) + if err != nil { + return err + } + generic.Set(v.ptr, val) + return nil +} + +// String returns a string representation of our generic value +func (v *GenericValue) String() string { + return generic.Stringify(v.Get()) +} + +// GenericVar defines a generic flag with specified name, default value, and usage string. +// The argument p points to a generic variable in which to store the value of the flag. +func (f *FlagSet) GenericVar(ptr interface{}, name string, value interface{}, usage string) { + generic.Set(ptr, value) + f.Var(NewGenericValue(ptr), name, usage) +} + +// Generic defines a generic flag with specified name, default value, and usage string. +// The return value is the address of a generic variable that stores the value of the flag. +func (f *FlagSet) Generic(name string, value interface{}, usage string) interface{} { + if value == nil { + panic(fmt.Errorf("creating generic from nil interface %s", name)) + } + ptr := generic.New(value) + f.GenericVar(ptr, name, value, usage) + return ptr +} + +// GenericVar defines a generic flag with specified name, default value, and usage string. +// The argument p points to a generic variable in which to store the value of the flag. +func GenericVar(ptr interface{}, name string, value interface{}, usage string) { + CommandLine.GenericVar(ptr, name, value, usage) +} + +// Generic defines a generic flag with specified name, default value, and usage string. +// The return value is the address of a generic variable that stores the value of the flag. +func Generic(name string, value interface{}, usage string) interface{} { + return CommandLine.Generic(name, value, usage) +} diff --git a/vendor/github.com/rancher/spur/generic/error.go b/vendor/github.com/rancher/spur/generic/error.go new file mode 100644 index 0000000000..7c80fe810c --- /dev/null +++ b/vendor/github.com/rancher/spur/generic/error.go @@ -0,0 +1,32 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package generic + +import ( + "errors" + "strconv" +) + +// errParse is returned by Set if a flag's value fails to parse, such as with an invalid integer for Int. +// It then gets wrapped through failf to provide more information. +var errParse = errors.New("parse error") + +// errRange is returned by Set if a flag's value is out of range. +// It then gets wrapped through failf to provide more information. +var errRange = errors.New("value out of range") + +func numError(err error) error { + ne, ok := err.(*strconv.NumError) + if !ok { + return err + } + if ne.Err == strconv.ErrSyntax { + return errParse + } + if ne.Err == strconv.ErrRange { + return errRange + } + return err +} diff --git a/vendor/github.com/rancher/spur/generic/generic.go b/vendor/github.com/rancher/spur/generic/generic.go new file mode 100644 index 0000000000..02a9dbb45b --- /dev/null +++ b/vendor/github.com/rancher/spur/generic/generic.go @@ -0,0 +1,241 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package generic + +import ( + "encoding/json" + "fmt" + "reflect" + "time" + + "gopkg.in/yaml.v2" +) + +// Marshal is the function used for marshaling slices +var Marshal = json.Marshal + +// Unmarshal is the function used for un-marshaling slices +var Unmarshal = yaml.Unmarshal + +// ToStringFunc is the function definition for converting types to strings +type ToStringFunc = func(interface{}) (string, bool) + +// FromStringFunc is the function definition for converting strings to types +type FromStringFunc = func(string) (interface{}, error) + +// ToStringMap provides a mapping of type to string conversion function +var ToStringMap = map[string]ToStringFunc{} + +// FromStringMap provides a mapping of string to type conversion function +var FromStringMap = map[string]FromStringFunc{} + +// TimeLayouts provides a list of layouts to attempt when converting time strings +var TimeLayouts = []string{ + time.RFC3339Nano, + time.RFC3339, + time.UnixDate, + time.RubyDate, + time.ANSIC, + time.RFC822, + time.RFC822Z, + time.RFC850, + time.RFC1123, + time.RFC1123Z, + time.StampNano, + time.StampMicro, + time.StampMilli, + time.Stamp, + time.Kitchen, +} + +// ToString is a convenience function for converting types to strings as defined in ToStringMap +func ToString(value interface{}) (string, bool) { + if value == nil { + return "", false + } + if toString := ToStringMap[TypeOf(value).String()]; toString != nil { + return toString(value) + } + return "", false +} + +// FromString is a convenience function for converting strings to types as defined in FromStringMap +func FromString(value string, ptr interface{}) error { + PtrPanic(ptr) + typ := reflect.TypeOf(ptr).Elem().String() + fromString := FromStringMap[typ] + if fromString == nil { + return errParse + } + val, err := fromString(value) + if err != nil { + return numError(err) + } + Set(ptr, val) + return nil +} + +// TypeOf returns the dereferenced value's type +func TypeOf(value interface{}) reflect.Type { + typ := reflect.TypeOf(value) + if typ != nil && typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + return typ +} + +// ElemTypeOf returns the dereferenced value's type or TypeOf is not an Elem +func ElemTypeOf(value interface{}) reflect.Type { + typ := TypeOf(value) + if typ.Kind() == reflect.Slice { + return typ.Elem() + } + return typ +} + +// New returns a new reflection with TypeOf value +func New(value interface{}) interface{} { + return reflect.New(TypeOf(value)).Interface() +} + +// NewElem returns a new reflection with ElemTypeOf value +func NewElem(value interface{}) interface{} { + return reflect.New(ElemTypeOf(value)).Interface() +} + +// Zero returns a zero reflection with TypeOf value +func Zero(value interface{}) interface{} { + return reflect.Zero(TypeOf(value)).Interface() +} + +// IsSlice return true if the TypeOf value is a slice +func IsSlice(value interface{}) bool { + if value == nil { + return false + } + return TypeOf(value).Kind() == reflect.Slice +} + +// PtrPanic halts execution if the passed ptr is not a pointer +func PtrPanic(ptr interface{}) { + if !IsPtr(ptr) { + panic(fmt.Errorf("expected pointer type, got %s", reflect.TypeOf(ptr).String())) + } +} + +// Set will assign the contents of ptr to value +func Set(ptr interface{}, value interface{}) { + PtrPanic(ptr) + if value == nil { + return + } + reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(value)) +} + +// Len returns the length of a slice, or -1 if not a slice +func Len(value interface{}) int { + if !IsSlice(value) { + return -1 + } + return reflect.ValueOf(value).Len() +} + +// Index will return the value of a slice at a given index +func Index(value interface{}, i int) interface{} { + if !IsSlice(value) { + return nil + } + return reflect.ValueOf(value).Index(i).Interface() +} + +// Append will append an element onto a generic slice +func Append(slice interface{}, elem interface{}) interface{} { + return reflect.Append(reflect.ValueOf(slice), reflect.ValueOf(elem)).Interface() +} + +// IsPtr returns true if the given value is of kind reflect.Ptr +func IsPtr(value interface{}) bool { + if value == nil { + return false + } + return reflect.TypeOf(value).Kind() == reflect.Ptr +} + +// ValueOfPtr returns the contents of a pointer, or the given value if not a pointer +func ValueOfPtr(value interface{}) interface{} { + if !IsPtr(value) { + return value + } + elem := reflect.ValueOf(value).Elem() + if !elem.IsValid() { + return nil + } + return elem.Interface() +} + +// Convert will return a new result of type src, where value is converted to the type +// of src or appended if src is a slice and value is an element +func Convert(src interface{}, value interface{}) (interface{}, error) { + // Convert an element + elem, err := ConvertElem(src, value) + if !IsSlice(src) { + // Return value and error if not a slice + return elem, err + } + // Try deserializing as string + if s, ok := value.(string); ok { + val := New(src) + if err := Unmarshal([]byte(s), val); err == nil { + return ValueOfPtr(val), nil + } + } + // If no error from converting element return appended value + if err == nil { + return Append(src, elem), nil + } + // Try evaluating value as a slice of interfaces + otherValue, ok := value.([]interface{}) + if !ok { + return nil, errParse + } + // Create a new slice and append each converted element + slice := Zero(src) + for _, other := range otherValue { + elem, err := ConvertElem(src, other) + if err != nil { + return nil, err + } + slice = Append(slice, elem) + } + return slice, nil +} + +// ConvertElem will return a new result, where value is converted to the type +// of src or returned as an element if src is a slice +func ConvertElem(src interface{}, value interface{}) (interface{}, error) { + // Get our value as a string + s, ok := value.(string) + if !ok { + if s, ok = ToString(value); !ok { + return nil, errParse + } + } + // Return a new value from the string + ptr := NewElem(src) + err := FromString(s, ptr) + return ValueOfPtr(ptr), err +} + +// Stringify returns the ToString version of the value, or the Marshaled version +// in the case of slices, otherwise panic if cannot be converted to string +func Stringify(value interface{}) string { + if s, ok := ToString(value); ok { + return s + } + if b, err := Marshal(value); err == nil { + return string(b) + } + panic(errParse) +} diff --git a/vendor/github.com/rancher/spur/generic/string_from.go b/vendor/github.com/rancher/spur/generic/string_from.go new file mode 100644 index 0000000000..ec698c06cc --- /dev/null +++ b/vendor/github.com/rancher/spur/generic/string_from.go @@ -0,0 +1,57 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package generic + +import ( + "strconv" + "time" +) + +func init() { + FromStringMap["string"] = func(s string) (interface{}, error) { + return s, nil + } + FromStringMap["bool"] = func(s string) (interface{}, error) { + if s == "" { + s = "false" + } + v, err := strconv.ParseBool(s) + return bool(v), err + } + FromStringMap["int"] = func(s string) (interface{}, error) { + v, err := strconv.ParseInt(s, 0, strconv.IntSize) + return int(v), err + } + FromStringMap["int64"] = func(s string) (interface{}, error) { + v, err := strconv.ParseInt(s, 0, 64) + return int64(v), err + } + FromStringMap["uint"] = func(s string) (interface{}, error) { + v, err := strconv.ParseUint(s, 0, strconv.IntSize) + return uint(v), err + } + FromStringMap["uint64"] = func(s string) (interface{}, error) { + v, err := strconv.ParseUint(s, 0, 64) + return uint64(v), err + } + FromStringMap["float64"] = func(s string) (interface{}, error) { + v, err := strconv.ParseFloat(s, 64) + return float64(v), err + } + FromStringMap["time.Duration"] = func(s string) (interface{}, error) { + if v, err := time.ParseDuration(s); err == nil { + return time.Duration(v), nil + } + return nil, errParse + } + FromStringMap["time.Time"] = func(s string) (interface{}, error) { + for _, layout := range TimeLayouts { + if v, err := time.Parse(layout, s); err == nil { + return time.Time(v), nil + } + } + return nil, errParse + } +} diff --git a/vendor/github.com/rancher/spur/generic/string_to.go b/vendor/github.com/rancher/spur/generic/string_to.go new file mode 100644 index 0000000000..6d2ea98ad9 --- /dev/null +++ b/vendor/github.com/rancher/spur/generic/string_to.go @@ -0,0 +1,43 @@ +// Copyright 2020 Rancher Labs, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package generic + +import ( + "strconv" + "time" +) + +func init() { + ToStringMap["string"] = func(value interface{}) (string, bool) { + return value.(string), true + } + ToStringMap["bool"] = func(value interface{}) (string, bool) { + return strconv.FormatBool(value.(bool)), true + } + ToStringMap["int"] = func(value interface{}) (string, bool) { + return strconv.Itoa(value.(int)), true + } + ToStringMap["int64"] = func(value interface{}) (string, bool) { + return strconv.FormatInt(value.(int64), 10), true + } + ToStringMap["uint"] = func(value interface{}) (string, bool) { + return strconv.FormatUint(uint64(value.(uint)), 10), true + } + ToStringMap["uint64"] = func(value interface{}) (string, bool) { + return strconv.FormatUint(value.(uint64), 10), true + } + ToStringMap["float64"] = func(value interface{}) (string, bool) { + return strconv.FormatFloat(value.(float64), 'g', -1, 64), true + } + ToStringMap["time.Duration"] = func(value interface{}) (string, bool) { + return value.(time.Duration).String(), true + } + ToStringMap["time.Time"] = func(value interface{}) (string, bool) { + if len(TimeLayouts) > 0 { + return value.(time.Time).Format(TimeLayouts[0]), true + } + return "", false + } +} diff --git a/vendor/gopkg.in/yaml.v2/apic.go b/vendor/gopkg.in/yaml.v2/apic.go index 1f7e87e672..d2c2308f1f 100644 --- a/vendor/gopkg.in/yaml.v2/apic.go +++ b/vendor/gopkg.in/yaml.v2/apic.go @@ -86,6 +86,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) { raw_buffer: make([]byte, 0, output_raw_buffer_size), states: make([]yaml_emitter_state_t, 0, initial_stack_size), events: make([]yaml_event_t, 0, initial_queue_size), + best_width: -1, } } diff --git a/vendor/modules.txt b/vendor/modules.txt index cd4d8b3c23..3aebca4a05 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -361,7 +361,7 @@ github.com/coreos/go-systemd/dbus github.com/coreos/go-systemd/journal # github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea github.com/coreos/pkg/capnslog -# github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d +# github.com/cpuguy83/go-md2man/v2 v2.0.0 github.com/cpuguy83/go-md2man/v2/md2man # github.com/cyphar/filepath-securejoin v0.2.2 github.com/cyphar/filepath-securejoin @@ -756,6 +756,11 @@ github.com/rancher/kine/pkg/server github.com/rancher/kine/pkg/tls # github.com/rancher/remotedialer v0.2.0 github.com/rancher/remotedialer +# github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a +github.com/rancher/spur/cli +github.com/rancher/spur/cli/altsrc +github.com/rancher/spur/flag +github.com/rancher/spur/generic # github.com/rancher/wrangler v0.6.1 github.com/rancher/wrangler/pkg/apply github.com/rancher/wrangler/pkg/apply/injectors @@ -1205,7 +1210,7 @@ gopkg.in/square/go-jose.v2/json gopkg.in/square/go-jose.v2/jwt # gopkg.in/warnings.v0 v0.1.1 gopkg.in/warnings.v0 -# gopkg.in/yaml.v2 v2.2.8 +# gopkg.in/yaml.v2 v2.3.0 gopkg.in/yaml.v2 # k8s.io/api v0.18.0 => github.com/rancher/kubernetes/staging/src/k8s.io/api v1.18.4-k3s1 k8s.io/api/admission/v1