From d84ff4c5b9825ebf657fbecea6236793140e72fe Mon Sep 17 00:00:00 2001 From: hackerman <3372410+aeneasr@users.noreply.github.com> Date: Mon, 15 Apr 2019 15:47:43 +0200 Subject: [PATCH] cmd: Add resilience to CLI REST commands (#1359) Closes #846 Signed-off-by: aeneasr --- cmd/cli/handler_helper.go | 29 ++++++++++++++++++++++++----- cmd/clients.go | 2 ++ cmd/keys.go | 2 ++ cmd/token.go | 3 +++ go.mod | 2 +- go.sum | 5 ++--- 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/cmd/cli/handler_helper.go b/cmd/cli/handler_helper.go index d14ef8b9861..0aff6a0c395 100644 --- a/cmd/cli/handler_helper.go +++ b/cmd/cli/handler_helper.go @@ -23,8 +23,12 @@ package cli import ( "crypto/tls" "encoding/json" + "fmt" "net/http" "os" + "time" + + "github.com/ory/x/httpx" "github.com/olekukonko/tablewriter" "github.com/sawadashota/encrypta" @@ -42,16 +46,31 @@ func configureClient(cmd *cobra.Command) *hydra.OryHydra { } type transport struct { - *http.Transport - cmd *cobra.Command + Transport http.RoundTripper + cmd *cobra.Command } func newTransport(cmd *cobra.Command) *transport { return &transport{ cmd: cmd, - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{InsecureSkipVerify: flagx.MustGetBool(cmd, "skip-tls-verify")}, - }, + Transport: httpx.NewResilientRoundTripper( + &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: flagx.MustGetBool(cmd, "skip-tls-verify")}, + }, + time.Second, + flagx.MustGetDuration(cmd, "fail-after"), + ).WithShouldRetry( + func(res *http.Response, err error) bool { + if err != nil { + fmt.Printf("Unable to connect: %s\n", err) + return true + } else if res.StatusCode == 0 || res.StatusCode >= 500 { + fmt.Printf(`Unable to connect to "%s", unexpected HTTP error status code: %d\n`, res.Request.URL.String(), res.StatusCode) + return true + } + return false + }, + ), } } diff --git a/cmd/clients.go b/cmd/clients.go index f57aee229c3..1c2ef63db6e 100644 --- a/cmd/clients.go +++ b/cmd/clients.go @@ -22,6 +22,7 @@ package cmd import ( "os" + "time" "github.com/spf13/cobra" ) @@ -36,6 +37,7 @@ func init() { RootCmd.AddCommand(clientsCmd) //clientsCmd.PersistentFlags().Bool("dry", false, "do not execute the command but show the corresponding curl command instead") clientsCmd.PersistentFlags().Bool("fake-tls-termination", false, `Fake tls termination by adding "X-Forwarded-Proto: https" to http headers`) + clientsCmd.PersistentFlags().Duration("fail-after", time.Minute, `Stop retrying after the specified duration`) clientsCmd.PersistentFlags().String("access-token", os.Getenv("OAUTH2_ACCESS_TOKEN"), "Set an access token to be used in the Authorization header, defaults to environment variable OAUTH2_ACCESS_TOKEN") clientsCmd.PersistentFlags().String("endpoint", os.Getenv("HYDRA_ADMIN_URL"), "Set the URL where ORY Hydra is hosted, defaults to environment variable HYDRA_ADMIN_URL") diff --git a/cmd/keys.go b/cmd/keys.go index 2d6e312f158..372cd601c0b 100644 --- a/cmd/keys.go +++ b/cmd/keys.go @@ -22,6 +22,7 @@ package cmd import ( "os" + "time" "github.com/spf13/cobra" ) @@ -36,6 +37,7 @@ func init() { RootCmd.AddCommand(keysCmd) //keysCmd.PersistentFlags().Bool("dry", false, "do not execute the command but show the corresponding curl command instead") keysCmd.PersistentFlags().Bool("fake-tls-termination", false, `fake tls termination by adding "X-Forwarded-Proto: https" to http headers`) + keysCmd.PersistentFlags().Duration("fail-after", time.Minute, `Stop retrying after the specified duration`) keysCmd.PersistentFlags().String("access-token", os.Getenv("OAUTH2_ACCESS_TOKEN"), "Set an access token to be used in the Authorization header, defaults to environment variable OAUTH2_ACCESS_TOKEN") keysCmd.PersistentFlags().String("endpoint", os.Getenv("HYDRA_ADMIN_URL"), "Set the URL where ORY Hydra is hosted, defaults to environment variable HYDRA_ADMIN_URL") diff --git a/cmd/token.go b/cmd/token.go index 7cd25ae0c26..8b8c38658d2 100644 --- a/cmd/token.go +++ b/cmd/token.go @@ -21,6 +21,8 @@ package cmd import ( + "time" + "github.com/spf13/cobra" ) @@ -33,5 +35,6 @@ var tokenCmd = &cobra.Command{ func init() { RootCmd.AddCommand(tokenCmd) //tokenCmd.PersistentFlags().Bool("dry", false, "do not execute the command but show the corresponding curl command instead") + tokenCmd.PersistentFlags().Duration("fail-after", time.Minute, `Stop retrying after the specified duration`) tokenCmd.PersistentFlags().Bool("fake-tls-termination", false, `fake tls termination by adding "X-Forwarded-Proto: https" to http headers`) } diff --git a/go.mod b/go.mod index d1b0d58b3c1..6318104e2ea 100644 --- a/go.mod +++ b/go.mod @@ -48,7 +48,7 @@ require ( github.com/ory/go-convenience v0.1.0 github.com/ory/graceful v0.1.1 github.com/ory/herodot v0.6.0 - github.com/ory/x v0.0.43 + github.com/ory/x v0.0.47 github.com/pborman/uuid v1.2.0 github.com/phayes/freeport v0.0.0-20171002181615-b8543db493a5 github.com/pkg/errors v0.8.1 diff --git a/go.sum b/go.sum index f42205275f0..1c3c57622fc 100644 --- a/go.sum +++ b/go.sum @@ -511,9 +511,8 @@ github.com/ory/graceful v0.1.1/go.mod h1:zqu70l95WrKHF4AZ6tXHvAqAvpY6M7g6ttaAVcM github.com/ory/herodot v0.5.1/go.mod h1:3BOneqcyBsVybCPAJoi92KN2BpJHcmDqAMcAAaJiJow= github.com/ory/herodot v0.6.0 h1:Dcs4yH1Qw1GIgGCvvvdafhT8xjwElTE//8xLmHtPEYA= github.com/ory/herodot v0.6.0/go.mod h1:3BOneqcyBsVybCPAJoi92KN2BpJHcmDqAMcAAaJiJow= -github.com/ory/sqlcon v0.0.7/go.mod h1:oOyCmOJWAs8F0bnGmmIvGA9/4K1JqVL0D9JgvAaVc3U= -github.com/ory/x v0.0.43 h1:gpZm3A6fjI2z/8xkSGktZiumQrlys/C8rmodVryM1yM= -github.com/ory/x v0.0.43/go.mod h1:wY34Yfy/lRklrrVbChZHqOQxhbSHH2a6bSJ6o3YFKY8= +github.com/ory/x v0.0.47 h1:cF0u521fXN3nZ1h7z5r6LfZVEaL6WBHrbiY4jR1HFog= +github.com/ory/x v0.0.47/go.mod h1:LVQf17Z8SK/y0H0ewDuIqJLDCjQ2eOIfQT5l0LH53ls= github.com/parnurzeal/gorequest v0.2.15/go.mod h1:3Kh2QUMJoqw3icWAecsyzkpY7UzRfDhbRdTjtNwNiUE= github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=