Merge branch 'master-v3' into master-v3
This commit is contained in:
commit
3548642cb3
@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.13 as builder
|
FROM golang:1.14 as builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN make build && bin/k3d version
|
RUN make build && bin/k3d version
|
||||||
|
|||||||
@ -25,6 +25,7 @@ package create
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
@ -50,8 +51,17 @@ func NewCmdCreateCluster() *cobra.Command {
|
|||||||
Long: `Create a new k3s cluster with containerized nodes (k3s in docker).`,
|
Long: `Create a new k3s cluster with containerized nodes (k3s in docker).`,
|
||||||
Args: cobra.RangeArgs(0, 1), // exactly one cluster name can be set (default: k3d.DefaultClusterName)
|
Args: cobra.RangeArgs(0, 1), // exactly one cluster name can be set (default: k3d.DefaultClusterName)
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
// parse args and flags
|
||||||
cluster := parseCreateClusterCmd(cmd, args, createClusterOpts)
|
cluster := parseCreateClusterCmd(cmd, args, createClusterOpts)
|
||||||
if err := k3dCluster.CreateCluster(cluster, runtimes.SelectedRuntime); err != nil {
|
|
||||||
|
// check if a cluster with that name exists already
|
||||||
|
if _, err := k3dCluster.GetCluster(cluster, runtimes.SelectedRuntime); err == nil {
|
||||||
|
log.Fatalf("Failed to create cluster '%s' because a cluster with that name already exists", cluster.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// create cluster
|
||||||
|
if err := k3dCluster.CreateCluster(cmd.Context(), cluster, runtimes.SelectedRuntime); err != nil {
|
||||||
|
// rollback if creation failed
|
||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
log.Errorln("Failed to create cluster >>> Rolling Back")
|
log.Errorln("Failed to create cluster >>> Rolling Back")
|
||||||
if err := k3dCluster.DeleteCluster(cluster, runtimes.SelectedRuntime); err != nil {
|
if err := k3dCluster.DeleteCluster(cluster, runtimes.SelectedRuntime); err != nil {
|
||||||
@ -60,6 +70,8 @@ func NewCmdCreateCluster() *cobra.Command {
|
|||||||
}
|
}
|
||||||
log.Fatalln("Cluster creation FAILED, all changes have been rolled back!")
|
log.Fatalln("Cluster creation FAILED, all changes have been rolled back!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// print information on how to use the cluster with kubectl
|
||||||
log.Infof("Cluster '%s' created successfully. You can now use it like this:", cluster.Name)
|
log.Infof("Cluster '%s' created successfully. You can now use it like this:", cluster.Name)
|
||||||
fmt.Printf("export KUBECONFIG=$(%s get kubeconfig %s)\n", os.Args[0], cluster.Name)
|
fmt.Printf("export KUBECONFIG=$(%s get kubeconfig %s)\n", os.Args[0], cluster.Name)
|
||||||
fmt.Println("kubectl cluster-info")
|
fmt.Println("kubectl cluster-info")
|
||||||
@ -69,7 +81,7 @@ func NewCmdCreateCluster() *cobra.Command {
|
|||||||
/*********
|
/*********
|
||||||
* Flags *
|
* Flags *
|
||||||
*********/
|
*********/
|
||||||
cmd.Flags().StringArrayP("api-port", "a", []string{"6443"}, "Specify the Kubernetes API server port (Format: `--api-port [HOST:]HOSTPORT[@NODEFILTER]`\n - Example: `k3d create -m 3 -a 0.0.0.0:6550@master[0] -a 0.0.0.0:6551@master[1]` ")
|
cmd.Flags().StringP("api-port", "a", k3d.DefaultAPIPort, "Specify the Kubernetes API server port (Format: `--api-port [HOST:]HOSTPORT`\n - Example: `k3d create -m 3 -a 0.0.0.0:6550` ")
|
||||||
cmd.Flags().IntP("masters", "m", 1, "Specify how many masters you want to create")
|
cmd.Flags().IntP("masters", "m", 1, "Specify how many masters you want to create")
|
||||||
cmd.Flags().IntP("workers", "w", 0, "Specify how many workers you want to create")
|
cmd.Flags().IntP("workers", "w", 0, "Specify how many workers you want to create")
|
||||||
cmd.Flags().String("image", fmt.Sprintf("%s:%s", k3d.DefaultK3sImageRepo, version.GetK3sVersion(false)), "Specify k3s image that you want to use for the nodes")
|
cmd.Flags().String("image", fmt.Sprintf("%s:%s", k3d.DefaultK3sImageRepo, version.GetK3sVersion(false)), "Specify k3s image that you want to use for the nodes")
|
||||||
@ -77,16 +89,13 @@ func NewCmdCreateCluster() *cobra.Command {
|
|||||||
cmd.Flags().String("secret", "", "Specify a cluster secret. By default, we generate one.")
|
cmd.Flags().String("secret", "", "Specify a cluster secret. By default, we generate one.")
|
||||||
cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `--volume [SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d create -w 2 -v /my/path@worker[0,1] -v /tmp/test:/tmp/other@master[0]`")
|
cmd.Flags().StringArrayP("volume", "v", nil, "Mount volumes into the nodes (Format: `--volume [SOURCE:]DEST[@NODEFILTER[;NODEFILTER...]]`\n - Example: `k3d create -w 2 -v /my/path@worker[0,1] -v /tmp/test:/tmp/other@master[0]`")
|
||||||
cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d create -w 2 -p 8080:80@worker[0] -p 8081@worker[1]`")
|
cmd.Flags().StringArrayP("port", "p", nil, "Map ports from the node containers to the host (Format: `[HOST:][HOSTPORT:]CONTAINERPORT[/PROTOCOL][@NODEFILTER]`)\n - Example: `k3d create -w 2 -p 8080:80@worker[0] -p 8081@worker[1]`")
|
||||||
cmd.Flags().IntVar(&createClusterOpts.WaitForMaster, "wait", -1, "Wait for a specified amount of time (seconds >= 0, where 0 means forever) for the master(s) to be ready or timeout and rollback before returning")
|
cmd.Flags().BoolVar(&createClusterOpts.WaitForMaster, "wait", false, "Wait for for the master(s) to be ready before returning. Use `--timeout DURATION` to not wait forever.")
|
||||||
|
cmd.Flags().DurationVar(&createClusterOpts.Timeout, "timeout", 0*time.Second, "Rollback changes if cluster couldn't be created in specified duration.")
|
||||||
|
|
||||||
/* Image Importing */
|
/* Image Importing */
|
||||||
cmd.Flags().BoolVar(&createClusterOpts.DisableImageVolume, "no-image-volume", false, "Disable the creation of a volume for importing images")
|
cmd.Flags().BoolVar(&createClusterOpts.DisableImageVolume, "no-image-volume", false, "Disable the creation of a volume for importing images")
|
||||||
|
|
||||||
/* Multi Master Configuration */
|
/* Multi Master Configuration */
|
||||||
// multi-master - general
|
|
||||||
// TODO: implement load-balancer/proxy for multi-master setups
|
|
||||||
cmd.Flags().BoolVar(&createClusterOpts.DisableLoadbalancer, "no-lb", false, "[WIP] Disable automatic deployment of a load balancer in Multi-Master setups")
|
|
||||||
cmd.Flags().String("lb-port", "0.0.0.0:6443", "[WIP] Specify port to be exposed by the master load balancer (Format: `[HOST:]HOSTPORT)")
|
|
||||||
|
|
||||||
// multi-master - datastore
|
// multi-master - datastore
|
||||||
// TODO: implement multi-master setups with external data store
|
// TODO: implement multi-master setups with external data store
|
||||||
@ -161,6 +170,9 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string, createClusterOpts
|
|||||||
network.Name = networkName
|
network.Name = networkName
|
||||||
network.External = true
|
network.External = true
|
||||||
}
|
}
|
||||||
|
if networkName == "host" && (masterCount+workerCount) > 1 {
|
||||||
|
log.Fatalln("Can only run a single node in hostnetwork mode")
|
||||||
|
}
|
||||||
|
|
||||||
// --secret
|
// --secret
|
||||||
secret, err := cmd.Flags().GetString("secret")
|
secret, err := cmd.Flags().GetString("secret")
|
||||||
@ -168,70 +180,27 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string, createClusterOpts
|
|||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --wait
|
// --timeout
|
||||||
if cmd.Flags().Changed("wait") && createClusterOpts.WaitForMaster < 0 {
|
if cmd.Flags().Changed("timeout") && createClusterOpts.Timeout <= 0*time.Second {
|
||||||
log.Fatalln("Value of '--wait' can't be less than 0")
|
log.Fatalln("--timeout DURATION must be >= 1s")
|
||||||
}
|
}
|
||||||
|
|
||||||
// --api-port
|
// --api-port
|
||||||
apiPortFlags, err := cmd.Flags().GetStringArray("api-port")
|
apiPort, err := cmd.Flags().GetString("api-port")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// error out if we have more api-ports than masters specified
|
|
||||||
if len(apiPortFlags) > masterCount {
|
|
||||||
log.Fatalf("Cannot expose more api-ports than master nodes exist (%d > %d)", len(apiPortFlags), masterCount)
|
|
||||||
}
|
|
||||||
|
|
||||||
ipPortCombinations := map[string]struct{}{} // only for finding duplicates
|
|
||||||
apiPortFilters := map[string]struct{}{} // only for deduplication
|
|
||||||
exposeAPIToFiltersMap := map[k3d.ExposeAPI][]string{}
|
|
||||||
for _, apiPortFlag := range apiPortFlags {
|
|
||||||
|
|
||||||
// split the flag value from the node filter
|
|
||||||
apiPortString, filters, err := cliutil.SplitFiltersFromFlag(apiPortFlag)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's only one master node, we don't need a node filter, but if there's more than one, we need exactly one node filter per api-port flag
|
|
||||||
if len(filters) > 1 || (len(filters) == 0 && masterCount > 1) {
|
|
||||||
log.Fatalf("Exactly one node filter required per '--api-port' flag, but got %d on flag %s", len(filters), apiPortFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// add default, if no filter was set and we only have a single master node
|
|
||||||
if len(filters) == 0 && masterCount == 1 {
|
|
||||||
filters = []string{"master[0]"}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only one api-port mapping allowed per master node
|
|
||||||
if _, exists := apiPortFilters[filters[0]]; exists {
|
|
||||||
log.Fatalf("Cannot assign multiple api-port mappings to the same node: duplicate '%s'", filters[0])
|
|
||||||
}
|
|
||||||
apiPortFilters[filters[0]] = struct{}{}
|
|
||||||
|
|
||||||
// parse the port mapping
|
// parse the port mapping
|
||||||
exposeAPI, err := cliutil.ParseAPIPort(apiPortString)
|
exposeAPI, err := cliutil.ParseAPIPort(apiPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
|
if exposeAPI.Host == "" {
|
||||||
// error out on duplicates
|
exposeAPI.Host = k3d.DefaultAPIHost
|
||||||
ipPort := fmt.Sprintf("%s:%s", exposeAPI.HostIP, exposeAPI.Port)
|
|
||||||
if _, exists := ipPortCombinations[ipPort]; exists {
|
|
||||||
log.Fatalf("Duplicate IP:PORT combination '%s' for the Api Port is not allowed", ipPort)
|
|
||||||
}
|
}
|
||||||
ipPortCombinations[ipPort] = struct{}{}
|
if exposeAPI.HostIP == "" {
|
||||||
|
exposeAPI.HostIP = k3d.DefaultAPIHost
|
||||||
// add to map
|
|
||||||
exposeAPIToFiltersMap[exposeAPI] = filters
|
|
||||||
}
|
|
||||||
|
|
||||||
// --lb-port
|
|
||||||
lbPort, err := cmd.Flags().GetString("lb-port")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --datastore-endpoint
|
// --datastore-endpoint
|
||||||
@ -319,6 +288,7 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string, createClusterOpts
|
|||||||
Network: network,
|
Network: network,
|
||||||
Secret: secret,
|
Secret: secret,
|
||||||
CreateClusterOpts: createClusterOpts,
|
CreateClusterOpts: createClusterOpts,
|
||||||
|
ExposeAPI: exposeAPI,
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate list of nodes
|
// generate list of nodes
|
||||||
@ -336,7 +306,7 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string, createClusterOpts
|
|||||||
MasterOpts: k3d.MasterOpts{},
|
MasterOpts: k3d.MasterOpts{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: by default, we don't expose an API port, even if we only have a single master: should we change that?
|
// TODO: by default, we don't expose an API port: should we change that?
|
||||||
// -> if we want to change that, simply add the exposeAPI struct here
|
// -> if we want to change that, simply add the exposeAPI struct here
|
||||||
|
|
||||||
// first master node will be init node if we have more than one master specified but no external datastore
|
// first master node will be init node if we have more than one master specified but no external datastore
|
||||||
@ -363,20 +333,6 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string, createClusterOpts
|
|||||||
cluster.Nodes = append(cluster.Nodes, &node)
|
cluster.Nodes = append(cluster.Nodes, &node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// add masterOpts
|
|
||||||
for exposeAPI, filters := range exposeAPIToFiltersMap {
|
|
||||||
nodes, err := cliutil.FilterNodes(cluster.Nodes, filters)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln(err)
|
|
||||||
}
|
|
||||||
for _, node := range nodes {
|
|
||||||
if node.Role != k3d.MasterRole {
|
|
||||||
log.Fatalf("Node returned by filters '%+v' for exposing the API is not a master node", filters)
|
|
||||||
}
|
|
||||||
node.MasterOpts.ExposeAPI = exposeAPI
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// append volumes
|
// append volumes
|
||||||
for volume, filters := range volumeFilterMap {
|
for volume, filters := range volumeFilterMap {
|
||||||
nodes, err := cliutil.FilterNodes(cluster.Nodes, filters)
|
nodes, err := cliutil.FilterNodes(cluster.Nodes, filters)
|
||||||
@ -405,15 +361,7 @@ func parseCreateClusterCmd(cmd *cobra.Command, args []string, createClusterOpts
|
|||||||
/**********************
|
/**********************
|
||||||
* Utility Containers *
|
* Utility Containers *
|
||||||
**********************/
|
**********************/
|
||||||
|
// ...
|
||||||
// TODO: create load balancer and other util containers // TODO: for now, this will only work with the docker provider (?) -> can replace dynamic docker lookup with static traefik config (?)
|
|
||||||
if masterCount > 1 && !createClusterOpts.DisableLoadbalancer { // TODO: add traefik to the same network and add traefik labels to the master node containers
|
|
||||||
log.Debugln("Creating LB in front of master nodes")
|
|
||||||
cluster.MasterLoadBalancer = &k3d.ClusterLoadbalancer{
|
|
||||||
Image: k3d.DefaultLBImage,
|
|
||||||
ExposedPort: lbPort,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return cluster
|
return cluster
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,7 @@ func NewCmdCreateNode() *cobra.Command {
|
|||||||
// add flags
|
// add flags
|
||||||
cmd.Flags().Int("replicas", 1, "Number of replicas of this node specification.")
|
cmd.Flags().Int("replicas", 1, "Number of replicas of this node specification.")
|
||||||
cmd.Flags().String("role", string(k3d.WorkerRole), "Specify node role [master, worker]")
|
cmd.Flags().String("role", string(k3d.WorkerRole), "Specify node role [master, worker]")
|
||||||
cmd.Flags().StringP("cluster", "c", "", "[REQUIRED] Select the cluster that the node shall connect to.")
|
cmd.Flags().StringP("cluster", "c", k3d.DefaultClusterName, "Select the cluster that the node shall connect to.")
|
||||||
if err := cmd.MarkFlagRequired("cluster"); err != nil {
|
if err := cmd.MarkFlagRequired("cluster"); err != nil {
|
||||||
log.Fatalln("Failed to mark required flag '--cluster'")
|
log.Fatalln("Failed to mark required flag '--cluster'")
|
||||||
}
|
}
|
||||||
@ -78,6 +78,7 @@ func parseCreateNodeCmd(cmd *cobra.Command, args []string) ([]*k3d.Node, *k3d.Cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --role
|
// --role
|
||||||
|
// TODO: createNode: for --role=master, update the nginx config and add TLS-SAN and server connection, etc.
|
||||||
roleStr, err := cmd.Flags().GetString("role")
|
roleStr, err := cmd.Flags().GetString("role")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("No node role specified")
|
log.Errorln("No node role specified")
|
||||||
|
|||||||
@ -91,7 +91,7 @@ func parseGetClusterCmd(cmd *cobra.Command, args []string) (*k3d.Cluster, bool)
|
|||||||
return nil, headersOff
|
return nil, headersOff
|
||||||
}
|
}
|
||||||
|
|
||||||
cluster := &k3d.Cluster{Name: args[0]} // TODO: validate name first?
|
cluster := &k3d.Cluster{Name: args[0]}
|
||||||
|
|
||||||
return cluster, headersOff
|
return cluster, headersOff
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ func printClusters(clusters []*k3d.Cluster, headersOff bool) {
|
|||||||
defer tabwriter.Flush()
|
defer tabwriter.Flush()
|
||||||
|
|
||||||
if !headersOff {
|
if !headersOff {
|
||||||
headers := []string{"NAME", "MASTERS", "WORKERS"} // TODO: add status
|
headers := []string{"NAME", "MASTERS", "WORKERS"} // TODO: getCluster: add status column
|
||||||
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t"))
|
_, err := fmt.Fprintf(tabwriter, "%s\n", strings.Join(headers, "\t"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("Failed to print headers")
|
log.Fatalln("Failed to print headers")
|
||||||
|
|||||||
@ -37,7 +37,7 @@ func NewCmdGetKubeconfig() *cobra.Command {
|
|||||||
|
|
||||||
// create new command
|
// create new command
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "kubeconfig NAME", // TODO: enable putting more than one name or even --all
|
Use: "kubeconfig NAME", // TODO: getKubeconfig: allow more than one cluster name or even --all
|
||||||
Short: "Get kubeconfig",
|
Short: "Get kubeconfig",
|
||||||
Long: `Get kubeconfig.`,
|
Long: `Get kubeconfig.`,
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
@ -61,7 +61,7 @@ func NewCmdGetKubeconfig() *cobra.Command {
|
|||||||
if err := cmd.MarkFlagFilename("output"); err != nil {
|
if err := cmd.MarkFlagFilename("output"); err != nil {
|
||||||
log.Fatalln("Failed to mark flag --output as filename")
|
log.Fatalln("Failed to mark flag --output as filename")
|
||||||
}
|
}
|
||||||
// cmd.Flags().BoolP("all", "a", false, "Get kubeconfigs from all existing clusters") // TODO:
|
// cmd.Flags().BoolP("all", "a", false, "Get kubeconfigs from all existing clusters") // TODO: getKubeconfig: enable --all flag
|
||||||
|
|
||||||
// done
|
// done
|
||||||
return cmd
|
return cmd
|
||||||
@ -75,5 +75,5 @@ func parseGetKubeconfigCmd(cmd *cobra.Command, args []string) (*k3d.Cluster, str
|
|||||||
log.Fatalln("No output specified")
|
log.Fatalln("No output specified")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &k3d.Cluster{Name: args[0]}, output // TODO: validate first
|
return &k3d.Cluster{Name: args[0]}, output
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,7 +41,7 @@ func NewCmdGetNode() *cobra.Command {
|
|||||||
|
|
||||||
// create new command
|
// create new command
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "node", // TODO: set one or more names or --all flag
|
Use: "node NAME", // TODO: getNode: allow one or more names or --all flag
|
||||||
Short: "Get node",
|
Short: "Get node",
|
||||||
Aliases: []string{"nodes"},
|
Aliases: []string{"nodes"},
|
||||||
Long: `Get node.`,
|
Long: `Get node.`,
|
||||||
|
|||||||
@ -77,7 +77,7 @@ func parseLoadImageCmd(cmd *cobra.Command, args []string) ([]string, []k3d.Clust
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
}
|
}
|
||||||
if cmd.Flags().Changed("tar") { // TODO: implement import from local tarball
|
if cmd.Flags().Changed("tar") { // TODO: loadImage: implement import from local tarball
|
||||||
log.Fatalf("--tar flag not supported yet '%s'", localTarball)
|
log.Fatalf("--tar flag not supported yet '%s'", localTarball)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -161,7 +161,7 @@ func NewCmdCompletion() *cobra.Command {
|
|||||||
Use: "completion SHELL",
|
Use: "completion SHELL",
|
||||||
Short: "Generate completion scripts for [bash, zsh, powershell | psh]",
|
Short: "Generate completion scripts for [bash, zsh, powershell | psh]",
|
||||||
Long: `Generate completion scripts for [bash, zsh, powershell | psh]`,
|
Long: `Generate completion scripts for [bash, zsh, powershell | psh]`,
|
||||||
Args: cobra.ExactArgs(1), // TODO: add support for 0 args = auto detection
|
Args: cobra.ExactArgs(1), // TODO: NewCmdCompletion: add support for 0 args = auto detection
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if f, ok := completionFunctions[args[0]]; ok {
|
if f, ok := completionFunctions[args[0]]; ok {
|
||||||
if err := f(os.Stdout); err != nil {
|
if err := f(os.Stdout); err != nil {
|
||||||
|
|||||||
@ -34,7 +34,7 @@ func NewCmdStartNode() *cobra.Command {
|
|||||||
|
|
||||||
// create new command
|
// create new command
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "node NAME", // TODO: allow one or more names or --all
|
Use: "node NAME", // TODO: startNode: allow one or more names or --all
|
||||||
Short: "Start an existing k3d node",
|
Short: "Start an existing k3d node",
|
||||||
Long: `Start an existing k3d node.`,
|
Long: `Start an existing k3d node.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -52,10 +52,10 @@ func NewCmdStartNode() *cobra.Command {
|
|||||||
|
|
||||||
// parseStartNodeCmd parses the command input into variables required to start a node
|
// parseStartNodeCmd parses the command input into variables required to start a node
|
||||||
func parseStartNodeCmd(cmd *cobra.Command, args []string) *k3d.Node {
|
func parseStartNodeCmd(cmd *cobra.Command, args []string) *k3d.Node {
|
||||||
// node name // TODO: allow node filters, e.g. `k3d start nodes mycluster@worker` to start all worker nodes of cluster 'mycluster'
|
// node name // TODO: startNode: allow node filters, e.g. `k3d start nodes mycluster@worker` to start all worker nodes of cluster 'mycluster'
|
||||||
if len(args) == 0 || len(args[0]) == 0 {
|
if len(args) == 0 || len(args[0]) == 0 {
|
||||||
log.Fatalln("No node name given")
|
log.Fatalln("No node name given")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &k3d.Node{Name: args[0]} // TODO: validate and allow for more than one
|
return &k3d.Node{Name: args[0]}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ func NewCmdStopNode() *cobra.Command {
|
|||||||
|
|
||||||
// create new command
|
// create new command
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "node NAME", // TODO: allow one or more names or --all",
|
Use: "node NAME", // TODO: stopNode: allow one or more names or --all",
|
||||||
Short: "Stop an existing k3d node",
|
Short: "Stop an existing k3d node",
|
||||||
Long: `Stop an existing k3d node.`,
|
Long: `Stop an existing k3d node.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -58,5 +58,5 @@ func parseStopNodeCmd(cmd *cobra.Command, args []string) *k3d.Node {
|
|||||||
log.Fatalln("No node name given")
|
log.Fatalln("No node name given")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &k3d.Node{Name: args[0]} // TODO: validate and allow for more than one
|
return &k3d.Node{Name: args[0]}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,7 @@ func FilterNodes(nodes []*k3d.Node, filters []string) ([]*k3d.Node, error) {
|
|||||||
|
|
||||||
// if one of the filters is 'all', we only return this and drop all others
|
// if one of the filters is 'all', we only return this and drop all others
|
||||||
if submatches["group"] == "all" {
|
if submatches["group"] == "all" {
|
||||||
// TODO: only log if really more than one is specified
|
// TODO: filterNodes: only log if really more than one is specified
|
||||||
log.Warnf("Node filter 'all' set, but more were specified in '%+v'", filters)
|
log.Warnf("Node filter 'all' set, but more were specified in '%+v'", filters)
|
||||||
return nodes, nil
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,5 +70,5 @@ func ParseAPIPort(portString string) (k3d.ExposeAPI, error) {
|
|||||||
|
|
||||||
// ValidatePortMap validates a port mapping
|
// ValidatePortMap validates a port mapping
|
||||||
func ValidatePortMap(portmap string) (string, error) {
|
func ValidatePortMap(portmap string) (string, error) {
|
||||||
return portmap, nil // TODO: add validation of port mapping
|
return portmap, nil // TODO: ValidatePortMap: add validation of port mapping
|
||||||
}
|
}
|
||||||
|
|||||||
5
go.mod
5
go.mod
@ -18,7 +18,6 @@ require (
|
|||||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
|
||||||
github.com/go-test/deep v1.0.4
|
github.com/go-test/deep v1.0.4
|
||||||
github.com/gogo/googleapis v1.3.0 // indirect
|
github.com/gogo/googleapis v1.3.0 // indirect
|
||||||
github.com/golang/protobuf v1.3.1 // indirect
|
|
||||||
github.com/google/go-cmp v0.3.0 // indirect
|
github.com/google/go-cmp v0.3.0 // indirect
|
||||||
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5
|
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5
|
||||||
github.com/imdario/mergo v0.3.7 // indirect
|
github.com/imdario/mergo v0.3.7 // indirect
|
||||||
@ -30,12 +29,14 @@ require (
|
|||||||
github.com/opencontainers/runtime-spec v1.0.1 // indirect
|
github.com/opencontainers/runtime-spec v1.0.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.5.0
|
github.com/sirupsen/logrus v1.5.0
|
||||||
github.com/spf13/cobra v0.0.5
|
github.com/spf13/cobra v0.0.5
|
||||||
|
github.com/spf13/cobra v1.0.0
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 // indirect
|
||||||
go.etcd.io/bbolt v1.3.3 // indirect
|
go.etcd.io/bbolt v1.3.3 // indirect
|
||||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc // indirect
|
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc // indirect
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||||
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 // indirect
|
golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 // indirect
|
||||||
golang.org/x/text v0.3.2 // indirect
|
golang.org/x/text v0.3.2 // indirect
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
|
||||||
google.golang.org/grpc v1.23.0 // indirect
|
google.golang.org/grpc v1.23.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
gotest.tools v2.2.0+incompatible // indirect
|
gotest.tools v2.2.0+incompatible // indirect
|
||||||
|
|||||||
82
go.sum
82
go.sum
@ -10,18 +10,24 @@ github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+q
|
|||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
|
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
|
||||||
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
|
||||||
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o=
|
github.com/OpenPeeDeeP/depguard v1.0.0/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o=
|
||||||
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
|
||||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0=
|
||||||
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||||
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8=
|
||||||
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50=
|
||||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||||
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/containerd/cgroups v0.0.0-20190923161937-abd0b19954a6 h1:jHSIafTFvTm7oBNnA8ZOzfmYylo9J3YzJHKOfUkeL94=
|
github.com/containerd/cgroups v0.0.0-20190923161937-abd0b19954a6 h1:jHSIafTFvTm7oBNnA8ZOzfmYylo9J3YzJHKOfUkeL94=
|
||||||
github.com/containerd/cgroups v0.0.0-20190923161937-abd0b19954a6/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
github.com/containerd/cgroups v0.0.0-20190923161937-abd0b19954a6/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
|
||||||
@ -35,18 +41,21 @@ github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8 h1:jYCTS/16RWXXtV
|
|||||||
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||||
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd h1:bRLyitWw3PT/2YuVaCKTPg0cA5dOFKFwKtkfcP2dLsA=
|
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd h1:bRLyitWw3PT/2YuVaCKTPg0cA5dOFKFwKtkfcP2dLsA=
|
||||||
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
|
github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk=
|
||||||
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
|
github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0=
|
||||||
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/docker/distribution v0.0.0-20171011171712-7484e51bf6af/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
github.com/docker/distribution v0.0.0-20171011171712-7484e51bf6af/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c h1:6L6qod4JzOm9KEqmfSyO6ZhsnN9dlcISRt+xdoyZeGE=
|
github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c h1:6L6qod4JzOm9KEqmfSyO6ZhsnN9dlcISRt+xdoyZeGE=
|
||||||
@ -68,10 +77,15 @@ github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
|
|||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
|
github.com/go-critic/go-critic v0.3.5-0.20190526074819-1df300866540/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
|
||||||
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
|
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
|
||||||
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
|
||||||
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
|
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
|
||||||
@ -98,6 +112,7 @@ github.com/gogo/protobuf v1.3.0 h1:G8O7TerXerS4F6sx9OV7/nRfJdnXgHZu/S/7F2SN+UE=
|
|||||||
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||||
@ -121,6 +136,7 @@ github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlS
|
|||||||
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
|
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
|
||||||
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
|
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
|
||||||
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
|
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
@ -130,7 +146,11 @@ github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu
|
|||||||
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
@ -143,7 +163,9 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
|
|||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM=
|
github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM=
|
||||||
@ -154,6 +176,7 @@ github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM52
|
|||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
@ -181,9 +204,11 @@ github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQ
|
|||||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
|
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c h1:nXxl5PrvVm2L/wCy8dQu6DMTwH4oIuGN8GJDAlqDdVE=
|
||||||
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||||
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
|
||||||
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
@ -202,26 +227,40 @@ github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/
|
|||||||
github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083 h1:BVsJT8+ZbyuL3hypz/HmEiM8h2P6hBQGig4el9/MdjA=
|
github.com/prometheus/common v0.0.0-20180110214958-89604d197083 h1:BVsJT8+ZbyuL3hypz/HmEiM8h2P6hBQGig4el9/MdjA=
|
||||||
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7 h1:hhvfGDVThBnd4kYisSFmYuHYeUhglxcwag7FhVPH9zM=
|
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7 h1:hhvfGDVThBnd4kYisSFmYuHYeUhglxcwag7FhVPH9zM=
|
||||||
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
||||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
@ -230,7 +269,9 @@ github.com/sirupsen/logrus v1.5.0 h1:1N5EYkVAPEywqZRJd7cwnRtCb6xJx7NH3T3WUTF980Q
|
|||||||
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
|
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
|
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
|
||||||
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
@ -239,17 +280,18 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
|||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||||
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
|
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||||
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
|
||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||||
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
@ -259,43 +301,57 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
||||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
github.com/timakin/bodyclose v0.0.0-20190721030226-87058b9bfcec/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/ultraware/funlen v0.0.1/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
github.com/ultraware/funlen v0.0.1/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
||||||
github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
||||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||||
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||||
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA=
|
||||||
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg=
|
||||||
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
|
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
|
||||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -317,6 +373,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
|||||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
@ -333,9 +390,12 @@ google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11K
|
|||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
|
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
@ -344,6 +404,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8
|
|||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@ -351,6 +412,7 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
|||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||||
|
|||||||
@ -23,22 +23,28 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
k3drt "github.com/rancher/k3d/pkg/runtimes"
|
k3drt "github.com/rancher/k3d/pkg/runtimes"
|
||||||
k3d "github.com/rancher/k3d/pkg/types"
|
k3d "github.com/rancher/k3d/pkg/types"
|
||||||
"github.com/rancher/k3d/pkg/util"
|
"github.com/rancher/k3d/pkg/util"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateCluster creates a new cluster consisting of
|
// CreateCluster creates a new cluster consisting of
|
||||||
// - some containerized k3s nodes
|
// - some containerized k3s nodes
|
||||||
// - a docker network
|
// - a docker network
|
||||||
func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
||||||
|
if cluster.CreateClusterOpts.Timeout > 0*time.Second {
|
||||||
|
var cancel context.CancelFunc
|
||||||
|
ctx, cancel = context.WithTimeout(ctx, cluster.CreateClusterOpts.Timeout)
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Network
|
* Network
|
||||||
@ -88,7 +94,7 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
extraLabels["k3d.cluster.volumes.imagevolume"] = imageVolumeName
|
extraLabels["k3d.cluster.imageVolume"] = imageVolumeName
|
||||||
|
|
||||||
// attach volume to nodes
|
// attach volume to nodes
|
||||||
for _, node := range cluster.Nodes {
|
for _, node := range cluster.Nodes {
|
||||||
@ -117,14 +123,16 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
|||||||
// node role specific settings
|
// node role specific settings
|
||||||
if node.Role == k3d.MasterRole {
|
if node.Role == k3d.MasterRole {
|
||||||
|
|
||||||
|
node.MasterOpts.ExposeAPI = cluster.ExposeAPI
|
||||||
|
|
||||||
// the cluster has an init master node, but its not this one, so connect it to the init node
|
// the cluster has an init master node, but its not this one, so connect it to the init node
|
||||||
if cluster.InitNode != nil && !node.MasterOpts.IsInit {
|
if cluster.InitNode != nil && !node.MasterOpts.IsInit {
|
||||||
node.Args = append(node.Args, "--server", fmt.Sprintf("https://%s:%d", cluster.InitNode.Name, 6443))
|
node.Args = append(node.Args, "--server", fmt.Sprintf("https://%s:%s", cluster.InitNode.Name, k3d.DefaultAPIPort))
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if node.Role == k3d.WorkerRole {
|
} else if node.Role == k3d.WorkerRole {
|
||||||
// connection url
|
// connection url
|
||||||
connectionURL := fmt.Sprintf("https://%s:%d", generateNodeName(cluster.Name, k3d.MasterRole, 0), 6443)
|
connectionURL := fmt.Sprintf("https://%s:%s", generateNodeName(cluster.Name, k3d.MasterRole, 0), k3d.DefaultAPIPort)
|
||||||
node.Env = append(node.Env, fmt.Sprintf("K3S_URL=%s", connectionURL))
|
node.Env = append(node.Env, fmt.Sprintf("K3S_URL=%s", connectionURL))
|
||||||
node.Labels["k3d.cluster.url"] = connectionURL
|
node.Labels["k3d.cluster.url"] = connectionURL
|
||||||
}
|
}
|
||||||
@ -159,6 +167,12 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
|||||||
|
|
||||||
// wait for the initnode to come up before doing anything else
|
// wait for the initnode to come up before doing anything else
|
||||||
for {
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
log.Errorln("Failed to bring up initializing master node in time")
|
||||||
|
return fmt.Errorf(">>> %w", ctx.Err())
|
||||||
|
default:
|
||||||
|
}
|
||||||
log.Debugln("Waiting for initializing master node...")
|
log.Debugln("Waiting for initializing master node...")
|
||||||
logreader, err := runtime.GetNodeLogs(cluster.InitNode)
|
logreader, err := runtime.GetNodeLogs(cluster.InitNode)
|
||||||
defer logreader.Close()
|
defer logreader.Close()
|
||||||
@ -167,7 +181,7 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
|||||||
log.Errorln(err)
|
log.Errorln(err)
|
||||||
log.Errorln("Failed to get logs from the initializig master node.. waiting for 3 seconds instead")
|
log.Errorln("Failed to get logs from the initializig master node.. waiting for 3 seconds instead")
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
goto initNodeFinished
|
break
|
||||||
}
|
}
|
||||||
buf := new(bytes.Buffer)
|
buf := new(bytes.Buffer)
|
||||||
nRead, _ := buf.ReadFrom(logreader)
|
nRead, _ := buf.ReadFrom(logreader)
|
||||||
@ -176,16 +190,13 @@ func CreateCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
|||||||
log.Debugln("Initializing master node is up... continuing")
|
log.Debugln("Initializing master node is up... continuing")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(time.Second) // TODO: timeout
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initNodeFinished:
|
|
||||||
|
|
||||||
// vars to support waiting for master nodes to be ready
|
// vars to support waiting for master nodes to be ready
|
||||||
var waitForMasterWaitgroup sync.WaitGroup
|
waitForMasterWaitgroup, ctx := errgroup.WithContext(ctx)
|
||||||
waitForMasterErrChan := make(chan error, 1) // FIXME: we should do something different here, e.g. concurrently read from the channel and append to a slice of errors
|
|
||||||
|
|
||||||
// create all other nodes, but skip the init node
|
// create all other nodes, but skip the init node
|
||||||
for _, node := range cluster.Nodes {
|
for _, node := range cluster.Nodes {
|
||||||
@ -196,6 +207,8 @@ initNodeFinished:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) // FIXME: arbitrary wait for one second to avoid race conditions of masters registering
|
||||||
|
|
||||||
// name suffix
|
// name suffix
|
||||||
suffix = masterCount
|
suffix = masterCount
|
||||||
masterCount++
|
masterCount++
|
||||||
@ -210,41 +223,59 @@ initNodeFinished:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// asynchronously wait for this master node to be ready (by checking the logs for a specific log mesage)
|
// asynchronously wait for this master node to be ready (by checking the logs for a specific log mesage)
|
||||||
if node.Role == k3d.MasterRole && cluster.CreateClusterOpts.WaitForMaster >= 0 {
|
if node.Role == k3d.MasterRole && cluster.CreateClusterOpts.WaitForMaster {
|
||||||
waitForMasterWaitgroup.Add(1)
|
masterNode := node
|
||||||
go func(masterNode *k3d.Node) {
|
waitForMasterWaitgroup.Go(func() error {
|
||||||
|
// TODO: avoid `level=fatal msg="starting kubernetes: preparing server: post join: a configuration change is already in progress (5)"`
|
||||||
|
// ... by scanning for this line in logs and restarting the container in case it appears
|
||||||
log.Debugf("Starting to wait for master node '%s'", masterNode.Name)
|
log.Debugf("Starting to wait for master node '%s'", masterNode.Name)
|
||||||
// TODO: it may be better to give endtime=starttime+timeout here so that there is no difference between the instances (go func may be called with a few (milli-)seconds difference)
|
return WaitForNodeLogMessage(ctx, runtime, masterNode, "Wrote kubeconfig")
|
||||||
err := WaitForNodeLogMessage(runtime, masterNode, "Wrote kubeconfig", (time.Duration(cluster.CreateClusterOpts.WaitForMaster) * time.Second))
|
})
|
||||||
waitForMasterErrChan <- err
|
|
||||||
if err == nil {
|
|
||||||
log.Debugf("Master Node '%s' ready", masterNode.Name)
|
|
||||||
}
|
|
||||||
}(node)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// block until all masters are ready (if --wait was set) and collect errors if not
|
if err := waitForMasterWaitgroup.Wait(); err != nil {
|
||||||
if cluster.CreateClusterOpts.WaitForMaster >= 0 {
|
|
||||||
errs := []error{}
|
|
||||||
go func() {
|
|
||||||
for elem := range waitForMasterErrChan {
|
|
||||||
if elem != nil {
|
|
||||||
errs = append(errs, elem)
|
|
||||||
}
|
|
||||||
waitForMasterWaitgroup.Done()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
waitForMasterWaitgroup.Wait()
|
|
||||||
if len(errs) != 0 {
|
|
||||||
log.Errorln("Failed to bring up all master nodes in time. Check the logs:")
|
log.Errorln("Failed to bring up all master nodes in time. Check the logs:")
|
||||||
for _, e := range errs {
|
log.Errorln(">>> ", err)
|
||||||
log.Errorln(">>> ", e)
|
return fmt.Errorf("Failed to bring up cluster")
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Auxiliary Containers
|
||||||
|
*/
|
||||||
|
// *** MasterLoadBalancer ***
|
||||||
|
|
||||||
|
// Generate a comma-separated list of master/server names to pass to the proxy container
|
||||||
|
servers := ""
|
||||||
|
for _, node := range cluster.Nodes {
|
||||||
|
if node.Role == k3d.MasterRole {
|
||||||
|
log.Debugf("Node NAME: %s", node.Name)
|
||||||
|
if servers == "" {
|
||||||
|
servers = node.Name
|
||||||
|
} else {
|
||||||
|
servers = fmt.Sprintf("%s,%s", servers, node.Name)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("Failed to bring up cluster") // TODO: in case of failure, we should rollback
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create proxy as a modified node with proxyRole
|
||||||
|
lbNode := &k3d.Node{
|
||||||
|
Name: fmt.Sprintf("%s-%s-masterlb", k3d.DefaultObjectNamePrefix, cluster.Name),
|
||||||
|
Image: k3d.DefaultLBImage,
|
||||||
|
Ports: []string{fmt.Sprintf("%s:%s:%s/tcp", cluster.ExposeAPI.Host, cluster.ExposeAPI.Port, k3d.DefaultAPIPort)},
|
||||||
|
Env: []string{
|
||||||
|
fmt.Sprintf("SERVERS=%s", servers),
|
||||||
|
fmt.Sprintf("PORT=%s", k3d.DefaultAPIPort),
|
||||||
|
},
|
||||||
|
Role: k3d.NoRole,
|
||||||
|
Labels: k3d.DefaultObjectLabels, // TODO: createLoadBalancer: add more expressive labels
|
||||||
|
Network: cluster.Network.Name,
|
||||||
|
}
|
||||||
|
log.Infof("Creating LoadBalancer '%s'", lbNode.Name)
|
||||||
|
if err := CreateNode(lbNode, runtime); err != nil {
|
||||||
|
log.Errorln("Failed to create loadbalancer")
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,6 +283,7 @@ initNodeFinished:
|
|||||||
func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
||||||
|
|
||||||
log.Infof("Deleting cluster '%s'", cluster.Name)
|
log.Infof("Deleting cluster '%s'", cluster.Name)
|
||||||
|
log.Debugf("%+v", cluster)
|
||||||
|
|
||||||
failed := 0
|
failed := 0
|
||||||
for _, node := range cluster.Nodes {
|
for _, node := range cluster.Nodes {
|
||||||
@ -262,27 +294,27 @@ func DeleteCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the cluster network, if it was created for/by this cluster (and if it's not in use anymore) // TODO: does this make sense or should we always try to delete it? (Will fail anyway, if it's still in use)
|
// Delete the cluster network, if it was created for/by this cluster (and if it's not in use anymore)
|
||||||
if network, ok := cluster.Nodes[0].Labels["k3d.cluster.network"]; ok {
|
if cluster.Network.Name != "" {
|
||||||
if !cluster.Network.External || cluster.Nodes[0].Labels["k3d.cluster.network.external"] == "false" {
|
if !cluster.Network.External {
|
||||||
log.Infof("Deleting cluster network '%s'", network)
|
log.Infof("Deleting cluster network '%s'", cluster.Network.Name)
|
||||||
if err := runtime.DeleteNetwork(network); err != nil {
|
if err := runtime.DeleteNetwork(cluster.Network.Name); err != nil {
|
||||||
if strings.HasSuffix(err.Error(), "active endpoints") {
|
if strings.HasSuffix(err.Error(), "active endpoints") {
|
||||||
log.Warningf("Failed to delete cluster network '%s' because it's still in use: is there another cluster using it?", network)
|
log.Warningf("Failed to delete cluster network '%s' because it's still in use: is there another cluster using it?", cluster.Network.Name)
|
||||||
} else {
|
} else {
|
||||||
log.Warningf("Failed to delete cluster network '%s': '%+v'", network, err)
|
log.Warningf("Failed to delete cluster network '%s': '%+v'", cluster.Network.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if cluster.Network.External || cluster.Nodes[0].Labels["k3d.cluster.network.external"] == "true" {
|
} else if cluster.Network.External {
|
||||||
log.Debugf("Skip deletion of cluster network '%s' because it's managed externally", network)
|
log.Debugf("Skip deletion of cluster network '%s' because it's managed externally", cluster.Network.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete image volume
|
// delete image volume
|
||||||
if imagevolume, ok := cluster.Nodes[0].Labels["k3d.cluster.volumes.imagevolume"]; ok {
|
if cluster.ImageVolume != "" {
|
||||||
log.Infof("Deleting image volume '%s'", imagevolume)
|
log.Infof("Deleting image volume '%s'", cluster.ImageVolume)
|
||||||
if err := runtime.DeleteVolume(imagevolume); err != nil {
|
if err := runtime.DeleteVolume(cluster.ImageVolume); err != nil {
|
||||||
log.Warningf("Failed to delete image volume '%s' of cluster '%s': Try to delete it manually", cluster.Name, imagevolume)
|
log.Warningf("Failed to delete image volume '%s' of cluster '%s': Try to delete it manually", cluster.ImageVolume, cluster.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +386,16 @@ func populateClusterFieldsFromLabels(cluster *k3d.Cluster) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get image volume // TODO: enable external image volumes the same way we do it with networks
|
||||||
|
if cluster.ImageVolume == "" {
|
||||||
|
if imageVolumeName, ok := node.Labels["k3d.cluster.imageVolume"]; ok {
|
||||||
|
cluster.ImageVolume = imageVolumeName
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import (
|
|||||||
// GetKubeconfig grabs the kubeconfig file from /output from a master node container and puts it into a local directory
|
// GetKubeconfig grabs the kubeconfig file from /output from a master node container and puts it into a local directory
|
||||||
func GetKubeconfig(runtime runtimes.Runtime, cluster *k3d.Cluster) ([]byte, error) {
|
func GetKubeconfig(runtime runtimes.Runtime, cluster *k3d.Cluster) ([]byte, error) {
|
||||||
// get all master nodes for the selected cluster
|
// get all master nodes for the selected cluster
|
||||||
|
// TODO: getKubeconfig: we should make sure, that the master node we're trying to getch is actually running
|
||||||
masterNodes, err := runtime.GetNodesByLabel(map[string]string{"k3d.cluster": cluster.Name, "k3d.role": string(k3d.MasterRole)})
|
masterNodes, err := runtime.GetNodesByLabel(map[string]string{"k3d.cluster": cluster.Name, "k3d.role": string(k3d.MasterRole)})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("Failed to get master nodes")
|
log.Errorln("Failed to get master nodes")
|
||||||
@ -49,8 +50,8 @@ func GetKubeconfig(runtime runtimes.Runtime, cluster *k3d.Cluster) ([]byte, erro
|
|||||||
// prefer a master node, which actually has the port exposed
|
// prefer a master node, which actually has the port exposed
|
||||||
var chosenMaster *k3d.Node
|
var chosenMaster *k3d.Node
|
||||||
chosenMaster = nil
|
chosenMaster = nil
|
||||||
APIPort := "6443" // TODO: use default from types
|
APIPort := k3d.DefaultAPIPort
|
||||||
APIHost := "localhost" // TODO: use default from types
|
APIHost := k3d.DefaultAPIHost
|
||||||
|
|
||||||
for _, master := range masterNodes {
|
for _, master := range masterNodes {
|
||||||
if _, ok := master.Labels["k3d.master.api.port"]; ok {
|
if _, ok := master.Labels["k3d.master.api.port"]; ok {
|
||||||
|
|||||||
@ -24,6 +24,7 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -125,8 +126,6 @@ func CreateNode(node *k3d.Node, runtime runtimes.Runtime) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Debugf("spec = %+v\n", node)
|
log.Debugf("spec = %+v\n", node)
|
||||||
} else {
|
|
||||||
return fmt.Errorf("Unknown node role '%s'", node.Role)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -164,19 +163,14 @@ func patchMasterSpec(node *k3d.Node) error {
|
|||||||
// role label
|
// role label
|
||||||
node.Labels["k3d.role"] = string(k3d.MasterRole) // TODO: maybe put those in a global var DefaultMasterNodeSpec?
|
node.Labels["k3d.role"] = string(k3d.MasterRole) // TODO: maybe put those in a global var DefaultMasterNodeSpec?
|
||||||
|
|
||||||
// extra settings to expose the API port (if wanted)
|
// Add labels and TLS SAN for the exposed API
|
||||||
if node.MasterOpts.ExposeAPI.Port != "" {
|
// FIXME: For now, the labels concerning the API on the master nodes are only being used for configuring the kubeconfig
|
||||||
if node.MasterOpts.ExposeAPI.Host == "" {
|
|
||||||
node.MasterOpts.ExposeAPI.Host = "0.0.0.0"
|
|
||||||
}
|
|
||||||
node.Labels["k3d.master.api.hostIP"] = node.MasterOpts.ExposeAPI.HostIP // TODO: maybe get docker machine IP here
|
node.Labels["k3d.master.api.hostIP"] = node.MasterOpts.ExposeAPI.HostIP // TODO: maybe get docker machine IP here
|
||||||
|
|
||||||
node.Labels["k3d.master.api.host"] = node.MasterOpts.ExposeAPI.Host
|
node.Labels["k3d.master.api.host"] = node.MasterOpts.ExposeAPI.Host
|
||||||
|
node.Labels["k3d.master.api.port"] = node.MasterOpts.ExposeAPI.Port
|
||||||
|
|
||||||
node.Args = append(node.Args, "--tls-san", node.MasterOpts.ExposeAPI.Host) // add TLS SAN for non default host name
|
node.Args = append(node.Args, "--tls-san", node.MasterOpts.ExposeAPI.Host) // add TLS SAN for non default host name
|
||||||
node.Labels["k3d.master.api.port"] = node.MasterOpts.ExposeAPI.Port
|
|
||||||
node.Ports = append(node.Ports, fmt.Sprintf("%s:%s:6443/tcp", node.MasterOpts.ExposeAPI.Host, node.MasterOpts.ExposeAPI.Port)) // TODO: get '6443' from defaultport variable
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,17 +197,14 @@ func GetNode(node *k3d.Node, runtime runtimes.Runtime) (*k3d.Node, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WaitForNodeLogMessage follows the logs of a node container and returns if it finds a specific line in there (or timeout is reached)
|
// WaitForNodeLogMessage follows the logs of a node container and returns if it finds a specific line in there (or timeout is reached)
|
||||||
func WaitForNodeLogMessage(runtime runtimes.Runtime, node *k3d.Node, message string, timeout time.Duration) error {
|
func WaitForNodeLogMessage(ctx context.Context, runtime runtimes.Runtime, node *k3d.Node, message string) error {
|
||||||
start := time.Now()
|
|
||||||
for {
|
for {
|
||||||
|
select {
|
||||||
// return error if we've reached the timeout without having read the message
|
case <-ctx.Done():
|
||||||
if timeout != 0 && time.Now().After(start.Add(timeout)) {
|
return ctx.Err()
|
||||||
return fmt.Errorf("Timed out waiting for log message '%s' from node '%s'", message, node.Name)
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Debugf("Waiting for log message '%s' from node '%s'...", message, node.Name)
|
|
||||||
|
|
||||||
// read the logs
|
// read the logs
|
||||||
out, err := runtime.GetNodeLogs(node)
|
out, err := runtime.GetNodeLogs(node)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -234,7 +225,8 @@ func WaitForNodeLogMessage(runtime runtimes.Runtime, node *k3d.Node, message str
|
|||||||
if nRead > 0 && strings.Contains(output, message) {
|
if nRead > 0 && strings.Contains(output, message) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(1 * time.Second)
|
|
||||||
}
|
}
|
||||||
|
time.Sleep(500 * time.Millisecond) // wait for half a second to avoid overloading docker (error `socket: too many open files`)
|
||||||
|
log.Debugf("Finished waiting for log message '%s' from node '%s'", message, node.Name)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/filters"
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
k3d "github.com/rancher/k3d/pkg/types"
|
k3d "github.com/rancher/k3d/pkg/types"
|
||||||
@ -50,20 +51,23 @@ func createContainer(dockerNode *NodeInDocker, name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create container
|
// create container
|
||||||
create: // label used to restart creation process, if we're only missing the image
|
var resp container.ContainerCreateCreatedBody
|
||||||
resp, err := docker.ContainerCreate(ctx, &dockerNode.ContainerConfig, &dockerNode.HostConfig, &dockerNode.NetworkingConfig, name)
|
for {
|
||||||
|
resp, err = docker.ContainerCreate(ctx, &dockerNode.ContainerConfig, &dockerNode.HostConfig, &dockerNode.NetworkingConfig, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if client.IsErrNotFound(err) {
|
if client.IsErrNotFound(err) {
|
||||||
if err := pullImage(&ctx, docker, dockerNode.ContainerConfig.Image); err != nil {
|
if err := pullImage(&ctx, docker, dockerNode.ContainerConfig.Image); err != nil {
|
||||||
log.Errorln("Failed to create container")
|
log.Errorln("Failed to create container")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
goto create
|
continue
|
||||||
}
|
}
|
||||||
log.Errorln("Failed to create container")
|
log.Errorln("Failed to create container")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Debugln("Created container", resp.ID)
|
log.Debugln("Created container", resp.ID)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// start container
|
// start container
|
||||||
if err := docker.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
|
if err := docker.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil {
|
||||||
|
|||||||
@ -23,9 +23,9 @@ package docker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
|
|
||||||
k3d "github.com/rancher/k3d/pkg/types"
|
k3d "github.com/rancher/k3d/pkg/types"
|
||||||
@ -45,8 +45,7 @@ func (d Docker) CreateNetworkIfNotPresent(name string) (string, bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// (1) configure list filters
|
// (1) configure list filters
|
||||||
args := GetDefaultObjectLabelsFilter("")
|
args := filters.NewArgs()
|
||||||
args.Del("label", fmt.Sprintf("k3d.cluster=%s", "")) // We don't filter for cluster name here
|
|
||||||
args.Add("name", name)
|
args.Add("name", name)
|
||||||
|
|
||||||
// (2) get filtered list of networks
|
// (2) get filtered list of networks
|
||||||
@ -94,3 +93,14 @@ func (d Docker) DeleteNetwork(ID string) error {
|
|||||||
// (3) delete network
|
// (3) delete network
|
||||||
return docker.NetworkRemove(ctx, ID)
|
return docker.NetworkRemove(ctx, ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNetwork gets information about a network by its ID
|
||||||
|
func GetNetwork(ID string) (types.NetworkResource, error) {
|
||||||
|
ctx := context.Background()
|
||||||
|
docker, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln("Failed to create docker client")
|
||||||
|
return types.NetworkResource{}, err
|
||||||
|
}
|
||||||
|
return docker.NetworkInspect(ctx, ID, types.NetworkInspectOptions{})
|
||||||
|
}
|
||||||
|
|||||||
@ -86,12 +86,16 @@ func TranslateNodeToContainer(node *k3d.Node) (*NodeInDocker, error) {
|
|||||||
}
|
}
|
||||||
containerConfig.ExposedPorts = exposedPorts
|
containerConfig.ExposedPorts = exposedPorts
|
||||||
hostConfig.PortBindings = portBindings
|
hostConfig.PortBindings = portBindings
|
||||||
|
|
||||||
/* Network */
|
/* Network */
|
||||||
networkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
|
networkingConfig.EndpointsConfig = map[string]*network.EndpointSettings{
|
||||||
node.Network: { // TODO: fill
|
node.Network: {},
|
||||||
Aliases: []string{node.Name}, // TODO: fill
|
}
|
||||||
},
|
netInfo, err := GetNetwork(node.Network)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnln("Failed to get network information")
|
||||||
|
log.Warnln(err)
|
||||||
|
} else if netInfo.Driver == "host" {
|
||||||
|
hostConfig.NetworkMode = "host"
|
||||||
}
|
}
|
||||||
|
|
||||||
return &NodeInDocker{
|
return &NodeInDocker{
|
||||||
|
|||||||
@ -45,10 +45,10 @@ func LoadImagesIntoCluster(runtime runtimes.Runtime, images []string, cluster *k
|
|||||||
return fmt.Errorf("Failed to get network for cluster '%s'", cluster.Name)
|
return fmt.Errorf("Failed to get network for cluster '%s'", cluster.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := cluster.Nodes[0].Labels["k3d.cluster.volumes.imagevolume"]; !ok { // TODO: add failover solution
|
if _, ok := cluster.Nodes[0].Labels["k3d.cluster.imageVolume"]; !ok { // TODO: add failover solution
|
||||||
return fmt.Errorf("Failed to find image volume for cluster '%s'", cluster.Name)
|
return fmt.Errorf("Failed to find image volume for cluster '%s'", cluster.Name)
|
||||||
}
|
}
|
||||||
imageVolume := cluster.Nodes[0].Labels["k3d.cluster.volumes.imagevolume"]
|
imageVolume := cluster.Nodes[0].Labels["k3d.cluster.imageVolume"]
|
||||||
|
|
||||||
// create tools node to export images
|
// create tools node to export images
|
||||||
log.Infoln("Starting k3d-tools node...")
|
log.Infoln("Starting k3d-tools node...")
|
||||||
|
|||||||
@ -23,6 +23,7 @@ package types
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultClusterName specifies the default name used for newly created clusters
|
// DefaultClusterName specifies the default name used for newly created clusters
|
||||||
@ -38,7 +39,7 @@ const DefaultClusterNameMaxLength = 32
|
|||||||
const DefaultK3sImageRepo = "docker.io/rancher/k3s"
|
const DefaultK3sImageRepo = "docker.io/rancher/k3s"
|
||||||
|
|
||||||
// DefaultLBImage defines the default cluster load balancer image
|
// DefaultLBImage defines the default cluster load balancer image
|
||||||
const DefaultLBImage = "docker.io/library/traefik:v2.0"
|
const DefaultLBImage = "docker.io/iwilltry42/k3d-proxy:v0.0.1"
|
||||||
|
|
||||||
// DefaultObjectNamePrefix defines the name prefix for every object created by k3d
|
// DefaultObjectNamePrefix defines the name prefix for every object created by k3d
|
||||||
const DefaultObjectNamePrefix = "k3d"
|
const DefaultObjectNamePrefix = "k3d"
|
||||||
@ -50,7 +51,8 @@ type Role string
|
|||||||
const (
|
const (
|
||||||
MasterRole Role = "master"
|
MasterRole Role = "master"
|
||||||
WorkerRole Role = "worker"
|
WorkerRole Role = "worker"
|
||||||
NoRole Role = "nope"
|
NoRole Role = "noRole"
|
||||||
|
ProxyRole Role = "proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultK3dRoles defines the roles available for nodes
|
// DefaultK3dRoles defines the roles available for nodes
|
||||||
@ -87,11 +89,17 @@ const DefaultConfigDirName = ".k3d" // should end up in $HOME/
|
|||||||
// DefaultKubeconfigPrefix defines the default prefix for kubeconfig files
|
// DefaultKubeconfigPrefix defines the default prefix for kubeconfig files
|
||||||
const DefaultKubeconfigPrefix = DefaultObjectNamePrefix + "-kubeconfig"
|
const DefaultKubeconfigPrefix = DefaultObjectNamePrefix + "-kubeconfig"
|
||||||
|
|
||||||
|
// DefaultAPIPort defines the default Kubernetes API Port
|
||||||
|
const DefaultAPIPort = "6443"
|
||||||
|
|
||||||
|
// DefaultAPIHost defines the default host (IP) for the Kubernetes API
|
||||||
|
const DefaultAPIHost = "0.0.0.0"
|
||||||
|
|
||||||
// CreateClusterOpts describe a set of options one can set when creating a cluster
|
// CreateClusterOpts describe a set of options one can set when creating a cluster
|
||||||
type CreateClusterOpts struct {
|
type CreateClusterOpts struct {
|
||||||
DisableImageVolume bool
|
DisableImageVolume bool
|
||||||
DisableLoadbalancer bool
|
WaitForMaster bool
|
||||||
WaitForMaster int
|
Timeout time.Duration
|
||||||
K3sServerArgs []string
|
K3sServerArgs []string
|
||||||
K3sAgentArgs []string
|
K3sAgentArgs []string
|
||||||
}
|
}
|
||||||
@ -109,9 +117,10 @@ type Cluster struct {
|
|||||||
Secret string `yaml:"cluster_secret" json:"clusterSecret,omitempty"`
|
Secret string `yaml:"cluster_secret" json:"clusterSecret,omitempty"`
|
||||||
Nodes []*Node `yaml:"nodes" json:"nodes,omitempty"`
|
Nodes []*Node `yaml:"nodes" json:"nodes,omitempty"`
|
||||||
InitNode *Node // init master node
|
InitNode *Node // init master node
|
||||||
MasterLoadBalancer *ClusterLoadbalancer `yaml:"master_loadbalancer" json:"masterLoadBalancer,omitempty"`
|
|
||||||
ExternalDatastore ExternalDatastore `yaml:"external_datastore" json:"externalDatastore,omitempty"`
|
ExternalDatastore ExternalDatastore `yaml:"external_datastore" json:"externalDatastore,omitempty"`
|
||||||
CreateClusterOpts *CreateClusterOpts `yaml:"options" json:"options,omitempty"`
|
CreateClusterOpts *CreateClusterOpts `yaml:"options" json:"options,omitempty"`
|
||||||
|
ExposeAPI ExposeAPI `yaml:"expose_api" json:"exposeAPI,omitempty"`
|
||||||
|
ImageVolume string `yaml:"image_volume" json:"imageVolume,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Node describes a k3d node
|
// Node describes a k3d node
|
||||||
@ -133,8 +142,8 @@ type Node struct {
|
|||||||
|
|
||||||
// MasterOpts describes some additional master role specific opts
|
// MasterOpts describes some additional master role specific opts
|
||||||
type MasterOpts struct {
|
type MasterOpts struct {
|
||||||
ExposeAPI ExposeAPI `yaml:"expose_api" json:"exposeAPI,omitempty"`
|
|
||||||
IsInit bool `yaml:"is_initializing_master" json:"isInitializingMaster,omitempty"`
|
IsInit bool `yaml:"is_initializing_master" json:"isInitializingMaster,omitempty"`
|
||||||
|
ExposeAPI ExposeAPI // filled automatically
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExternalDatastore describes an external datastore used for HA/multi-master clusters
|
// ExternalDatastore describes an external datastore used for HA/multi-master clusters
|
||||||
@ -160,9 +169,3 @@ type WorkerOpts struct{}
|
|||||||
func GetDefaultObjectName(name string) string {
|
func GetDefaultObjectName(name string) string {
|
||||||
return fmt.Sprintf("%s-%s", DefaultObjectNamePrefix, name)
|
return fmt.Sprintf("%s-%s", DefaultObjectNamePrefix, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClusterLoadbalancer describes a loadbalancer deployed in front of a multi-master cluster
|
|
||||||
type ClusterLoadbalancer struct {
|
|
||||||
Image string
|
|
||||||
ExposedPort string `yaml:"exposed_port" json:"exposedPort,omitempty"`
|
|
||||||
}
|
|
||||||
|
|||||||
13
proxy/Dockerfile
Normal file
13
proxy/Dockerfile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
FROM nginx:1.16.0-alpine
|
||||||
|
|
||||||
|
RUN apk -U --no-cache add curl ca-certificates\
|
||||||
|
&& mkdir -p /etc/confd \
|
||||||
|
&& curl -sLf https://github.com/kelseyhightower/confd/releases/download/v0.16.0/confd-0.16.0-linux-amd64 > /usr/bin/confd \
|
||||||
|
&& chmod +x /usr/bin/confd \
|
||||||
|
&& apk del curl
|
||||||
|
|
||||||
|
COPY templates /etc/confd/templates/
|
||||||
|
COPY conf.d /etc/confd/conf.d/
|
||||||
|
COPY nginx-proxy /usr/bin/
|
||||||
|
|
||||||
|
ENTRYPOINT nginx-proxy
|
||||||
7
proxy/conf.d/nginx.toml
Normal file
7
proxy/conf.d/nginx.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[template]
|
||||||
|
src = "nginx.tmpl"
|
||||||
|
dest = "/etc/nginx/nginx.conf"
|
||||||
|
keys = [
|
||||||
|
"SERVERS",
|
||||||
|
"PORT",
|
||||||
|
]
|
||||||
7
proxy/nginx-proxy
Executable file
7
proxy/nginx-proxy
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Run confd
|
||||||
|
confd -onetime -backend env
|
||||||
|
|
||||||
|
# Start nginx
|
||||||
|
nginx -g 'daemon off;'
|
||||||
23
proxy/templates/nginx.tmpl
Normal file
23
proxy/templates/nginx.tmpl
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
error_log stderr notice;
|
||||||
|
|
||||||
|
worker_processes auto;
|
||||||
|
events {
|
||||||
|
multi_accept on;
|
||||||
|
use epoll;
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream {
|
||||||
|
upstream kube_apiserver {
|
||||||
|
{{ $servers := split (getenv "SERVERS") "," }}{{range $servers}}
|
||||||
|
server {{.}}:{{getenv "PORT"}};
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen {{getenv "PORT"}};
|
||||||
|
proxy_pass kube_apiserver;
|
||||||
|
proxy_timeout 30;
|
||||||
|
proxy_connect_timeout 2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -59,8 +59,8 @@ check_url() {
|
|||||||
|
|
||||||
check_k3d_clusters() {
|
check_k3d_clusters() {
|
||||||
[ -n "$EXE" ] || abort "EXE is not defined"
|
[ -n "$EXE" ] || abort "EXE is not defined"
|
||||||
for c in "c1" "c2" ; do
|
for c in "$@" ; do
|
||||||
kc=$($EXE get kubeconfig $c)
|
kc=$($EXE get kubeconfig "$c")
|
||||||
[ -n "$kc" ] || abort "could not obtain a kubeconfig for $c"
|
[ -n "$kc" ] || abort "could not obtain a kubeconfig for $c"
|
||||||
if kubectl --kubeconfig="$kc" cluster-info ; then
|
if kubectl --kubeconfig="$kc" cluster-info ; then
|
||||||
passed "cluster $c is reachable (with kubeconfig=$kc)"
|
passed "cluster $c is reachable (with kubeconfig=$kc)"
|
||||||
@ -76,3 +76,6 @@ check_registry() {
|
|||||||
check_url $REGISTRY/v2/_catalog
|
check_url $REGISTRY/v2/_catalog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_volume_exists() {
|
||||||
|
docker volume inspect "$1" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@ CURR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|||||||
source "$CURR_DIR/common.sh"
|
source "$CURR_DIR/common.sh"
|
||||||
|
|
||||||
info "Creating two clusters..."
|
info "Creating two clusters..."
|
||||||
$EXE --verbose create cluster c1 --wait 60 --api-port 6443 || failed "could not create cluster c1"
|
$EXE --verbose create cluster c1 --wait --timeout 60s --api-port 6443 || failed "could not create cluster c1"
|
||||||
$EXE --verbose create cluster c2 --wait 60 --api-port 6444 || failed "could not create cluster c2"
|
$EXE --verbose create cluster c2 --wait --timeout 60s --api-port 6444 || failed "could not create cluster c2"
|
||||||
|
|
||||||
info "Checking we have access to both clusters..."
|
info "Checking we have access to both clusters..."
|
||||||
check_k3d_clusters "c1" "c2" || failed "error checking cluster"
|
check_k3d_clusters "c1" "c2" || failed "error checking cluster"
|
||||||
|
|||||||
38
tests/test_multi_master.sh
Executable file
38
tests/test_multi_master.sh
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
CURR_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
[ -d "$CURR_DIR" ] || { echo "FATAL: no current dir (maybe running in zsh?)"; exit 1; }
|
||||||
|
|
||||||
|
# shellcheck source=./common.sh
|
||||||
|
source "$CURR_DIR/common.sh"
|
||||||
|
|
||||||
|
info "Creating cluster multimaster..."
|
||||||
|
$EXE --verbose create cluster "multimaster" --masters 3 --api-port 6443 --wait --timeout 360s || failed "could not create cluster multimaster"
|
||||||
|
|
||||||
|
info "Checking we have access to the cluster..."
|
||||||
|
check_k3d_clusters "multimaster" || failed "error checking cluster"
|
||||||
|
|
||||||
|
info "Checking that we have 3 servers online..."
|
||||||
|
check_multi_master() {
|
||||||
|
for c in "$@" ; do
|
||||||
|
kc=$($EXE get kubeconfig "$c")
|
||||||
|
[ -n "$kc" ] || abort "could not obtain a kubeconfig for $c"
|
||||||
|
nodeCount=$(kubectl --kubeconfig="$kc" get nodes -o=custom-columns=NAME:.metadata.name --no-headers | wc -l)
|
||||||
|
if [[ $nodeCount == 3 ]]; then
|
||||||
|
passed "cluster $c has 3 nodes, as expected"
|
||||||
|
else
|
||||||
|
warn "cluster $c has incorrect number of nodes: $nodeCount != 3"
|
||||||
|
kubectl --kubeconfig="$kc" get nodes -o=custom-columns=NAME:.metadata.name --no-headers
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
check_multi_master "multimaster"
|
||||||
|
|
||||||
|
info "Deleting cluster multimaster..."
|
||||||
|
$EXE delete cluster "multimaster" || failed "could not delete the cluster multimaster"
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
||||||
5
vendor/github.com/spf13/cobra/.gitignore
generated
vendored
5
vendor/github.com/spf13/cobra/.gitignore
generated
vendored
@ -32,7 +32,8 @@ Session.vim
|
|||||||
tags
|
tags
|
||||||
|
|
||||||
*.exe
|
*.exe
|
||||||
|
|
||||||
cobra.test
|
cobra.test
|
||||||
|
bin
|
||||||
|
|
||||||
.idea/*
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|||||||
26
vendor/github.com/spf13/cobra/.travis.yml
generated
vendored
26
vendor/github.com/spf13/cobra/.travis.yml
generated
vendored
@ -3,29 +3,27 @@ language: go
|
|||||||
stages:
|
stages:
|
||||||
- diff
|
- diff
|
||||||
- test
|
- test
|
||||||
|
- build
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.10.x
|
|
||||||
- 1.11.x
|
|
||||||
- 1.12.x
|
- 1.12.x
|
||||||
|
- 1.13.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- go get -u github.com/kyoh86/richgo
|
||||||
|
- go get -u github.com/mitchellh/gox
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- go: tip
|
- go: tip
|
||||||
include:
|
include:
|
||||||
- stage: diff
|
- stage: diff
|
||||||
go: 1.12.x
|
go: 1.13.x
|
||||||
script: diff -u <(echo -n) <(gofmt -d -s .)
|
script: make fmt
|
||||||
|
- stage: build
|
||||||
|
go: 1.13.x
|
||||||
|
script: make cobra_generator
|
||||||
|
|
||||||
before_install:
|
|
||||||
- mkdir -p bin
|
|
||||||
- curl -Lso bin/shellcheck https://github.com/caarlos0/shellcheck-docker/releases/download/v0.6.0/shellcheck
|
|
||||||
- chmod +x bin/shellcheck
|
|
||||||
- go get -u github.com/kyoh86/richgo
|
|
||||||
script:
|
script:
|
||||||
- PATH=$PATH:$PWD/bin richgo test -v ./...
|
- make test
|
||||||
- go build
|
|
||||||
- if [ -z $NOVET ]; then
|
|
||||||
diff -u <(echo -n) <(go vet . 2>&1 | grep -vE 'ExampleCommand|bash_completions.*Fprint');
|
|
||||||
fi
|
|
||||||
|
|||||||
36
vendor/github.com/spf13/cobra/Makefile
generated
vendored
Normal file
36
vendor/github.com/spf13/cobra/Makefile
generated
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
BIN="./bin"
|
||||||
|
SRC=$(shell find . -name "*.go")
|
||||||
|
|
||||||
|
ifeq (, $(shell which richgo))
|
||||||
|
$(warning "could not find richgo in $(PATH), run: go get github.com/kyoh86/richgo")
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: fmt vet test cobra_generator install_deps clean
|
||||||
|
|
||||||
|
default: all
|
||||||
|
|
||||||
|
all: fmt vet test cobra_generator
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
$(info ******************** checking formatting ********************)
|
||||||
|
@test -z $(shell gofmt -l $(SRC)) || (gofmt -d $(SRC); exit 1)
|
||||||
|
|
||||||
|
test: install_deps vet
|
||||||
|
$(info ******************** running tests ********************)
|
||||||
|
richgo test -v ./...
|
||||||
|
|
||||||
|
cobra_generator: install_deps
|
||||||
|
$(info ******************** building generator ********************)
|
||||||
|
mkdir -p $(BIN)
|
||||||
|
make -C cobra all
|
||||||
|
|
||||||
|
install_deps:
|
||||||
|
$(info ******************** downloading dependencies ********************)
|
||||||
|
go get -v ./...
|
||||||
|
|
||||||
|
vet:
|
||||||
|
$(info ******************** vetting ********************)
|
||||||
|
go vet ./...
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(BIN)
|
||||||
55
vendor/github.com/spf13/cobra/README.md
generated
vendored
55
vendor/github.com/spf13/cobra/README.md
generated
vendored
@ -24,11 +24,13 @@ Many of the most widely used Go projects are built using Cobra, such as:
|
|||||||
[Prototool](https://github.com/uber/prototool),
|
[Prototool](https://github.com/uber/prototool),
|
||||||
[mattermost-server](https://github.com/mattermost/mattermost-server),
|
[mattermost-server](https://github.com/mattermost/mattermost-server),
|
||||||
[Gardener](https://github.com/gardener/gardenctl),
|
[Gardener](https://github.com/gardener/gardenctl),
|
||||||
|
[Linkerd](https://linkerd.io/),
|
||||||
|
[Github CLI](https://github.com/cli/cli)
|
||||||
etc.
|
etc.
|
||||||
|
|
||||||
[](https://travis-ci.org/spf13/cobra)
|
[](https://travis-ci.org/spf13/cobra)
|
||||||
[](https://circleci.com/gh/spf13/cobra)
|
|
||||||
[](https://godoc.org/github.com/spf13/cobra)
|
[](https://godoc.org/github.com/spf13/cobra)
|
||||||
|
[](https://goreportcard.com/report/github.com/spf13/cobra)
|
||||||
|
|
||||||
# Table of Contents
|
# Table of Contents
|
||||||
|
|
||||||
@ -208,6 +210,8 @@ You will additionally define flags and handle configuration in your init() funct
|
|||||||
For example cmd/root.go:
|
For example cmd/root.go:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -217,22 +221,47 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Used for flags.
|
||||||
|
cfgFile string
|
||||||
|
userLicense string
|
||||||
|
|
||||||
|
rootCmd = &cobra.Command{
|
||||||
|
Use: "cobra",
|
||||||
|
Short: "A generator for Cobra based Applications",
|
||||||
|
Long: `Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
|
to quickly create a Cobra application.`,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Execute executes the root command.
|
||||||
|
func Execute() error {
|
||||||
|
return rootCmd.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initConfig)
|
cobra.OnInitialize(initConfig)
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
|
||||||
rootCmd.PersistentFlags().StringVarP(&projectBase, "projectbase", "b", "", "base project directory eg. github.com/spf13/")
|
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
|
||||||
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "Author name for copyright attribution")
|
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
|
||||||
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "Name of license for the project (can provide `licensetext` in config)")
|
rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
|
||||||
rootCmd.PersistentFlags().Bool("viper", true, "Use Viper for configuration")
|
|
||||||
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
|
||||||
viper.BindPFlag("projectbase", rootCmd.PersistentFlags().Lookup("projectbase"))
|
|
||||||
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
|
viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
|
||||||
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
|
||||||
viper.SetDefault("license", "apache")
|
viper.SetDefault("license", "apache")
|
||||||
|
|
||||||
|
rootCmd.AddCommand(addCmd)
|
||||||
|
rootCmd.AddCommand(initCmd)
|
||||||
|
}
|
||||||
|
|
||||||
|
func er(msg interface{}) {
|
||||||
|
fmt.Println("Error:", msg)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func initConfig() {
|
func initConfig() {
|
||||||
// Don't forget to read config either from cfgFile or from home directory!
|
|
||||||
if cfgFile != "" {
|
if cfgFile != "" {
|
||||||
// Use config file from the flag.
|
// Use config file from the flag.
|
||||||
viper.SetConfigFile(cfgFile)
|
viper.SetConfigFile(cfgFile)
|
||||||
@ -240,8 +269,7 @@ func initConfig() {
|
|||||||
// Find home directory.
|
// Find home directory.
|
||||||
home, err := homedir.Dir()
|
home, err := homedir.Dir()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
er(err)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search config in home directory with name ".cobra" (without extension).
|
// Search config in home directory with name ".cobra" (without extension).
|
||||||
@ -249,9 +277,10 @@ func initConfig() {
|
|||||||
viper.SetConfigName(".cobra")
|
viper.SetConfigName(".cobra")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
viper.AutomaticEnv()
|
||||||
fmt.Println("Can't read config:", err)
|
|
||||||
os.Exit(1)
|
if err := viper.ReadInConfig(); err == nil {
|
||||||
|
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -459,7 +488,7 @@ For many years people have printed back to the screen.`,
|
|||||||
Echo works a lot like print, except it has a child command.`,
|
Echo works a lot like print, except it has a child command.`,
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Println("Print: " + strings.Join(args, " "))
|
fmt.Println("Echo: " + strings.Join(args, " "))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
vendor/github.com/spf13/cobra/args.go
generated
vendored
10
vendor/github.com/spf13/cobra/args.go
generated
vendored
@ -2,6 +2,7 @@ package cobra
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PositionalArgs func(cmd *Command, args []string) error
|
type PositionalArgs func(cmd *Command, args []string) error
|
||||||
@ -34,8 +35,15 @@ func NoArgs(cmd *Command, args []string) error {
|
|||||||
// OnlyValidArgs returns an error if any args are not in the list of ValidArgs.
|
// OnlyValidArgs returns an error if any args are not in the list of ValidArgs.
|
||||||
func OnlyValidArgs(cmd *Command, args []string) error {
|
func OnlyValidArgs(cmd *Command, args []string) error {
|
||||||
if len(cmd.ValidArgs) > 0 {
|
if len(cmd.ValidArgs) > 0 {
|
||||||
|
// Remove any description that may be included in ValidArgs.
|
||||||
|
// A description is following a tab character.
|
||||||
|
var validArgs []string
|
||||||
|
for _, v := range cmd.ValidArgs {
|
||||||
|
validArgs = append(validArgs, strings.Split(v, "\t")[0])
|
||||||
|
}
|
||||||
|
|
||||||
for _, v := range args {
|
for _, v := range args {
|
||||||
if !stringInSlice(v, cmd.ValidArgs) {
|
if !stringInSlice(v, validArgs) {
|
||||||
return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0]))
|
return fmt.Errorf("invalid argument %q for %q%s", v, cmd.CommandPath(), cmd.findSuggestions(args[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
104
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
104
vendor/github.com/spf13/cobra/bash_completions.go
generated
vendored
@ -58,9 +58,71 @@ __%[1]s_contains_word()
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__%[1]s_handle_go_custom_completion()
|
||||||
|
{
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: cur is ${cur}, words[*] is ${words[*]}, #words[@] is ${#words[@]}"
|
||||||
|
|
||||||
|
local out requestComp lastParam lastChar comp directive args
|
||||||
|
|
||||||
|
# Prepare the command to request completions for the program.
|
||||||
|
# Calling ${words[0]} instead of directly %[1]s allows to handle aliases
|
||||||
|
args=("${words[@]:1}")
|
||||||
|
requestComp="${words[0]} %[2]s ${args[*]}"
|
||||||
|
|
||||||
|
lastParam=${words[$((${#words[@]}-1))]}
|
||||||
|
lastChar=${lastParam:$((${#lastParam}-1)):1}
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: lastParam ${lastParam}, lastChar ${lastChar}"
|
||||||
|
|
||||||
|
if [ -z "${cur}" ] && [ "${lastChar}" != "=" ]; then
|
||||||
|
# If the last parameter is complete (there is a space following it)
|
||||||
|
# We add an extra empty parameter so we can indicate this to the go method.
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: Adding extra empty parameter"
|
||||||
|
requestComp="${requestComp} \"\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: calling ${requestComp}"
|
||||||
|
# Use eval to handle any environment variables and such
|
||||||
|
out=$(eval "${requestComp}" 2>/dev/null)
|
||||||
|
|
||||||
|
# Extract the directive integer at the very end of the output following a colon (:)
|
||||||
|
directive=${out##*:}
|
||||||
|
# Remove the directive
|
||||||
|
out=${out%%:*}
|
||||||
|
if [ "${directive}" = "${out}" ]; then
|
||||||
|
# There is not directive specified
|
||||||
|
directive=0
|
||||||
|
fi
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: the completion directive is: ${directive}"
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: the completions are: ${out[*]}"
|
||||||
|
|
||||||
|
if [ $((directive & %[3]d)) -ne 0 ]; then
|
||||||
|
# Error code. No completion.
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: received error from custom completion go code"
|
||||||
|
return
|
||||||
|
else
|
||||||
|
if [ $((directive & %[4]d)) -ne 0 ]; then
|
||||||
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: activating no space"
|
||||||
|
compopt -o nospace
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ $((directive & %[5]d)) -ne 0 ]; then
|
||||||
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
|
__%[1]s_debug "${FUNCNAME[0]}: activating no file completion"
|
||||||
|
compopt +o default
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
while IFS='' read -r comp; do
|
||||||
|
COMPREPLY+=("$comp")
|
||||||
|
done < <(compgen -W "${out[*]}" -- "$cur")
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
__%[1]s_handle_reply()
|
__%[1]s_handle_reply()
|
||||||
{
|
{
|
||||||
__%[1]s_debug "${FUNCNAME[0]}"
|
__%[1]s_debug "${FUNCNAME[0]}"
|
||||||
|
local comp
|
||||||
case $cur in
|
case $cur in
|
||||||
-*)
|
-*)
|
||||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
@ -72,7 +134,9 @@ __%[1]s_handle_reply()
|
|||||||
else
|
else
|
||||||
allflags=("${flags[*]} ${two_word_flags[*]}")
|
allflags=("${flags[*]} ${two_word_flags[*]}")
|
||||||
fi
|
fi
|
||||||
COMPREPLY=( $(compgen -W "${allflags[*]}" -- "$cur") )
|
while IFS='' read -r comp; do
|
||||||
|
COMPREPLY+=("$comp")
|
||||||
|
done < <(compgen -W "${allflags[*]}" -- "$cur")
|
||||||
if [[ $(type -t compopt) = "builtin" ]]; then
|
if [[ $(type -t compopt) = "builtin" ]]; then
|
||||||
[[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace
|
[[ "${COMPREPLY[0]}" == *= ]] || compopt +o nospace
|
||||||
fi
|
fi
|
||||||
@ -118,14 +182,22 @@ __%[1]s_handle_reply()
|
|||||||
completions=("${commands[@]}")
|
completions=("${commands[@]}")
|
||||||
if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
|
if [[ ${#must_have_one_noun[@]} -ne 0 ]]; then
|
||||||
completions=("${must_have_one_noun[@]}")
|
completions=("${must_have_one_noun[@]}")
|
||||||
|
elif [[ -n "${has_completion_function}" ]]; then
|
||||||
|
# if a go completion function is provided, defer to that function
|
||||||
|
completions=()
|
||||||
|
__%[1]s_handle_go_custom_completion
|
||||||
fi
|
fi
|
||||||
if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
|
if [[ ${#must_have_one_flag[@]} -ne 0 ]]; then
|
||||||
completions+=("${must_have_one_flag[@]}")
|
completions+=("${must_have_one_flag[@]}")
|
||||||
fi
|
fi
|
||||||
COMPREPLY=( $(compgen -W "${completions[*]}" -- "$cur") )
|
while IFS='' read -r comp; do
|
||||||
|
COMPREPLY+=("$comp")
|
||||||
|
done < <(compgen -W "${completions[*]}" -- "$cur")
|
||||||
|
|
||||||
if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then
|
if [[ ${#COMPREPLY[@]} -eq 0 && ${#noun_aliases[@]} -gt 0 && ${#must_have_one_noun[@]} -ne 0 ]]; then
|
||||||
COMPREPLY=( $(compgen -W "${noun_aliases[*]}" -- "$cur") )
|
while IFS='' read -r comp; do
|
||||||
|
COMPREPLY+=("$comp")
|
||||||
|
done < <(compgen -W "${noun_aliases[*]}" -- "$cur")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
|
if [[ ${#COMPREPLY[@]} -eq 0 ]]; then
|
||||||
@ -160,7 +232,7 @@ __%[1]s_handle_filename_extension_flag()
|
|||||||
__%[1]s_handle_subdirs_in_dir_flag()
|
__%[1]s_handle_subdirs_in_dir_flag()
|
||||||
{
|
{
|
||||||
local dir="$1"
|
local dir="$1"
|
||||||
pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1
|
pushd "${dir}" >/dev/null 2>&1 && _filedir -d && popd >/dev/null 2>&1 || return
|
||||||
}
|
}
|
||||||
|
|
||||||
__%[1]s_handle_flag()
|
__%[1]s_handle_flag()
|
||||||
@ -272,7 +344,7 @@ __%[1]s_handle_word()
|
|||||||
__%[1]s_handle_word
|
__%[1]s_handle_word
|
||||||
}
|
}
|
||||||
|
|
||||||
`, name))
|
`, name, ShellCompNoDescRequestCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp))
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePostscript(buf *bytes.Buffer, name string) {
|
func writePostscript(buf *bytes.Buffer, name string) {
|
||||||
@ -297,6 +369,7 @@ func writePostscript(buf *bytes.Buffer, name string) {
|
|||||||
local commands=("%[1]s")
|
local commands=("%[1]s")
|
||||||
local must_have_one_flag=()
|
local must_have_one_flag=()
|
||||||
local must_have_one_noun=()
|
local must_have_one_noun=()
|
||||||
|
local has_completion_function
|
||||||
local last_command
|
local last_command
|
||||||
local nouns=()
|
local nouns=()
|
||||||
|
|
||||||
@ -397,7 +470,22 @@ func writeLocalNonPersistentFlag(buf *bytes.Buffer, flag *pflag.Flag) {
|
|||||||
buf.WriteString(fmt.Sprintf(format, name))
|
buf.WriteString(fmt.Sprintf(format, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup annotations for go completions for registered flags
|
||||||
|
func prepareCustomAnnotationsForFlags(cmd *Command) {
|
||||||
|
for flag := range flagCompletionFunctions {
|
||||||
|
// Make sure the completion script calls the __*_go_custom_completion function for
|
||||||
|
// every registered flag. We need to do this here (and not when the flag was registered
|
||||||
|
// for completion) so that we can know the root command name for the prefix
|
||||||
|
// of __<prefix>_go_custom_completion
|
||||||
|
if flag.Annotations == nil {
|
||||||
|
flag.Annotations = map[string][]string{}
|
||||||
|
}
|
||||||
|
flag.Annotations[BashCompCustom] = []string{fmt.Sprintf("__%[1]s_handle_go_custom_completion", cmd.Root().Name())}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
func writeFlags(buf *bytes.Buffer, cmd *Command) {
|
||||||
|
prepareCustomAnnotationsForFlags(cmd)
|
||||||
buf.WriteString(` flags=()
|
buf.WriteString(` flags=()
|
||||||
two_word_flags=()
|
two_word_flags=()
|
||||||
local_nonpersistent_flags=()
|
local_nonpersistent_flags=()
|
||||||
@ -460,8 +548,14 @@ func writeRequiredNouns(buf *bytes.Buffer, cmd *Command) {
|
|||||||
buf.WriteString(" must_have_one_noun=()\n")
|
buf.WriteString(" must_have_one_noun=()\n")
|
||||||
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
sort.Sort(sort.StringSlice(cmd.ValidArgs))
|
||||||
for _, value := range cmd.ValidArgs {
|
for _, value := range cmd.ValidArgs {
|
||||||
|
// Remove any description that may be included following a tab character.
|
||||||
|
// Descriptions are not supported by bash completion.
|
||||||
|
value = strings.Split(value, "\t")[0]
|
||||||
buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
|
buf.WriteString(fmt.Sprintf(" must_have_one_noun+=(%q)\n", value))
|
||||||
}
|
}
|
||||||
|
if cmd.ValidArgsFunction != nil {
|
||||||
|
buf.WriteString(" has_completion_function=1\n")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeCmdAliases(buf *bytes.Buffer, cmd *Command) {
|
func writeCmdAliases(buf *bytes.Buffer, cmd *Command) {
|
||||||
|
|||||||
239
vendor/github.com/spf13/cobra/bash_completions.md
generated
vendored
239
vendor/github.com/spf13/cobra/bash_completions.md
generated
vendored
@ -56,7 +56,149 @@ func main() {
|
|||||||
|
|
||||||
`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior.
|
`out.sh` will get you completions of subcommands and flags. Copy it to `/etc/bash_completion.d/` as described [here](https://debian-administration.org/article/316/An_introduction_to_bash_completion_part_1) and reset your terminal to use autocompletion. If you make additional annotations to your code, you can get even more intelligent and flexible behavior.
|
||||||
|
|
||||||
## Creating your own custom functions
|
## Have the completions code complete your 'nouns'
|
||||||
|
|
||||||
|
### Static completion of nouns
|
||||||
|
|
||||||
|
This method allows you to provide a pre-defined list of completion choices for your nouns using the `validArgs` field.
|
||||||
|
For example, if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like:
|
||||||
|
|
||||||
|
```go
|
||||||
|
validArgs []string = { "pod", "node", "service", "replicationcontroller" }
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
|
||||||
|
Short: "Display one or many resources",
|
||||||
|
Long: get_long,
|
||||||
|
Example: get_example,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
err := RunGet(f, out, cmd, args)
|
||||||
|
util.CheckErr(err)
|
||||||
|
},
|
||||||
|
ValidArgs: validArgs,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# kubectl get [tab][tab]
|
||||||
|
node pod replicationcontroller service
|
||||||
|
```
|
||||||
|
|
||||||
|
### Plural form and shortcuts for nouns
|
||||||
|
|
||||||
|
If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`:
|
||||||
|
|
||||||
|
```go
|
||||||
|
argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" }
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
...
|
||||||
|
ValidArgs: validArgs,
|
||||||
|
ArgAliases: argAliases
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by
|
||||||
|
the completion algorithm if entered manually, e.g. in:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# kubectl get rc [tab][tab]
|
||||||
|
backend frontend database
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns
|
||||||
|
in this example again instead of the replication controllers.
|
||||||
|
|
||||||
|
### Dynamic completion of nouns
|
||||||
|
|
||||||
|
In some cases it is not possible to provide a list of possible completions in advance. Instead, the list of completions must be determined at execution-time. Cobra provides two ways of defining such dynamic completion of nouns. Note that both these methods can be used along-side each other as long as they are not both used for the same command.
|
||||||
|
|
||||||
|
**Note**: *Custom Completions written in Go* will automatically work for other shell-completion scripts (e.g., Fish shell), while *Custom Completions written in Bash* will only work for Bash shell-completion. It is therefore recommended to use *Custom Completions written in Go*.
|
||||||
|
|
||||||
|
#### 1. Custom completions of nouns written in Go
|
||||||
|
|
||||||
|
In a similar fashion as for static completions, you can use the `ValidArgsFunction` field to provide a Go function that Cobra will execute when it needs the list of completion choices for the nouns of a command. Note that either `ValidArgs` or `ValidArgsFunction` can be used for a single cobra command, but not both.
|
||||||
|
Simplified code from `helm status` looks like:
|
||||||
|
|
||||||
|
```go
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "status RELEASE_NAME",
|
||||||
|
Short: "Display the status of the named release",
|
||||||
|
Long: status_long,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) {
|
||||||
|
RunGet(args[0])
|
||||||
|
},
|
||||||
|
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
return nil, cobra.ShellCompDirectiveNoFileComp
|
||||||
|
}
|
||||||
|
return getReleasesFromCluster(toComplete), cobra.ShellCompDirectiveNoFileComp
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
Where `getReleasesFromCluster()` is a Go function that obtains the list of current Helm releases running on the Kubernetes cluster.
|
||||||
|
Notice we put the `ValidArgsFunction` on the `status` subcommand. Let's assume the Helm releases on the cluster are: `harbor`, `notary`, `rook` and `thanos` then this dynamic completion will give results like
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# helm status [tab][tab]
|
||||||
|
harbor notary rook thanos
|
||||||
|
```
|
||||||
|
You may have noticed the use of `cobra.ShellCompDirective`. These directives are bit fields allowing to control some shell completion behaviors for your particular completion. You can combine them with the bit-or operator such as `cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp`
|
||||||
|
```go
|
||||||
|
// Indicates an error occurred and completions should be ignored.
|
||||||
|
ShellCompDirectiveError
|
||||||
|
// Indicates that the shell should not add a space after the completion,
|
||||||
|
// even if there is a single completion provided.
|
||||||
|
ShellCompDirectiveNoSpace
|
||||||
|
// Indicates that the shell should not provide file completion even when
|
||||||
|
// no completion is provided.
|
||||||
|
// This currently does not work for zsh or bash < 4
|
||||||
|
ShellCompDirectiveNoFileComp
|
||||||
|
// Indicates that the shell will perform its default behavior after completions
|
||||||
|
// have been provided (this implies !ShellCompDirectiveNoSpace && !ShellCompDirectiveNoFileComp).
|
||||||
|
ShellCompDirectiveDefault
|
||||||
|
```
|
||||||
|
|
||||||
|
When using the `ValidArgsFunction`, Cobra will call your registered function after having parsed all flags and arguments provided in the command-line. You therefore don't need to do this parsing yourself. For example, when a user calls `helm status --namespace my-rook-ns [tab][tab]`, Cobra will call your registered `ValidArgsFunction` after having parsed the `--namespace` flag, as it would have done when calling the `RunE` function.
|
||||||
|
|
||||||
|
##### Debugging
|
||||||
|
|
||||||
|
Cobra achieves dynamic completions written in Go through the use of a hidden command called by the completion script. To debug your Go completion code, you can call this hidden command directly:
|
||||||
|
```bash
|
||||||
|
# helm __complete status har<ENTER>
|
||||||
|
harbor
|
||||||
|
:4
|
||||||
|
Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr
|
||||||
|
```
|
||||||
|
***Important:*** If the noun to complete is empty, you must pass an empty parameter to the `__complete` command:
|
||||||
|
```bash
|
||||||
|
# helm __complete status ""<ENTER>
|
||||||
|
harbor
|
||||||
|
notary
|
||||||
|
rook
|
||||||
|
thanos
|
||||||
|
:4
|
||||||
|
Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr
|
||||||
|
```
|
||||||
|
Calling the `__complete` command directly allows you to run the Go debugger to troubleshoot your code. You can also add printouts to your code; Cobra provides the following functions to use for printouts in Go completion code:
|
||||||
|
```go
|
||||||
|
// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE
|
||||||
|
// is set to a file path) and optionally prints to stderr.
|
||||||
|
cobra.CompDebug(msg string, printToStdErr bool) {
|
||||||
|
cobra.CompDebugln(msg string, printToStdErr bool)
|
||||||
|
|
||||||
|
// Prints to the completion script debug file (if BASH_COMP_DEBUG_FILE
|
||||||
|
// is set to a file path) and to stderr.
|
||||||
|
cobra.CompError(msg string)
|
||||||
|
cobra.CompErrorln(msg string)
|
||||||
|
```
|
||||||
|
***Important:*** You should **not** leave traces that print to stdout in your completion code as they will be interpreted as completion choices by the completion script. Instead, use the cobra-provided debugging traces functions mentioned above.
|
||||||
|
|
||||||
|
#### 2. Custom completions of nouns written in Bash
|
||||||
|
|
||||||
|
This method allows you to inject bash functions into the completion script. Those bash functions are responsible for providing the completion choices for your own completions.
|
||||||
|
|
||||||
Some more actual code that works in kubernetes:
|
Some more actual code that works in kubernetes:
|
||||||
|
|
||||||
@ -111,58 +253,6 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
|||||||
|
|
||||||
The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__kubectl_custom_func()` (`__<command-use>_custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods!
|
The `BashCompletionFunction` option is really only valid/useful on the root command. Doing the above will cause `__kubectl_custom_func()` (`__<command-use>_custom_func()`) to be called when the built in processor was unable to find a solution. In the case of kubernetes a valid command might look something like `kubectl get pod [mypod]`. If you type `kubectl get pod [tab][tab]` the `__kubectl_customc_func()` will run because the cobra.Command only understood "kubectl" and "get." `__kubectl_custom_func()` will see that the cobra.Command is "kubectl_get" and will thus call another helper `__kubectl_get_resource()`. `__kubectl_get_resource` will look at the 'nouns' collected. In our example the only noun will be `pod`. So it will call `__kubectl_parse_get pod`. `__kubectl_parse_get` will actually call out to kubernetes and get any pods. It will then set `COMPREPLY` to valid pods!
|
||||||
|
|
||||||
## Have the completions code complete your 'nouns'
|
|
||||||
|
|
||||||
In the above example "pod" was assumed to already be typed. But if you want `kubectl get [tab][tab]` to show a list of valid "nouns" you have to set them. Simplified code from `kubectl get` looks like:
|
|
||||||
|
|
||||||
```go
|
|
||||||
validArgs []string = { "pod", "node", "service", "replicationcontroller" }
|
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
|
|
||||||
Short: "Display one or many resources",
|
|
||||||
Long: get_long,
|
|
||||||
Example: get_example,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
err := RunGet(f, out, cmd, args)
|
|
||||||
util.CheckErr(err)
|
|
||||||
},
|
|
||||||
ValidArgs: validArgs,
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice we put the "ValidArgs" on the "get" subcommand. Doing so will give results like
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# kubectl get [tab][tab]
|
|
||||||
node pod replicationcontroller service
|
|
||||||
```
|
|
||||||
|
|
||||||
## Plural form and shortcuts for nouns
|
|
||||||
|
|
||||||
If your nouns have a number of aliases, you can define them alongside `ValidArgs` using `ArgAliases`:
|
|
||||||
|
|
||||||
```go
|
|
||||||
argAliases []string = { "pods", "nodes", "services", "svc", "replicationcontrollers", "rc" }
|
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
|
||||||
...
|
|
||||||
ValidArgs: validArgs,
|
|
||||||
ArgAliases: argAliases
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The aliases are not shown to the user on tab completion, but they are accepted as valid nouns by
|
|
||||||
the completion algorithm if entered manually, e.g. in:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# kubectl get rc [tab][tab]
|
|
||||||
backend frontend database
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that without declaring `rc` as an alias, the completion algorithm would show the list of nouns
|
|
||||||
in this example again instead of the replication controllers.
|
|
||||||
|
|
||||||
## Mark flags as required
|
## Mark flags as required
|
||||||
|
|
||||||
Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy.
|
Most of the time completions will only show subcommands. But if a flag is required to make a subcommand work, you probably want it to show up when the user types [tab][tab]. Marking a flag as 'Required' is incredibly easy.
|
||||||
@ -211,8 +301,45 @@ So while there are many other files in the CWD it only shows me subdirs and thos
|
|||||||
|
|
||||||
# Specify custom flag completion
|
# Specify custom flag completion
|
||||||
|
|
||||||
Similar to the filename completion and filtering using cobra.BashCompFilenameExt, you can specify
|
As for nouns, Cobra provides two ways of defining dynamic completion of flags. Note that both these methods can be used along-side each other as long as they are not both used for the same flag.
|
||||||
a custom flag completion function with cobra.BashCompCustom:
|
|
||||||
|
**Note**: *Custom Completions written in Go* will automatically work for other shell-completion scripts (e.g., Fish shell), while *Custom Completions written in Bash* will only work for Bash shell-completion. It is therefore recommended to use *Custom Completions written in Go*.
|
||||||
|
|
||||||
|
## 1. Custom completions of flags written in Go
|
||||||
|
|
||||||
|
To provide a Go function that Cobra will execute when it needs the list of completion choices for a flag, you must register the function in the following manner:
|
||||||
|
|
||||||
|
```go
|
||||||
|
flagName := "output"
|
||||||
|
cmd.RegisterFlagCompletionFunc(flagName, func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
|
return []string{"json", "table", "yaml"}, cobra.ShellCompDirectiveDefault
|
||||||
|
})
|
||||||
|
```
|
||||||
|
Notice that calling `RegisterFlagCompletionFunc()` is done through the `command` with which the flag is associated. In our example this dynamic completion will give results like so:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# helm status --output [tab][tab]
|
||||||
|
json table yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debugging
|
||||||
|
|
||||||
|
You can also easily debug your Go completion code for flags:
|
||||||
|
```bash
|
||||||
|
# helm __complete status --output ""
|
||||||
|
json
|
||||||
|
table
|
||||||
|
yaml
|
||||||
|
:4
|
||||||
|
Completion ended with directive: ShellCompDirectiveNoFileComp # This is on stderr
|
||||||
|
```
|
||||||
|
***Important:*** You should **not** leave traces that print to stdout in your completion code as they will be interpreted as completion choices by the completion script. Instead, use the cobra-provided debugging traces functions mentioned in the above section.
|
||||||
|
|
||||||
|
## 2. Custom completions of flags written in Bash
|
||||||
|
|
||||||
|
Alternatively, you can use bash code for flag custom completion. Similar to the filename
|
||||||
|
completion and filtering using `cobra.BashCompFilenameExt`, you can specify
|
||||||
|
a custom flag completion bash function with `cobra.BashCompCustom`:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
annotation := make(map[string][]string)
|
annotation := make(map[string][]string)
|
||||||
@ -226,7 +353,7 @@ a custom flag completion function with cobra.BashCompCustom:
|
|||||||
cmd.Flags().AddFlag(flag)
|
cmd.Flags().AddFlag(flag)
|
||||||
```
|
```
|
||||||
|
|
||||||
In addition add the `__handle_namespace_flag` implementation in the `BashCompletionFunction`
|
In addition add the `__kubectl_get_namespaces` implementation in the `BashCompletionFunction`
|
||||||
value, e.g.:
|
value, e.g.:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
4
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
4
vendor/github.com/spf13/cobra/cobra.go
generated
vendored
@ -52,7 +52,7 @@ var EnableCommandSorting = true
|
|||||||
// if the CLI is started from explorer.exe.
|
// if the CLI is started from explorer.exe.
|
||||||
// To disable the mousetrap, just set this variable to blank string ("").
|
// To disable the mousetrap, just set this variable to blank string ("").
|
||||||
// Works only on Microsoft Windows.
|
// Works only on Microsoft Windows.
|
||||||
var MousetrapHelpText string = `This is a command line tool.
|
var MousetrapHelpText = `This is a command line tool.
|
||||||
|
|
||||||
You need to open cmd.exe and run it from there.
|
You need to open cmd.exe and run it from there.
|
||||||
`
|
`
|
||||||
@ -61,7 +61,7 @@ You need to open cmd.exe and run it from there.
|
|||||||
// if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed.
|
// if the CLI is started from explorer.exe. Set to 0 to wait for the return key to be pressed.
|
||||||
// To disable the mousetrap, just set MousetrapHelpText to blank string ("").
|
// To disable the mousetrap, just set MousetrapHelpText to blank string ("").
|
||||||
// Works only on Microsoft Windows.
|
// Works only on Microsoft Windows.
|
||||||
var MousetrapDisplayDuration time.Duration = 5 * time.Second
|
var MousetrapDisplayDuration = 5 * time.Second
|
||||||
|
|
||||||
// AddTemplateFunc adds a template function that's available to Usage and Help
|
// AddTemplateFunc adds a template function that's available to Usage and Help
|
||||||
// template generation.
|
// template generation.
|
||||||
|
|||||||
50
vendor/github.com/spf13/cobra/command.go
generated
vendored
50
vendor/github.com/spf13/cobra/command.go
generated
vendored
@ -17,6 +17,7 @@ package cobra
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -56,6 +57,10 @@ type Command struct {
|
|||||||
|
|
||||||
// ValidArgs is list of all valid non-flag arguments that are accepted in bash completions
|
// ValidArgs is list of all valid non-flag arguments that are accepted in bash completions
|
||||||
ValidArgs []string
|
ValidArgs []string
|
||||||
|
// ValidArgsFunction is an optional function that provides valid non-flag arguments for bash completion.
|
||||||
|
// It is a dynamic version of using ValidArgs.
|
||||||
|
// Only one of ValidArgs and ValidArgsFunction can be used for a command.
|
||||||
|
ValidArgsFunction func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
||||||
|
|
||||||
// Expected arguments
|
// Expected arguments
|
||||||
Args PositionalArgs
|
Args PositionalArgs
|
||||||
@ -80,7 +85,8 @@ type Command struct {
|
|||||||
|
|
||||||
// Version defines the version for this command. If this value is non-empty and the command does not
|
// Version defines the version for this command. If this value is non-empty and the command does not
|
||||||
// define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
|
// define a "version" flag, a "version" boolean flag will be added to the command and, if specified,
|
||||||
// will print content of the "Version" variable.
|
// will print content of the "Version" variable. A shorthand "v" flag will also be added if the
|
||||||
|
// command does not define one.
|
||||||
Version string
|
Version string
|
||||||
|
|
||||||
// The *Run functions are executed in the following order:
|
// The *Run functions are executed in the following order:
|
||||||
@ -140,9 +146,11 @@ type Command struct {
|
|||||||
// TraverseChildren parses flags on all parents before executing child command.
|
// TraverseChildren parses flags on all parents before executing child command.
|
||||||
TraverseChildren bool
|
TraverseChildren bool
|
||||||
|
|
||||||
//FParseErrWhitelist flag parse errors to be ignored
|
// FParseErrWhitelist flag parse errors to be ignored
|
||||||
FParseErrWhitelist FParseErrWhitelist
|
FParseErrWhitelist FParseErrWhitelist
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
|
||||||
// commands is the list of commands supported by this program.
|
// commands is the list of commands supported by this program.
|
||||||
commands []*Command
|
commands []*Command
|
||||||
// parent is a parent command for this command.
|
// parent is a parent command for this command.
|
||||||
@ -202,6 +210,12 @@ type Command struct {
|
|||||||
errWriter io.Writer
|
errWriter io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Context returns underlying command context. If command wasn't
|
||||||
|
// executed with ExecuteContext Context returns Background context.
|
||||||
|
func (c *Command) Context() context.Context {
|
||||||
|
return c.ctx
|
||||||
|
}
|
||||||
|
|
||||||
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
// SetArgs sets arguments for the command. It is set to os.Args[1:] by default, if desired, can be overridden
|
||||||
// particularly useful when testing.
|
// particularly useful when testing.
|
||||||
func (c *Command) SetArgs(a []string) {
|
func (c *Command) SetArgs(a []string) {
|
||||||
@ -228,7 +242,7 @@ func (c *Command) SetErr(newErr io.Writer) {
|
|||||||
c.errWriter = newErr
|
c.errWriter = newErr
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetOut sets the source for input data
|
// SetIn sets the source for input data
|
||||||
// If newIn is nil, os.Stdin is used.
|
// If newIn is nil, os.Stdin is used.
|
||||||
func (c *Command) SetIn(newIn io.Reader) {
|
func (c *Command) SetIn(newIn io.Reader) {
|
||||||
c.inReader = newIn
|
c.inReader = newIn
|
||||||
@ -297,7 +311,7 @@ func (c *Command) ErrOrStderr() io.Writer {
|
|||||||
return c.getErr(os.Stderr)
|
return c.getErr(os.Stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrOrStderr returns output to stderr
|
// InOrStdin returns input to stdin
|
||||||
func (c *Command) InOrStdin() io.Reader {
|
func (c *Command) InOrStdin() io.Reader {
|
||||||
return c.getIn(os.Stdin)
|
return c.getIn(os.Stdin)
|
||||||
}
|
}
|
||||||
@ -369,6 +383,8 @@ func (c *Command) HelpFunc() func(*Command, []string) {
|
|||||||
}
|
}
|
||||||
return func(c *Command, a []string) {
|
return func(c *Command, a []string) {
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
// The help should be sent to stdout
|
||||||
|
// See https://github.com/spf13/cobra/issues/1002
|
||||||
err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
|
err := tmpl(c.OutOrStdout(), c.HelpTemplate(), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Println(err)
|
c.Println(err)
|
||||||
@ -857,6 +873,13 @@ func (c *Command) preRun() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExecuteContext is the same as Execute(), but sets the ctx on the command.
|
||||||
|
// Retrieve ctx by calling cmd.Context() inside your *Run lifecycle functions.
|
||||||
|
func (c *Command) ExecuteContext(ctx context.Context) error {
|
||||||
|
c.ctx = ctx
|
||||||
|
return c.Execute()
|
||||||
|
}
|
||||||
|
|
||||||
// Execute uses the args (os.Args[1:] by default)
|
// Execute uses the args (os.Args[1:] by default)
|
||||||
// and run through the command tree finding appropriate matches
|
// and run through the command tree finding appropriate matches
|
||||||
// for commands and then corresponding flags.
|
// for commands and then corresponding flags.
|
||||||
@ -867,6 +890,10 @@ func (c *Command) Execute() error {
|
|||||||
|
|
||||||
// ExecuteC executes the command.
|
// ExecuteC executes the command.
|
||||||
func (c *Command) ExecuteC() (cmd *Command, err error) {
|
func (c *Command) ExecuteC() (cmd *Command, err error) {
|
||||||
|
if c.ctx == nil {
|
||||||
|
c.ctx = context.Background()
|
||||||
|
}
|
||||||
|
|
||||||
// Regardless of what command execute is called on, run on Root only
|
// Regardless of what command execute is called on, run on Root only
|
||||||
if c.HasParent() {
|
if c.HasParent() {
|
||||||
return c.Root().ExecuteC()
|
return c.Root().ExecuteC()
|
||||||
@ -888,6 +915,9 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
|||||||
args = os.Args[1:]
|
args = os.Args[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize the hidden command to be used for bash completion
|
||||||
|
c.initCompleteCmd(args)
|
||||||
|
|
||||||
var flags []string
|
var flags []string
|
||||||
if c.TraverseChildren {
|
if c.TraverseChildren {
|
||||||
cmd, flags, err = c.Traverse(args)
|
cmd, flags, err = c.Traverse(args)
|
||||||
@ -911,6 +941,12 @@ func (c *Command) ExecuteC() (cmd *Command, err error) {
|
|||||||
cmd.commandCalledAs.name = cmd.Name()
|
cmd.commandCalledAs.name = cmd.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We have to pass global context to children command
|
||||||
|
// if context is present on the parent command.
|
||||||
|
if cmd.ctx == nil {
|
||||||
|
cmd.ctx = c.ctx
|
||||||
|
}
|
||||||
|
|
||||||
err = cmd.execute(flags)
|
err = cmd.execute(flags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Always show help if requested, even if SilenceErrors is in
|
// Always show help if requested, even if SilenceErrors is in
|
||||||
@ -994,8 +1030,12 @@ func (c *Command) InitDefaultVersionFlag() {
|
|||||||
} else {
|
} else {
|
||||||
usage += c.Name()
|
usage += c.Name()
|
||||||
}
|
}
|
||||||
|
if c.Flags().ShorthandLookup("v") == nil {
|
||||||
|
c.Flags().BoolP("version", "v", false, usage)
|
||||||
|
} else {
|
||||||
c.Flags().Bool("version", false, usage)
|
c.Flags().Bool("version", false, usage)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitDefaultHelpCmd adds default help command to c.
|
// InitDefaultHelpCmd adds default help command to c.
|
||||||
@ -1547,7 +1587,7 @@ func (c *Command) ParseFlags(args []string) error {
|
|||||||
beforeErrorBufLen := c.flagErrorBuf.Len()
|
beforeErrorBufLen := c.flagErrorBuf.Len()
|
||||||
c.mergePersistentFlags()
|
c.mergePersistentFlags()
|
||||||
|
|
||||||
//do it here after merging all flags and just before parse
|
// do it here after merging all flags and just before parse
|
||||||
c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
|
c.Flags().ParseErrorsWhitelist = flag.ParseErrorsWhitelist(c.FParseErrWhitelist)
|
||||||
|
|
||||||
err := c.Flags().Parse(args)
|
err := c.Flags().Parse(args)
|
||||||
|
|||||||
384
vendor/github.com/spf13/cobra/custom_completions.go
generated
vendored
Normal file
384
vendor/github.com/spf13/cobra/custom_completions.go
generated
vendored
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
package cobra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ShellCompRequestCmd is the name of the hidden command that is used to request
|
||||||
|
// completion results from the program. It is used by the shell completion scripts.
|
||||||
|
ShellCompRequestCmd = "__complete"
|
||||||
|
// ShellCompNoDescRequestCmd is the name of the hidden command that is used to request
|
||||||
|
// completion results without their description. It is used by the shell completion scripts.
|
||||||
|
ShellCompNoDescRequestCmd = "__completeNoDesc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Global map of flag completion functions.
|
||||||
|
var flagCompletionFunctions = map[*pflag.Flag]func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective){}
|
||||||
|
|
||||||
|
// ShellCompDirective is a bit map representing the different behaviors the shell
|
||||||
|
// can be instructed to have once completions have been provided.
|
||||||
|
type ShellCompDirective int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// ShellCompDirectiveError indicates an error occurred and completions should be ignored.
|
||||||
|
ShellCompDirectiveError ShellCompDirective = 1 << iota
|
||||||
|
|
||||||
|
// ShellCompDirectiveNoSpace indicates that the shell should not add a space
|
||||||
|
// after the completion even if there is a single completion provided.
|
||||||
|
ShellCompDirectiveNoSpace
|
||||||
|
|
||||||
|
// ShellCompDirectiveNoFileComp indicates that the shell should not provide
|
||||||
|
// file completion even when no completion is provided.
|
||||||
|
// This currently does not work for zsh or bash < 4
|
||||||
|
ShellCompDirectiveNoFileComp
|
||||||
|
|
||||||
|
// ShellCompDirectiveDefault indicates to let the shell perform its default
|
||||||
|
// behavior after completions have been provided.
|
||||||
|
ShellCompDirectiveDefault ShellCompDirective = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
// RegisterFlagCompletionFunc should be called to register a function to provide completion for a flag.
|
||||||
|
func (c *Command) RegisterFlagCompletionFunc(flagName string, f func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)) error {
|
||||||
|
flag := c.Flag(flagName)
|
||||||
|
if flag == nil {
|
||||||
|
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' does not exist", flagName)
|
||||||
|
}
|
||||||
|
if _, exists := flagCompletionFunctions[flag]; exists {
|
||||||
|
return fmt.Errorf("RegisterFlagCompletionFunc: flag '%s' already registered", flagName)
|
||||||
|
}
|
||||||
|
flagCompletionFunctions[flag] = f
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a string listing the different directive enabled in the specified parameter
|
||||||
|
func (d ShellCompDirective) string() string {
|
||||||
|
var directives []string
|
||||||
|
if d&ShellCompDirectiveError != 0 {
|
||||||
|
directives = append(directives, "ShellCompDirectiveError")
|
||||||
|
}
|
||||||
|
if d&ShellCompDirectiveNoSpace != 0 {
|
||||||
|
directives = append(directives, "ShellCompDirectiveNoSpace")
|
||||||
|
}
|
||||||
|
if d&ShellCompDirectiveNoFileComp != 0 {
|
||||||
|
directives = append(directives, "ShellCompDirectiveNoFileComp")
|
||||||
|
}
|
||||||
|
if len(directives) == 0 {
|
||||||
|
directives = append(directives, "ShellCompDirectiveDefault")
|
||||||
|
}
|
||||||
|
|
||||||
|
if d > ShellCompDirectiveError+ShellCompDirectiveNoSpace+ShellCompDirectiveNoFileComp {
|
||||||
|
return fmt.Sprintf("ERROR: unexpected ShellCompDirective value: %d", d)
|
||||||
|
}
|
||||||
|
return strings.Join(directives, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds a special hidden command that can be used to request custom completions.
|
||||||
|
func (c *Command) initCompleteCmd(args []string) {
|
||||||
|
completeCmd := &Command{
|
||||||
|
Use: fmt.Sprintf("%s [command-line]", ShellCompRequestCmd),
|
||||||
|
Aliases: []string{ShellCompNoDescRequestCmd},
|
||||||
|
DisableFlagsInUseLine: true,
|
||||||
|
Hidden: true,
|
||||||
|
DisableFlagParsing: true,
|
||||||
|
Args: MinimumNArgs(1),
|
||||||
|
Short: "Request shell completion choices for the specified command-line",
|
||||||
|
Long: fmt.Sprintf("%[2]s is a special command that is used by the shell completion logic\n%[1]s",
|
||||||
|
"to request completion choices for the specified command-line.", ShellCompRequestCmd),
|
||||||
|
Run: func(cmd *Command, args []string) {
|
||||||
|
finalCmd, completions, directive, err := cmd.getCompletions(args)
|
||||||
|
if err != nil {
|
||||||
|
CompErrorln(err.Error())
|
||||||
|
// Keep going for multiple reasons:
|
||||||
|
// 1- There could be some valid completions even though there was an error
|
||||||
|
// 2- Even without completions, we need to print the directive
|
||||||
|
}
|
||||||
|
|
||||||
|
noDescriptions := (cmd.CalledAs() == ShellCompNoDescRequestCmd)
|
||||||
|
for _, comp := range completions {
|
||||||
|
if noDescriptions {
|
||||||
|
// Remove any description that may be included following a tab character.
|
||||||
|
comp = strings.Split(comp, "\t")[0]
|
||||||
|
}
|
||||||
|
// Print each possible completion to stdout for the completion script to consume.
|
||||||
|
fmt.Fprintln(finalCmd.OutOrStdout(), comp)
|
||||||
|
}
|
||||||
|
|
||||||
|
if directive > ShellCompDirectiveError+ShellCompDirectiveNoSpace+ShellCompDirectiveNoFileComp {
|
||||||
|
directive = ShellCompDirectiveDefault
|
||||||
|
}
|
||||||
|
|
||||||
|
// As the last printout, print the completion directive for the completion script to parse.
|
||||||
|
// The directive integer must be that last character following a single colon (:).
|
||||||
|
// The completion script expects :<directive>
|
||||||
|
fmt.Fprintf(finalCmd.OutOrStdout(), ":%d\n", directive)
|
||||||
|
|
||||||
|
// Print some helpful info to stderr for the user to understand.
|
||||||
|
// Output from stderr must be ignored by the completion script.
|
||||||
|
fmt.Fprintf(finalCmd.ErrOrStderr(), "Completion ended with directive: %s\n", directive.string())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c.AddCommand(completeCmd)
|
||||||
|
subCmd, _, err := c.Find(args)
|
||||||
|
if err != nil || subCmd.Name() != ShellCompRequestCmd {
|
||||||
|
// Only create this special command if it is actually being called.
|
||||||
|
// This reduces possible side-effects of creating such a command;
|
||||||
|
// for example, having this command would cause problems to a
|
||||||
|
// cobra program that only consists of the root command, since this
|
||||||
|
// command would cause the root command to suddenly have a subcommand.
|
||||||
|
c.RemoveCommand(completeCmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Command) getCompletions(args []string) (*Command, []string, ShellCompDirective, error) {
|
||||||
|
var completions []string
|
||||||
|
|
||||||
|
// The last argument, which is not completely typed by the user,
|
||||||
|
// should not be part of the list of arguments
|
||||||
|
toComplete := args[len(args)-1]
|
||||||
|
trimmedArgs := args[:len(args)-1]
|
||||||
|
|
||||||
|
// Find the real command for which completion must be performed
|
||||||
|
finalCmd, finalArgs, err := c.Root().Find(trimmedArgs)
|
||||||
|
if err != nil {
|
||||||
|
// Unable to find the real command. E.g., <program> someInvalidCmd <TAB>
|
||||||
|
return c, completions, ShellCompDirectiveDefault, fmt.Errorf("Unable to find a command for arguments: %v", trimmedArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// When doing completion of a flag name, as soon as an argument starts with
|
||||||
|
// a '-' we know it is a flag. We cannot use isFlagArg() here as it requires
|
||||||
|
// the flag to be complete
|
||||||
|
if len(toComplete) > 0 && toComplete[0] == '-' && !strings.Contains(toComplete, "=") {
|
||||||
|
// We are completing a flag name
|
||||||
|
finalCmd.NonInheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
|
completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
|
||||||
|
})
|
||||||
|
finalCmd.InheritedFlags().VisitAll(func(flag *pflag.Flag) {
|
||||||
|
completions = append(completions, getFlagNameCompletions(flag, toComplete)...)
|
||||||
|
})
|
||||||
|
|
||||||
|
directive := ShellCompDirectiveDefault
|
||||||
|
if len(completions) > 0 {
|
||||||
|
if strings.HasSuffix(completions[0], "=") {
|
||||||
|
directive = ShellCompDirectiveNoSpace
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finalCmd, completions, directive, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var flag *pflag.Flag
|
||||||
|
if !finalCmd.DisableFlagParsing {
|
||||||
|
// We only do flag completion if we are allowed to parse flags
|
||||||
|
// This is important for commands which have requested to do their own flag completion.
|
||||||
|
flag, finalArgs, toComplete, err = checkIfFlagCompletion(finalCmd, finalArgs, toComplete)
|
||||||
|
if err != nil {
|
||||||
|
// Error while attempting to parse flags
|
||||||
|
return finalCmd, completions, ShellCompDirectiveDefault, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if flag == nil {
|
||||||
|
// Complete subcommand names
|
||||||
|
for _, subCmd := range finalCmd.Commands() {
|
||||||
|
if subCmd.IsAvailableCommand() && strings.HasPrefix(subCmd.Name(), toComplete) {
|
||||||
|
completions = append(completions, fmt.Sprintf("%s\t%s", subCmd.Name(), subCmd.Short))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(finalCmd.ValidArgs) > 0 {
|
||||||
|
// Always complete ValidArgs, even if we are completing a subcommand name.
|
||||||
|
// This is for commands that have both subcommands and ValidArgs.
|
||||||
|
for _, validArg := range finalCmd.ValidArgs {
|
||||||
|
if strings.HasPrefix(validArg, toComplete) {
|
||||||
|
completions = append(completions, validArg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are ValidArgs specified (even if they don't match), we stop completion.
|
||||||
|
// Only one of ValidArgs or ValidArgsFunction can be used for a single command.
|
||||||
|
return finalCmd, completions, ShellCompDirectiveNoFileComp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always let the logic continue so as to add any ValidArgsFunction completions,
|
||||||
|
// even if we already found sub-commands.
|
||||||
|
// This is for commands that have subcommands but also specify a ValidArgsFunction.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the flags and extract the arguments to prepare for calling the completion function
|
||||||
|
if err = finalCmd.ParseFlags(finalArgs); err != nil {
|
||||||
|
return finalCmd, completions, ShellCompDirectiveDefault, fmt.Errorf("Error while parsing flags from args %v: %s", finalArgs, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only remove the flags from the arguments if DisableFlagParsing is not set.
|
||||||
|
// This is important for commands which have requested to do their own flag completion.
|
||||||
|
if !finalCmd.DisableFlagParsing {
|
||||||
|
finalArgs = finalCmd.Flags().Args()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the completion function for the flag or command
|
||||||
|
var completionFn func(cmd *Command, args []string, toComplete string) ([]string, ShellCompDirective)
|
||||||
|
if flag != nil {
|
||||||
|
completionFn = flagCompletionFunctions[flag]
|
||||||
|
} else {
|
||||||
|
completionFn = finalCmd.ValidArgsFunction
|
||||||
|
}
|
||||||
|
if completionFn == nil {
|
||||||
|
// Go custom completion not supported/needed for this flag or command
|
||||||
|
return finalCmd, completions, ShellCompDirectiveDefault, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the registered completion function to get the completions
|
||||||
|
comps, directive := completionFn(finalCmd, finalArgs, toComplete)
|
||||||
|
completions = append(completions, comps...)
|
||||||
|
return finalCmd, completions, directive, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFlagNameCompletions(flag *pflag.Flag, toComplete string) []string {
|
||||||
|
if nonCompletableFlag(flag) {
|
||||||
|
return []string{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var completions []string
|
||||||
|
flagName := "--" + flag.Name
|
||||||
|
if strings.HasPrefix(flagName, toComplete) {
|
||||||
|
// Flag without the =
|
||||||
|
completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
|
||||||
|
|
||||||
|
if len(flag.NoOptDefVal) == 0 {
|
||||||
|
// Flag requires a value, so it can be suffixed with =
|
||||||
|
flagName += "="
|
||||||
|
completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flagName = "-" + flag.Shorthand
|
||||||
|
if len(flag.Shorthand) > 0 && strings.HasPrefix(flagName, toComplete) {
|
||||||
|
completions = append(completions, fmt.Sprintf("%s\t%s", flagName, flag.Usage))
|
||||||
|
}
|
||||||
|
|
||||||
|
return completions
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkIfFlagCompletion(finalCmd *Command, args []string, lastArg string) (*pflag.Flag, []string, string, error) {
|
||||||
|
var flagName string
|
||||||
|
trimmedArgs := args
|
||||||
|
flagWithEqual := false
|
||||||
|
if isFlagArg(lastArg) {
|
||||||
|
if index := strings.Index(lastArg, "="); index >= 0 {
|
||||||
|
flagName = strings.TrimLeft(lastArg[:index], "-")
|
||||||
|
lastArg = lastArg[index+1:]
|
||||||
|
flagWithEqual = true
|
||||||
|
} else {
|
||||||
|
return nil, nil, "", errors.New("Unexpected completion request for flag")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(flagName) == 0 {
|
||||||
|
if len(args) > 0 {
|
||||||
|
prevArg := args[len(args)-1]
|
||||||
|
if isFlagArg(prevArg) {
|
||||||
|
// Only consider the case where the flag does not contain an =.
|
||||||
|
// If the flag contains an = it means it has already been fully processed,
|
||||||
|
// so we don't need to deal with it here.
|
||||||
|
if index := strings.Index(prevArg, "="); index < 0 {
|
||||||
|
flagName = strings.TrimLeft(prevArg, "-")
|
||||||
|
|
||||||
|
// Remove the uncompleted flag or else there could be an error created
|
||||||
|
// for an invalid value for that flag
|
||||||
|
trimmedArgs = args[:len(args)-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(flagName) == 0 {
|
||||||
|
// Not doing flag completion
|
||||||
|
return nil, trimmedArgs, lastArg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
flag := findFlag(finalCmd, flagName)
|
||||||
|
if flag == nil {
|
||||||
|
// Flag not supported by this command, nothing to complete
|
||||||
|
err := fmt.Errorf("Subcommand '%s' does not support flag '%s'", finalCmd.Name(), flagName)
|
||||||
|
return nil, nil, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !flagWithEqual {
|
||||||
|
if len(flag.NoOptDefVal) != 0 {
|
||||||
|
// We had assumed dealing with a two-word flag but the flag is a boolean flag.
|
||||||
|
// In that case, there is no value following it, so we are not really doing flag completion.
|
||||||
|
// Reset everything to do noun completion.
|
||||||
|
trimmedArgs = args
|
||||||
|
flag = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return flag, trimmedArgs, lastArg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func findFlag(cmd *Command, name string) *pflag.Flag {
|
||||||
|
flagSet := cmd.Flags()
|
||||||
|
if len(name) == 1 {
|
||||||
|
// First convert the short flag into a long flag
|
||||||
|
// as the cmd.Flag() search only accepts long flags
|
||||||
|
if short := flagSet.ShorthandLookup(name); short != nil {
|
||||||
|
name = short.Name
|
||||||
|
} else {
|
||||||
|
set := cmd.InheritedFlags()
|
||||||
|
if short = set.ShorthandLookup(name); short != nil {
|
||||||
|
name = short.Name
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cmd.Flag(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompDebug prints the specified string to the same file as where the
|
||||||
|
// completion script prints its logs.
|
||||||
|
// Note that completion printouts should never be on stdout as they would
|
||||||
|
// be wrongly interpreted as actual completion choices by the completion script.
|
||||||
|
func CompDebug(msg string, printToStdErr bool) {
|
||||||
|
msg = fmt.Sprintf("[Debug] %s", msg)
|
||||||
|
|
||||||
|
// Such logs are only printed when the user has set the environment
|
||||||
|
// variable BASH_COMP_DEBUG_FILE to the path of some file to be used.
|
||||||
|
if path := os.Getenv("BASH_COMP_DEBUG_FILE"); path != "" {
|
||||||
|
f, err := os.OpenFile(path,
|
||||||
|
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err == nil {
|
||||||
|
defer f.Close()
|
||||||
|
f.WriteString(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if printToStdErr {
|
||||||
|
// Must print to stderr for this not to be read by the completion script.
|
||||||
|
fmt.Fprintf(os.Stderr, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompDebugln prints the specified string with a newline at the end
|
||||||
|
// to the same file as where the completion script prints its logs.
|
||||||
|
// Such logs are only printed when the user has set the environment
|
||||||
|
// variable BASH_COMP_DEBUG_FILE to the path of some file to be used.
|
||||||
|
func CompDebugln(msg string, printToStdErr bool) {
|
||||||
|
CompDebug(fmt.Sprintf("%s\n", msg), printToStdErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompError prints the specified completion message to stderr.
|
||||||
|
func CompError(msg string) {
|
||||||
|
msg = fmt.Sprintf("[Error] %s", msg)
|
||||||
|
CompDebug(msg, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompErrorln prints the specified completion message to stderr with a newline at the end.
|
||||||
|
func CompErrorln(msg string) {
|
||||||
|
CompError(fmt.Sprintf("%s\n", msg))
|
||||||
|
}
|
||||||
172
vendor/github.com/spf13/cobra/fish_completions.go
generated
vendored
Normal file
172
vendor/github.com/spf13/cobra/fish_completions.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
package cobra
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func genFishComp(buf *bytes.Buffer, name string, includeDesc bool) {
|
||||||
|
compCmd := ShellCompRequestCmd
|
||||||
|
if !includeDesc {
|
||||||
|
compCmd = ShellCompNoDescRequestCmd
|
||||||
|
}
|
||||||
|
buf.WriteString(fmt.Sprintf("# fish completion for %-36s -*- shell-script -*-\n", name))
|
||||||
|
buf.WriteString(fmt.Sprintf(`
|
||||||
|
function __%[1]s_debug
|
||||||
|
set file "$BASH_COMP_DEBUG_FILE"
|
||||||
|
if test -n "$file"
|
||||||
|
echo "$argv" >> $file
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function __%[1]s_perform_completion
|
||||||
|
__%[1]s_debug "Starting __%[1]s_perform_completion with: $argv"
|
||||||
|
|
||||||
|
set args (string split -- " " "$argv")
|
||||||
|
set lastArg "$args[-1]"
|
||||||
|
|
||||||
|
__%[1]s_debug "args: $args"
|
||||||
|
__%[1]s_debug "last arg: $lastArg"
|
||||||
|
|
||||||
|
set emptyArg ""
|
||||||
|
if test -z "$lastArg"
|
||||||
|
__%[1]s_debug "Setting emptyArg"
|
||||||
|
set emptyArg \"\"
|
||||||
|
end
|
||||||
|
__%[1]s_debug "emptyArg: $emptyArg"
|
||||||
|
|
||||||
|
set requestComp "$args[1] %[2]s $args[2..-1] $emptyArg"
|
||||||
|
__%[1]s_debug "Calling $requestComp"
|
||||||
|
|
||||||
|
set results (eval $requestComp 2> /dev/null)
|
||||||
|
set comps $results[1..-2]
|
||||||
|
set directiveLine $results[-1]
|
||||||
|
|
||||||
|
# For Fish, when completing a flag with an = (e.g., <program> -n=<TAB>)
|
||||||
|
# completions must be prefixed with the flag
|
||||||
|
set flagPrefix (string match -r -- '-.*=' "$lastArg")
|
||||||
|
|
||||||
|
__%[1]s_debug "Comps: $comps"
|
||||||
|
__%[1]s_debug "DirectiveLine: $directiveLine"
|
||||||
|
__%[1]s_debug "flagPrefix: $flagPrefix"
|
||||||
|
|
||||||
|
for comp in $comps
|
||||||
|
printf "%%s%%s\n" "$flagPrefix" "$comp"
|
||||||
|
end
|
||||||
|
|
||||||
|
printf "%%s\n" "$directiveLine"
|
||||||
|
end
|
||||||
|
|
||||||
|
# This function does three things:
|
||||||
|
# 1- Obtain the completions and store them in the global __%[1]s_comp_results
|
||||||
|
# 2- Set the __%[1]s_comp_do_file_comp flag if file completion should be performed
|
||||||
|
# and unset it otherwise
|
||||||
|
# 3- Return true if the completion results are not empty
|
||||||
|
function __%[1]s_prepare_completions
|
||||||
|
# Start fresh
|
||||||
|
set --erase __%[1]s_comp_do_file_comp
|
||||||
|
set --erase __%[1]s_comp_results
|
||||||
|
|
||||||
|
# Check if the command-line is already provided. This is useful for testing.
|
||||||
|
if not set --query __%[1]s_comp_commandLine
|
||||||
|
set __%[1]s_comp_commandLine (commandline)
|
||||||
|
end
|
||||||
|
__%[1]s_debug "commandLine is: $__%[1]s_comp_commandLine"
|
||||||
|
|
||||||
|
set results (__%[1]s_perform_completion "$__%[1]s_comp_commandLine")
|
||||||
|
set --erase __%[1]s_comp_commandLine
|
||||||
|
__%[1]s_debug "Completion results: $results"
|
||||||
|
|
||||||
|
if test -z "$results"
|
||||||
|
__%[1]s_debug "No completion, probably due to a failure"
|
||||||
|
# Might as well do file completion, in case it helps
|
||||||
|
set --global __%[1]s_comp_do_file_comp 1
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
set directive (string sub --start 2 $results[-1])
|
||||||
|
set --global __%[1]s_comp_results $results[1..-2]
|
||||||
|
|
||||||
|
__%[1]s_debug "Completions are: $__%[1]s_comp_results"
|
||||||
|
__%[1]s_debug "Directive is: $directive"
|
||||||
|
|
||||||
|
if test -z "$directive"
|
||||||
|
set directive 0
|
||||||
|
end
|
||||||
|
|
||||||
|
set compErr (math (math --scale 0 $directive / %[3]d) %% 2)
|
||||||
|
if test $compErr -eq 1
|
||||||
|
__%[1]s_debug "Received error directive: aborting."
|
||||||
|
# Might as well do file completion, in case it helps
|
||||||
|
set --global __%[1]s_comp_do_file_comp 1
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
set nospace (math (math --scale 0 $directive / %[4]d) %% 2)
|
||||||
|
set nofiles (math (math --scale 0 $directive / %[5]d) %% 2)
|
||||||
|
|
||||||
|
__%[1]s_debug "nospace: $nospace, nofiles: $nofiles"
|
||||||
|
|
||||||
|
# Important not to quote the variable for count to work
|
||||||
|
set numComps (count $__%[1]s_comp_results)
|
||||||
|
__%[1]s_debug "numComps: $numComps"
|
||||||
|
|
||||||
|
if test $numComps -eq 1; and test $nospace -ne 0
|
||||||
|
# To support the "nospace" directive we trick the shell
|
||||||
|
# by outputting an extra, longer completion.
|
||||||
|
__%[1]s_debug "Adding second completion to perform nospace directive"
|
||||||
|
set --append __%[1]s_comp_results $__%[1]s_comp_results[1].
|
||||||
|
end
|
||||||
|
|
||||||
|
if test $numComps -eq 0; and test $nofiles -eq 0
|
||||||
|
__%[1]s_debug "Requesting file completion"
|
||||||
|
set --global __%[1]s_comp_do_file_comp 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# If we don't want file completion, we must return true even if there
|
||||||
|
# are no completions found. This is because fish will perform the last
|
||||||
|
# completion command, even if its condition is false, if no other
|
||||||
|
# completion command was triggered
|
||||||
|
return (not set --query __%[1]s_comp_do_file_comp)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Remove any pre-existing completions for the program since we will be handling all of them
|
||||||
|
# TODO this cleanup is not sufficient. Fish completions are only loaded once the user triggers
|
||||||
|
# them, so the below deletion will not work as it is run too early. What else can we do?
|
||||||
|
complete -c %[1]s -e
|
||||||
|
|
||||||
|
# The order in which the below two lines are defined is very important so that __%[1]s_prepare_completions
|
||||||
|
# is called first. It is __%[1]s_prepare_completions that sets up the __%[1]s_comp_do_file_comp variable.
|
||||||
|
#
|
||||||
|
# This completion will be run second as complete commands are added FILO.
|
||||||
|
# It triggers file completion choices when __%[1]s_comp_do_file_comp is set.
|
||||||
|
complete -c %[1]s -n 'set --query __%[1]s_comp_do_file_comp'
|
||||||
|
|
||||||
|
# This completion will be run first as complete commands are added FILO.
|
||||||
|
# The call to __%[1]s_prepare_completions will setup both __%[1]s_comp_results abd __%[1]s_comp_do_file_comp.
|
||||||
|
# It provides the program's completion choices.
|
||||||
|
complete -c %[1]s -n '__%[1]s_prepare_completions' -f -a '$__%[1]s_comp_results'
|
||||||
|
|
||||||
|
`, name, compCmd, ShellCompDirectiveError, ShellCompDirectiveNoSpace, ShellCompDirectiveNoFileComp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenFishCompletion generates fish completion file and writes to the passed writer.
|
||||||
|
func (c *Command) GenFishCompletion(w io.Writer, includeDesc bool) error {
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
genFishComp(buf, c.Name(), includeDesc)
|
||||||
|
_, err := buf.WriteTo(w)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenFishCompletionFile generates fish completion file.
|
||||||
|
func (c *Command) GenFishCompletionFile(filename string, includeDesc bool) error {
|
||||||
|
outFile, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer outFile.Close()
|
||||||
|
|
||||||
|
return c.GenFishCompletion(outFile, includeDesc)
|
||||||
|
}
|
||||||
7
vendor/github.com/spf13/cobra/fish_completions.md
generated
vendored
Normal file
7
vendor/github.com/spf13/cobra/fish_completions.md
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
## Generating Fish Completions for your own cobra.Command
|
||||||
|
|
||||||
|
Cobra supports native Fish completions generated from the root `cobra.Command`. You can use the `command.GenFishCompletion()` or `command.GenFishCompletionFile()` functions. You must provide these functions with a parameter indicating if the completions should be annotated with a description; Cobra will provide the description automatically based on usage information. You can choose to make this option configurable by your users.
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
* Custom completions implemented using the `ValidArgsFunction` and `RegisterFlagCompletionFunc()` are supported automatically but the ones implemented in Bash scripting are not.
|
||||||
5
vendor/github.com/spf13/cobra/go.mod
generated
vendored
5
vendor/github.com/spf13/cobra/go.mod
generated
vendored
@ -3,11 +3,10 @@ module github.com/spf13/cobra
|
|||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/BurntSushi/toml v0.3.1 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.0
|
||||||
github.com/cpuguy83/go-md2man v1.0.10
|
|
||||||
github.com/inconshreveable/mousetrap v1.0.0
|
github.com/inconshreveable/mousetrap v1.0.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/spf13/pflag v1.0.3
|
github.com/spf13/pflag v1.0.3
|
||||||
github.com/spf13/viper v1.3.2
|
github.com/spf13/viper v1.4.0
|
||||||
gopkg.in/yaml.v2 v2.2.2
|
gopkg.in/yaml.v2 v2.2.2
|
||||||
)
|
)
|
||||||
|
|||||||
120
vendor/github.com/spf13/cobra/go.sum
generated
vendored
120
vendor/github.com/spf13/cobra/go.sum
generated
vendored
@ -1,31 +1,91 @@
|
|||||||
|
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
|
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
|
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
|
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
||||||
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||||
@ -34,18 +94,56 @@ github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9
|
|||||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
|
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a h1:1n5lsVfiQW3yfsRGu98756EH1YthsFqr/5mxHduZW2A=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
|
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
|
||||||
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||||
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|||||||
7
vendor/github.com/spf13/pflag/.travis.yml
generated
vendored
7
vendor/github.com/spf13/pflag/.travis.yml
generated
vendored
@ -3,8 +3,9 @@ sudo: false
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.7.3
|
- 1.9.x
|
||||||
- 1.8.1
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
- tip
|
- tip
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
@ -12,7 +13,7 @@ matrix:
|
|||||||
- go: tip
|
- go: tip
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- go get github.com/golang/lint/golint
|
- go get golang.org/x/lint/golint
|
||||||
- export PATH=$GOPATH/bin:$PATH
|
- export PATH=$GOPATH/bin:$PATH
|
||||||
- go install ./...
|
- go install ./...
|
||||||
|
|
||||||
|
|||||||
4
vendor/github.com/spf13/pflag/README.md
generated
vendored
4
vendor/github.com/spf13/pflag/README.md
generated
vendored
@ -86,8 +86,8 @@ fmt.Println("ip has value ", *ip)
|
|||||||
fmt.Println("flagvar has value ", flagvar)
|
fmt.Println("flagvar has value ", flagvar)
|
||||||
```
|
```
|
||||||
|
|
||||||
There are helpers function to get values later if you have the FlagSet but
|
There are helper functions available to get the value stored in a Flag if you have a FlagSet but find
|
||||||
it was difficult to keep up with all of the flag pointers in your code.
|
it difficult to keep up with all of the pointers in your code.
|
||||||
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
|
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
|
||||||
can use GetInt() to get the int value. But notice that 'flagname' must exist
|
can use GetInt() to get the int value. But notice that 'flagname' must exist
|
||||||
and it must be an int. GetString("flagname") will fail.
|
and it must be an int. GetString("flagname") will fail.
|
||||||
|
|||||||
38
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
38
vendor/github.com/spf13/pflag/bool_slice.go
generated
vendored
@ -71,6 +71,44 @@ func (s *boolSliceValue) String() string {
|
|||||||
return "[" + out + "]"
|
return "[" + out + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *boolSliceValue) fromString(val string) (bool, error) {
|
||||||
|
return strconv.ParseBool(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *boolSliceValue) toString(val bool) string {
|
||||||
|
return strconv.FormatBool(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *boolSliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *boolSliceValue) Replace(val []string) error {
|
||||||
|
out := make([]bool, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *boolSliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func boolSliceConv(val string) (interface{}, error) {
|
func boolSliceConv(val string) (interface{}, error) {
|
||||||
val = strings.Trim(val, "[]")
|
val = strings.Trim(val, "[]")
|
||||||
// Empty string would cause a slice with one (empty) entry
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
|||||||
4
vendor/github.com/spf13/pflag/count.go
generated
vendored
4
vendor/github.com/spf13/pflag/count.go
generated
vendored
@ -46,7 +46,7 @@ func (f *FlagSet) GetCount(name string) (int, error) {
|
|||||||
|
|
||||||
// CountVar defines a count flag with specified name, default value, and usage string.
|
// CountVar defines a count flag with specified name, default value, and usage string.
|
||||||
// The argument p points to an int variable in which to store the value of the flag.
|
// The argument p points to an int variable in which to store the value of the flag.
|
||||||
// A count flag will add 1 to its value evey time it is found on the command line
|
// A count flag will add 1 to its value every time it is found on the command line
|
||||||
func (f *FlagSet) CountVar(p *int, name string, usage string) {
|
func (f *FlagSet) CountVar(p *int, name string, usage string) {
|
||||||
f.CountVarP(p, name, "", usage)
|
f.CountVarP(p, name, "", usage)
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func CountVarP(p *int, name, shorthand string, usage string) {
|
|||||||
|
|
||||||
// Count defines a count flag with specified name, default value, and usage string.
|
// Count defines a count flag with specified name, default value, and usage string.
|
||||||
// The return value is the address of an int variable that stores the value of the flag.
|
// The return value is the address of an int variable that stores the value of the flag.
|
||||||
// A count flag will add 1 to its value evey time it is found on the command line
|
// A count flag will add 1 to its value every time it is found on the command line
|
||||||
func (f *FlagSet) Count(name string, usage string) *int {
|
func (f *FlagSet) Count(name string, usage string) *int {
|
||||||
p := new(int)
|
p := new(int)
|
||||||
f.CountVarP(p, name, "", usage)
|
f.CountVarP(p, name, "", usage)
|
||||||
|
|||||||
38
vendor/github.com/spf13/pflag/duration_slice.go
generated
vendored
38
vendor/github.com/spf13/pflag/duration_slice.go
generated
vendored
@ -51,6 +51,44 @@ func (s *durationSliceValue) String() string {
|
|||||||
return "[" + strings.Join(out, ",") + "]"
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) fromString(val string) (time.Duration, error) {
|
||||||
|
return time.ParseDuration(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) toString(val time.Duration) string {
|
||||||
|
return fmt.Sprintf("%s", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) Replace(val []string) error {
|
||||||
|
out := make([]time.Duration, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *durationSliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func durationSliceConv(val string) (interface{}, error) {
|
func durationSliceConv(val string) (interface{}, error) {
|
||||||
val = strings.Trim(val, "[]")
|
val = strings.Trim(val, "[]")
|
||||||
// Empty string would cause a slice with one (empty) entry
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
|||||||
16
vendor/github.com/spf13/pflag/flag.go
generated
vendored
16
vendor/github.com/spf13/pflag/flag.go
generated
vendored
@ -57,9 +57,9 @@ that give one-letter shorthands for flags. You can use these by appending
|
|||||||
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
var ip = flag.IntP("flagname", "f", 1234, "help message")
|
||||||
var flagvar bool
|
var flagvar bool
|
||||||
func init() {
|
func init() {
|
||||||
flag.BoolVarP("boolname", "b", true, "help message")
|
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
|
||||||
}
|
}
|
||||||
flag.VarP(&flagVar, "varname", "v", 1234, "help message")
|
flag.VarP(&flagval, "varname", "v", "help message")
|
||||||
Shorthand letters can be used with single dashes on the command line.
|
Shorthand letters can be used with single dashes on the command line.
|
||||||
Boolean shorthand flags can be combined with other shorthand flags.
|
Boolean shorthand flags can be combined with other shorthand flags.
|
||||||
|
|
||||||
@ -190,6 +190,18 @@ type Value interface {
|
|||||||
Type() string
|
Type() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SliceValue is a secondary interface to all flags which hold a list
|
||||||
|
// of values. This allows full control over the value of list flags,
|
||||||
|
// and avoids complicated marshalling and unmarshalling to csv.
|
||||||
|
type SliceValue interface {
|
||||||
|
// Append adds the specified value to the end of the flag value list.
|
||||||
|
Append(string) error
|
||||||
|
// Replace will fully overwrite any data currently in the flag value list.
|
||||||
|
Replace([]string) error
|
||||||
|
// GetSlice returns the flag value list as an array of strings.
|
||||||
|
GetSlice() []string
|
||||||
|
}
|
||||||
|
|
||||||
// sortFlags returns the flags as a slice in lexicographical sorted order.
|
// sortFlags returns the flags as a slice in lexicographical sorted order.
|
||||||
func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
func sortFlags(flags map[NormalizedName]*Flag) []*Flag {
|
||||||
list := make(sort.StringSlice, len(flags))
|
list := make(sort.StringSlice, len(flags))
|
||||||
|
|||||||
174
vendor/github.com/spf13/pflag/float32_slice.go
generated
vendored
Normal file
174
vendor/github.com/spf13/pflag/float32_slice.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- float32Slice Value
|
||||||
|
type float32SliceValue struct {
|
||||||
|
value *[]float32
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFloat32SliceValue(val []float32, p *[]float32) *float32SliceValue {
|
||||||
|
isv := new(float32SliceValue)
|
||||||
|
isv.value = p
|
||||||
|
*isv.value = val
|
||||||
|
return isv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]float32, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
var temp64 float64
|
||||||
|
temp64, err = strconv.ParseFloat(d, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out[i] = float32(temp64)
|
||||||
|
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) Type() string {
|
||||||
|
return "float32Slice"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) String() string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = fmt.Sprintf("%f", d)
|
||||||
|
}
|
||||||
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) fromString(val string) (float32, error) {
|
||||||
|
t64, err := strconv.ParseFloat(val, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return float32(t64), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) toString(val float32) string {
|
||||||
|
return fmt.Sprintf("%f", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) Replace(val []string) error {
|
||||||
|
out := make([]float32, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float32SliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func float32SliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []float32{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]float32, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
var temp64 float64
|
||||||
|
temp64, err = strconv.ParseFloat(d, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out[i] = float32(temp64)
|
||||||
|
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFloat32Slice return the []float32 value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetFloat32Slice(name string) ([]float32, error) {
|
||||||
|
val, err := f.getFlagType(name, "float32Slice", float32SliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []float32{}, err
|
||||||
|
}
|
||||||
|
return val.([]float32), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32SliceVar defines a float32Slice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []float32 variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
|
||||||
|
f.VarP(newFloat32SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
|
||||||
|
f.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32SliceVar defines a float32[] flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a float32[] variable in which to store the value of the flag.
|
||||||
|
func Float32SliceVar(p *[]float32, name string, value []float32, usage string) {
|
||||||
|
CommandLine.VarP(newFloat32SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32SliceVarP is like Float32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Float32SliceVarP(p *[]float32, name, shorthand string, value []float32, usage string) {
|
||||||
|
CommandLine.VarP(newFloat32SliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []float32 variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) Float32Slice(name string, value []float32, usage string) *[]float32 {
|
||||||
|
p := []float32{}
|
||||||
|
f.Float32SliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
|
||||||
|
p := []float32{}
|
||||||
|
f.Float32SliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32Slice defines a []float32 flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []float32 variable that stores the value of the flag.
|
||||||
|
func Float32Slice(name string, value []float32, usage string) *[]float32 {
|
||||||
|
return CommandLine.Float32SliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float32SliceP is like Float32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Float32SliceP(name, shorthand string, value []float32, usage string) *[]float32 {
|
||||||
|
return CommandLine.Float32SliceP(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
166
vendor/github.com/spf13/pflag/float64_slice.go
generated
vendored
Normal file
166
vendor/github.com/spf13/pflag/float64_slice.go
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- float64Slice Value
|
||||||
|
type float64SliceValue struct {
|
||||||
|
value *[]float64
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFloat64SliceValue(val []float64, p *[]float64) *float64SliceValue {
|
||||||
|
isv := new(float64SliceValue)
|
||||||
|
isv.value = p
|
||||||
|
*isv.value = val
|
||||||
|
return isv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]float64, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = strconv.ParseFloat(d, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) Type() string {
|
||||||
|
return "float64Slice"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) String() string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = fmt.Sprintf("%f", d)
|
||||||
|
}
|
||||||
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) fromString(val string) (float64, error) {
|
||||||
|
return strconv.ParseFloat(val, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) toString(val float64) string {
|
||||||
|
return fmt.Sprintf("%f", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) Replace(val []string) error {
|
||||||
|
out := make([]float64, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *float64SliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func float64SliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []float64{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]float64, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = strconv.ParseFloat(d, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFloat64Slice return the []float64 value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetFloat64Slice(name string) ([]float64, error) {
|
||||||
|
val, err := f.getFlagType(name, "float64Slice", float64SliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []float64{}, err
|
||||||
|
}
|
||||||
|
return val.([]float64), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64SliceVar defines a float64Slice 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(p *[]float64, name string, value []float64, usage string) {
|
||||||
|
f.VarP(newFloat64SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
|
||||||
|
f.VarP(newFloat64SliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(p *[]float64, name string, value []float64, usage string) {
|
||||||
|
CommandLine.VarP(newFloat64SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64SliceVarP is like Float64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Float64SliceVarP(p *[]float64, name, shorthand string, value []float64, usage string) {
|
||||||
|
CommandLine.VarP(newFloat64SliceValue(value, p), name, shorthand, 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 {
|
||||||
|
p := []float64{}
|
||||||
|
f.Float64SliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
|
||||||
|
p := []float64{}
|
||||||
|
f.Float64SliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.Float64SliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Float64SliceP is like Float64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Float64SliceP(name, shorthand string, value []float64, usage string) *[]float64 {
|
||||||
|
return CommandLine.Float64SliceP(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
3
vendor/github.com/spf13/pflag/go.mod
generated
vendored
Normal file
3
vendor/github.com/spf13/pflag/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/spf13/pflag
|
||||||
|
|
||||||
|
go 1.12
|
||||||
0
vendor/github.com/spf13/pflag/go.sum
generated
vendored
Normal file
0
vendor/github.com/spf13/pflag/go.sum
generated
vendored
Normal file
174
vendor/github.com/spf13/pflag/int32_slice.go
generated
vendored
Normal file
174
vendor/github.com/spf13/pflag/int32_slice.go
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- int32Slice Value
|
||||||
|
type int32SliceValue struct {
|
||||||
|
value *[]int32
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInt32SliceValue(val []int32, p *[]int32) *int32SliceValue {
|
||||||
|
isv := new(int32SliceValue)
|
||||||
|
isv.value = p
|
||||||
|
*isv.value = val
|
||||||
|
return isv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]int32, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
var temp64 int64
|
||||||
|
temp64, err = strconv.ParseInt(d, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
out[i] = int32(temp64)
|
||||||
|
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) Type() string {
|
||||||
|
return "int32Slice"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) String() string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = fmt.Sprintf("%d", d)
|
||||||
|
}
|
||||||
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) fromString(val string) (int32, error) {
|
||||||
|
t64, err := strconv.ParseInt(val, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return int32(t64), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) toString(val int32) string {
|
||||||
|
return fmt.Sprintf("%d", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) Replace(val []string) error {
|
||||||
|
out := make([]int32, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int32SliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func int32SliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []int32{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]int32, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
var temp64 int64
|
||||||
|
temp64, err = strconv.ParseInt(d, 0, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
out[i] = int32(temp64)
|
||||||
|
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInt32Slice return the []int32 value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetInt32Slice(name string) ([]int32, error) {
|
||||||
|
val, err := f.getFlagType(name, "int32Slice", int32SliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []int32{}, err
|
||||||
|
}
|
||||||
|
return val.([]int32), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32SliceVar defines a int32Slice flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a []int32 variable in which to store the value of the flag.
|
||||||
|
func (f *FlagSet) Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
|
||||||
|
f.VarP(newInt32SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
|
||||||
|
f.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32SliceVar defines a int32[] flag with specified name, default value, and usage string.
|
||||||
|
// The argument p points to a int32[] variable in which to store the value of the flag.
|
||||||
|
func Int32SliceVar(p *[]int32, name string, value []int32, usage string) {
|
||||||
|
CommandLine.VarP(newInt32SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32SliceVarP is like Int32SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Int32SliceVarP(p *[]int32, name, shorthand string, value []int32, usage string) {
|
||||||
|
CommandLine.VarP(newInt32SliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []int32 variable that stores the value of the flag.
|
||||||
|
func (f *FlagSet) Int32Slice(name string, value []int32, usage string) *[]int32 {
|
||||||
|
p := []int32{}
|
||||||
|
f.Int32SliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
|
||||||
|
p := []int32{}
|
||||||
|
f.Int32SliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32Slice defines a []int32 flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a []int32 variable that stores the value of the flag.
|
||||||
|
func Int32Slice(name string, value []int32, usage string) *[]int32 {
|
||||||
|
return CommandLine.Int32SliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int32SliceP is like Int32Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Int32SliceP(name, shorthand string, value []int32, usage string) *[]int32 {
|
||||||
|
return CommandLine.Int32SliceP(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
166
vendor/github.com/spf13/pflag/int64_slice.go
generated
vendored
Normal file
166
vendor/github.com/spf13/pflag/int64_slice.go
generated
vendored
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- int64Slice Value
|
||||||
|
type int64SliceValue struct {
|
||||||
|
value *[]int64
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInt64SliceValue(val []int64, p *[]int64) *int64SliceValue {
|
||||||
|
isv := new(int64SliceValue)
|
||||||
|
isv.value = p
|
||||||
|
*isv.value = val
|
||||||
|
return isv
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]int64, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = strconv.ParseInt(d, 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
*s.value = append(*s.value, out...)
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) Type() string {
|
||||||
|
return "int64Slice"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) String() string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = fmt.Sprintf("%d", d)
|
||||||
|
}
|
||||||
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) fromString(val string) (int64, error) {
|
||||||
|
return strconv.ParseInt(val, 0, 64)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) toString(val int64) string {
|
||||||
|
return fmt.Sprintf("%d", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) Replace(val []string) error {
|
||||||
|
out := make([]int64, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *int64SliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func int64SliceConv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
if len(val) == 0 {
|
||||||
|
return []int64{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make([]int64, len(ss))
|
||||||
|
for i, d := range ss {
|
||||||
|
var err error
|
||||||
|
out[i], err = strconv.ParseInt(d, 0, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInt64Slice return the []int64 value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetInt64Slice(name string) ([]int64, error) {
|
||||||
|
val, err := f.getFlagType(name, "int64Slice", int64SliceConv)
|
||||||
|
if err != nil {
|
||||||
|
return []int64{}, err
|
||||||
|
}
|
||||||
|
return val.([]int64), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64SliceVar defines a int64Slice 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(p *[]int64, name string, value []int64, usage string) {
|
||||||
|
f.VarP(newInt64SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
|
||||||
|
f.VarP(newInt64SliceValue(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(p *[]int64, name string, value []int64, usage string) {
|
||||||
|
CommandLine.VarP(newInt64SliceValue(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64SliceVarP is like Int64SliceVar, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Int64SliceVarP(p *[]int64, name, shorthand string, value []int64, usage string) {
|
||||||
|
CommandLine.VarP(newInt64SliceValue(value, p), name, shorthand, 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 {
|
||||||
|
p := []int64{}
|
||||||
|
f.Int64SliceVarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
|
||||||
|
p := []int64{}
|
||||||
|
f.Int64SliceVarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.Int64SliceP(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Int64SliceP is like Int64Slice, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func Int64SliceP(name, shorthand string, value []int64, usage string) *[]int64 {
|
||||||
|
return CommandLine.Int64SliceP(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
30
vendor/github.com/spf13/pflag/int_slice.go
generated
vendored
30
vendor/github.com/spf13/pflag/int_slice.go
generated
vendored
@ -51,6 +51,36 @@ func (s *intSliceValue) String() string {
|
|||||||
return "[" + strings.Join(out, ",") + "]"
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *intSliceValue) Append(val string) error {
|
||||||
|
i, err := strconv.Atoi(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *intSliceValue) Replace(val []string) error {
|
||||||
|
out := make([]int, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = strconv.Atoi(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *intSliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = strconv.Itoa(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func intSliceConv(val string) (interface{}, error) {
|
func intSliceConv(val string) (interface{}, error) {
|
||||||
val = strings.Trim(val, "[]")
|
val = strings.Trim(val, "[]")
|
||||||
// Empty string would cause a slice with one (empty) entry
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
|||||||
40
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
40
vendor/github.com/spf13/pflag/ip_slice.go
generated
vendored
@ -72,9 +72,47 @@ func (s *ipSliceValue) String() string {
|
|||||||
return "[" + out + "]"
|
return "[" + out + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ipSliceValue) fromString(val string) (net.IP, error) {
|
||||||
|
return net.ParseIP(strings.TrimSpace(val)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ipSliceValue) toString(val net.IP) string {
|
||||||
|
return val.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ipSliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ipSliceValue) Replace(val []string) error {
|
||||||
|
out := make([]net.IP, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ipSliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func ipSliceConv(val string) (interface{}, error) {
|
func ipSliceConv(val string) (interface{}, error) {
|
||||||
val = strings.Trim(val, "[]")
|
val = strings.Trim(val, "[]")
|
||||||
// Emtpy string would cause a slice with one (empty) entry
|
// Empty string would cause a slice with one (empty) entry
|
||||||
if len(val) == 0 {
|
if len(val) == 0 {
|
||||||
return []net.IP{}, nil
|
return []net.IP{}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
26
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
26
vendor/github.com/spf13/pflag/string_array.go
generated
vendored
@ -23,6 +23,32 @@ func (s *stringArrayValue) Set(val string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stringArrayValue) Append(val string) error {
|
||||||
|
*s.value = append(*s.value, val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringArrayValue) Replace(val []string) error {
|
||||||
|
out := make([]string, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i] = d
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringArrayValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = d
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func (s *stringArrayValue) Type() string {
|
func (s *stringArrayValue) Type() string {
|
||||||
return "stringArray"
|
return "stringArray"
|
||||||
}
|
}
|
||||||
|
|||||||
22
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
22
vendor/github.com/spf13/pflag/string_slice.go
generated
vendored
@ -62,6 +62,20 @@ func (s *stringSliceValue) String() string {
|
|||||||
return "[" + str + "]"
|
return "[" + str + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceValue) Append(val string) error {
|
||||||
|
*s.value = append(*s.value, val)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceValue) Replace(val []string) error {
|
||||||
|
*s.value = val
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringSliceValue) GetSlice() []string {
|
||||||
|
return *s.value
|
||||||
|
}
|
||||||
|
|
||||||
func stringSliceConv(sval string) (interface{}, error) {
|
func stringSliceConv(sval string) (interface{}, error) {
|
||||||
sval = sval[1 : len(sval)-1]
|
sval = sval[1 : len(sval)-1]
|
||||||
// An empty string would cause a slice with one (empty) string
|
// An empty string would cause a slice with one (empty) string
|
||||||
@ -84,7 +98,7 @@ func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
|
|||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
// The argument p points to a []string variable in which to store the value of the flag.
|
||||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
// For example:
|
// For example:
|
||||||
// --ss="v1,v2" -ss="v3"
|
// --ss="v1,v2" --ss="v3"
|
||||||
// will result in
|
// will result in
|
||||||
// []string{"v1", "v2", "v3"}
|
// []string{"v1", "v2", "v3"}
|
||||||
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
|
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
|
||||||
@ -100,7 +114,7 @@ func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []s
|
|||||||
// The argument p points to a []string variable in which to store the value of the flag.
|
// The argument p points to a []string variable in which to store the value of the flag.
|
||||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
// For example:
|
// For example:
|
||||||
// --ss="v1,v2" -ss="v3"
|
// --ss="v1,v2" --ss="v3"
|
||||||
// will result in
|
// will result in
|
||||||
// []string{"v1", "v2", "v3"}
|
// []string{"v1", "v2", "v3"}
|
||||||
func StringSliceVar(p *[]string, name string, value []string, usage string) {
|
func StringSliceVar(p *[]string, name string, value []string, usage string) {
|
||||||
@ -116,7 +130,7 @@ func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage
|
|||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
// The return value is the address of a []string variable that stores the value of the flag.
|
||||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
// For example:
|
// For example:
|
||||||
// --ss="v1,v2" -ss="v3"
|
// --ss="v1,v2" --ss="v3"
|
||||||
// will result in
|
// will result in
|
||||||
// []string{"v1", "v2", "v3"}
|
// []string{"v1", "v2", "v3"}
|
||||||
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
|
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
|
||||||
@ -136,7 +150,7 @@ func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage str
|
|||||||
// The return value is the address of a []string variable that stores the value of the flag.
|
// The return value is the address of a []string variable that stores the value of the flag.
|
||||||
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
// Compared to StringArray flags, StringSlice flags take comma-separated value as arguments and split them accordingly.
|
||||||
// For example:
|
// For example:
|
||||||
// --ss="v1,v2" -ss="v3"
|
// --ss="v1,v2" --ss="v3"
|
||||||
// will result in
|
// will result in
|
||||||
// []string{"v1", "v2", "v3"}
|
// []string{"v1", "v2", "v3"}
|
||||||
func StringSlice(name string, value []string, usage string) *[]string {
|
func StringSlice(name string, value []string, usage string) *[]string {
|
||||||
|
|||||||
149
vendor/github.com/spf13/pflag/string_to_int64.go
generated
vendored
Normal file
149
vendor/github.com/spf13/pflag/string_to_int64.go
generated
vendored
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
package pflag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -- stringToInt64 Value
|
||||||
|
type stringToInt64Value struct {
|
||||||
|
value *map[string]int64
|
||||||
|
changed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStringToInt64Value(val map[string]int64, p *map[string]int64) *stringToInt64Value {
|
||||||
|
ssv := new(stringToInt64Value)
|
||||||
|
ssv.value = p
|
||||||
|
*ssv.value = val
|
||||||
|
return ssv
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format: a=1,b=2
|
||||||
|
func (s *stringToInt64Value) Set(val string) error {
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make(map[string]int64, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !s.changed {
|
||||||
|
*s.value = out
|
||||||
|
} else {
|
||||||
|
for k, v := range out {
|
||||||
|
(*s.value)[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.changed = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToInt64Value) Type() string {
|
||||||
|
return "stringToInt64"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *stringToInt64Value) String() string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
i := 0
|
||||||
|
for k, v := range *s.value {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteRune(',')
|
||||||
|
}
|
||||||
|
buf.WriteString(k)
|
||||||
|
buf.WriteRune('=')
|
||||||
|
buf.WriteString(strconv.FormatInt(v, 10))
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return "[" + buf.String() + "]"
|
||||||
|
}
|
||||||
|
|
||||||
|
func stringToInt64Conv(val string) (interface{}, error) {
|
||||||
|
val = strings.Trim(val, "[]")
|
||||||
|
// An empty string would cause an empty map
|
||||||
|
if len(val) == 0 {
|
||||||
|
return map[string]int64{}, nil
|
||||||
|
}
|
||||||
|
ss := strings.Split(val, ",")
|
||||||
|
out := make(map[string]int64, len(ss))
|
||||||
|
for _, pair := range ss {
|
||||||
|
kv := strings.SplitN(pair, "=", 2)
|
||||||
|
if len(kv) != 2 {
|
||||||
|
return nil, fmt.Errorf("%s must be formatted as key=value", pair)
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
out[kv[0]], err = strconv.ParseInt(kv[1], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringToInt64 return the map[string]int64 value of a flag with the given name
|
||||||
|
func (f *FlagSet) GetStringToInt64(name string) (map[string]int64, error) {
|
||||||
|
val, err := f.getFlagType(name, "stringToInt64", stringToInt64Conv)
|
||||||
|
if err != nil {
|
||||||
|
return map[string]int64{}, err
|
||||||
|
}
|
||||||
|
return val.(map[string]int64), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p point64s to a map[string]int64 variable in which to store the values of the multiple flags.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
|
||||||
|
f.VarP(newStringToInt64Value(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
|
||||||
|
f.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64Var defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The argument p point64s to a map[string]int64 variable in which to store the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToInt64Var(p *map[string]int64, name string, value map[string]int64, usage string) {
|
||||||
|
CommandLine.VarP(newStringToInt64Value(value, p), name, "", usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64VarP is like StringToInt64Var, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToInt64VarP(p *map[string]int64, name, shorthand string, value map[string]int64, usage string) {
|
||||||
|
CommandLine.VarP(newStringToInt64Value(value, p), name, shorthand, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64 defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func (f *FlagSet) StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
|
||||||
|
p := map[string]int64{}
|
||||||
|
f.StringToInt64VarP(&p, name, "", value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func (f *FlagSet) StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
|
||||||
|
p := map[string]int64{}
|
||||||
|
f.StringToInt64VarP(&p, name, shorthand, value, usage)
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64 defines a string flag with specified name, default value, and usage string.
|
||||||
|
// The return value is the address of a map[string]int64 variable that stores the value of the flag.
|
||||||
|
// The value of each argument will not try to be separated by comma
|
||||||
|
func StringToInt64(name string, value map[string]int64, usage string) *map[string]int64 {
|
||||||
|
return CommandLine.StringToInt64P(name, "", value, usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringToInt64P is like StringToInt64, but accepts a shorthand letter that can be used after a single dash.
|
||||||
|
func StringToInt64P(name, shorthand string, value map[string]int64, usage string) *map[string]int64 {
|
||||||
|
return CommandLine.StringToInt64P(name, shorthand, value, usage)
|
||||||
|
}
|
||||||
42
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
42
vendor/github.com/spf13/pflag/uint_slice.go
generated
vendored
@ -50,6 +50,48 @@ func (s *uintSliceValue) String() string {
|
|||||||
return "[" + strings.Join(out, ",") + "]"
|
return "[" + strings.Join(out, ",") + "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) fromString(val string) (uint, error) {
|
||||||
|
t, err := strconv.ParseUint(val, 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return uint(t), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) toString(val uint) string {
|
||||||
|
return fmt.Sprintf("%d", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) Append(val string) error {
|
||||||
|
i, err := s.fromString(val)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
*s.value = append(*s.value, i)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) Replace(val []string) error {
|
||||||
|
out := make([]uint, len(val))
|
||||||
|
for i, d := range val {
|
||||||
|
var err error
|
||||||
|
out[i], err = s.fromString(d)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s.value = out
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *uintSliceValue) GetSlice() []string {
|
||||||
|
out := make([]string, len(*s.value))
|
||||||
|
for i, d := range *s.value {
|
||||||
|
out[i] = s.toString(d)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
func uintSliceConv(val string) (interface{}, error) {
|
func uintSliceConv(val string) (interface{}, error) {
|
||||||
val = strings.Trim(val, "[]")
|
val = strings.Trim(val, "[]")
|
||||||
// Empty string would cause a slice with one (empty) entry
|
// Empty string would cause a slice with one (empty) entry
|
||||||
|
|||||||
9
vendor/modules.txt
vendored
9
vendor/modules.txt
vendored
@ -141,7 +141,6 @@ github.com/gogo/protobuf/proto
|
|||||||
github.com/gogo/protobuf/sortkeys
|
github.com/gogo/protobuf/sortkeys
|
||||||
github.com/gogo/protobuf/types
|
github.com/gogo/protobuf/types
|
||||||
# github.com/golang/protobuf v1.3.1
|
# github.com/golang/protobuf v1.3.1
|
||||||
## explicit
|
|
||||||
github.com/golang/protobuf/proto
|
github.com/golang/protobuf/proto
|
||||||
github.com/golang/protobuf/ptypes
|
github.com/golang/protobuf/ptypes
|
||||||
github.com/golang/protobuf/ptypes/any
|
github.com/golang/protobuf/ptypes/any
|
||||||
@ -186,10 +185,11 @@ github.com/pkg/errors
|
|||||||
## explicit
|
## explicit
|
||||||
github.com/sirupsen/logrus
|
github.com/sirupsen/logrus
|
||||||
github.com/sirupsen/logrus/hooks/writer
|
github.com/sirupsen/logrus/hooks/writer
|
||||||
# github.com/spf13/cobra v0.0.5
|
# github.com/spf13/cobra v1.0.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/spf13/cobra
|
github.com/spf13/cobra
|
||||||
# github.com/spf13/pflag v1.0.3
|
# github.com/spf13/pflag v1.0.5
|
||||||
|
## explicit
|
||||||
github.com/spf13/pflag
|
github.com/spf13/pflag
|
||||||
# github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
# github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
||||||
## explicit
|
## explicit
|
||||||
@ -209,6 +209,7 @@ golang.org/x/net/internal/timeseries
|
|||||||
golang.org/x/net/proxy
|
golang.org/x/net/proxy
|
||||||
golang.org/x/net/trace
|
golang.org/x/net/trace
|
||||||
# golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
# golang.org/x/sync v0.0.0-20190423024810-112230192c58
|
||||||
|
## explicit
|
||||||
golang.org/x/sync/errgroup
|
golang.org/x/sync/errgroup
|
||||||
golang.org/x/sync/semaphore
|
golang.org/x/sync/semaphore
|
||||||
# golang.org/x/sys v0.0.0-20190902133755-9109b7679e13
|
# golang.org/x/sys v0.0.0-20190902133755-9109b7679e13
|
||||||
@ -221,8 +222,6 @@ golang.org/x/text/secure/bidirule
|
|||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/bidi
|
golang.org/x/text/unicode/bidi
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
# golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
|
|
||||||
## explicit
|
|
||||||
# google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
|
# google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
|
||||||
google.golang.org/genproto/googleapis/rpc/status
|
google.golang.org/genproto/googleapis/rpc/status
|
||||||
# google.golang.org/grpc v1.23.0
|
# google.golang.org/grpc v1.23.0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user