Commit ae5c5850 authored by Darren Shepherd's avatar Darren Shepherd

Revert "Add config file support"

This reverts commit e1dc3451. Signed-off-by: 's avatarDarren Shepherd <darren@rancher.com>
parent 447097a5
...@@ -5,13 +5,13 @@ import ( ...@@ -5,13 +5,13 @@ import (
"github.com/rancher/k3s/pkg/cli/agent" "github.com/rancher/k3s/pkg/cli/agent"
"github.com/rancher/k3s/pkg/cli/cmds" "github.com/rancher/k3s/pkg/cli/cmds"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
) )
func main() { func main() {
app := cmds.NewApp() app := cmds.NewApp()
app.Commands = []*cli.Command{ app.Commands = []cli.Command{
cmds.NewAgentCommand(agent.Run), cmds.NewAgentCommand(agent.Run),
} }
......
...@@ -14,8 +14,8 @@ import ( ...@@ -14,8 +14,8 @@ import (
"github.com/rancher/k3s/pkg/datadir" "github.com/rancher/k3s/pkg/datadir"
"github.com/rancher/k3s/pkg/untar" "github.com/rancher/k3s/pkg/untar"
"github.com/rancher/k3s/pkg/version" "github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
) )
func main() { func main() {
...@@ -24,7 +24,7 @@ func main() { ...@@ -24,7 +24,7 @@ func main() {
} }
app := cmds.NewApp() app := cmds.NewApp()
app.Commands = []*cli.Command{ app.Commands = []cli.Command{
cmds.NewServerCommand(wrap(version.Program+"-server", os.Args)), cmds.NewServerCommand(wrap(version.Program+"-server", os.Args)),
cmds.NewAgentCommand(wrap(version.Program+"-agent", os.Args)), cmds.NewAgentCommand(wrap(version.Program+"-agent", os.Args)),
cmds.NewKubectlCommand(externalCLIAction("kubectl")), cmds.NewKubectlCommand(externalCLIAction("kubectl")),
...@@ -56,7 +56,7 @@ func runCLIs() bool { ...@@ -56,7 +56,7 @@ func runCLIs() bool {
func externalCLIAction(cmd string) func(cli *cli.Context) error { func externalCLIAction(cmd string) func(cli *cli.Context) error {
return func(cli *cli.Context) error { return func(cli *cli.Context) error {
return externalCLI(cmd, cli.String("data-dir"), cli.Args().Slice()) return externalCLI(cmd, cli.String("data-dir"), cli.Args())
} }
} }
...@@ -100,6 +100,7 @@ func stageAndRun(dataDir string, cmd string, args []string) error { ...@@ -100,6 +100,7 @@ func stageAndRun(dataDir string, cmd string, args []string) error {
if err != nil { if err != nil {
return err return err
} }
logrus.Debugf("Running %s %v", cmd, args) logrus.Debugf("Running %s %v", cmd, args)
return syscall.Exec(cmd, args, os.Environ()) return syscall.Exec(cmd, args, os.Environ())
} }
......
...@@ -15,8 +15,8 @@ import ( ...@@ -15,8 +15,8 @@ import (
"github.com/rancher/k3s/pkg/containerd" "github.com/rancher/k3s/pkg/containerd"
ctr2 "github.com/rancher/k3s/pkg/ctr" ctr2 "github.com/rancher/k3s/pkg/ctr"
kubectl2 "github.com/rancher/k3s/pkg/kubectl" kubectl2 "github.com/rancher/k3s/pkg/kubectl"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
) )
func init() { func init() {
...@@ -35,7 +35,7 @@ func main() { ...@@ -35,7 +35,7 @@ func main() {
os.Args[0] = cmd os.Args[0] = cmd
app := cmds.NewApp() app := cmds.NewApp()
app.Commands = []*cli.Command{ app.Commands = []cli.Command{
cmds.NewServerCommand(server.Run), cmds.NewServerCommand(server.Run),
cmds.NewAgentCommand(agent.Run), cmds.NewAgentCommand(agent.Run),
cmds.NewKubectlCommand(kubectl.Run), cmds.NewKubectlCommand(kubectl.Run),
......
...@@ -86,7 +86,6 @@ require ( ...@@ -86,7 +86,6 @@ require (
github.com/rancher/helm-controller v0.7.2 github.com/rancher/helm-controller v0.7.2
github.com/rancher/kine v0.4.0 github.com/rancher/kine v0.4.0
github.com/rancher/remotedialer v0.2.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 v0.6.1
github.com/rancher/wrangler-api v0.6.0 github.com/rancher/wrangler-api v0.6.0
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
......
...@@ -186,6 +186,7 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+ ...@@ -186,6 +186,7 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
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-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 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
...@@ -382,6 +383,7 @@ github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= ...@@ -382,6 +383,7 @@ github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-containerregistry v0.0.0-20190617215043-876b8855d23c/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk= github.com/google/go-containerregistry v0.0.0-20190617215043-876b8855d23c/go.mod h1:yZAFP63pRshzrEYLXLGPmUt0Ay+2zdjmMN1loCnRLUk=
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 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.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 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
...@@ -557,6 +559,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN ...@@ -557,6 +559,7 @@ 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 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/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/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976 h1:aZQToFSLH8ejFeSkTc3r3L4dPImcj7Ib/KgmkQqbGGg= github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976 h1:aZQToFSLH8ejFeSkTc3r3L4dPImcj7Ib/KgmkQqbGGg=
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0=
...@@ -581,6 +584,7 @@ github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB ...@@ -581,6 +584,7 @@ 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 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.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.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.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw= github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
...@@ -618,6 +622,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR ...@@ -618,6 +622,7 @@ github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
...@@ -719,9 +724,8 @@ github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na ...@@ -719,9 +724,8 @@ github.com/rancher/moq v0.0.0-20190404221404-ee5226d43009/go.mod h1:wpITyDPTi/Na
github.com/rancher/nocode v0.0.0-20200630202308-cb097102c09f/go.mod h1:iAAt6Amgbysi6srDJs9SxGSbG2j/JSRb/xCrnEtA69g= 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 h1:xD7t3K6JYwTdAsxmGtTHQMkEkFgKouQ1foLxVW424Dc=
github.com/rancher/remotedialer v0.2.0/go.mod h1:tkU8ZvrR5lRgaKWaX71nAy6daeqvPFx/lJEnbW7tXSI= 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.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.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.0/go.mod h1:L4HtjPeX8iqLgsxfJgz+JjKMcX2q3qbRXSeTlC/CSd4=
github.com/rancher/wrangler v0.6.1 h1:7tyLk/FV2zCQkYg5SEtT4lSlsHNwa5yMOa797/VJhiQ= github.com/rancher/wrangler v0.6.1 h1:7tyLk/FV2zCQkYg5SEtT4lSlsHNwa5yMOa797/VJhiQ=
...@@ -1044,6 +1048,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T ...@@ -1044,6 +1048,7 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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-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.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 h1:4r+yNT0+8SWcOkXP+63H2zQbN+USnC73cjGUxnDF94Q=
gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
...@@ -1068,7 +1073,6 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt ...@@ -1068,7 +1073,6 @@ google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63 h1:YzfoEYWbODU5Fbt
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
...@@ -1102,6 +1106,7 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= ...@@ -1102,6 +1106,7 @@ 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.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.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/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.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
...@@ -1119,6 +1124,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh ...@@ -1119,6 +1124,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 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-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-20191120174120-e74f70b9b27e/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
...@@ -1157,6 +1163,7 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65 h1:xJNnO2qz ...@@ -1157,6 +1163,7 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65 h1:xJNnO2qz
sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff v0.0.0-20190426204423-ea680f03cc65/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
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.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 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
......
...@@ -14,13 +14,13 @@ import ( ...@@ -14,13 +14,13 @@ import (
"github.com/rancher/k3s/pkg/cli/crictl" "github.com/rancher/k3s/pkg/cli/crictl"
"github.com/rancher/k3s/pkg/cli/kubectl" "github.com/rancher/k3s/pkg/cli/kubectl"
"github.com/rancher/k3s/pkg/cli/server" "github.com/rancher/k3s/pkg/cli/server"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
) )
func main() { func main() {
app := cmds.NewApp() app := cmds.NewApp()
app.Commands = []*cli.Command{ app.Commands = []cli.Command{
cmds.NewServerCommand(server.Run), cmds.NewServerCommand(server.Run),
cmds.NewAgentCommand(agent.Run), cmds.NewAgentCommand(agent.Run),
cmds.NewKubectlCommand(kubectl.Run), cmds.NewKubectlCommand(kubectl.Run),
......
...@@ -13,9 +13,9 @@ import ( ...@@ -13,9 +13,9 @@ import (
"github.com/rancher/k3s/pkg/netutil" "github.com/rancher/k3s/pkg/netutil"
"github.com/rancher/k3s/pkg/token" "github.com/rancher/k3s/pkg/token"
"github.com/rancher/k3s/pkg/version" "github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/rancher/wrangler/pkg/signals" "github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
) )
func Run(ctx *cli.Context) error { func Run(ctx *cli.Context) error {
...@@ -23,6 +23,9 @@ func Run(ctx *cli.Context) error { ...@@ -23,6 +23,9 @@ func Run(ctx *cli.Context) error {
// database credentials or other secrets. // database credentials or other secrets.
gspt.SetProcTitle(os.Args[0] + " agent") gspt.SetProcTitle(os.Args[0] + " agent")
if err := cmds.InitLogging(); err != nil {
return err
}
if os.Getuid() != 0 && runtime.GOOS != "windows" { if os.Getuid() != 0 && runtime.GOOS != "windows" {
return fmt.Errorf("agent must be ran as root") return fmt.Errorf("agent must be ran as root")
} }
...@@ -59,7 +62,7 @@ func Run(ctx *cli.Context) error { ...@@ -59,7 +62,7 @@ func Run(ctx *cli.Context) error {
} }
cfg := cmds.AgentConfig cfg := cmds.AgentConfig
cfg.Debug = ctx.Bool("debug") cfg.Debug = ctx.GlobalBool("debug")
cfg.DataDir = dataDir cfg.DataDir = dataDir
contextCtx := signals.SetupSignalHandler(context.Background()) contextCtx := signals.SetupSignalHandler(context.Background())
......
...@@ -6,8 +6,7 @@ import ( ...@@ -6,8 +6,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rancher/k3s/pkg/version" "github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli" "github.com/urfave/cli"
"github.com/rancher/spur/cli/altsrc"
) )
type Agent struct { type Agent struct {
...@@ -33,13 +32,13 @@ type Agent struct { ...@@ -33,13 +32,13 @@ type Agent struct {
RootlessAlreadyUnshared bool RootlessAlreadyUnshared bool
WithNodeID bool WithNodeID bool
EnableSELinux bool EnableSELinux bool
ExtraKubeletArgs []string
ExtraKubeProxyArgs []string
Labels []string
Taints []string
PrivateRegistry string
ProtectKernelDefaults bool ProtectKernelDefaults bool
AgentShared AgentShared
ExtraKubeletArgs cli.StringSlice
ExtraKubeProxyArgs cli.StringSlice
Labels cli.StringSlice
Taints cli.StringSlice
PrivateRegistry string
} }
type AgentShared struct { type AgentShared struct {
...@@ -62,7 +61,7 @@ var ( ...@@ -62,7 +61,7 @@ var (
NodeNameFlag = cli.StringFlag{ NodeNameFlag = cli.StringFlag{
Name: "node-name", Name: "node-name",
Usage: "(agent/node) Node name", Usage: "(agent/node) Node name",
EnvVars: []string{version.ProgramUpper + "_NODE_NAME"}, EnvVar: version.ProgramUpper + "_NODE_NAME",
Destination: &AgentConfig.NodeName, Destination: &AgentConfig.NodeName,
} }
WithNodeIDFlag = cli.BoolFlag{ WithNodeIDFlag = cli.BoolFlag{
...@@ -116,34 +115,33 @@ var ( ...@@ -116,34 +115,33 @@ var (
ResolvConfFlag = cli.StringFlag{ ResolvConfFlag = cli.StringFlag{
Name: "resolv-conf", Name: "resolv-conf",
Usage: "(agent/networking) Kubelet resolv.conf file", Usage: "(agent/networking) Kubelet resolv.conf file",
EnvVars: []string{version.ProgramUpper + "_RESOLV_CONF"}, EnvVar: version.ProgramUpper + "_RESOLV_CONF",
Destination: &AgentConfig.ResolvConf, Destination: &AgentConfig.ResolvConf,
} }
ExtraKubeletArgs = cli.StringSliceFlag{ ExtraKubeletArgs = cli.StringSliceFlag{
Name: "kubelet-arg", Name: "kubelet-arg",
Usage: "(agent/flags) Customized flag for kubelet process", Usage: "(agent/flags) Customized flag for kubelet process",
Destination: &AgentConfig.ExtraKubeletArgs, Value: &AgentConfig.ExtraKubeletArgs,
} }
ExtraKubeProxyArgs = cli.StringSliceFlag{ ExtraKubeProxyArgs = cli.StringSliceFlag{
Name: "kube-proxy-arg", Name: "kube-proxy-arg",
Usage: "(agent/flags) Customized flag for kube-proxy process", Usage: "(agent/flags) Customized flag for kube-proxy process",
Destination: &AgentConfig.ExtraKubeProxyArgs, Value: &AgentConfig.ExtraKubeProxyArgs,
} }
NodeTaints = cli.StringSliceFlag{ NodeTaints = cli.StringSliceFlag{
Name: "node-taint", Name: "node-taint",
Usage: "(agent/node) Registering kubelet with set of taints", Usage: "(agent/node) Registering kubelet with set of taints",
Destination: &AgentConfig.Taints, Value: &AgentConfig.Taints,
} }
NodeLabels = cli.StringSliceFlag{ NodeLabels = cli.StringSliceFlag{
Name: "node-label", Name: "node-label",
Usage: "(agent/node) Registering and starting kubelet with set of labels", Usage: "(agent/node) Registering and starting kubelet with set of labels",
Destination: &AgentConfig.Labels, Value: &AgentConfig.Labels,
} }
DisableSELinuxFlag = cli.BoolFlag{ DisableSELinuxFlag = cli.BoolTFlag{
Name: "disable-selinux", Name: "disable-selinux",
Usage: "(deprecated) Use --selinux to explicitly enable SELinux", Usage: "(deprecated) Use --selinux to explicitly enable SELinux",
Hidden: true, Hidden: true,
Value: true, // disabled by default
} }
ProtectKernelDefaultsFlag = cli.BoolFlag{ ProtectKernelDefaultsFlag = cli.BoolFlag{
Name: "protect-kernel-defaults", Name: "protect-kernel-defaults",
...@@ -155,7 +153,7 @@ var ( ...@@ -155,7 +153,7 @@ var (
Usage: "(agent/node) Enable SELinux in containerd", Usage: "(agent/node) Enable SELinux in containerd",
Hidden: false, Hidden: false,
Destination: &AgentConfig.EnableSELinux, Destination: &AgentConfig.EnableSELinux,
EnvVars: []string{version.ProgramUpper + "_SELINUX"}, EnvVar: version.ProgramUpper + "_SELINUX",
} }
) )
...@@ -169,67 +167,60 @@ func CheckSELinuxFlags(ctx *cli.Context) error { ...@@ -169,67 +167,60 @@ func CheckSELinuxFlags(ctx *cli.Context) error {
} }
return nil return nil
} }
func NewAgentCommand(action func(ctx *cli.Context) error) *cli.Command { func NewAgentCommand(action func(ctx *cli.Context) error) cli.Command {
return &cli.Command{ return cli.Command{
Name: "agent", Name: "agent",
Usage: "Run node agent", Usage: "Run node agent",
UsageText: appName + " agent [OPTIONS]", UsageText: appName + " agent [OPTIONS]",
Before: func(ctx *cli.Context) error { Before: CheckSELinuxFlags,
if err := CheckSELinuxFlags(ctx); err != nil { Action: action,
return err
}
return DebugContext(cli.InitAllInputSource(altsrc.NewConfigFromFlag(ConfigFlag.Name)))(ctx)
},
Action: InitLogging(action),
Flags: []cli.Flag{ Flags: []cli.Flag{
&ConfigFlag, VLevel,
&DebugFlag, VModule,
&VLevel, LogFile,
&VModule, AlsoLogToStderr,
&LogFile, cli.StringFlag{
&AlsoLogToStderr,
&cli.StringFlag{
Name: "token,t", Name: "token,t",
Usage: "(cluster) Token to use for authentication", Usage: "(cluster) Token to use for authentication",
EnvVars: []string{version.ProgramUpper + "_TOKEN"}, EnvVar: version.ProgramUpper + "_TOKEN",
Destination: &AgentConfig.Token, Destination: &AgentConfig.Token,
}, },
&cli.StringFlag{ cli.StringFlag{
Name: "token-file", Name: "token-file",
Usage: "(cluster) Token file to use for authentication", Usage: "(cluster) Token file to use for authentication",
EnvVars: []string{version.ProgramUpper + "_TOKEN_FILE"}, EnvVar: version.ProgramUpper + "_TOKEN_FILE",
Destination: &AgentConfig.TokenFile, Destination: &AgentConfig.TokenFile,
}, },
&cli.StringFlag{ cli.StringFlag{
Name: "server,s", Name: "server,s",
Usage: "(cluster) Server to connect to", Usage: "(cluster) Server to connect to",
EnvVars: []string{version.ProgramUpper + "_URL"}, EnvVar: version.ProgramUpper + "_URL",
Destination: &AgentConfig.ServerURL, Destination: &AgentConfig.ServerURL,
}, },
&cli.StringFlag{ cli.StringFlag{
Name: "data-dir,d", Name: "data-dir,d",
Usage: "(agent/data) Folder to hold state", Usage: "(agent/data) Folder to hold state",
Destination: &AgentConfig.DataDir, Destination: &AgentConfig.DataDir,
Value: "/var/lib/rancher/" + version.Program + "", Value: "/var/lib/rancher/" + version.Program + "",
}, },
&NodeNameFlag, NodeNameFlag,
&WithNodeIDFlag, WithNodeIDFlag,
&NodeLabels, NodeLabels,
&NodeTaints, NodeTaints,
&DockerFlag, DockerFlag,
&CRIEndpointFlag, CRIEndpointFlag,
&PauseImageFlag, PauseImageFlag,
&SnapshotterFlag, SnapshotterFlag,
&PrivateRegistryFlag, PrivateRegistryFlag,
&NodeIPFlag, NodeIPFlag,
&NodeExternalIPFlag, NodeExternalIPFlag,
&ResolvConfFlag, ResolvConfFlag,
&FlannelIfaceFlag, FlannelIfaceFlag,
&FlannelConfFlag, FlannelConfFlag,
&ExtraKubeletArgs, ExtraKubeletArgs,
&ExtraKubeProxyArgs, ExtraKubeProxyArgs,
&ProtectKernelDefaultsFlag, ProtectKernelDefaultsFlag,
&cli.BoolFlag{ cli.BoolFlag{
Name: "rootless", Name: "rootless",
Usage: "(experimental) Run rootless", Usage: "(experimental) Run rootless",
Destination: &AgentConfig.Rootless, Destination: &AgentConfig.Rootless,
...@@ -239,12 +230,12 @@ func NewAgentCommand(action func(ctx *cli.Context) error) *cli.Command { ...@@ -239,12 +230,12 @@ func NewAgentCommand(action func(ctx *cli.Context) error) *cli.Command {
// Deprecated/hidden below // Deprecated/hidden below
&DisableSELinuxFlag, &DisableSELinuxFlag,
&FlannelFlag, FlannelFlag,
&cli.StringFlag{ cli.StringFlag{
Name: "cluster-secret", Name: "cluster-secret",
Usage: "(deprecated) use --token", Usage: "(deprecated) use --token",
Destination: &AgentConfig.ClusterSecret, Destination: &AgentConfig.ClusterSecret,
EnvVars: []string{version.ProgramUpper + "_CLUSTER_SECRET"}, EnvVar: version.ProgramUpper + "_CLUSTER_SECRET",
}, },
}, },
} }
......
package cmds package cmds
import ( import (
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
func NewCheckConfigCommand(action func(*cli.Context) error) *cli.Command { func NewCheckConfigCommand(action func(*cli.Context) error) cli.Command {
return &cli.Command{ return cli.Command{
Name: "check-config", Name: "check-config",
Usage: "Run config check", Usage: "Run config check",
SkipFlagParsing: true, SkipFlagParsing: true,
SkipArgReorder: true,
Action: action, Action: action,
} }
} }
package cmds
import (
"github.com/rancher/spur/cli"
)
var (
DefaultConfig = "/etc/rancher/k3s/config.yaml"
ConfigFlag = cli.StringFlag{
Name: "config",
Aliases: []string{"c"},
Usage: "(config) Load configuration from `FILE`",
EnvVars: []string{"K3S_CONFIG_FILE"},
Value: DefaultConfig,
}
)
package cmds package cmds
import ( import (
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
func NewCRICTL(action func(*cli.Context) error) *cli.Command { func NewCRICTL(action func(*cli.Context) error) cli.Command {
return &cli.Command{ return cli.Command{
Name: "crictl", Name: "crictl",
Usage: "Run crictl", Usage: "Run crictl",
SkipFlagParsing: true, SkipFlagParsing: true,
SkipArgReorder: true,
Action: action, Action: action,
} }
} }
package cmds package cmds
import ( import (
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
func NewCtrCommand(action func(*cli.Context) error) *cli.Command { func NewCtrCommand(action func(*cli.Context) error) cli.Command {
return &cli.Command{ return cli.Command{
Name: "ctr", Name: "ctr",
Usage: "Run ctr", Usage: "Run ctr",
SkipFlagParsing: true, SkipFlagParsing: true,
SkipArgReorder: true,
Action: action, Action: action,
} }
} }
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
}
}
package cmds package cmds
import ( import (
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
func NewKubectlCommand(action func(*cli.Context) error) *cli.Command { func NewKubectlCommand(action func(*cli.Context) error) cli.Command {
return &cli.Command{ return cli.Command{
Name: "kubectl", Name: "kubectl",
Usage: "Run kubectl", Usage: "Run kubectl",
SkipFlagParsing: true, SkipFlagParsing: true,
SkipArgReorder: true,
Action: action, Action: action,
} }
} }
...@@ -12,7 +12,7 @@ import ( ...@@ -12,7 +12,7 @@ import (
"github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/reexec"
"github.com/natefinch/lumberjack" "github.com/natefinch/lumberjack"
"github.com/rancher/k3s/pkg/version" "github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
type Log struct { type Log struct {
...@@ -49,31 +49,22 @@ var ( ...@@ -49,31 +49,22 @@ var (
logSetupOnce sync.Once logSetupOnce sync.Once
) )
func InitLogging(action func(*cli.Context) error) func(*cli.Context) error { func InitLogging() error {
return func(ctx *cli.Context) error { var rErr error
var ( logSetupOnce.Do(func() {
err error if LogConfig.LogFile != "" && os.Getenv("_K3S_LOG_REEXEC_") == "" {
reExec bool rErr = runWithLogging()
) return
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 action != nil {
return action(ctx) if err := checkUnixTimestamp(); err != nil {
rErr = err
return
} }
return nil
} setupLogging()
})
return rErr
} }
func checkUnixTimestamp() error { func checkUnixTimestamp() error {
......
...@@ -5,7 +5,12 @@ import ( ...@@ -5,7 +5,12 @@ import (
"os" "os"
"github.com/rancher/k3s/pkg/version" "github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var (
Debug bool
) )
func init() { func init() {
...@@ -23,8 +28,21 @@ func NewApp() *cli.App { ...@@ -23,8 +28,21 @@ func NewApp() *cli.App {
cli.VersionPrinter = func(c *cli.Context) { cli.VersionPrinter = func(c *cli.Context) {
fmt.Printf("%s version %s\n", app.Name, app.Version) fmt.Printf("%s version %s\n", app.Name, app.Version)
} }
app.Flags = []cli.Flag{&DebugFlag} app.Flags = []cli.Flag{
app.Before = DebugContext(nil) 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
}
return app return app
} }
...@@ -2,7 +2,7 @@ package crictl ...@@ -2,7 +2,7 @@ package crictl
import ( import (
"github.com/kubernetes-sigs/cri-tools/cmd/crictl" "github.com/kubernetes-sigs/cri-tools/cmd/crictl"
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
func Run(ctx *cli.Context) error { func Run(ctx *cli.Context) error {
......
...@@ -2,7 +2,7 @@ package ctr ...@@ -2,7 +2,7 @@ package ctr
import ( import (
"github.com/rancher/k3s/pkg/ctr" "github.com/rancher/k3s/pkg/ctr"
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
func Run(ctx *cli.Context) error { func Run(ctx *cli.Context) error {
......
...@@ -2,7 +2,7 @@ package kubectl ...@@ -2,7 +2,7 @@ package kubectl
import ( import (
"github.com/rancher/k3s/pkg/kubectl" "github.com/rancher/k3s/pkg/kubectl"
"github.com/rancher/spur/cli" "github.com/urfave/cli"
) )
func Run(ctx *cli.Context) error { func Run(ctx *cli.Context) error {
......
...@@ -19,9 +19,9 @@ import ( ...@@ -19,9 +19,9 @@ import (
"github.com/rancher/k3s/pkg/server" "github.com/rancher/k3s/pkg/server"
"github.com/rancher/k3s/pkg/token" "github.com/rancher/k3s/pkg/token"
"github.com/rancher/k3s/pkg/version" "github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/rancher/wrangler/pkg/signals" "github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/urfave/cli"
"k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/net"
kubeapiserverflag "k8s.io/component-base/cli/flag" kubeapiserverflag "k8s.io/component-base/cli/flag"
"k8s.io/kubernetes/pkg/master" "k8s.io/kubernetes/pkg/master"
...@@ -32,6 +32,9 @@ import ( ...@@ -32,6 +32,9 @@ import (
) )
func Run(app *cli.Context) error { func Run(app *cli.Context) error {
if err := cmds.InitLogging(); err != nil {
return err
}
return run(app, &cmds.ServerConfig) return run(app, &cmds.ServerConfig)
} }
...@@ -263,7 +266,7 @@ func run(app *cli.Context, cfg *cmds.Server) error { ...@@ -263,7 +266,7 @@ func run(app *cli.Context, cfg *cmds.Server) error {
} }
agentConfig := cmds.AgentConfig agentConfig := cmds.AgentConfig
agentConfig.Debug = app.Bool("debug") agentConfig.Debug = app.GlobalBool("bool")
agentConfig.DataDir = filepath.Dir(serverConfig.ControlConfig.DataDir) agentConfig.DataDir = filepath.Dir(serverConfig.ControlConfig.DataDir)
agentConfig.ServerURL = url agentConfig.ServerURL = url
agentConfig.Token = token agentConfig.Token = token
......
*.coverprofile
*.orig
node_modules/
vendor
.idea
internal/*/built-example
coverage.txt
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.
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__)
}
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
}
}
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
}
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)
}
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
}
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
}
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
}
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
}
// +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
}
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
}
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)
}
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
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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)
}
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
}
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
}
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)
}
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
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
}
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())
}
}
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
}
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
}
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 }}`
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.
// 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__)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
// 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)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment