From 3b016610e7175fc8b06de7105ab4215c721e3ebe Mon Sep 17 00:00:00 2001 From: Hidetake Iwata Date: Mon, 10 Aug 2020 17:20:12 +0900 Subject: [PATCH] Add --skip-open-browser flag --- README.md | 1 + e2e_test/Makefile | 3 +- e2e_test/main.go | 1 + pkg/authproxy/auth_proxy.go | 63 +++++++++++++++++++++++-------------- pkg/cmd/cmd.go | 3 ++ 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 832f073..78196c7 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ Flags: -n, --namespace string If present, the namespace scope for this CLI request --request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0") -s, --server string The address and port of the Kubernetes API server + --skip-open-browser If set, skip opening the browser --skip_headers If true, avoid header prefixes in the log messages --skip_log_headers If true, avoid headers when opening log files --stderrthreshold severity logs at or above this threshold go to stderr (default 2) diff --git a/e2e_test/Makefile b/e2e_test/Makefile index a28816d..5f24c59 100644 --- a/e2e_test/Makefile +++ b/e2e_test/Makefile @@ -27,8 +27,7 @@ deploy: cluster .PHONY: test test: main.go - #TODO: add an option to skip opening the browser - BROWSER=/bin/true go run main.go + go run main.go .PHONY: delete-cluster delete-cluster: diff --git a/e2e_test/main.go b/e2e_test/main.go index 50acb59..3d44fd5 100644 --- a/e2e_test/main.go +++ b/e2e_test/main.go @@ -41,6 +41,7 @@ func runKauthproxy(chInterrupt <-chan struct{}) error { c := exec.Command("../kauthproxy", "--namespace=kubernetes-dashboard", "--user=tester", + "--skip-open-browser", "https://kubernetes-dashboard.svc", ) c.Stdout = os.Stdout diff --git a/pkg/authproxy/auth_proxy.go b/pkg/authproxy/auth_proxy.go index d9d0d76..fb7edc0 100644 --- a/pkg/authproxy/auth_proxy.go +++ b/pkg/authproxy/auth_proxy.go @@ -49,6 +49,7 @@ type Option struct { Namespace string TargetURL *url.URL BindAddressCandidates []string + SkipOpenBrowser bool } // Do runs the use-case. @@ -75,23 +76,28 @@ func (u *AuthProxy) Do(ctx context.Context, o Option) error { return xerrors.Errorf("could not create a transport for reverse proxy: %w", err) } u.Logger.V(1).Infof("client -> reverse_proxy -> port_forwarder:%d -> pod -> container:%d", transitPort, containerPort) - pfo := portforwarder.Option{ - Config: o.Config, - SourcePort: transitPort, - TargetPodURL: pod.GetSelfLink(), - TargetContainerPort: containerPort, - } - rpo := reverseproxy.Option{ - Transport: rpTransport, - BindAddressCandidates: o.BindAddressCandidates, - TargetScheme: o.TargetURL.Scheme, - TargetHost: "localhost", - TargetPort: transitPort, - } + var once sync.Once + ro := runOption{ + portForwarderOption: portforwarder.Option{ + Config: o.Config, + SourcePort: transitPort, + TargetPodURL: pod.GetSelfLink(), + TargetContainerPort: containerPort, + }, + reverseProxyOption: reverseproxy.Option{ + Transport: rpTransport, + BindAddressCandidates: o.BindAddressCandidates, + TargetScheme: o.TargetURL.Scheme, + TargetHost: "localhost", + TargetPort: transitPort, + }, + skipOpenBrowser: o.SkipOpenBrowser, + onceOpenBrowser: &once, + } b := backoff.NewExponentialBackOff() if err := backoff.Retry(func() error { - if err := u.run(ctx, pfo, rpo, &once); err != nil { + if err := u.run(ctx, ro); err != nil { if xerrors.Is(err, portForwarderConnectionLostError) { u.Logger.Printf("retrying: %s", err) return err @@ -105,6 +111,13 @@ func (u *AuthProxy) Do(ctx context.Context, o Option) error { return nil } +type runOption struct { + portForwarderOption portforwarder.Option + reverseProxyOption reverseproxy.Option + skipOpenBrowser bool + onceOpenBrowser *sync.Once +} + // run runs a port forwarder and reverse proxy, and waits for them, as follows: // // 1. Run a port forwarder. @@ -119,7 +132,7 @@ func (u *AuthProxy) Do(ctx context.Context, o Option) error { // This never returns nil. // It returns an error which wraps context.Canceled if the context is canceled. // It returns portForwarderConnectionLostError if a connection has lost. -func (u *AuthProxy) run(ctx context.Context, pfo portforwarder.Option, rpo reverseproxy.Option, once *sync.Once) error { +func (u *AuthProxy) run(ctx context.Context, o runOption) error { portForwarderIsReady := make(chan struct{}) reverseProxyIsReady := make(chan reverseproxy.Instance, 1) stopPortForwarder := make(chan struct{}) @@ -129,7 +142,7 @@ func (u *AuthProxy) run(ctx context.Context, pfo portforwarder.Option, rpo rever // start a port forwarder eg.Go(func() error { u.Logger.V(1).Infof("starting a port forwarder") - if err := u.PortForwarder.Run(pfo, portForwarderIsReady, stopPortForwarder); err != nil { + if err := u.PortForwarder.Run(o.portForwarderOption, portForwarderIsReady, stopPortForwarder); err != nil { return xerrors.Errorf("could not run a port forwarder: %w", err) } u.Logger.V(1).Infof("stopped the port forwarder") @@ -151,7 +164,7 @@ func (u *AuthProxy) run(ctx context.Context, pfo portforwarder.Option, rpo rever select { case <-portForwarderIsReady: u.Logger.V(1).Infof("starting a reverse proxy") - if err := u.ReverseProxy.Run(rpo, reverseProxyIsReady); err != nil { + if err := u.ReverseProxy.Run(o.reverseProxyOption, reverseProxyIsReady); err != nil { return xerrors.Errorf("could not run a reverse proxy: %w", err) } u.Logger.V(1).Infof("stopped the reverse proxy") @@ -168,12 +181,16 @@ func (u *AuthProxy) run(ctx context.Context, pfo portforwarder.Option, rpo rever case rp := <-reverseProxyIsReady: u.Logger.V(1).Infof("the reverse proxy is ready") rpURL := rp.URL().String() - u.Logger.Printf("Open %s", rpURL) - once.Do(func() { - if err := u.Browser.Open(rpURL); err != nil { - u.Logger.Printf("error while opening the browser: %s", err) - } - }) + if o.skipOpenBrowser { + u.Logger.Printf("Please open %s in the browser", rpURL) + } else { + o.onceOpenBrowser.Do(func() { + u.Logger.V(1).Infof("opening %s in the browser", rpURL) + if err := u.Browser.Open(rpURL); err != nil { + u.Logger.Printf("Please open %s in the browser (could not open the browser: %s)", rpURL, err) + } + }) + } // shutdown the reverse proxy when the context is done eg.Go(func() error { <-ctx.Done() diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index 394b47a..18a276d 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -57,11 +57,13 @@ func (cmd *Cmd) Run(ctx context.Context, osArgs []string, version string) int { type rootCmdOptions struct { k8sOptions *genericclioptions.ConfigFlags addressCandidates []string + skipOpenBrowser bool } func (o *rootCmdOptions) addFlags(f *pflag.FlagSet) { o.k8sOptions.AddFlags(f) f.StringArrayVar(&o.addressCandidates, "address", defaultAddress, "The address on which to run the proxy. If set multiple times, it will try binding the address in order") + f.BoolVar(&o.skipOpenBrowser, "skip-open-browser", false, "If set, skip opening the browser") } func (cmd *Cmd) newRootCmd() *cobra.Command { @@ -108,6 +110,7 @@ func (cmd *Cmd) runRootCmd(ctx context.Context, o rootCmdOptions, args []string) Namespace: namespace, TargetURL: remoteURL, BindAddressCandidates: o.addressCandidates, + SkipOpenBrowser: o.skipOpenBrowser, } if err := cmd.AuthProxy.Do(ctx, authProxyOption); err != nil { return xerrors.Errorf("could not run an authentication proxy: %w", err)