Skip to content

Commit

Permalink
add several --tube-* flags, look for kubectl in $PATH
Browse files Browse the repository at this point in the history
  • Loading branch information
kovetskiy committed Mar 20, 2019
1 parent c655c4a commit 86904b1
Show file tree
Hide file tree
Showing 7 changed files with 331 additions and 102 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,13 @@ the same time.
tubectl exec +sys '(apiserver|scheduler)%' -- id
```
### Custom flags
Tubectl supports a few own flags, they all have prefix `--tube`:
* `--tube-version` - prints version of the program
* `--tube-debug` - enables debug mode, also can be turned on by `TUBEKIT_DEBUG`
* `--tube-help` - prints short help message about the program.
### Authors
Expand Down
85 changes: 85 additions & 0 deletions cmd/tubectl/complete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"fmt"
"regexp"
"strings"

"github.com/reconquest/karma-go"
)

func matchResources(resources []Resource, params *ParamsMatch) ([]Resource, error) {
exp, err := regexp.Compile(params.Query)
if err != nil {
return nil, karma.Format(
err,
"unable to compile regexp: %s", params.Query,
)
}

matched := []Resource{}
for _, resource := range resources {
if exp.MatchString(resource.Name) {
matched = append(matched, resource)
}
}

return matched, nil
}

func completeParams(client string, params *Params) (*Params, error) {
if params.CompleteContext {
contexts, err := parseKubernetesContexts()
if err != nil {
return params, err
}

completed := complete(contexts, params.Context)
if completed == "" && params.Context != "" {
return params, fmt.Errorf(
"unable to find such context: %s",
params.Context,
)
}

params.Context = completed
}

if params.CompleteNamespace {
namespaces, err := requestNamespaces(client, params)
if err != nil {
return params, karma.Format(
err,
"unable to retrieve list of available namespaces",
)
}

completed := complete(namespaces, params.Namespace)
if completed == "" && params.Context != "" {
return params, fmt.Errorf(
"unable to find such namespace in context %s: %s",
params.Context,
params.Namespace,
)
}

params.Namespace = completed
}

return params, nil
}

func complete(items []string, query string) string {
var partial string
for _, item := range items {
if item == query {
return item
}

if strings.Contains(item, query) {
partial = item
}
}

return partial
}
60 changes: 60 additions & 0 deletions cmd/tubectl/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package main

import (
"fmt"
"strings"
)

const (
argPrefix = "--tube-"
)

type Flags struct {
Help bool
Debug bool
Version bool
}

func parseFlags(raw []string) ([]string, *Flags, error) {
args := make([]string, len(raw))
copy(args, raw)

flags := &Flags{}
for i := 0; i < len(args); i++ {
if i == 0 {
continue
}

arg := args[i]

if arg == "--" {
break
}

if strings.HasPrefix(arg, argPrefix) {
suffix := strings.TrimPrefix(arg, argPrefix)

switch suffix {
case "help":
flags.Help = true

case "debug":
flags.Debug = true

case "version":
flags.Version = true

default:
return raw, nil, fmt.Errorf(
"unexpected flag %q specified, see %shelp",
arg, argPrefix,
)
}

args = append(args[:i], args[i+1:]...)
i--
}
}

return args, flags, nil
}
92 changes: 92 additions & 0 deletions cmd/tubectl/flags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package main

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestFlags(t *testing.T) {
test := assert.New(t)

testcases := []struct {
raw []string
after []string
flags *Flags
}{
{
[]string{"x", "--version"},
[]string{"x", "--version"},
&Flags{},
},
{
[]string{"x", "a", "b", "c%%", "@d", "--", "e", "", "v"},
[]string{"x", "a", "b", "c%%", "@d", "--", "e", "", "v"},
&Flags{},
},
{
[]string{"x", "--version", "--tube-version", "@after"},
[]string{"x", "--version", "@after"},
&Flags{
Version: true,
},
},
{
[]string{"x", "--version", "--tube-debug", "@after"},
[]string{"x", "--version", "@after"},
&Flags{
Debug: true,
},
},
{
[]string{"x", "--version", "--tube-help", "@after"},
[]string{"x", "--version", "@after"},
&Flags{
Help: true,
},
},
{
[]string{"x", "--version", "--tube-help"},
[]string{"x", "--version"},
&Flags{
Help: true,
},
},
{
[]string{"x", "--version", "--tube-help", "--tube-version", "--tube-debug"},
[]string{"x", "--version"},
&Flags{
Help: true,
Version: true,
Debug: true,
},
},
{
[]string{"x", "--version", "--", "--tube-help"},
[]string{"x", "--version", "--", "--tube-help"},
&Flags{},
},
{
[]string{"x", "--tube-unexpected"},
[]string{"x", "--tube-unexpected"},
nil,
},
}

for _, testcase := range testcases {
args, flags, err := parseFlags(testcase.raw)
if !test.EqualValues(testcase.flags, flags, "%q", testcase.raw) {
t.FailNow()
}

if !test.EqualValues(testcase.after, args, "%q", testcase.raw) {
t.FailNow()
}

if testcase.flags == nil {
if !test.Error(err) {
t.FailNow()
}
}
}
}
12 changes: 6 additions & 6 deletions cmd/tubectl/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ func parseKubernetesContexts() ([]string, error) {
return contexts, nil
}

func requestNamespaces(ctlPath string, params *Params) ([]string, error) {
func requestNamespaces(client string, params *Params) ([]string, error) {
// omit namespace argument because requesting list of them
cmd, args := getCommand(
ctlPath, buildArgContext(params.Context), "", "",
client, buildArgContext(params.Context), "", "",
"get", "namespaces", "-o", "json",
)

Expand Down Expand Up @@ -73,9 +73,9 @@ func requestNamespaces(ctlPath string, params *Params) ([]string, error) {
return namespaces, nil
}

func requestResources(ctlPath string, params *Params) ([]Resource, error) {
func requestResources(client string, params *Params) ([]Resource, error) {
cmd, args := getCommand(
ctlPath,
client,
buildArgContext(params.Context),
buildArgNamespace(params.Namespace),
buildArgAllNamespaces(params.AllNamespaces),
Expand Down Expand Up @@ -132,7 +132,7 @@ func unmarshalResources(contents []byte) ([]Resource, error) {
}

func getCommand(
ctlPath string,
client string,
argContext,
argNamespace string,
argAllNamespaces string,
Expand All @@ -152,7 +152,7 @@ func getCommand(
args = append(args, argAllNamespaces)
}

return exec.Command(ctlPath, args...), append([]string{ctlPath}, args...)
return exec.Command(client, args...), append([]string{client}, args...)
}

func buildArgContext(value string) string {
Expand Down
Loading

0 comments on commit 86904b1

Please sign in to comment.