Revert "Add config file support"

This reverts commit e1dc3451bc.

Signed-off-by: Darren Shepherd <darren@rancher.com>
This commit is contained in:
Darren Shepherd 2020-08-29 12:46:55 -07:00
parent 447097a597
commit ae5c585050
93 changed files with 255 additions and 6251 deletions

View File

@ -5,13 +5,13 @@ import (
"github.com/rancher/k3s/pkg/cli/agent"
"github.com/rancher/k3s/pkg/cli/cmds"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
func main() {
app := cmds.NewApp()
app.Commands = []*cli.Command{
app.Commands = []cli.Command{
cmds.NewAgentCommand(agent.Run),
}

View File

@ -14,8 +14,8 @@ import (
"github.com/rancher/k3s/pkg/datadir"
"github.com/rancher/k3s/pkg/untar"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
func main() {
@ -24,7 +24,7 @@ func main() {
}
app := cmds.NewApp()
app.Commands = []*cli.Command{
app.Commands = []cli.Command{
cmds.NewServerCommand(wrap(version.Program+"-server", os.Args)),
cmds.NewAgentCommand(wrap(version.Program+"-agent", os.Args)),
cmds.NewKubectlCommand(externalCLIAction("kubectl")),
@ -56,7 +56,7 @@ func runCLIs() bool {
func externalCLIAction(cmd string) func(cli *cli.Context) error {
return func(cli *cli.Context) error {
return externalCLI(cmd, cli.String("data-dir"), cli.Args().Slice())
return externalCLI(cmd, cli.String("data-dir"), cli.Args())
}
}
@ -100,6 +100,7 @@ func stageAndRun(dataDir string, cmd string, args []string) error {
if err != nil {
return err
}
logrus.Debugf("Running %s %v", cmd, args)
return syscall.Exec(cmd, args, os.Environ())
}

View File

@ -15,8 +15,8 @@ import (
"github.com/rancher/k3s/pkg/containerd"
ctr2 "github.com/rancher/k3s/pkg/ctr"
kubectl2 "github.com/rancher/k3s/pkg/kubectl"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
func init() {
@ -35,7 +35,7 @@ func main() {
os.Args[0] = cmd
app := cmds.NewApp()
app.Commands = []*cli.Command{
app.Commands = []cli.Command{
cmds.NewServerCommand(server.Run),
cmds.NewAgentCommand(agent.Run),
cmds.NewKubectlCommand(kubectl.Run),

1
go.mod
View File

@ -86,7 +86,6 @@ require (
github.com/rancher/helm-controller v0.7.2
github.com/rancher/kine v0.4.0
github.com/rancher/remotedialer v0.2.0
github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a
github.com/rancher/wrangler v0.6.1
github.com/rancher/wrangler-api v0.6.0
github.com/robfig/cron/v3 v3.0.1

13
go.sum
View File

@ -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-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
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 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
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=
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/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@ -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/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976 h1:aZQToFSLH8ejFeSkTc3r3L4dPImcj7Ib/KgmkQqbGGg=
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
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -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/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -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/remotedialer v0.2.0 h1:xD7t3K6JYwTdAsxmGtTHQMkEkFgKouQ1foLxVW424Dc=
github.com/rancher/remotedialer v0.2.0/go.mod h1:tkU8ZvrR5lRgaKWaX71nAy6daeqvPFx/lJEnbW7tXSI=
github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a h1:MIWeFYPZ/XXnskvcUqV8W89PFs+n/mr4YWMHeZuMpYs=
github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a/go.mod h1:Q6L6c+4FRxY5CF1xG3oEAfH3tSQDf0NAZes7q7wRyPE=
github.com/rancher/wrangler v0.1.4/go.mod h1:EYP7cqpg42YqElaCm+U9ieSrGQKAXxUH5xsr+XGpWyE=
github.com/rancher/wrangler v0.4.0 h1:iLvuJcZkd38E3RGG74dFMMNEju0PeTzfT1PQiv5okVU=
github.com/rancher/wrangler v0.4.0/go.mod h1:1cR91WLhZgkZ+U4fV9nVuXqKurWbgXcIReU4wnQvTN8=
github.com/rancher/wrangler v0.6.0/go.mod h1:L4HtjPeX8iqLgsxfJgz+JjKMcX2q3qbRXSeTlC/CSd4=
github.com/rancher/wrangler v0.6.1 h1:7tyLk/FV2zCQkYg5SEtT4lSlsHNwa5yMOa797/VJhiQ=
@ -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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/gonum v0.6.2 h1:4r+yNT0+8SWcOkXP+63H2zQbN+USnC73cjGUxnDF94Q=
gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
@ -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/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk=
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=
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=
@ -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.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.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -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=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e h1:HqlU9dKk5YVs7R84jmq6U3Wo/XslpkxHpBv2iWHLtLc=
k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/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
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/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.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@ -14,13 +14,13 @@ import (
"github.com/rancher/k3s/pkg/cli/crictl"
"github.com/rancher/k3s/pkg/cli/kubectl"
"github.com/rancher/k3s/pkg/cli/server"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
func main() {
app := cmds.NewApp()
app.Commands = []*cli.Command{
app.Commands = []cli.Command{
cmds.NewServerCommand(server.Run),
cmds.NewAgentCommand(agent.Run),
cmds.NewKubectlCommand(kubectl.Run),

View File

@ -13,9 +13,9 @@ import (
"github.com/rancher/k3s/pkg/netutil"
"github.com/rancher/k3s/pkg/token"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
func Run(ctx *cli.Context) error {
@ -23,6 +23,9 @@ func Run(ctx *cli.Context) error {
// database credentials or other secrets.
gspt.SetProcTitle(os.Args[0] + " agent")
if err := cmds.InitLogging(); err != nil {
return err
}
if os.Getuid() != 0 && runtime.GOOS != "windows" {
return fmt.Errorf("agent must be ran as root")
}
@ -59,7 +62,7 @@ func Run(ctx *cli.Context) error {
}
cfg := cmds.AgentConfig
cfg.Debug = ctx.Bool("debug")
cfg.Debug = ctx.GlobalBool("debug")
cfg.DataDir = dataDir
contextCtx := signals.SetupSignalHandler(context.Background())

View File

@ -6,8 +6,7 @@ import (
"github.com/pkg/errors"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/rancher/spur/cli/altsrc"
"github.com/urfave/cli"
)
type Agent struct {
@ -33,13 +32,13 @@ type Agent struct {
RootlessAlreadyUnshared bool
WithNodeID bool
EnableSELinux bool
ExtraKubeletArgs []string
ExtraKubeProxyArgs []string
Labels []string
Taints []string
PrivateRegistry string
ProtectKernelDefaults bool
AgentShared
ExtraKubeletArgs cli.StringSlice
ExtraKubeProxyArgs cli.StringSlice
Labels cli.StringSlice
Taints cli.StringSlice
PrivateRegistry string
}
type AgentShared struct {
@ -62,7 +61,7 @@ var (
NodeNameFlag = cli.StringFlag{
Name: "node-name",
Usage: "(agent/node) Node name",
EnvVars: []string{version.ProgramUpper + "_NODE_NAME"},
EnvVar: version.ProgramUpper + "_NODE_NAME",
Destination: &AgentConfig.NodeName,
}
WithNodeIDFlag = cli.BoolFlag{
@ -116,34 +115,33 @@ var (
ResolvConfFlag = cli.StringFlag{
Name: "resolv-conf",
Usage: "(agent/networking) Kubelet resolv.conf file",
EnvVars: []string{version.ProgramUpper + "_RESOLV_CONF"},
EnvVar: version.ProgramUpper + "_RESOLV_CONF",
Destination: &AgentConfig.ResolvConf,
}
ExtraKubeletArgs = cli.StringSliceFlag{
Name: "kubelet-arg",
Usage: "(agent/flags) Customized flag for kubelet process",
Destination: &AgentConfig.ExtraKubeletArgs,
Name: "kubelet-arg",
Usage: "(agent/flags) Customized flag for kubelet process",
Value: &AgentConfig.ExtraKubeletArgs,
}
ExtraKubeProxyArgs = cli.StringSliceFlag{
Name: "kube-proxy-arg",
Usage: "(agent/flags) Customized flag for kube-proxy process",
Destination: &AgentConfig.ExtraKubeProxyArgs,
Name: "kube-proxy-arg",
Usage: "(agent/flags) Customized flag for kube-proxy process",
Value: &AgentConfig.ExtraKubeProxyArgs,
}
NodeTaints = cli.StringSliceFlag{
Name: "node-taint",
Usage: "(agent/node) Registering kubelet with set of taints",
Destination: &AgentConfig.Taints,
Name: "node-taint",
Usage: "(agent/node) Registering kubelet with set of taints",
Value: &AgentConfig.Taints,
}
NodeLabels = cli.StringSliceFlag{
Name: "node-label",
Usage: "(agent/node) Registering and starting kubelet with set of labels",
Destination: &AgentConfig.Labels,
Name: "node-label",
Usage: "(agent/node) Registering and starting kubelet with set of labels",
Value: &AgentConfig.Labels,
}
DisableSELinuxFlag = cli.BoolFlag{
DisableSELinuxFlag = cli.BoolTFlag{
Name: "disable-selinux",
Usage: "(deprecated) Use --selinux to explicitly enable SELinux",
Hidden: true,
Value: true, // disabled by default
}
ProtectKernelDefaultsFlag = cli.BoolFlag{
Name: "protect-kernel-defaults",
@ -155,7 +153,7 @@ var (
Usage: "(agent/node) Enable SELinux in containerd",
Hidden: false,
Destination: &AgentConfig.EnableSELinux,
EnvVars: []string{version.ProgramUpper + "_SELINUX"},
EnvVar: version.ProgramUpper + "_SELINUX",
}
)
@ -169,67 +167,60 @@ func CheckSELinuxFlags(ctx *cli.Context) error {
}
return nil
}
func NewAgentCommand(action func(ctx *cli.Context) error) *cli.Command {
return &cli.Command{
func NewAgentCommand(action func(ctx *cli.Context) error) cli.Command {
return cli.Command{
Name: "agent",
Usage: "Run node agent",
UsageText: appName + " agent [OPTIONS]",
Before: func(ctx *cli.Context) error {
if err := CheckSELinuxFlags(ctx); err != nil {
return err
}
return DebugContext(cli.InitAllInputSource(altsrc.NewConfigFromFlag(ConfigFlag.Name)))(ctx)
},
Action: InitLogging(action),
Before: CheckSELinuxFlags,
Action: action,
Flags: []cli.Flag{
&ConfigFlag,
&DebugFlag,
&VLevel,
&VModule,
&LogFile,
&AlsoLogToStderr,
&cli.StringFlag{
VLevel,
VModule,
LogFile,
AlsoLogToStderr,
cli.StringFlag{
Name: "token,t",
Usage: "(cluster) Token to use for authentication",
EnvVars: []string{version.ProgramUpper + "_TOKEN"},
EnvVar: version.ProgramUpper + "_TOKEN",
Destination: &AgentConfig.Token,
},
&cli.StringFlag{
cli.StringFlag{
Name: "token-file",
Usage: "(cluster) Token file to use for authentication",
EnvVars: []string{version.ProgramUpper + "_TOKEN_FILE"},
EnvVar: version.ProgramUpper + "_TOKEN_FILE",
Destination: &AgentConfig.TokenFile,
},
&cli.StringFlag{
cli.StringFlag{
Name: "server,s",
Usage: "(cluster) Server to connect to",
EnvVars: []string{version.ProgramUpper + "_URL"},
EnvVar: version.ProgramUpper + "_URL",
Destination: &AgentConfig.ServerURL,
},
&cli.StringFlag{
cli.StringFlag{
Name: "data-dir,d",
Usage: "(agent/data) Folder to hold state",
Destination: &AgentConfig.DataDir,
Value: "/var/lib/rancher/" + version.Program + "",
},
&NodeNameFlag,
&WithNodeIDFlag,
&NodeLabels,
&NodeTaints,
&DockerFlag,
&CRIEndpointFlag,
&PauseImageFlag,
&SnapshotterFlag,
&PrivateRegistryFlag,
&NodeIPFlag,
&NodeExternalIPFlag,
&ResolvConfFlag,
&FlannelIfaceFlag,
&FlannelConfFlag,
&ExtraKubeletArgs,
&ExtraKubeProxyArgs,
&ProtectKernelDefaultsFlag,
&cli.BoolFlag{
NodeNameFlag,
WithNodeIDFlag,
NodeLabels,
NodeTaints,
DockerFlag,
CRIEndpointFlag,
PauseImageFlag,
SnapshotterFlag,
PrivateRegistryFlag,
NodeIPFlag,
NodeExternalIPFlag,
ResolvConfFlag,
FlannelIfaceFlag,
FlannelConfFlag,
ExtraKubeletArgs,
ExtraKubeProxyArgs,
ProtectKernelDefaultsFlag,
cli.BoolFlag{
Name: "rootless",
Usage: "(experimental) Run rootless",
Destination: &AgentConfig.Rootless,
@ -239,12 +230,12 @@ func NewAgentCommand(action func(ctx *cli.Context) error) *cli.Command {
// Deprecated/hidden below
&DisableSELinuxFlag,
&FlannelFlag,
&cli.StringFlag{
FlannelFlag,
cli.StringFlag{
Name: "cluster-secret",
Usage: "(deprecated) use --token",
Destination: &AgentConfig.ClusterSecret,
EnvVars: []string{version.ProgramUpper + "_CLUSTER_SECRET"},
EnvVar: version.ProgramUpper + "_CLUSTER_SECRET",
},
},
}

View File

@ -1,14 +1,15 @@
package cmds
import (
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
func NewCheckConfigCommand(action func(*cli.Context) error) *cli.Command {
return &cli.Command{
func NewCheckConfigCommand(action func(*cli.Context) error) cli.Command {
return cli.Command{
Name: "check-config",
Usage: "Run config check",
SkipFlagParsing: true,
SkipArgReorder: true,
Action: action,
}
}

View File

@ -1,16 +0,0 @@
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,
}
)

View File

@ -1,14 +1,15 @@
package cmds
import (
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
func NewCRICTL(action func(*cli.Context) error) *cli.Command {
return &cli.Command{
func NewCRICTL(action func(*cli.Context) error) cli.Command {
return cli.Command{
Name: "crictl",
Usage: "Run crictl",
SkipFlagParsing: true,
SkipArgReorder: true,
Action: action,
}
}

View File

@ -1,14 +1,15 @@
package cmds
import (
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
func NewCtrCommand(action func(*cli.Context) error) *cli.Command {
return &cli.Command{
func NewCtrCommand(action func(*cli.Context) error) cli.Command {
return cli.Command{
Name: "ctr",
Usage: "Run ctr",
SkipFlagParsing: true,
SkipArgReorder: true,
Action: action,
}
}

View File

@ -1,31 +0,0 @@
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
}
}

View File

@ -1,14 +1,15 @@
package cmds
import (
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
func NewKubectlCommand(action func(*cli.Context) error) *cli.Command {
return &cli.Command{
func NewKubectlCommand(action func(*cli.Context) error) cli.Command {
return cli.Command{
Name: "kubectl",
Usage: "Run kubectl",
SkipFlagParsing: true,
SkipArgReorder: true,
Action: action,
}
}

View File

@ -12,7 +12,7 @@ import (
"github.com/docker/docker/pkg/reexec"
"github.com/natefinch/lumberjack"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
type Log struct {
@ -49,31 +49,22 @@ var (
logSetupOnce sync.Once
)
func InitLogging(action func(*cli.Context) error) func(*cli.Context) error {
return func(ctx *cli.Context) error {
var (
err error
reExec bool
)
logSetupOnce.Do(func() {
if LogConfig.LogFile != "" && os.Getenv("_K3S_LOG_REEXEC_") == "" {
reExec = true
err = runWithLogging()
return
}
if err = checkUnixTimestamp(); err != nil {
return
}
setupLogging()
})
if reExec || err != nil {
return err
func InitLogging() error {
var rErr error
logSetupOnce.Do(func() {
if LogConfig.LogFile != "" && os.Getenv("_K3S_LOG_REEXEC_") == "" {
rErr = runWithLogging()
return
}
if action != nil {
return action(ctx)
if err := checkUnixTimestamp(); err != nil {
rErr = err
return
}
return nil
}
setupLogging()
})
return rErr
}
func checkUnixTimestamp() error {

View File

@ -5,7 +5,12 @@ import (
"os"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)
var (
Debug bool
)
func init() {
@ -23,8 +28,21 @@ func NewApp() *cli.App {
cli.VersionPrinter = func(c *cli.Context) {
fmt.Printf("%s version %s\n", app.Name, app.Version)
}
app.Flags = []cli.Flag{&DebugFlag}
app.Before = DebugContext(nil)
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "debug",
Usage: "Turn on debug logs",
Destination: &Debug,
EnvVar: version.ProgramUpper + "_DEBUG",
},
}
app.Before = func(ctx *cli.Context) error {
if Debug {
logrus.SetLevel(logrus.DebugLevel)
}
return nil
}
return app
}

View File

@ -5,8 +5,7 @@ import (
"github.com/rancher/k3s/pkg/daemons/config"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/rancher/spur/cli/altsrc"
"github.com/urfave/cli"
)
const (
@ -37,12 +36,12 @@ type Server struct {
DisableAgent bool
KubeConfigOutput string
KubeConfigMode string
TLSSan []string
TLSSan cli.StringSlice
BindAddress string
ExtraAPIArgs []string
ExtraSchedulerArgs []string
ExtraControllerArgs []string
ExtraCloudControllerArgs []string
ExtraAPIArgs cli.StringSlice
ExtraSchedulerArgs cli.StringSlice
ExtraControllerArgs cli.StringSlice
ExtraCloudControllerArgs cli.StringSlice
Rootless bool
DatastoreEndpoint string
DatastoreCAFile string
@ -70,153 +69,146 @@ type Server struct {
var ServerConfig Server
func NewServerCommand(action func(*cli.Context) error) *cli.Command {
return &cli.Command{
func NewServerCommand(action func(*cli.Context) error) cli.Command {
return cli.Command{
Name: "server",
Usage: "Run management server",
UsageText: appName + " server [OPTIONS]",
Before: func(ctx *cli.Context) error {
if err := CheckSELinuxFlags(ctx); err != nil {
return err
}
return DebugContext(cli.InitAllInputSource(altsrc.NewConfigFromFlag(ConfigFlag.Name)))(ctx)
},
Action: InitLogging(action),
Before: CheckSELinuxFlags,
Action: action,
Flags: []cli.Flag{
&ConfigFlag,
&DebugFlag,
&VLevel,
&VModule,
&LogFile,
&AlsoLogToStderr,
&cli.StringFlag{
VLevel,
VModule,
LogFile,
AlsoLogToStderr,
cli.StringFlag{
Name: "bind-address",
Usage: "(listener) " + version.Program + " bind address (default: 0.0.0.0)",
Destination: &ServerConfig.BindAddress,
},
&cli.IntFlag{
cli.IntFlag{
Name: "https-listen-port",
Usage: "(listener) HTTPS listen port",
Value: 6443,
Destination: &ServerConfig.HTTPSPort,
},
&cli.StringFlag{
cli.StringFlag{
Name: "advertise-address",
Usage: "(listener) IP address that apiserver uses to advertise to members of the cluster (default: node-external-ip/node-ip)",
Destination: &ServerConfig.AdvertiseIP,
},
&cli.IntFlag{
cli.IntFlag{
Name: "advertise-port",
Usage: "(listener) Port that apiserver uses to advertise to members of the cluster (default: listen-port)",
Destination: &ServerConfig.AdvertisePort,
},
&cli.StringSliceFlag{
Name: "tls-san",
Usage: "(listener) Add additional hostname or IP as a Subject Alternative Name in the TLS cert",
Destination: &ServerConfig.TLSSan,
cli.StringSliceFlag{
Name: "tls-san",
Usage: "(listener) Add additional hostname or IP as a Subject Alternative Name in the TLS cert",
Value: &ServerConfig.TLSSan,
},
&cli.StringFlag{
cli.StringFlag{
Name: "data-dir,d",
Usage: "(data) Folder to hold state default /var/lib/rancher/" + version.Program + " or ${HOME}/.rancher/" + version.Program + " if not root",
Destination: &ServerConfig.DataDir,
},
&cli.StringFlag{
cli.StringFlag{
Name: "cluster-cidr",
Usage: "(networking) Network CIDR to use for pod IPs",
Destination: &ServerConfig.ClusterCIDR,
Value: "10.42.0.0/16",
},
&cli.StringFlag{
cli.StringFlag{
Name: "service-cidr",
Usage: "(networking) Network CIDR to use for services IPs",
Destination: &ServerConfig.ServiceCIDR,
Value: "10.43.0.0/16",
},
&cli.StringFlag{
cli.StringFlag{
Name: "cluster-dns",
Usage: "(networking) Cluster IP for coredns service. Should be in your service-cidr range (default: 10.43.0.10)",
Destination: &ServerConfig.ClusterDNS,
Value: "",
},
&cli.StringFlag{
cli.StringFlag{
Name: "cluster-domain",
Usage: "(networking) Cluster Domain",
Destination: &ServerConfig.ClusterDomain,
Value: "cluster.local",
},
&cli.StringFlag{
cli.StringFlag{
Name: "flannel-backend",
Usage: "(networking) One of 'none', 'vxlan', 'ipsec', 'host-gw', or 'wireguard'",
Destination: &ServerConfig.FlannelBackend,
Value: "vxlan",
},
&cli.StringFlag{
cli.StringFlag{
Name: "token,t",
Usage: "(cluster) Shared secret used to join a server or agent to a cluster",
Destination: &ServerConfig.Token,
EnvVars: []string{version.ProgramUpper + "_TOKEN"},
EnvVar: version.ProgramUpper + "_TOKEN",
},
&cli.StringFlag{
cli.StringFlag{
Name: "token-file",
Usage: "(cluster) File containing the cluster-secret/token",
Destination: &ServerConfig.TokenFile,
EnvVars: []string{version.ProgramUpper + "_TOKEN_FILE"},
EnvVar: version.ProgramUpper + "_TOKEN_FILE",
},
&cli.StringFlag{
cli.StringFlag{
Name: "write-kubeconfig,o",
Usage: "(client) Write kubeconfig for admin client to this file",
Destination: &ServerConfig.KubeConfigOutput,
EnvVars: []string{version.ProgramUpper + "_KUBECONFIG_OUTPUT"},
EnvVar: version.ProgramUpper + "_KUBECONFIG_OUTPUT",
},
&cli.StringFlag{
cli.StringFlag{
Name: "write-kubeconfig-mode",
Usage: "(client) Write kubeconfig with this mode",
Destination: &ServerConfig.KubeConfigMode,
EnvVars: []string{version.ProgramUpper + "_KUBECONFIG_MODE"},
EnvVar: version.ProgramUpper + "_KUBECONFIG_MODE",
},
&cli.StringSliceFlag{
Name: "kube-apiserver-arg",
Usage: "(flags) Customized flag for kube-apiserver process",
Destination: &ServerConfig.ExtraAPIArgs,
cli.StringSliceFlag{
Name: "kube-apiserver-arg",
Usage: "(flags) Customized flag for kube-apiserver process",
Value: &ServerConfig.ExtraAPIArgs,
},
&cli.StringSliceFlag{
Name: "kube-scheduler-arg",
Usage: "(flags) Customized flag for kube-scheduler process",
Destination: &ServerConfig.ExtraSchedulerArgs,
cli.StringSliceFlag{
Name: "kube-scheduler-arg",
Usage: "(flags) Customized flag for kube-scheduler process",
Value: &ServerConfig.ExtraSchedulerArgs,
},
&cli.StringSliceFlag{
Name: "kube-controller-manager-arg",
Usage: "(flags) Customized flag for kube-controller-manager process",
Destination: &ServerConfig.ExtraControllerArgs,
cli.StringSliceFlag{
Name: "kube-controller-manager-arg",
Usage: "(flags) Customized flag for kube-controller-manager process",
Value: &ServerConfig.ExtraControllerArgs,
},
&cli.StringSliceFlag{
Name: "kube-cloud-controller-manager-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Destination: &ServerConfig.ExtraCloudControllerArgs,
cli.StringSliceFlag{
Name: "kube-cloud-controller-manager-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Value: &ServerConfig.ExtraCloudControllerArgs,
},
&cli.StringFlag{
cli.StringFlag{
Name: "datastore-endpoint",
Usage: "(db) Specify etcd, Mysql, Postgres, or Sqlite (default) data source name",
Destination: &ServerConfig.DatastoreEndpoint,
EnvVars: []string{version.ProgramUpper + "_DATASTORE_ENDPOINT"},
EnvVar: version.ProgramUpper + "_DATASTORE_ENDPOINT",
},
&cli.StringFlag{
cli.StringFlag{
Name: "datastore-cafile",
Usage: "(db) TLS Certificate Authority file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreCAFile,
EnvVars: []string{version.ProgramUpper + "_DATASTORE_CAFILE"},
EnvVar: version.ProgramUpper + "_DATASTORE_CAFILE",
},
&cli.StringFlag{
cli.StringFlag{
Name: "datastore-certfile",
Usage: "(db) TLS certification file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreCertFile,
EnvVars: []string{version.ProgramUpper + "_DATASTORE_CERTFILE"},
EnvVar: version.ProgramUpper + "_DATASTORE_CERTFILE",
},
&cli.StringFlag{
cli.StringFlag{
Name: "datastore-keyfile",
Usage: "(db) TLS key file used to secure datastore backend communication",
Destination: &ServerConfig.DatastoreKeyFile,
EnvVars: []string{version.ProgramUpper + "_DATASTORE_KEYFILE"},
EnvVar: version.ProgramUpper + "_DATASTORE_KEYFILE",
},
&cli.BoolFlag{
Name: "etcd-disable-snapshots",
@ -240,88 +232,88 @@ func NewServerCommand(action func(*cli.Context) error) *cli.Command {
Usage: "(db) Directory to save db snapshots. (Default location: ${data-dir}/db/snapshots)",
Destination: &ServerConfig.EtcdSnapshotDir,
},
&cli.StringFlag{
cli.StringFlag{
Name: "default-local-storage-path",
Usage: "(storage) Default local storage path for local provisioner storage class",
Destination: &ServerConfig.DefaultLocalStoragePath,
},
&cli.StringSliceFlag{
cli.StringSliceFlag{
Name: "disable",
Usage: "(components) Do not deploy packaged components and delete any deployed components (valid items: " + DisableItems + ")",
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "disable-scheduler",
Usage: "(components) Disable Kubernetes default scheduler",
Destination: &ServerConfig.DisableScheduler,
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "disable-cloud-controller",
Usage: "(components) Disable " + version.Program + " default cloud controller manager",
Destination: &ServerConfig.DisableCCM,
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "disable-kube-proxy",
Usage: "(components) Disable running kube-proxy",
Destination: &ServerConfig.DisableKubeProxy,
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "disable-network-policy",
Usage: "(components) Disable " + version.Program + " default network policy controller",
Destination: &ServerConfig.DisableNPC,
},
&NodeNameFlag,
&WithNodeIDFlag,
&NodeLabels,
&NodeTaints,
&DockerFlag,
&CRIEndpointFlag,
&PauseImageFlag,
&SnapshotterFlag,
&PrivateRegistryFlag,
&NodeIPFlag,
&NodeExternalIPFlag,
&ResolvConfFlag,
&FlannelIfaceFlag,
&FlannelConfFlag,
&ExtraKubeletArgs,
&ExtraKubeProxyArgs,
&ProtectKernelDefaultsFlag,
&cli.BoolFlag{
NodeNameFlag,
WithNodeIDFlag,
NodeLabels,
NodeTaints,
DockerFlag,
CRIEndpointFlag,
PauseImageFlag,
SnapshotterFlag,
PrivateRegistryFlag,
NodeIPFlag,
NodeExternalIPFlag,
ResolvConfFlag,
FlannelIfaceFlag,
FlannelConfFlag,
ExtraKubeletArgs,
ExtraKubeProxyArgs,
ProtectKernelDefaultsFlag,
cli.BoolFlag{
Name: "rootless",
Usage: "(experimental) Run rootless",
Destination: &ServerConfig.Rootless,
},
&cli.StringFlag{
cli.StringFlag{
Name: "agent-token",
Usage: "(experimental/cluster) Shared secret used to join agents to the cluster, but not servers",
Destination: &ServerConfig.AgentToken,
EnvVars: []string{version.ProgramUpper + "_AGENT_TOKEN"},
EnvVar: version.ProgramUpper + "_AGENT_TOKEN",
},
&cli.StringFlag{
cli.StringFlag{
Name: "agent-token-file",
Usage: "(experimental/cluster) File containing the agent secret",
Destination: &ServerConfig.AgentTokenFile,
EnvVars: []string{version.ProgramUpper + "_AGENT_TOKEN_FILE"},
EnvVar: version.ProgramUpper + "_AGENT_TOKEN_FILE",
},
&cli.StringFlag{
cli.StringFlag{
Name: "server,s",
Hidden: hideClusterFlags,
Usage: "(experimental/cluster) Server to connect to, used to join a cluster",
EnvVars: []string{version.ProgramUpper + "_URL"},
EnvVar: version.ProgramUpper + "_URL",
Destination: &ServerConfig.ServerURL,
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "cluster-init",
Hidden: hideClusterFlags,
Usage: "(experimental/cluster) Initialize a new cluster",
EnvVars: []string{version.ProgramUpper + "_CLUSTER_INIT"},
EnvVar: version.ProgramUpper + "_CLUSTER_INIT",
Destination: &ServerConfig.ClusterInit,
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "cluster-reset",
Hidden: hideClusterFlags,
Usage: "(experimental/cluster) Forget all peers and become sole member of a new cluster",
EnvVars: []string{version.ProgramUpper + "_CLUSTER_RESET"},
EnvVar: version.ProgramUpper + "_CLUSTER_RESET",
Destination: &ServerConfig.ClusterReset,
},
&cli.StringFlag{
@ -329,7 +321,7 @@ func NewServerCommand(action func(*cli.Context) error) *cli.Command {
Usage: "(db) Path to snapshot file to be restored",
Destination: &ServerConfig.ClusterResetRestorePath,
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "secrets-encryption",
Usage: "(experimental) Enable Secret encryption at rest",
Destination: &ServerConfig.EncryptSecrets,
@ -339,34 +331,34 @@ func NewServerCommand(action func(*cli.Context) error) *cli.Command {
// Hidden/Deprecated flags below
&DisableSELinuxFlag,
&FlannelFlag,
&cli.StringSliceFlag{
FlannelFlag,
cli.StringSliceFlag{
Name: "no-deploy",
Usage: "(deprecated) Do not deploy packaged components (valid items: " + DisableItems + ")",
},
&cli.StringFlag{
cli.StringFlag{
Name: "cluster-secret",
Usage: "(deprecated) use --token",
Destination: &ServerConfig.ClusterSecret,
EnvVars: []string{version.ProgramUpper + "_CLUSTER_SECRET"},
EnvVar: version.ProgramUpper + "_CLUSTER_SECRET",
},
&cli.BoolFlag{
cli.BoolFlag{
Name: "disable-agent",
Usage: "Do not run a local agent and register a local kubelet",
Hidden: true,
Destination: &ServerConfig.DisableAgent,
},
&cli.StringSliceFlag{
Hidden: true,
Name: "kube-controller-arg",
Usage: "(flags) Customized flag for kube-controller-manager process",
Destination: &ServerConfig.ExtraControllerArgs,
cli.StringSliceFlag{
Hidden: true,
Name: "kube-controller-arg",
Usage: "(flags) Customized flag for kube-controller-manager process",
Value: &ServerConfig.ExtraControllerArgs,
},
&cli.StringSliceFlag{
Hidden: true,
Name: "kube-cloud-controller-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Destination: &ServerConfig.ExtraCloudControllerArgs,
cli.StringSliceFlag{
Hidden: true,
Name: "kube-cloud-controller-arg",
Usage: "(flags) Customized flag for kube-cloud-controller-manager process",
Value: &ServerConfig.ExtraCloudControllerArgs,
},
},
}

View File

@ -2,7 +2,7 @@ package crictl
import (
"github.com/kubernetes-sigs/cri-tools/cmd/crictl"
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
func Run(ctx *cli.Context) error {

View File

@ -2,7 +2,7 @@ package ctr
import (
"github.com/rancher/k3s/pkg/ctr"
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
func Run(ctx *cli.Context) error {

View File

@ -2,7 +2,7 @@ package kubectl
import (
"github.com/rancher/k3s/pkg/kubectl"
"github.com/rancher/spur/cli"
"github.com/urfave/cli"
)
func Run(ctx *cli.Context) error {

View File

@ -19,9 +19,9 @@ import (
"github.com/rancher/k3s/pkg/server"
"github.com/rancher/k3s/pkg/token"
"github.com/rancher/k3s/pkg/version"
"github.com/rancher/spur/cli"
"github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
"k8s.io/apimachinery/pkg/util/net"
kubeapiserverflag "k8s.io/component-base/cli/flag"
"k8s.io/kubernetes/pkg/master"
@ -32,6 +32,9 @@ import (
)
func Run(app *cli.Context) error {
if err := cmds.InitLogging(); err != nil {
return err
}
return run(app, &cmds.ServerConfig)
}
@ -263,7 +266,7 @@ func run(app *cli.Context, cfg *cmds.Server) error {
}
agentConfig := cmds.AgentConfig
agentConfig.Debug = app.Bool("debug")
agentConfig.Debug = app.GlobalBool("bool")
agentConfig.DataDir = filepath.Dir(serverConfig.ControlConfig.DataDir)
agentConfig.ServerURL = url
agentConfig.Token = token

View File

@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,2 +0,0 @@
[flake8]
max-line-length = 120

View File

@ -1,7 +0,0 @@
*.coverprofile
*.orig
node_modules/
vendor
.idea
internal/*/built-example
coverage.txt

View File

@ -1,21 +0,0 @@
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.

View File

@ -1,40 +0,0 @@
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__)
}

View File

@ -1,23 +0,0 @@
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
}
}

View File

@ -1,49 +0,0 @@
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
}

View File

@ -1,56 +0,0 @@
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)
}

View File

@ -1,540 +0,0 @@
package cli
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
"sort"
"time"
"github.com/rancher/spur/flag"
)
// App is the main structure of a cli application. It is recommended that
// an app be created with the cli.NewApp() function
type App struct {
// The name of the program. Defaults to path.Base(os.Args[0])
Name string
// Full name of command for help, defaults to Name
HelpName string
// Description of the program.
Usage string
// Text to override the USAGE section of help
UsageText string
// Description of the program argument format.
ArgsUsage string
// Version of the program
Version string
// Description of the program
Description string
// List of commands to execute
Commands []*Command
// List of flags to parse
Flags []Flag
// Boolean to enable bash completion commands
EnableBashCompletion bool
// Boolean to hide built-in help command and help flag
HideHelp bool
// Boolean to hide built-in help command but keep help flag.
// Ignored if HideHelp is true.
HideHelpCommand bool
// Boolean to hide built-in version flag and the VERSION section of help
HideVersion bool
// categories contains the categorized commands and is populated on app startup
categories CommandCategories
// An action to execute when the shell completion flag is set
BashComplete BashCompleteFunc
// An action to execute before any subcommands are run, but after the context is ready
// If a non-nil error is returned, no subcommands are run
Before BeforeFunc
// An action to execute after any subcommands are run, but after the subcommand has finished
// It is run even if Action() panics
After AfterFunc
// The action to execute when no subcommands are specified
Action ActionFunc
// Execute this function if the proper command cannot be found
CommandNotFound CommandNotFoundFunc
// Execute this function if an usage error occurs
OnUsageError OnUsageErrorFunc
// Compilation date
Compiled time.Time
// List of all authors who contributed
Authors []*Author
// Copyright of the binary if any
Copyright string
// Writer writer to write output to
Writer io.Writer
// ErrWriter writes error output
ErrWriter io.Writer
// ExitErrHandler processes any error encountered while running an App before
// it is returned to the caller. If no function is provided, HandleExitCoder
// is used as the default behavior.
ExitErrHandler ExitErrHandlerFunc
// Other custom info
Metadata map[string]interface{}
// Carries a function which returns app specific info.
ExtraInfo func() map[string]string
// CustomAppHelpTemplate the text template for app help topic.
// cli.go uses text/template to render templates. You can
// render custom help text by setting this variable.
CustomAppHelpTemplate string
// Boolean to enable short-option handling so user can combine several
// single-character bool arguments into one
// i.e. foobar -o -v -> foobar -ov
UseShortOptionHandling bool
didSetup bool
}
type showHelpFunc = func(context *Context) error
type showHelpError struct {
error
}
// ShowHelpOnError will take a BeforeFunc and show command usage on error
func ShowHelpOnError(someFunc BeforeFunc) BeforeFunc {
return func(context *Context) error {
if err := someFunc(context); err != nil {
return showHelpError{err}
}
return nil
}
}
// Tries to find out when this binary was compiled.
// Returns the current time if it fails to find it.
func compileTime() time.Time {
info, err := os.Stat(os.Args[0])
if err != nil {
return time.Now()
}
return info.ModTime()
}
// NewApp creates a new cli Application with some reasonable defaults for Name,
// Usage, Version and Action.
func NewApp() *App {
return &App{
Name: filepath.Base(os.Args[0]),
HelpName: filepath.Base(os.Args[0]),
Usage: "A new cli application",
UsageText: "",
BashComplete: DefaultAppComplete,
Action: helpCommand.Action,
Compiled: compileTime(),
Writer: os.Stdout,
ErrWriter: os.Stderr,
}
}
// Setup runs initialization code to ensure all data structures are ready for
// `Run` or inspection prior to `Run`. It is internally called by `Run`, but
// will return early if setup has already happened.
func (a *App) Setup() {
if a.didSetup {
return
}
a.didSetup = true
if a.Name == "" {
a.Name = filepath.Base(os.Args[0])
}
if a.HelpName == "" {
a.HelpName = filepath.Base(os.Args[0])
}
if a.Usage == "" {
a.Usage = "A new cli application"
}
if a.Version == "" {
a.HideVersion = true
}
if a.BashComplete == nil {
a.BashComplete = DefaultAppComplete
}
if a.Action == nil {
a.Action = helpCommand.Action
}
if a.Compiled == (time.Time{}) {
a.Compiled = compileTime()
}
if a.Writer == nil {
a.Writer = os.Stdout
}
if a.ErrWriter == nil {
a.ErrWriter = os.Stderr
}
var newCommands []*Command
for _, c := range a.Commands {
if c.HelpName == "" {
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
}
newCommands = append(newCommands, c)
}
a.Commands = newCommands
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
if !a.HideHelpCommand {
a.appendCommand(helpCommand)
}
if HelpFlag != nil {
a.appendFlag(HelpFlag)
}
}
if !a.HideVersion {
a.appendFlag(VersionFlag)
}
a.categories = newCommandCategories()
for _, command := range a.Commands {
a.categories.AddCommand(command.Category, command)
}
sort.Sort(a.categories.(*commandCategories))
if a.Metadata == nil {
a.Metadata = make(map[string]interface{})
}
}
func (a *App) newFlagSet() (*flag.FlagSet, error) {
return flagSet(a.Name, a.Flags)
}
func (a *App) useShortOptionHandling() bool {
return a.UseShortOptionHandling
}
// Run is the entry point to the cli app. Parses the arguments slice and routes
// to the proper flag/args combination
func (a *App) Run(arguments []string) (err error) {
return a.RunContext(context.Background(), arguments)
}
// RunContext is like Run except it takes a Context that will be
// passed to its commands and sub-commands. Through this, you can
// propagate timeouts and cancellation requests
func (a *App) RunContext(ctx context.Context, arguments []string) (err error) {
if len(arguments) == 0 {
return fmt.Errorf("arguments not provided")
}
a.Setup()
// handle the completion flag separately from the flagset since
// completion could be attempted after a flag, but before its value was put
// on the command line. this causes the flagset to interpret the completion
// flag name as the value of the flag before it which is undesirable
// note that we can only do this because the shell autocomplete function
// always appends the completion flag at the end of the command
shellComplete, arguments := checkShellCompleteFlag(a, arguments)
set, err := a.newFlagSet()
if err != nil {
return err
}
err = parseIter(set, a, arguments[1:], shellComplete)
nerr := normalizeFlags(a.Flags, set)
context := NewContext(a, set, &Context{Context: ctx})
if nerr != nil {
fmt.Fprintln(a.Writer, nerr)
ShowAppHelp(context)
return nerr
}
context.shellComplete = shellComplete
if checkCompletions(context) {
return nil
}
if err != nil {
return a.helpOnError(ShowAppHelp, context, showHelpError{err})
}
if !a.HideHelp && checkHelp(context) {
ShowAppHelp(context)
return nil
}
if !a.HideVersion && checkVersion(context) {
ShowVersion(context)
return nil
}
cerr := checkRequiredFlags(a.Flags, context)
if cerr != nil {
ShowAppHelp(context)
return cerr
}
if a.After != nil {
defer func() {
if afterErr := a.After(context); afterErr != nil {
a.handleExitCoder(context, err)
if err != nil {
err = newMultiError(err, afterErr)
} else {
err = afterErr
}
}
}()
}
if a.Before != nil {
if err := a.Before(context); err != nil {
return a.helpOnError(ShowAppHelp, context, err)
}
}
args := context.Args()
if args.Present() {
name := args.First()
c := a.Command(name)
if c != nil {
return c.Run(context)
}
}
if a.Action == nil {
a.Action = helpCommand.Action
}
// Run default Action
err = a.Action(context)
a.handleExitCoder(context, err)
return err
}
func (a *App) helpOnError(showHelp showHelpFunc, context *Context, err error) error {
if err == nil {
return nil
}
if e, ok := err.(showHelpError); ok {
err = e.error
if a.OnUsageError != nil {
err = a.OnUsageError(context, err, false)
} else {
fmt.Fprintf(a.Writer, "%s:\n %s\n\n", "Incorrect Usage", err.Error())
showHelp(context)
}
}
a.handleExitCoder(context, err)
return err
}
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
//
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
// to cli.App.Run. This will cause the application to exit with the given error
// code in the cli.ExitCoder
func (a *App) RunAndExitOnError() {
if err := a.Run(os.Args); err != nil {
fmt.Fprintf(a.ErrWriter, "\nFatal: %s\n", err)
OsExiter(1)
}
}
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
// generate command-specific flags
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
// Setup also handles HideHelp and HideHelpCommand
a.Setup()
var newCmds []*Command
for _, c := range a.Commands {
if c.HelpName == "" {
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
}
newCmds = append(newCmds, c)
}
a.Commands = newCmds
set, err := a.newFlagSet()
if err != nil {
return err
}
err = parseIter(set, a, ctx.Args().Tail(), ctx.shellComplete)
nerr := normalizeFlags(a.Flags, set)
context := NewContext(a, set, ctx)
if nerr != nil {
fmt.Fprintln(a.Writer, nerr)
fmt.Fprintln(a.Writer)
if len(a.Commands) > 0 {
ShowSubcommandHelp(context)
} else {
ShowCommandHelp(ctx, context.Args().First())
}
return nerr
}
if checkCompletions(context) {
return nil
}
if err != nil {
return a.helpOnError(ShowSubcommandHelp, context, showHelpError{err})
}
if len(a.Commands) > 0 {
if checkSubcommandHelp(context) {
return nil
}
} else {
if checkCommandHelp(ctx, context.Args().First()) {
return nil
}
}
cerr := checkRequiredFlags(a.Flags, context)
if cerr != nil {
ShowSubcommandHelp(context)
return cerr
}
if a.After != nil {
defer func() {
if afterErr := a.After(context); afterErr != nil {
a.handleExitCoder(context, err)
if err != nil {
err = newMultiError(err, afterErr)
} else {
err = afterErr
}
}
}()
}
if a.Before != nil {
if err := a.Before(context); err != nil {
return a.helpOnError(ShowSubcommandHelp, context, err)
}
}
args := context.Args()
if args.Present() {
name := args.First()
c := a.Command(name)
if c != nil {
return c.Run(context)
}
}
// Run default Action
err = a.Action(context)
a.handleExitCoder(context, err)
return err
}
// Command returns the named command on App. Returns nil if the command does not exist
func (a *App) Command(name string) *Command {
for _, c := range a.Commands {
if c.HasName(name) {
return c
}
}
return nil
}
// VisibleCategories returns a slice of categories and commands that are
// Hidden=false
func (a *App) VisibleCategories() []CommandCategory {
ret := []CommandCategory{}
for _, category := range a.categories.Categories() {
if visible := func() CommandCategory {
if len(category.VisibleCommands()) > 0 {
return category
}
return nil
}(); visible != nil {
ret = append(ret, visible)
}
}
return ret
}
// VisibleCommands returns a slice of the Commands with Hidden=false
func (a *App) VisibleCommands() []*Command {
var ret []*Command
for _, command := range a.Commands {
if !command.Hidden {
ret = append(ret, command)
}
}
return ret
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func (a *App) VisibleFlags() []Flag {
return visibleFlags(a.Flags)
}
func (a *App) appendFlag(fl Flag) {
if !hasFlag(a.Flags, fl) {
a.Flags = append(a.Flags, fl)
}
}
func (a *App) appendCommand(c *Command) {
if !hasCommand(a.Commands, c) {
a.Commands = append(a.Commands, c)
}
}
func (a *App) handleExitCoder(context *Context, err error) {
if a.ExitErrHandler != nil {
a.ExitErrHandler(context, err)
} else {
HandleExitCoder(err)
}
}
// Author represents someone who has contributed to a cli project.
type Author struct {
Name string // The Authors name
Email string // The Authors email
}
// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
func (a *Author) String() string {
e := ""
if a.Email != "" {
e = " <" + a.Email + ">"
}
return fmt.Sprintf("%v%v", a.Name, e)
}
// HandleAction attempts to figure out which Action signature was used. If
// it's an ActionFunc or a func with the legacy signature for Action, the func
// is run! Panics on invalid function signature.
func HandleAction(action interface{}, context *Context) (err error) {
switch a := action.(type) {
case ActionFunc:
return a(context)
case func(*Context) error:
return a(context)
case func(*Context): // deprecated function signature
a(context)
return nil
}
panic(fmt.Sprintf("invalid Action type '%T', should be 'func(*Context) error'", action))
}

View File

@ -1,54 +0,0 @@
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
}

View File

@ -1,79 +0,0 @@
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
}

View File

@ -1,301 +0,0 @@
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
}

View File

@ -1,275 +0,0 @@
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
}

View File

@ -1,160 +0,0 @@
// +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
}

View File

@ -1,141 +0,0 @@
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
}

View File

@ -1,178 +0,0 @@
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)
}

View File

@ -1,318 +0,0 @@
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
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,40 +0,0 @@
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)
}

View File

@ -1,105 +0,0 @@
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
}

View File

@ -1,92 +0,0 @@
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
}

View File

@ -1,36 +0,0 @@
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)
}

View File

@ -1,44 +0,0 @@
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

View File

@ -1,378 +0,0 @@
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
}

View File

@ -1,79 +0,0 @@
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())
}
}

View File

@ -1,95 +0,0 @@
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
}

View File

@ -1,29 +0,0 @@
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
}

View File

@ -1,120 +0,0 @@
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 }}`

View File

@ -1,27 +0,0 @@
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.

View File

@ -1,35 +0,0 @@
// 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__)
}

View File

@ -1,661 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
Package flag implements command-line flag parsing.
Usage
Define flags using flag.String(), Bool(), Int(), etc.
This declares an integer flag, -n, stored in the pointer nFlag, with type *int:
import "flag"
var nFlag = flag.Int("n", 1234, "help message for flag n")
If you like, you can bind the flag to a variable using the Var() functions.
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}
Or you can create custom flags that satisfy the Value interface (with
pointer receivers) and couple them to flag parsing by
flag.Var(&flagVal, "name", "help message for flagname")
For such flags, the default value is just the initial value of the variable.
After all flags are defined, call
flag.Parse()
to parse the command line into the defined flags.
Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)
After parsing, the arguments following the flags are available as the
slice flag.Args() or individually as flag.Arg(i).
The arguments are indexed from 0 through flag.NArg()-1.
Command line flag syntax
The following forms are permitted:
-flag
-flag=x
-flag x // non-boolean flags only
One or two minus signs may be used; they are equivalent.
The last form is not permitted for boolean flags because the
meaning of the command
cmd -x *
where * is a Unix shell wildcard, will change if there is a file
called 0, false, etc. You must use the -flag=false form to turn
off a boolean flag.
Flag parsing stops just before the first non-flag argument
("-" is a non-flag argument) or after the terminator "--".
Integer flags accept 1234, 0664, 0x1234 and may be negative.
Boolean flags may be:
1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
Duration flags accept any input valid for time.ParseDuration.
The default set of command-line flags is controlled by
top-level functions. The FlagSet type allows one to define
independent sets of flags, such as to implement subcommands
in a command-line interface. The methods of FlagSet are
analogous to the top-level functions for the command-line
flag set.
*/
package flag
import (
"errors"
"fmt"
"io"
"os"
"reflect"
"sort"
"strings"
"github.com/rancher/spur/generic"
)
// ErrHelp is the error returned if the -help or -h flag is invoked
// but no such flag is defined.
var ErrHelp = errors.New("flag: help requested")
// Value is the interface to the dynamic value stored in a flag.
// (The default value is represented as a string.)
//
// If a Value has an IsBoolFlag() bool method returning true,
// the command-line parser makes -name equivalent to -name=true
// rather than using the next command-line argument.
//
// Set is called once, in command line order, for each flag present.
// The flag package may call the String method with a zero-valued receiver,
// such as a nil pointer.
type Value interface {
String() string
Set(interface{}) error
}
// Getter is an interface that allows the contents of a Value to be retrieved.
// It wraps the Value interface, rather than being part of it, because it
// appeared after Go 1 and its compatibility rules. All Value types provided
// by this package satisfy the Getter interface.
type Getter interface {
Value
Get() interface{}
}
// BoolFlag is an interface for determining if the value of a flag is needed.
type BoolFlag interface {
IsBoolFlag() bool
}
// IsBoolValue returns true for data types which don't require a flag value
func IsBoolValue(value interface{}) bool {
if v, ok := value.(BoolFlag); ok {
return v.IsBoolFlag()
}
var t reflect.Type
if v, ok := value.(Getter); ok {
t = generic.ElemTypeOf(v.Get())
} else {
t = generic.ElemTypeOf(value)
}
return t != nil && t.String() == "bool"
}
// ErrorHandling defines how FlagSet.Parse behaves if the parse fails.
type ErrorHandling int
// These constants cause FlagSet.Parse to behave as described if the parse fails.
const (
ContinueOnError ErrorHandling = iota // Return a descriptive error.
ExitOnError // Call os.Exit(2) or for -h/-help Exit(0).
PanicOnError // Call panic with a descriptive error.
)
// A FlagSet represents a set of defined flags. The zero value of a FlagSet
// has no name and has ContinueOnError error handling.
//
// Flag names must be unique within a FlagSet. An attempt to define a flag whose
// name is already in use will cause a panic.
type FlagSet struct {
// Usage is the function called when an error occurs while parsing flags.
// The field is a function (not a method) that may be changed to point to
// a custom error handler. What happens after Usage is called depends
// on the ErrorHandling setting; for the command line, this defaults
// to ExitOnError, which exits the program after calling Usage.
Usage func()
name string
parsed bool
actual map[string]*Flag
formal map[string]*Flag
args []string // arguments after flags
errorHandling ErrorHandling
output io.Writer // nil means stderr; use Output() accessor
}
// A Flag represents the state of a flag.
type Flag struct {
Name string // name as it appears on command line
Usage string // help message
Value Value // value as set
DefValue string // default value (as text); for usage message
}
// sortFlags returns the flags as a slice in lexicographical sorted order.
func sortFlags(flags map[string]*Flag) []*Flag {
result := make([]*Flag, len(flags))
i := 0
for _, f := range flags {
result[i] = f
i++
}
sort.Slice(result, func(i, j int) bool {
return result[i].Name < result[j].Name
})
return result
}
const invalidValueTemplate = "invalid value %q for flag -%s: %v"
func (f *FlagSet) addActual(name string, flag *Flag) {
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[name] = flag
}
// Output returns the destination for usage and error messages. os.Stderr is returned if
// output was not set or was set to nil.
func (f *FlagSet) Output() io.Writer {
if f.output == nil {
return os.Stderr
}
return f.output
}
// Name returns the name of the flag set.
func (f *FlagSet) Name() string {
return f.name
}
// ErrorHandling returns the error handling behavior of the flag set.
func (f *FlagSet) ErrorHandling() ErrorHandling {
return f.errorHandling
}
// SetOutput sets the destination for usage and error messages.
// If output is nil, os.Stderr is used.
func (f *FlagSet) SetOutput(output io.Writer) {
f.output = output
}
// VisitAll visits the flags in lexicographical order, calling fn for each.
// It visits all flags, even those not set.
func (f *FlagSet) VisitAll(fn func(*Flag)) {
for _, flag := range sortFlags(f.formal) {
fn(flag)
}
}
// VisitAll visits the command-line flags in lexicographical order, calling
// fn for each. It visits all flags, even those not set.
func VisitAll(fn func(*Flag)) {
CommandLine.VisitAll(fn)
}
// Visit visits the flags in lexicographical order, calling fn for each.
// It visits only those flags that have been set.
func (f *FlagSet) Visit(fn func(*Flag)) {
for _, flag := range sortFlags(f.actual) {
fn(flag)
}
}
// NeedsVisit marks the named flags for visit.
func (f *FlagSet) NeedsVisit(names ...string) {
for _, name := range names {
if flag := f.Lookup(name); flag != nil {
f.addActual(name, flag)
}
}
}
// Visit visits the command-line flags in lexicographical order, calling fn
// for each. It visits only those flags that have been set.
func Visit(fn func(*Flag)) {
CommandLine.Visit(fn)
}
// Lookup returns the Flag structure of the named flag, returning nil if none exists.
func (f *FlagSet) Lookup(name string) *Flag {
return f.formal[name]
}
// Lookup returns the Flag structure of the named command-line flag,
// returning nil if none exists.
func Lookup(name string) *Flag {
return CommandLine.formal[name]
}
// Set sets the value of the named flag.
func (f *FlagSet) Set(name string, value interface{}) error {
flag, ok := f.formal[name]
if !ok {
return fmt.Errorf("no such flag -%v", name)
}
err := flag.Value.Set(value)
if err != nil {
return fmt.Errorf(invalidValueTemplate, value, name, err)
}
f.addActual(name, flag)
return nil
}
// Set sets the value of the named command-line flag.
func Set(name string, value interface{}) error {
return CommandLine.Set(name, value)
}
// isZeroValue determines whether the string represents the zero
// value for a flag.
func isZeroValue(flag *Flag, value string) bool {
// Build a zero value of the flag's Value type, and see if the
// result of calling its String method equals the value passed in.
if val, ok := flag.Value.(Getter); ok {
if s, ok := generic.ToString(generic.Zero(val.Get())); ok {
return value == s
}
}
return false
}
// UnquoteUsage extracts a back-quoted name from the usage
// string for a flag and returns it and the un-quoted usage.
// Given "a `name` to show" it returns ("name", "a name to show").
// If there are no back quotes, the name is an educated guess of the
// type of the flag's value, or the empty string if the flag is boolean.
func UnquoteUsage(flag *Flag) (name string, usage string) {
// Look for a back-quoted name, but avoid the strings package.
usage = flag.Usage
for i := 0; i < len(usage); i++ {
if usage[i] == '`' {
for j := i + 1; j < len(usage); j++ {
if usage[j] == '`' {
name = usage[i+1 : j]
usage = usage[:i] + name + usage[j+1:]
return name, usage
}
}
break // Only one back quote; use type name.
}
}
// No explicit name, so use type if we can find one.
name = "value"
if v, ok := flag.Value.(Getter); ok {
name = generic.TypeOf(v.Get()).String()
}
if IsBoolValue(flag.Value) {
name = ""
}
return
}
// PrintDefaults prints, to standard error unless configured otherwise, the
// default values of all defined command-line flags in the set. See the
// documentation for the global function PrintDefaults for more information.
func (f *FlagSet) PrintDefaults() {
f.VisitAll(func(flag *Flag) {
s := fmt.Sprintf(" -%s", flag.Name) // Two spaces before -; see next two comments.
name, usage := UnquoteUsage(flag)
if len(name) > 0 {
s += " " + name
}
// Boolean flags of one ASCII letter are so common we
// treat them specially, putting their usage on the same line.
if len(s) <= 4 { // space, space, '-', 'x'.
s += "\t"
} else {
// Four spaces before the tab triggers good alignment
// for both 4- and 8-space tab stops.
s += "\n \t"
}
s += strings.ReplaceAll(usage, "\n", "\n \t")
if !isZeroValue(flag, flag.DefValue) {
if v, ok := flag.Value.(Getter); ok && generic.TypeOf(v.Get()).String() == "string" {
// put quotes on the value
s += fmt.Sprintf(" (default %q)", flag.DefValue)
} else {
s += fmt.Sprintf(" (default %v)", flag.DefValue)
}
}
fmt.Fprint(f.Output(), s, "\n")
})
}
// PrintDefaults prints, to standard error unless configured otherwise,
// a usage message showing the default settings of all defined
// command-line flags.
// For an integer valued flag x, the default output has the form
// -x int
// usage-message-for-x (default 7)
// The usage message will appear on a separate line for anything but
// a bool flag with a one-byte name. For bool flags, the type is
// omitted and if the flag name is one byte the usage message appears
// on the same line. The parenthetical default is omitted if the
// default is the zero value for the type. The listed type, here int,
// can be changed by placing a back-quoted name in the flag's usage
// string; the first such item in the message is taken to be a parameter
// name to show in the message and the back quotes are stripped from
// the message when displayed. For instance, given
// flag.String("I", "", "search `directory` for include files")
// the output will be
// -I directory
// search directory for include files.
//
// To change the destination for flag messages, call CommandLine.SetOutput.
func PrintDefaults() {
CommandLine.PrintDefaults()
}
// defaultUsage is the default function to print a usage message.
func (f *FlagSet) defaultUsage() {
if f.name == "" {
fmt.Fprintf(f.Output(), "Usage:\n")
} else {
fmt.Fprintf(f.Output(), "Usage of %s:\n", f.name)
}
f.PrintDefaults()
}
// NOTE: Usage is not just defaultUsage(CommandLine)
// because it serves (via godoc flag Usage) as the example
// for how to write your own usage function.
// Usage prints a usage message documenting all defined command-line flags
// to CommandLine's output, which by default is os.Stderr.
// It is called when an error occurs while parsing flags.
// The function is a variable that may be changed to point to a custom function.
// By default it prints a simple header and calls PrintDefaults; for details about the
// format of the output and how to control it, see the documentation for PrintDefaults.
// Custom usage functions may choose to exit the program; by default exiting
// happens anyway as the command line's error handling strategy is set to
// ExitOnError.
var Usage = func() {
fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
PrintDefaults()
}
// NFlag returns the number of flags that have been set.
func (f *FlagSet) NFlag() int { return len(f.actual) }
// NFlag returns the number of command-line flags that have been set.
func NFlag() int { return len(CommandLine.actual) }
// Arg returns the i'th argument. Arg(0) is the first remaining argument
// after flags have been processed. Arg returns an empty string if the
// requested element does not exist.
func (f *FlagSet) Arg(i int) string {
if i < 0 || i >= len(f.args) {
return ""
}
return f.args[i]
}
// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument
// after flags have been processed. Arg returns an empty string if the
// requested element does not exist.
func Arg(i int) string {
return CommandLine.Arg(i)
}
// NArg is the number of arguments remaining after flags have been processed.
func (f *FlagSet) NArg() int { return len(f.args) }
// NArg is the number of arguments remaining after flags have been processed.
func NArg() int { return len(CommandLine.args) }
// Args returns the non-flag arguments.
func (f *FlagSet) Args() []string { return f.args }
// Args returns the non-flag command-line arguments.
func Args() []string { return CommandLine.args }
// Var defines a flag with the specified name and usage string. The type and
// value of the flag are represented by the first argument, of type Value, which
// typically holds a user-defined implementation of Value. For instance, the
// caller could create a flag that turns a comma-separated string into a slice
// of strings by giving the slice the methods of Value; in particular, Set would
// decompose the comma-separated string into the slice.
func (f *FlagSet) Var(value Value, name string, usage string) {
// Remember the default value as a string; it won't change.
flag := &Flag{name, usage, value, value.String()}
_, alreadythere := f.formal[name]
if alreadythere {
var msg string
if f.name == "" {
msg = fmt.Sprintf("flag redefined: %s", name)
} else {
msg = fmt.Sprintf("%s flag redefined: %s", f.name, name)
}
fmt.Fprintln(f.Output(), msg)
panic(msg) // Happens only if flags are declared with identical names
}
if f.formal == nil {
f.formal = make(map[string]*Flag)
}
f.formal[name] = flag
}
// Var defines a flag with the specified name and usage string. The type and
// value of the flag are represented by the first argument, of type Value, which
// typically holds a user-defined implementation of Value. For instance, the
// caller could create a flag that turns a comma-separated string into a slice
// of strings by giving the slice the methods of Value; in particular, Set would
// decompose the comma-separated string into the slice.
func Var(value Value, name string, usage string) {
CommandLine.Var(value, name, usage)
}
// failf prints to standard error a formatted error and usage message and
// returns the error.
func (f *FlagSet) failf(format string, a ...interface{}) error {
err := fmt.Errorf(format, a...)
fmt.Fprintln(f.Output(), err)
f.usage()
return err
}
// usage calls the Usage method for the flag set if one is specified,
// or the appropriate default usage function otherwise.
func (f *FlagSet) usage() {
if f.Usage == nil {
f.defaultUsage()
} else {
f.Usage()
}
}
// parseOne parses one flag. It reports whether a flag was seen.
func (f *FlagSet) parseOne() (bool, error) {
if len(f.args) == 0 {
return false, nil
}
s := f.args[0]
if len(s) < 2 || s[0] != '-' {
return false, nil
}
numMinuses := 1
if s[1] == '-' {
numMinuses++
if len(s) == 2 { // "--" terminates the flags
f.args = f.args[1:]
return false, nil
}
}
name := s[numMinuses:]
if len(name) == 0 || name[0] == '-' || name[0] == '=' {
return false, f.failf("bad flag syntax: %s", s)
}
// it's a flag. does it have an argument?
f.args = f.args[1:]
hasValue := false
value := ""
for i := 1; i < len(name); i++ { // equals cannot be first
if name[i] == '=' {
value = name[i+1:]
hasValue = true
name = name[0:i]
break
}
}
m := f.formal
flag, alreadythere := m[name] // BUG
if !alreadythere {
if name == "help" || name == "h" { // special case for nice help message.
f.usage()
return false, ErrHelp
}
return false, f.failf("flag provided but not defined: -%s", name)
}
if IsBoolValue(flag.Value) { // special case: doesn't need an arg
if hasValue {
if err := flag.Value.Set(value); err != nil {
return false, f.failf(invalidValueTemplate, value, name, err)
}
} else {
if err := flag.Value.Set("true"); err != nil {
return false, f.failf("invalid boolean flag %s: %v", name, err)
}
}
} else {
// It must have a value, which might be the next argument.
if !hasValue && len(f.args) > 0 {
// value is the next arg
hasValue = true
value, f.args = f.args[0], f.args[1:]
}
if !hasValue {
return false, f.failf("flag needs an argument: -%s", name)
}
if err := flag.Value.Set(value); err != nil {
return false, f.failf(invalidValueTemplate, value, name, err)
}
}
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[name] = flag
return true, nil
}
// Parse parses flag definitions from the argument list, which should not
// include the command name. Must be called after all flags in the FlagSet
// are defined and before flags are accessed by the program.
// The return value will be ErrHelp if -help or -h were set but not defined.
func (f *FlagSet) Parse(arguments []string) error {
f.parsed = true
f.args = arguments
for {
seen, err := f.parseOne()
if seen {
continue
}
if err == nil {
break
}
switch f.errorHandling {
case ContinueOnError:
return err
case ExitOnError:
if err == ErrHelp {
os.Exit(0)
}
os.Exit(2)
case PanicOnError:
panic(err)
}
}
return nil
}
// Parsed reports whether f.Parse has been called.
func (f *FlagSet) Parsed() bool {
return f.parsed
}
// Parse parses the command-line flags from os.Args[1:]. Must be called
// after all flags are defined and before flags are accessed by the program.
func Parse() {
// Ignore errors; CommandLine is set for ExitOnError.
CommandLine.Parse(os.Args[1:])
}
// Parsed reports whether the command-line flags have been parsed.
func Parsed() bool {
return CommandLine.Parsed()
}
// CommandLine is the default set of command-line flags, parsed from os.Args.
// The top-level functions such as BoolVar, Arg, and so on are wrappers for the
// methods of CommandLine.
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
func init() {
// Override generic FlagSet default Usage with call to global Usage.
// Note: This is not CommandLine.Usage = Usage,
// because we want any eventual call to use any updated value of Usage,
// not the value it has when this line is run.
CommandLine.Usage = commandLineUsage
}
func commandLineUsage() {
Usage()
}
// NewFlagSet returns a new, empty flag set with the specified name and
// error handling property. If the name is not empty, it will be printed
// in the default usage message and in error messages.
func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
f := &FlagSet{
name: name,
errorHandling: errorHandling,
}
f.Usage = f.defaultUsage
return f
}
// Init sets the name and error handling property for a flag set.
// By default, the zero FlagSet uses an empty name and the
// ContinueOnError error handling policy.
func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
f.name = name
f.errorHandling = errorHandling
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,35 +0,0 @@
// 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)
}

View File

@ -1,83 +0,0 @@
// Copyright 2020 Rancher Labs, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package flag
import (
"fmt"
"time"
"github.com/rancher/spur/generic"
)
var _ = time.Time{}
// GenericValue takes a pointer to a generic type
type GenericValue struct {
ptr interface{}
set bool
}
// NewGenericValue returns a flag.Value given a pointer
func NewGenericValue(ptr interface{}) Value {
generic.PtrPanic(ptr)
return &GenericValue{ptr: ptr}
}
// Get returns the contents of the stored pointer
func (v *GenericValue) Get() interface{} {
return generic.ValueOfPtr(v.ptr)
}
// Set will convert a given value to the type of our pointer
// and store the new value
func (v *GenericValue) Set(value interface{}) error {
if generic.IsSlice(v.Get()) && !v.set {
// If this is a slice and has not already been set then
// clear any existing value
generic.Set(v.ptr, generic.Zero(v.Get()))
v.set = true
}
val, err := generic.Convert(v.Get(), value)
if err != nil {
return err
}
generic.Set(v.ptr, val)
return nil
}
// String returns a string representation of our generic value
func (v *GenericValue) String() string {
return generic.Stringify(v.Get())
}
// GenericVar defines a generic flag with specified name, default value, and usage string.
// The argument p points to a generic variable in which to store the value of the flag.
func (f *FlagSet) GenericVar(ptr interface{}, name string, value interface{}, usage string) {
generic.Set(ptr, value)
f.Var(NewGenericValue(ptr), name, usage)
}
// Generic defines a generic flag with specified name, default value, and usage string.
// The return value is the address of a generic variable that stores the value of the flag.
func (f *FlagSet) Generic(name string, value interface{}, usage string) interface{} {
if value == nil {
panic(fmt.Errorf("creating generic from nil interface %s", name))
}
ptr := generic.New(value)
f.GenericVar(ptr, name, value, usage)
return ptr
}
// GenericVar defines a generic flag with specified name, default value, and usage string.
// The argument p points to a generic variable in which to store the value of the flag.
func GenericVar(ptr interface{}, name string, value interface{}, usage string) {
CommandLine.GenericVar(ptr, name, value, usage)
}
// Generic defines a generic flag with specified name, default value, and usage string.
// The return value is the address of a generic variable that stores the value of the flag.
func Generic(name string, value interface{}, usage string) interface{} {
return CommandLine.Generic(name, value, usage)
}

View File

@ -1,32 +0,0 @@
// Copyright 2020 Rancher Labs, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package generic
import (
"errors"
"strconv"
)
// errParse is returned by Set if a flag's value fails to parse, such as with an invalid integer for Int.
// It then gets wrapped through failf to provide more information.
var errParse = errors.New("parse error")
// errRange is returned by Set if a flag's value is out of range.
// It then gets wrapped through failf to provide more information.
var errRange = errors.New("value out of range")
func numError(err error) error {
ne, ok := err.(*strconv.NumError)
if !ok {
return err
}
if ne.Err == strconv.ErrSyntax {
return errParse
}
if ne.Err == strconv.ErrRange {
return errRange
}
return err
}

View File

@ -1,241 +0,0 @@
// Copyright 2020 Rancher Labs, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package generic
import (
"encoding/json"
"fmt"
"reflect"
"time"
"gopkg.in/yaml.v2"
)
// Marshal is the function used for marshaling slices
var Marshal = json.Marshal
// Unmarshal is the function used for un-marshaling slices
var Unmarshal = yaml.Unmarshal
// ToStringFunc is the function definition for converting types to strings
type ToStringFunc = func(interface{}) (string, bool)
// FromStringFunc is the function definition for converting strings to types
type FromStringFunc = func(string) (interface{}, error)
// ToStringMap provides a mapping of type to string conversion function
var ToStringMap = map[string]ToStringFunc{}
// FromStringMap provides a mapping of string to type conversion function
var FromStringMap = map[string]FromStringFunc{}
// TimeLayouts provides a list of layouts to attempt when converting time strings
var TimeLayouts = []string{
time.RFC3339Nano,
time.RFC3339,
time.UnixDate,
time.RubyDate,
time.ANSIC,
time.RFC822,
time.RFC822Z,
time.RFC850,
time.RFC1123,
time.RFC1123Z,
time.StampNano,
time.StampMicro,
time.StampMilli,
time.Stamp,
time.Kitchen,
}
// ToString is a convenience function for converting types to strings as defined in ToStringMap
func ToString(value interface{}) (string, bool) {
if value == nil {
return "", false
}
if toString := ToStringMap[TypeOf(value).String()]; toString != nil {
return toString(value)
}
return "", false
}
// FromString is a convenience function for converting strings to types as defined in FromStringMap
func FromString(value string, ptr interface{}) error {
PtrPanic(ptr)
typ := reflect.TypeOf(ptr).Elem().String()
fromString := FromStringMap[typ]
if fromString == nil {
return errParse
}
val, err := fromString(value)
if err != nil {
return numError(err)
}
Set(ptr, val)
return nil
}
// TypeOf returns the dereferenced value's type
func TypeOf(value interface{}) reflect.Type {
typ := reflect.TypeOf(value)
if typ != nil && typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
return typ
}
// ElemTypeOf returns the dereferenced value's type or TypeOf is not an Elem
func ElemTypeOf(value interface{}) reflect.Type {
typ := TypeOf(value)
if typ.Kind() == reflect.Slice {
return typ.Elem()
}
return typ
}
// New returns a new reflection with TypeOf value
func New(value interface{}) interface{} {
return reflect.New(TypeOf(value)).Interface()
}
// NewElem returns a new reflection with ElemTypeOf value
func NewElem(value interface{}) interface{} {
return reflect.New(ElemTypeOf(value)).Interface()
}
// Zero returns a zero reflection with TypeOf value
func Zero(value interface{}) interface{} {
return reflect.Zero(TypeOf(value)).Interface()
}
// IsSlice return true if the TypeOf value is a slice
func IsSlice(value interface{}) bool {
if value == nil {
return false
}
return TypeOf(value).Kind() == reflect.Slice
}
// PtrPanic halts execution if the passed ptr is not a pointer
func PtrPanic(ptr interface{}) {
if !IsPtr(ptr) {
panic(fmt.Errorf("expected pointer type, got %s", reflect.TypeOf(ptr).String()))
}
}
// Set will assign the contents of ptr to value
func Set(ptr interface{}, value interface{}) {
PtrPanic(ptr)
if value == nil {
return
}
reflect.ValueOf(ptr).Elem().Set(reflect.ValueOf(value))
}
// Len returns the length of a slice, or -1 if not a slice
func Len(value interface{}) int {
if !IsSlice(value) {
return -1
}
return reflect.ValueOf(value).Len()
}
// Index will return the value of a slice at a given index
func Index(value interface{}, i int) interface{} {
if !IsSlice(value) {
return nil
}
return reflect.ValueOf(value).Index(i).Interface()
}
// Append will append an element onto a generic slice
func Append(slice interface{}, elem interface{}) interface{} {
return reflect.Append(reflect.ValueOf(slice), reflect.ValueOf(elem)).Interface()
}
// IsPtr returns true if the given value is of kind reflect.Ptr
func IsPtr(value interface{}) bool {
if value == nil {
return false
}
return reflect.TypeOf(value).Kind() == reflect.Ptr
}
// ValueOfPtr returns the contents of a pointer, or the given value if not a pointer
func ValueOfPtr(value interface{}) interface{} {
if !IsPtr(value) {
return value
}
elem := reflect.ValueOf(value).Elem()
if !elem.IsValid() {
return nil
}
return elem.Interface()
}
// Convert will return a new result of type src, where value is converted to the type
// of src or appended if src is a slice and value is an element
func Convert(src interface{}, value interface{}) (interface{}, error) {
// Convert an element
elem, err := ConvertElem(src, value)
if !IsSlice(src) {
// Return value and error if not a slice
return elem, err
}
// Try deserializing as string
if s, ok := value.(string); ok {
val := New(src)
if err := Unmarshal([]byte(s), val); err == nil {
return ValueOfPtr(val), nil
}
}
// If no error from converting element return appended value
if err == nil {
return Append(src, elem), nil
}
// Try evaluating value as a slice of interfaces
otherValue, ok := value.([]interface{})
if !ok {
return nil, errParse
}
// Create a new slice and append each converted element
slice := Zero(src)
for _, other := range otherValue {
elem, err := ConvertElem(src, other)
if err != nil {
return nil, err
}
slice = Append(slice, elem)
}
return slice, nil
}
// ConvertElem will return a new result, where value is converted to the type
// of src or returned as an element if src is a slice
func ConvertElem(src interface{}, value interface{}) (interface{}, error) {
// Get our value as a string
s, ok := value.(string)
if !ok {
if s, ok = ToString(value); !ok {
return nil, errParse
}
}
// Return a new value from the string
ptr := NewElem(src)
err := FromString(s, ptr)
return ValueOfPtr(ptr), err
}
// Stringify returns the ToString version of the value, or the Marshaled version
// in the case of slices, otherwise panic if cannot be converted to string
func Stringify(value interface{}) string {
if s, ok := ToString(value); ok {
return s
}
if b, err := Marshal(value); err == nil {
return string(b)
}
panic(errParse)
}

View File

@ -1,57 +0,0 @@
// Copyright 2020 Rancher Labs, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package generic
import (
"strconv"
"time"
)
func init() {
FromStringMap["string"] = func(s string) (interface{}, error) {
return s, nil
}
FromStringMap["bool"] = func(s string) (interface{}, error) {
if s == "" {
s = "false"
}
v, err := strconv.ParseBool(s)
return bool(v), err
}
FromStringMap["int"] = func(s string) (interface{}, error) {
v, err := strconv.ParseInt(s, 0, strconv.IntSize)
return int(v), err
}
FromStringMap["int64"] = func(s string) (interface{}, error) {
v, err := strconv.ParseInt(s, 0, 64)
return int64(v), err
}
FromStringMap["uint"] = func(s string) (interface{}, error) {
v, err := strconv.ParseUint(s, 0, strconv.IntSize)
return uint(v), err
}
FromStringMap["uint64"] = func(s string) (interface{}, error) {
v, err := strconv.ParseUint(s, 0, 64)
return uint64(v), err
}
FromStringMap["float64"] = func(s string) (interface{}, error) {
v, err := strconv.ParseFloat(s, 64)
return float64(v), err
}
FromStringMap["time.Duration"] = func(s string) (interface{}, error) {
if v, err := time.ParseDuration(s); err == nil {
return time.Duration(v), nil
}
return nil, errParse
}
FromStringMap["time.Time"] = func(s string) (interface{}, error) {
for _, layout := range TimeLayouts {
if v, err := time.Parse(layout, s); err == nil {
return time.Time(v), nil
}
}
return nil, errParse
}
}

View File

@ -1,43 +0,0 @@
// Copyright 2020 Rancher Labs, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package generic
import (
"strconv"
"time"
)
func init() {
ToStringMap["string"] = func(value interface{}) (string, bool) {
return value.(string), true
}
ToStringMap["bool"] = func(value interface{}) (string, bool) {
return strconv.FormatBool(value.(bool)), true
}
ToStringMap["int"] = func(value interface{}) (string, bool) {
return strconv.Itoa(value.(int)), true
}
ToStringMap["int64"] = func(value interface{}) (string, bool) {
return strconv.FormatInt(value.(int64), 10), true
}
ToStringMap["uint"] = func(value interface{}) (string, bool) {
return strconv.FormatUint(uint64(value.(uint)), 10), true
}
ToStringMap["uint64"] = func(value interface{}) (string, bool) {
return strconv.FormatUint(value.(uint64), 10), true
}
ToStringMap["float64"] = func(value interface{}) (string, bool) {
return strconv.FormatFloat(value.(float64), 'g', -1, 64), true
}
ToStringMap["time.Duration"] = func(value interface{}) (string, bool) {
return value.(time.Duration).String(), true
}
ToStringMap["time.Time"] = func(value interface{}) (string, bool) {
if len(TimeLayouts) > 0 {
return value.(time.Time).Format(TimeLayouts[0]), true
}
return "", false
}
}

1
vendor/gopkg.in/yaml.v2/apic.go generated vendored
View File

@ -86,7 +86,6 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) {
raw_buffer: make([]byte, 0, output_raw_buffer_size),
states: make([]yaml_emitter_state_t, 0, initial_stack_size),
events: make([]yaml_event_t, 0, initial_queue_size),
best_width: -1,
}
}

9
vendor/modules.txt vendored
View File

@ -400,7 +400,7 @@ github.com/coreos/go-systemd/v22/daemon
github.com/coreos/go-systemd/v22/dbus
# github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f
github.com/coreos/pkg/capnslog
# github.com/cpuguy83/go-md2man/v2 v2.0.0
# github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d
github.com/cpuguy83/go-md2man/v2/md2man
# github.com/cyphar/filepath-securejoin v0.2.2
github.com/cyphar/filepath-securejoin
@ -820,11 +820,6 @@ github.com/rancher/kine/pkg/server
github.com/rancher/kine/pkg/tls
# github.com/rancher/remotedialer v0.2.0
github.com/rancher/remotedialer
# github.com/rancher/spur v0.0.0-20200617165101-8702c8e4ce7a
github.com/rancher/spur/cli
github.com/rancher/spur/cli/altsrc
github.com/rancher/spur/flag
github.com/rancher/spur/generic
# github.com/rancher/wrangler v0.6.1
github.com/rancher/wrangler/pkg/apply
github.com/rancher/wrangler/pkg/apply/injectors
@ -1292,7 +1287,7 @@ gopkg.in/square/go-jose.v2/json
gopkg.in/square/go-jose.v2/jwt
# gopkg.in/warnings.v0 v0.1.1
gopkg.in/warnings.v0
# gopkg.in/yaml.v2 v2.3.0
# gopkg.in/yaml.v2 v2.2.8
gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
gopkg.in/yaml.v3