Skip to content

Commit

Permalink
Drop wrangler-cli dependency (#1896)
Browse files Browse the repository at this point in the history
  • Loading branch information
aruiz14 committed Jan 12, 2024
1 parent 1a500c4 commit 2d3f720
Show file tree
Hide file tree
Showing 13 changed files with 357 additions and 27 deletions.
9 changes: 7 additions & 2 deletions cmd/fleetagent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import (

"github.com/rancher/fleet/internal/cmd/agent"

command "github.com/rancher/wrangler-cli"
"github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus"
)

func main() {
command.Main(agent.App())
ctx := signals.SetupSignalContext()
cmd := agent.App()
if err := cmd.ExecuteContext(ctx); err != nil {
logrus.Fatal(err)
}
}
16 changes: 11 additions & 5 deletions cmd/fleetcli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
package main

import (
cmds "github.com/rancher/fleet/internal/cmd/cli"

command "github.com/rancher/wrangler-cli"

// Ensure GVKs are registered
_ "github.com/rancher/fleet/pkg/generated/controllers/fleet.cattle.io"
_ "github.com/rancher/wrangler/pkg/generated/controllers/apiextensions.k8s.io"
Expand All @@ -15,8 +11,18 @@ import (

// Add non-default auth providers
_ "k8s.io/client-go/plugin/pkg/client/auth"

"github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus"

cmds "github.com/rancher/fleet/internal/cmd/cli"
)

func main() {
command.Main(cmds.App())
ctx := signals.SetupSignalContext()
cmd := cmds.App()
if err := cmd.ExecuteContext(ctx); err != nil {
logrus.Fatal(err)
}

}
9 changes: 7 additions & 2 deletions cmd/fleetcontroller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ import (

"github.com/rancher/fleet/internal/cmd/controller"

command "github.com/rancher/wrangler-cli"
_ "github.com/rancher/wrangler/pkg/generated/controllers/apiextensions.k8s.io"
_ "github.com/rancher/wrangler/pkg/generated/controllers/networking.k8s.io"
"github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus"
)

func main() {
command.Main(controller.App())
ctx := signals.SetupSignalContext()
cmd := controller.App()
if err := cmd.ExecuteContext(ctx); err != nil {
logrus.Fatal(err)
}
}
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ require (
github.com/rancher/gitjob v0.1.77
github.com/rancher/lasso v0.0.0-20230810170912-a86ba6c749aa
github.com/rancher/wrangler v1.1.1
github.com/rancher/wrangler-cli v0.0.0-20220624114648-479c5692ba22
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
Expand Down Expand Up @@ -235,7 +234,6 @@ require (
k8s.io/code-generator v0.27.4 // indirect
k8s.io/component-base v0.27.4 // indirect
k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect
k8s.io/klog v1.0.0 // indirect
k8s.io/kubectl v0.27.3 // indirect
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
oras.land/oras-go v1.2.3 // indirect
Expand Down
5 changes: 0 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
Expand Down Expand Up @@ -847,8 +846,6 @@ github.com/rancher/lasso v0.0.0-20230810170912-a86ba6c749aa h1:iUxmcuDbIDs7L4k2+
github.com/rancher/lasso v0.0.0-20230810170912-a86ba6c749aa/go.mod h1:2c6KtWgSmJH1wEQBh336q9jnj79UwgBNczJowSuCixI=
github.com/rancher/wrangler v1.1.1 h1:wmqUwqc2M7ADfXnBCJTFkTB5ZREWpD78rnZMzmxwMvM=
github.com/rancher/wrangler v1.1.1/go.mod h1:ioVbKupzcBOdzsl55MvEDN0R1wdGggj8iNCYGFI5JvM=
github.com/rancher/wrangler-cli v0.0.0-20220624114648-479c5692ba22 h1:ADMwgJyVwmLXJBSm/nNobB1XGSmFCTA+TY/otxgIPu4=
github.com/rancher/wrangler-cli v0.0.0-20220624114648-479c5692ba22/go.mod h1:vyO9SU60oplNFa5ZqoEAFWmYKgj2F6remdy8p6H0SgI=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
Expand Down Expand Up @@ -1631,8 +1628,6 @@ k8s.io/component-base v0.27.4 h1:Wqc0jMKEDGjKXdae8hBXeskRP//vu1m6ypC+gwErj4c=
k8s.io/component-base v0.27.4/go.mod h1:hoiEETnLc0ioLv6WPeDt8vD34DDeB35MfQnxCARq3kY=
k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08=
k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
Expand Down
3 changes: 1 addition & 2 deletions internal/cmd/agent/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ import (

"github.com/spf13/cobra"

command "github.com/rancher/fleet/internal/cmd"
"github.com/rancher/fleet/pkg/version"

command "github.com/rancher/wrangler-cli"
)

var (
Expand Down
274 changes: 274 additions & 0 deletions internal/cmd/builder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
package cmd

// Copied from https://github.com/rancher/wrangler-cli

import (
"os"
"reflect"
"regexp"
"strconv"
"strings"
"unsafe"

"github.com/rancher/wrangler/pkg/signals"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var (
caseRegexp = regexp.MustCompile("([a-z])([A-Z])")
)

type PersistentPreRunnable interface {
PersistentPre(cmd *cobra.Command, args []string) error
}

type PreRunnable interface {
Pre(cmd *cobra.Command, args []string) error
}

type Runnable interface {
Run(cmd *cobra.Command, args []string) error
}

type customizer interface {
Customize(cmd *cobra.Command)
}

type fieldInfo struct {
FieldType reflect.StructField
FieldValue reflect.Value
}

func fields(obj interface{}) []fieldInfo {
ptrValue := reflect.ValueOf(obj)
objValue := ptrValue.Elem()

var result []fieldInfo

for i := 0; i < objValue.NumField(); i++ {
fieldType := objValue.Type().Field(i)
if fieldType.Anonymous && fieldType.Type.Kind() == reflect.Struct {
result = append(result, fields(objValue.Field(i).Addr().Interface())...)
} else if !fieldType.Anonymous {
result = append(result, fieldInfo{
FieldValue: objValue.Field(i),
FieldType: objValue.Type().Field(i),
})
}
}

return result
}

func Name(obj interface{}) string {
ptrValue := reflect.ValueOf(obj)
objValue := ptrValue.Elem()
commandName := strings.Replace(objValue.Type().Name(), "Command", "", 1)
commandName, _ = name(commandName, "", "")
return commandName
}

func Main(cmd *cobra.Command) {
ctx := signals.SetupSignalContext()
if err := cmd.ExecuteContext(ctx); err != nil {
logrus.Fatal(err)
}
}

// Command populates a cobra.Command object by extracting args from struct tags of the
// Runnable obj passed. Also the Run method is assigned to the RunE of the command.
// name = Override the struct field with

func Command(obj Runnable, cmd cobra.Command) *cobra.Command {
var (
envs []func()
arrays = map[string]reflect.Value{}
slices = map[string]reflect.Value{}
maps = map[string]reflect.Value{}
ptrValue = reflect.ValueOf(obj)
objValue = ptrValue.Elem()
)

c := cmd
if c.Use == "" {
c.Use = Name(obj)
}

for _, info := range fields(obj) {
fieldType := info.FieldType
v := info.FieldValue

name, alias := name(fieldType.Name, fieldType.Tag.Get("name"), fieldType.Tag.Get("short"))
usage := fieldType.Tag.Get("usage")
env := strings.Split(fieldType.Tag.Get("env"), ",")
defValue := fieldType.Tag.Get("default")
if len(env) == 1 && env[0] == "" {
env = nil
}
defInt, err := strconv.Atoi(defValue)
if err != nil {
defInt = 0
}

flags := c.PersistentFlags()
switch fieldType.Type.Kind() {
case reflect.Int:
flags.IntVarP((*int)(unsafe.Pointer(v.Addr().Pointer())), name, alias, defInt, usage)
case reflect.String:
flags.StringVarP((*string)(unsafe.Pointer(v.Addr().Pointer())), name, alias, defValue, usage)
case reflect.Slice:
switch fieldType.Tag.Get("split") {
case "false":
arrays[name] = v
flags.StringArrayP(name, alias, nil, usage)
default:
slices[name] = v
flags.StringSliceP(name, alias, nil, usage)
}
case reflect.Map:
maps[name] = v
flags.StringSliceP(name, alias, nil, usage)
case reflect.Bool:
flags.BoolVarP((*bool)(unsafe.Pointer(v.Addr().Pointer())), name, alias, false, usage)
default:
panic("Unknown kind on field " + fieldType.Name + " on " + objValue.Type().Name())
}

for _, env := range env {
envs = append(envs, func() {
v := os.Getenv(env)
if v != "" {
fv, err := flags.GetString(name)
if err == nil && (fv == "" || fv == defValue) {
_ = flags.Set(name, v)
}
}
})
}
}

if p, ok := obj.(PersistentPreRunnable); ok {
c.PersistentPreRunE = p.PersistentPre
}

if p, ok := obj.(PreRunnable); ok {
c.PreRunE = p.Pre
}

c.RunE = obj.Run
c.PersistentPreRunE = bind(c.PersistentPreRunE, arrays, slices, maps, envs)
c.PreRunE = bind(c.PreRunE, arrays, slices, maps, envs)
c.RunE = bind(c.RunE, arrays, slices, maps, envs)

cust, ok := obj.(customizer)
if ok {
cust.Customize(&c)
}

return &c
}

func assignMaps(app *cobra.Command, maps map[string]reflect.Value) error {
for k, v := range maps {
k = contextKey(k)
s, err := app.Flags().GetStringSlice(k)
if err != nil {
return err
}
if s != nil {
values := map[string]string{}
for _, part := range s {
parts := strings.SplitN(part, "=", 2)
if len(parts) == 1 {
values[parts[0]] = ""
} else {
values[parts[0]] = parts[1]
}
}
v.Set(reflect.ValueOf(values))
}
}
return nil
}

func assignSlices(app *cobra.Command, slices map[string]reflect.Value) error {
for k, v := range slices {
k = contextKey(k)
s, err := app.Flags().GetStringSlice(k)
if err != nil {
return err
}
if s != nil {
v.Set(reflect.ValueOf(s[:]))
}
}
return nil
}

func assignArrays(app *cobra.Command, arrays map[string]reflect.Value) error {
for k, v := range arrays {
k = contextKey(k)
s, err := app.Flags().GetStringArray(k)
if err != nil {
return err
}
if s != nil {
v.Set(reflect.ValueOf(s[:]))
}
}
return nil
}

func contextKey(name string) string {
parts := strings.Split(name, ",")
return parts[len(parts)-1]
}

func name(name, setName, short string) (string, string) {
if setName != "" {
return setName, short
}
parts := strings.Split(name, "_")
i := len(parts) - 1
name = caseRegexp.ReplaceAllString(parts[i], "$1-$2")
name = strings.ToLower(name)
result := append([]string{name}, parts[0:i]...)
for i := 0; i < len(result); i++ {
result[i] = strings.ToLower(result[i])
}
if short == "" && len(result) > 1 {
short = result[1]
}
return result[0], short
}

func bind(next func(*cobra.Command, []string) error,
arrays map[string]reflect.Value,
slices map[string]reflect.Value,
maps map[string]reflect.Value,
envs []func()) func(*cobra.Command, []string) error {
if next == nil {
return nil
}
return func(cmd *cobra.Command, args []string) error {
for _, envCallback := range envs {
envCallback()
}
if err := assignArrays(cmd, arrays); err != nil {
return err
}
if err := assignSlices(cmd, slices); err != nil {
return err
}
if err := assignMaps(cmd, maps); err != nil {
return err
}

if next != nil {
return next(cmd, args)
}

return nil
}
}
Loading

0 comments on commit 2d3f720

Please sign in to comment.