diff --git a/go.mod b/go.mod index d958519583d..4cf5bb4e942 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.23.3 require ( fybrik.io/crdoc v0.6.3 github.com/Masterminds/semver/v3 v3.3.0 - github.com/Netflix/go-expect v0.0.0-20180928190340-9d1f4485533b github.com/ahmetb/gen-crd-api-reference-docs v0.3.1-0.20240214155107-6cf1ede4da61 github.com/avast/retry-go v2.4.3+incompatible github.com/avast/retry-go/v4 v4.3.3 @@ -21,7 +20,6 @@ require ( github.com/google/go-github/v32 v32.0.0 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/go-multierror v1.1.1 - github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c github.com/kelseyhightower/envconfig v1.4.0 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.35.0 @@ -43,7 +41,6 @@ require ( golang.org/x/tools v0.26.0 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.36.1 - gopkg.in/AlecAivazis/survey.v1 v1.8.7 helm.sh/helm/v3 v3.16.2 istio.io/api v1.24.0-alpha.0.0.20241106042855-9e26cdd3450a istio.io/client-go v1.24.0-alpha.0.0.20241106043554-b5828356941f @@ -91,7 +88,6 @@ require ( github.com/containerd/containerd v1.7.12 // indirect github.com/containerd/continuity v0.4.3 // indirect github.com/containerd/log v0.1.0 // indirect - github.com/creack/pty v1.1.18 // indirect github.com/cyphar/filepath-securejoin v0.3.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect @@ -154,10 +150,8 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/k0kubun/pp v3.0.1+incompatible // indirect github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/klauspost/compress v1.17.9 // indirect - github.com/kr/pty v1.1.8 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect @@ -173,7 +167,6 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect diff --git a/go.sum b/go.sum index c215bbd66f2..35a5f92fb82 100644 --- a/go.sum +++ b/go.sum @@ -97,7 +97,6 @@ github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYx github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/Netflix/go-expect v0.0.0-20180928190340-9d1f4485533b h1:sSQK05nvxs4UkgCJaxihteu+r+6ela3dNMm7NVmsS3c= github.com/Netflix/go-expect v0.0.0-20180928190340-9d1f4485533b/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= @@ -577,7 +576,6 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c h1:kp3AxgXgDOmIJFR7bIwqFhwJ2qWar8tEQSE5XXhCfVk= github.com/hinshun/vt10x v0.0.0-20180809195222-d55458df857c/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= @@ -624,7 +622,6 @@ github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= @@ -648,8 +645,6 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/pty v1.1.8 h1:AkaSdXYQOWeaO3neb8EM634ahkXXe3jYbVh/F9lq+GI= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -703,7 +698,6 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.17/go.mod h1:WgzbA6oji13JREwiNsRDNfl7jYdPnmz+VEuLrA+/48M= @@ -1558,8 +1552,6 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/AlecAivazis/survey.v1 v1.8.2/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= -gopkg.in/AlecAivazis/survey.v1 v1.8.7 h1:oBJqtgsyBLg9K5FK9twNUbcPnbCPoh+R9a+7nag3qJM= -gopkg.in/AlecAivazis/survey.v1 v1.8.7/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA= 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 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/cliutil/ask.go b/pkg/cliutil/ask.go deleted file mode 100644 index b259f28a071..00000000000 --- a/pkg/cliutil/ask.go +++ /dev/null @@ -1,19 +0,0 @@ -package cliutil - -import ( - survey "gopkg.in/AlecAivazis/survey.v1" - "gopkg.in/AlecAivazis/survey.v1/terminal" -) - -func UseStdio(io terminal.Stdio) { - stdio = &io -} - -var stdio *terminal.Stdio - -func AskOne(p survey.Prompt, response interface{}, v survey.Validator, opts ...survey.AskOpt) error { - if stdio != nil { - opts = append(opts, survey.WithStdio(stdio.In, stdio.Out, stdio.Err)) - } - return survey.AskOne(p, response, v, opts...) -} diff --git a/pkg/cliutil/cliutil_suite_test.go b/pkg/cliutil/cliutil_suite_test.go deleted file mode 100644 index eedb67d2256..00000000000 --- a/pkg/cliutil/cliutil_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package cliutil_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestCliutil(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Cliutil Suite") -} diff --git a/pkg/cliutil/helm/hooks.go b/pkg/cliutil/helm/hooks.go deleted file mode 100644 index 6947286d204..00000000000 --- a/pkg/cliutil/helm/hooks.go +++ /dev/null @@ -1,24 +0,0 @@ -package helm - -import ( - "github.com/rotisserie/eris" - "helm.sh/helm/v3/pkg/release" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - _ "k8s.io/client-go/plugin/pkg/client/auth" - "sigs.k8s.io/yaml" -) - -// Some resources can be duplicated because of weirdness with Helm hooks, however we have a test that -// makes sure we don't produce such charts anymore, so this just returns all resources now. -func GetHooks(hooks []*release.Hook) (results []*release.Hook, err error) { - for _, hook := range hooks { - // Parse the resource in order to access the annotations - var resource struct{ Metadata metav1.ObjectMeta } - if err := yaml.Unmarshal([]byte(hook.Manifest), &resource); err != nil { - return nil, eris.Wrapf(err, "parsing resource: %s", hook.Manifest) - } - results = append(results, hook) - } - - return results, nil -} diff --git a/pkg/cliutil/input.go b/pkg/cliutil/input.go deleted file mode 100644 index 2ea670c8e97..00000000000 --- a/pkg/cliutil/input.go +++ /dev/null @@ -1,230 +0,0 @@ -package cliutil - -import ( - "fmt" - "strconv" - "strings" - - "gopkg.in/AlecAivazis/survey.v1" -) - -func GetYesInput(msg string) (bool, error) { - var yesAnswer string - - if err := GetStringInputDefault( - msg, - &yesAnswer, - "N", - ); err != nil { - return false, err - } - return strings.ToLower(yesAnswer) == "y", nil -} - -func GetStringInputLazyPrompt(msgProvider func() string, value *string) error { - return GetStringInputDefaultLazyPrompt(msgProvider, value, "") -} - -func GetStringInput(msg string, value *string) error { - return GetStringInputDefault(msg, value, "") -} - -func GetStringInputDefaultLazyPrompt(msgProvider func() string, value *string, defaultValue string) error { - prompt := &survey.Input{Message: msgProvider(), Default: defaultValue} - if err := AskOne(prompt, value, nil); err != nil { - return err - } - return nil -} - -func GetStringInputDefault(msg string, value *string, defaultValue string) error { - prompt := &survey.Input{Message: msg, Default: defaultValue} - if err := AskOne(prompt, value, nil); err != nil { - return err - } - return nil -} - -func GetUint32Input(msg string, value *uint32) error { - return GetUint32InputDefault(msg, value, 0) -} - -func GetUint32InputDefault(msg string, value *uint32, defaultValue uint32) error { - var strValue string - prompt := &survey.Input{Message: msg, Default: strconv.Itoa(int(defaultValue))} - if err := AskOne(prompt, &strValue, nil); err != nil { - return err - } - val, err := strconv.Atoi(strValue) - if err != nil { - return err - } - *value = uint32(val) - return nil -} - -func GetBoolInput(msg string, value *bool) error { - return GetBoolInputDefault(msg, value, false) -} - -func GetBoolInputDefault(msg string, value *bool, defaultValue bool) error { - var strValue string - defaultValueStr := "N" - if defaultValue { - defaultValueStr = "y" - } - prompt := &survey.Input{Message: msg + " [y/N]: ", Default: defaultValueStr} - if err := AskOne(prompt, &strValue, nil); err != nil { - return err - } - *value = strings.ToLower(strValue) == "y" - return nil -} - -func GetStringSliceInputLazyPrompt(msgProvider func() string, value *[]string) error { - for { - var entry string - if err := GetStringInputLazyPrompt(msgProvider, &entry); err != nil { - return err - } - - if entry == "" { - return nil - } - *value = append(*value, entry) - } -} - -func GetStringSliceInput(msg string, value *[]string) error { - for { - var entry string - if err := GetStringInput(msg, &entry); err != nil { - return err - } - - if entry == "" { - return nil - } - *value = append(*value, entry) - } -} - -func ChooseFromList(message string, choice *string, options []string) error { - if len(options) == 0 { - return fmt.Errorf("No options to select from (for prompt: %v)", message) - } - - question := &survey.Select{ - Message: message, - Options: options, - } - - if err := AskOne(question, choice, survey.Required); err != nil { - // this should not error - fmt.Println("error with input") - return err - } - - return nil -} - -func MultiChooseFromList(message string, choices *[]string, options []string) error { - if len(options) == 0 { - return fmt.Errorf("No options to select from (for prompt: %v)", message) - } - - question := &survey.MultiSelect{ - Message: message, - Options: options, - } - - if err := AskOne(question, choices, survey.Required); err != nil { - // this should not error - fmt.Println("error with input") - return err - } - - return nil -} - -func ChooseBool(message string, target *bool) error { - - yes, no := "yes", "no" - - question := &survey.Select{ - Message: message, - Options: []string{yes, no}, - } - - var choice string - if err := AskOne(question, &choice, survey.Required); err != nil { - return err - } - - *target = choice == yes - return nil -} - -type JoinerData interface { - Join() string - ID() string -} -type JoinerDataSlice []JoinerData - -func SelectJoinedData(message string, target *string, list []JoinerData) error { - var optionsList []string - for i, j := range list { - // construct the options - optionsList = append(optionsList, fmt.Sprintf("%v. %v", i, j.Join())) - } - question := &survey.Select{ - Message: message, - Options: optionsList, - } - - var choice string - if err := AskOne(question, &choice, survey.Required); err != nil { - return err - } - - parts := strings.SplitN(choice, ".", 2) - index, err := strconv.Atoi(parts[0]) - if err != nil { - return err - } - - *target = list[index].ID() - - return nil -} - -func EnsureCsv(message string, source string, target *[]string, staticMode bool) error { - if staticMode && source == "" { - return fmt.Errorf(message) - } - if !staticMode { - if err := GetStringInput(message, &source); err != nil { - return err - } - } - parts := strings.Split(source, ",") - *target = parts - return nil -} - -// Expected format of source: k1,v1,k2,v2 -func EnsureKVCsv(message string, source string, target *map[string]string, staticMode bool) error { - parts := []string{} - EnsureCsv(message, source, &parts, staticMode) - if len(parts) == 1 && parts[0] == "" { - // case where user does not specify any values - return nil - } - if len(parts)%2 != 0 { - return fmt.Errorf("Must provide one key per value (received an odd sum)") - } - for i := range len(parts) / 2 { - (*target)[parts[i*2]] = parts[i*2+1] - } - return nil -} diff --git a/pkg/cliutil/input_test.go b/pkg/cliutil/input_test.go deleted file mode 100644 index ecc1e8b3653..00000000000 --- a/pkg/cliutil/input_test.go +++ /dev/null @@ -1,24 +0,0 @@ -package cliutil_test - -import ( - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - - . "github.com/kgateway-dev/kgateway/pkg/cliutil" - "github.com/kgateway-dev/kgateway/pkg/cliutil/testutil" -) - -var _ = Describe("GetBoolInput", func() { - It("correctly sets the input value", func() { - testutil.ExpectInteractive(func(c *testutil.Console) { - c.ExpectString("test msg [y/N]: ") - c.SendLine("y") - c.ExpectEOF() - }, func() { - var val bool - err := GetBoolInput("test msg", &val) - Expect(err).NotTo(HaveOccurred()) - Expect(val).To(BeTrue()) - }) - }) -}) diff --git a/pkg/cliutil/install/kubernetes.go b/pkg/cliutil/install/kubernetes.go deleted file mode 100644 index c94bcb6f3f9..00000000000 --- a/pkg/cliutil/install/kubernetes.go +++ /dev/null @@ -1,71 +0,0 @@ -package install - -import ( - "bytes" - "fmt" - "io" - "os" - "os/exec" - - "github.com/kgateway-dev/kgateway/pkg/cliutil" -) - -// Deprecated: Prefer kubectl.Cli -type KubeCli interface { - Kubectl(stdin io.Reader, args ...string) error - KubectlOut(stdin io.Reader, args ...string) ([]byte, error) -} - -type CmdKubectl struct{} - -var _ KubeCli = &CmdKubectl{} - -func (k *CmdKubectl) Kubectl(stdin io.Reader, args ...string) error { - return Kubectl(stdin, args...) -} - -func (k *CmdKubectl) KubectlOut(stdin io.Reader, args ...string) ([]byte, error) { - return KubectlOut(stdin, args...) -} - -var verbose bool - -func SetVerbose(b bool) { - verbose = b -} - -// Deprecated: Prefer kubectl.Cli -func Kubectl(stdin io.Reader, args ...string) error { - _, err := KubectlOut(stdin, args...) - return err -} - -// Deprecated: Prefer kubectl.Cli -func KubectlOut(stdin io.Reader, args ...string) ([]byte, error) { - kubectl := exec.Command("kubectl", args...) - - if stdin != nil { - kubectl.Stdin = stdin - } - - var stdout, stderr io.Writer - if verbose { - fmt.Fprintf(os.Stderr, "running kubectl command: %v\n", kubectl.Args) - stdout = os.Stdout - stderr = os.Stderr - } else { - // use logfile - cliutil.Initialize() - stdout = cliutil.GetLogger() - stderr = cliutil.GetLogger() - } - - buf := &bytes.Buffer{} - - kubectl.Stdout = io.MultiWriter(stdout, buf) - kubectl.Stderr = io.MultiWriter(stderr, buf) - - err := kubectl.Run() - - return buf.Bytes(), err -} diff --git a/pkg/cliutil/list.go b/pkg/cliutil/list.go deleted file mode 100644 index 23502ccc67d..00000000000 --- a/pkg/cliutil/list.go +++ /dev/null @@ -1,11 +0,0 @@ -package cliutil - -// TODO(mitchdraft) move this to a util file -func Contains(a []string, s string) bool { - for _, n := range a { - if s == n { - return true - } - } - return false -} diff --git a/pkg/cliutil/logger.go b/pkg/cliutil/logger.go deleted file mode 100644 index da7a411f09a..00000000000 --- a/pkg/cliutil/logger.go +++ /dev/null @@ -1,64 +0,0 @@ -package cliutil - -import ( - "io" - "os" - "path/filepath" - "sync" - - "k8s.io/client-go/util/homedir" -) - -const ( - glooDir = ".gloo" - glooLogs = "debug.log" -) - -var ( - glooPath string - glooLogsPath string - logger io.Writer - mutex sync.Once -) - -func init() { - home := homedir.HomeDir() - glooPath = filepath.Join(home, glooDir) - glooLogsPath = filepath.Join(glooPath, glooLogs) -} - -func GetLogsPath() string { - return glooLogsPath -} - -func GetLogger() io.Writer { - Initialize() - return logger -} - -func Initialize() error { - var initError error - mutex.Do(func() { - if _, err := os.ReadDir(glooPath); err != nil { - if !os.IsNotExist(err) { - initError = err - return - } - err = os.Mkdir(glooPath, 0755) - if err != nil { - initError = err - return - } - } - file, err := os.OpenFile(glooLogsPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - initError = err - return - } - logger = file - }) - if initError != nil { - logger = os.Stdout - } - return initError -} diff --git a/pkg/cliutil/nsselect/nsutil_suite_test.go b/pkg/cliutil/nsselect/nsutil_suite_test.go deleted file mode 100644 index 8f74a9275c7..00000000000 --- a/pkg/cliutil/nsselect/nsutil_suite_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package nsselect_test - -import ( - "testing" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" -) - -func TestGit(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "NsSelect Test") -} diff --git a/pkg/cliutil/nsselect/types.go b/pkg/cliutil/nsselect/types.go deleted file mode 100644 index 61f2f8b2a9d..00000000000 --- a/pkg/cliutil/nsselect/types.go +++ /dev/null @@ -1,12 +0,0 @@ -package nsselect - -// All the cli-relevant resources keyed by namespace -type NsResourceMap map[string]*NsResource - -// NsResource contains lists of the resources needed by the cli associated* with given namespace. -// *the association is by the namespace in which the CRD is installed, unless otherwise noted. -type NsResource struct { - // keyed by namespace containing the CRD - Secrets []string - Upstreams []string -} diff --git a/pkg/cliutil/testutil/testutil.go b/pkg/cliutil/testutil/testutil.go deleted file mode 100644 index 4d742156318..00000000000 --- a/pkg/cliutil/testutil/testutil.go +++ /dev/null @@ -1,132 +0,0 @@ -package testutil - -import ( - "io" - "strings" - "time" - - expect "github.com/Netflix/go-expect" - "github.com/hinshun/vt10x" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "gopkg.in/AlecAivazis/survey.v1/terminal" - - "github.com/kgateway-dev/kgateway/pkg/cliutil" -) - -func Stdio(c *expect.Console) terminal.Stdio { - return terminal.Stdio{c.Tty(), c.Tty(), c.Tty()} -} - -func ExpectInteractive(userInput func(*Console), testCli func()) { - c, state, err := vt10x.NewVT10XConsole() - Expect(err).NotTo(HaveOccurred()) - defer c.Close() - cliutil.UseStdio(Stdio(c)) - // Dump the terminal's screen. - defer func() { GinkgoWriter.Write([]byte(expect.StripTrailingEmptyLines(state.String()))) }() - - doneC := make(chan struct{}) - go func() { - defer GinkgoRecover() - defer close(doneC) - - userInput(&Console{console: c}) - }() - - // time.Sleep(time.Hour) - go func() { - defer GinkgoRecover() - - testCli() - - // Close the slave end of the pty, and read the remaining bytes from the master end. - c.Tty().Close() - <-doneC - }() - - select { - case <-time.After(10 * time.Second): - c.Tty().Close() - Fail("test timed out") - case <-doneC: - } -} - -type Console struct { - console *expect.Console -} - -func (c *Console) ExpectString(s string) string { - ret, err := c.console.ExpectString(s) - Expect(err).NotTo(HaveOccurred()) - return ret -} - -func (c *Console) PressDown() { - // These codes are covered here: https://en.wikipedia.org/wiki/ANSI_escape_code - // see "Escape sequences" and "CSI sequences" - // 27 = Escape - // Alternatively, you can use the values written here: gopkg.in/AlecAivazis/survey.v1/terminal/sequences.go - // But I used the CSI as I seems to be more standard - - _, err := c.console.Write([]byte{27, '[', 'B'}) - Expect(err).NotTo(HaveOccurred()) -} - -func (c *Console) Esc() { - // I grabbed this value from here: gopkg.in/AlecAivazis/survey.v1/terminal/sequences.go - // Originally I tried to use escape codes (https://en.wikipedia.org/wiki/ANSI_escape_code) - // but it didnt work - _, err := c.console.Write([]byte{27}) - Expect(err).NotTo(HaveOccurred()) -} - -func (c *Console) SendLine(s string) int { - ret, err := c.console.SendLine(s) - Expect(err).NotTo(HaveOccurred()) - return ret -} - -func (c *Console) ExpectEOF() string { - ret, err := c.console.ExpectEOF() - Expect(err).NotTo(HaveOccurred()) - return ret -} - -type MockKubectl struct { - Expected []string - Next int - StdoutLines []string - StdoutLineIndex int -} - -func NewMockKubectl(cmds []string, stdoutLines []string) *MockKubectl { - return &MockKubectl{ - Expected: cmds, - Next: 0, - StdoutLines: stdoutLines, - } -} - -func (k *MockKubectl) Kubectl(stdin io.Reader, args ...string) error { - // If this fails then the CLI tried to run commands we didn't account for in the mock - Expect(k.Next).To(BeNumerically("<", len(k.Expected))) - Expect(stdin).To(BeNil()) - cmd := strings.Join(args, " ") - Expect(cmd).To(BeEquivalentTo(k.Expected[k.Next])) - k.Next = k.Next + 1 - return nil -} - -func (k *MockKubectl) KubectlOut(stdin io.Reader, args ...string) ([]byte, error) { - Expect(k.Next).To(BeNumerically("<", len(k.Expected)), "MockKubectl did not have a next command for KubectlOut") - Expect(stdin).To(BeNil(), "Should have passed nil to MockKubectl.KubectlOut") - cmd := strings.Join(args, " ") - Expect(cmd).To(BeEquivalentTo(k.Expected[k.Next]), "Wrong next command for MockKubectl.KubectlOut") - k.Next = k.Next + 1 - Expect(k.StdoutLineIndex).To(BeNumerically("<", len(k.StdoutLines)), "Mock kubectl has run out of stdout lines on command "+cmd) - stdOutLine := k.StdoutLines[k.StdoutLineIndex] - k.StdoutLineIndex = k.StdoutLineIndex + 1 - return []byte(stdOutLine), nil -} diff --git a/pkg/cliutil/uri.go b/pkg/cliutil/uri.go deleted file mode 100644 index 4fdf9337f1b..00000000000 --- a/pkg/cliutil/uri.go +++ /dev/null @@ -1,305 +0,0 @@ -package cliutil - -import ( - "bytes" - "context" - "fmt" - "io" - "net" - "net/http" - "os" - "os/exec" - "path/filepath" - "strconv" - "strings" - "time" - - "github.com/kgateway-dev/kgateway/pkg/utils/kubeutils" - - "github.com/avast/retry-go/v4" - - "github.com/kgateway-dev/kgateway/pkg/utils/kubeutils/portforward" - - "github.com/hashicorp/go-multierror" - errors "github.com/rotisserie/eris" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" -) - -const ( - defaultTimeout = 60 * time.Second -) - -var ( - defaultRetryOptions = []retry.Option{ - retry.LastErrorOnly(true), - retry.Delay(100 * time.Millisecond), - retry.DelayType(retry.BackOffDelay), - retry.Attempts(5), - } -) - -// GetResource identified by the given URI. -// The URI can either be a http(s) address or a relative/absolute file path. -func GetResource(uri string) (io.ReadCloser, error) { - var file io.ReadCloser - if strings.HasPrefix(uri, "http://") || strings.HasPrefix(uri, "https://") { - resp, err := http.Get(uri) - if err != nil { - return nil, err - } - if resp.StatusCode != http.StatusOK { - resp.Body.Close() - return nil, errors.Errorf("http GET returned status %d for resource %s", resp.StatusCode, uri) - } - - file = resp.Body - } else { - path, err := filepath.Abs(uri) - if err != nil { - return nil, errors.Wrapf(err, "getting absolute path for %v", uri) - } - - f, err := os.Open(path) - if err != nil { - return nil, errors.Wrapf(err, "opening file %v", path) - } - file = f - } - - // Write the body to file - return file, nil -} - -// GetIngressHost returns the host address of the ingress -func GetIngressHost(ctx context.Context, proxyName, proxyNamespace, proxyPort string, localCluster bool, clusterName string) (string, error) { - restCfg, err := kubeutils.GetRestConfigWithKubeContext("") - if err != nil { - return "", errors.Wrapf(err, "getting kube rest config") - } - kube, err := kubernetes.NewForConfig(restCfg) - if err != nil { - return "", errors.Wrapf(err, "starting kube client") - } - svc, err := kube.CoreV1().Services(proxyNamespace).Get(ctx, proxyName, metav1.GetOptions{}) - if err != nil { - return "", errors.Wrapf(err, "could not detect '%v' service in %v namespace. "+ - "Check that Gloo has been installed properly and is running with 'kubectl get pod -n gloo-system'", - proxyName, proxyNamespace) - } - var svcPort *corev1.ServicePort - switch len(svc.Spec.Ports) { - case 0: - return "", errors.Errorf("service %v is missing ports", proxyName) - case 1: - svcPort = &svc.Spec.Ports[0] - default: - for _, p := range svc.Spec.Ports { - if p.Name == proxyPort { - pDurable := p - svcPort = &pDurable - break - } - } - if svcPort == nil { - return "", errors.Errorf("named port %v not found on service %v", proxyPort, proxyName) - } - } - - var host, port string - serviceType := svc.Spec.Type - if localCluster { - serviceType = corev1.ServiceTypeNodePort - } - switch serviceType { - case corev1.ServiceTypeClusterIP: - // There are a few edge cases where glooctl could be run in an environment where this is not a fatal error - // However the service type ClusterIP does not accept incoming traffic which doesnt work as a ingress - logger := GetLogger() - logger.Write([]byte("Warning: Potentially invalid proxy configuration, proxy may not accepting incoming connections")) - host = svc.Spec.ClusterIP - port = fmt.Sprintf("%v", svcPort.Port) - case corev1.ServiceTypeNodePort: - // TODO: support more types of NodePort services - host, err = getNodeIp(ctx, svc, kube, clusterName) - if err != nil { - return "", errors.Wrapf(err, "") - } - port = fmt.Sprintf("%v", svcPort.NodePort) - case corev1.ServiceTypeLoadBalancer: - if len(svc.Status.LoadBalancer.Ingress) == 0 { - return "", errors.Errorf("load balancer ingress not found on service %v", proxyName) - } - host = svc.Status.LoadBalancer.Ingress[0].Hostname - if host == "" { - host = svc.Status.LoadBalancer.Ingress[0].IP - } - port = fmt.Sprintf("%v", svcPort.Port) - } - return host + ":" + port, nil -} - -func getNodeIp(ctx context.Context, svc *corev1.Service, kube kubernetes.Interface, clusterName string) (string, error) { - // pick a node where one of our pods is running - pods, err := kube.CoreV1().Pods(svc.Namespace).List(ctx, metav1.ListOptions{ - LabelSelector: labels.SelectorFromSet(svc.Spec.Selector).String(), - }) - if err != nil { - return "", err - } - var nodeName string - for _, pod := range pods.Items { - if pod.Spec.NodeName != "" { - nodeName = pod.Spec.NodeName - break - } - } - if nodeName == "" { - return "", errors.Errorf("no node found for %v's pods. ensure at least one pod has been deployed "+ - "for the %v service", svc.Name, svc.Name) - } - // special case for minikube - // we run `minikube ip` which avoids an issue where - // we get a NAT network IP when the minikube provider is virtualbox - if nodeName == "minikube" { - return minikubeIp(clusterName) - } - - node, err := kube.CoreV1().Nodes().Get(ctx, nodeName, metav1.GetOptions{}) - if err != nil { - return "", err - } - - for _, addr := range node.Status.Addresses { - return addr.Address, nil - } - - return "", errors.Errorf("no active addresses found for node %v", node.Name) -} - -func minikubeIp(clusterName string) (string, error) { - minikubeCmd := exec.Command("minikube", "ip", "-p", clusterName) - - hostname := &bytes.Buffer{} - - minikubeCmd.Stdout = hostname - minikubeCmd.Stderr = os.Stderr - err := minikubeCmd.Run() - - return strings.TrimSuffix(hostname.String(), "\n"), err -} - -// PortForward call kubectl port-forward. Callers are expected to clean up the returned portFwd *exec.cmd after the port-forward is no longer needed. -// Deprecated: Prefer portforward.NewPortForwarder -func PortForward(ctx context.Context, namespace string, resource string, localPort string, kubePort string, verbose bool) (portforward.PortForwarder, error) { - err := Initialize() - if err != nil { - return nil, err - } - logger := GetLogger() - - outWriter := logger - errWriter := io.MultiWriter(logger, os.Stderr) - if verbose { - outWriter = io.MultiWriter(logger, os.Stdout) - } - - resourceTypeName := strings.Split(resource, "/") // ie. deployment/gloo - localPortInt, err := strconv.Atoi(localPort) - if err != nil { - return nil, err - } - remotePortInt, err := strconv.Atoi(kubePort) - if err != nil { - return nil, err - } - - portForwarder := portforward.NewPortForwarder( - portforward.WithResource(resourceTypeName[1], namespace, resourceTypeName[0]), - portforward.WithPorts(localPortInt, remotePortInt), - portforward.WithWriters(outWriter, errWriter), - ) - - err = portForwarder.Start(ctx, defaultRetryOptions...) - if err != nil { - return nil, err - } - - return portForwarder, nil -} - -// PortForwardGet call kubectl port-forward and make a GET request. -// Callers are expected to clean up the returned portforward.PortForwarder after the port-forward is no longer needed. -// Deprecated: Prefer portforward.NewPortForwarder -func PortForwardGet(ctx context.Context, namespace string, resource string, localPort string, kubePort string, verbose bool, getPath string) (string, portforward.PortForwarder, error) { - - /** port-forward command **/ - portForwarder, err := PortForward(ctx, namespace, resource, localPort, kubePort, verbose) - if err != nil { - return "", nil, err - } - - localCtx, cancel := context.WithTimeout(ctx, defaultTimeout) - defer cancel() - - // wait for port-forward to be ready - retryInterval := time.Millisecond * 250 - result := make(chan string) - errs := make(chan error) - go func() { - for { - select { - case <-localCtx.Done(): - return - default: - } - res, err := http.Get(fmt.Sprintf("http://%s/%s", portForwarder.Address(), strings.TrimPrefix(getPath, "/"))) - if err != nil { - errs <- err - time.Sleep(retryInterval) - continue - } - if res.StatusCode != http.StatusOK { - errs <- errors.Errorf("invalid status code: %v %v", res.StatusCode, res.Status) - time.Sleep(retryInterval) - continue - } - b, err := io.ReadAll(res.Body) - if err != nil { - errs <- err - time.Sleep(retryInterval) - continue - } - res.Body.Close() - result <- string(b) - return - } - }() - - var multiErr *multierror.Error - for { - select { - case err := <-errs: - multiErr = multierror.Append(multiErr, err) - case res := <-result: - return res, portForwarder, nil - case <-localCtx.Done(): - return "", portForwarder, errors.Errorf("timed out trying to connect to localhost during port-forward, errors: %v", multiErr) - } - } - -} -func GetFreePort() (int, error) { - l, err := net.Listen("tcp", ":0") - if err != nil { - return 0, err - } - defer l.Close() - tcpAddr, ok := l.Addr().(*net.TCPAddr) - if !ok { - return 0, errors.Errorf("Error occurred looking for an open tcp port") - } - return tcpAddr.Port, nil -}