Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow resty backend timeout to be configurable #3637

Merged
merged 2 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ and this project adheres to [Semantic
Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased
- Added ability to make the Resty HTTP Timeout configurable.

### Added
- Added `flapping` field to check history, along with `is_flapping_start` and
Expand Down
2 changes: 1 addition & 1 deletion cli/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func New(config config.Config) *RestClient {
client := &RestClient{resty: restyInst, config: config}

// set http client timeout
restyInst.SetTimeout(15 * time.Second)
restyInst.SetTimeout(config.Timeout())

// Standardize redirect policy
restyInst.SetRedirectPolicy(resty.FlexibleRedirectPolicy(10))
Expand Down
12 changes: 12 additions & 0 deletions cli/client/config/basic/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"time"

"github.com/sensu/sensu-go/cli/commands/helpers"
"github.com/sensu/sensu-go/types"
Expand Down Expand Up @@ -34,6 +35,7 @@ type Cluster struct {
TrustedCAFile string `json:"trusted-ca-file"`
InsecureSkipTLSVerify bool `json:"insecure-skip-tls-verify"`
*types.Tokens
Timeout time.Duration `json:"timeout"`
}

// Profile contains the active configuration
Expand Down Expand Up @@ -110,6 +112,16 @@ func (c *Config) flags(flags *pflag.FlagSet) {
if value, err := flags.GetString("trusted-ca-file"); err == nil && value != "" {
c.Cluster.TrustedCAFile = value
}

if value, err := flags.GetString("timeout"); err == nil && value != "" {
duration, err := time.ParseDuration(value)
if err == nil {
c.Cluster.Timeout = duration
} else {
// Default to timeout of 15 seconds
c.Cluster.Timeout = 15 * time.Second
}
}
}

func (c *Config) open(path string) error {
Expand Down
10 changes: 10 additions & 0 deletions cli/client/config/basic/reader.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package basic

import (
"time"

"github.com/sensu/sensu-go/cli/client/config"
"github.com/sensu/sensu-go/types"
)
Expand Down Expand Up @@ -31,6 +33,14 @@ func (c *Config) Namespace() string {
return c.Profile.Namespace
}

// Timeout returns the configured timeout
func (c *Config) Timeout() time.Duration {
if c.Cluster.Timeout == 0*time.Second {
return config.DefaultTimeout
}
return c.Cluster.Timeout
}

// Tokens returns the active cluster JWT
func (c *Config) Tokens() *types.Tokens {
return c.Cluster.Tokens
Expand Down
11 changes: 11 additions & 0 deletions cli/client/config/basic/reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package basic

import (
"testing"
"time"

"github.com/sensu/sensu-go/cli/client/config"
"github.com/sensu/sensu-go/types"
Expand Down Expand Up @@ -33,6 +34,16 @@ func TestNamespaceDefault(t *testing.T) {
assert.Equal(t, config.DefaultNamespace, conf.Namespace())
}

func TestTimeout(t *testing.T) {
conf := &Config{Cluster: Cluster{Timeout: 30 * time.Second}}
assert.Equal(t, conf.Cluster.Timeout, conf.Timeout())
}

func TestTimeoutDefault(t *testing.T) {
conf := &Config{}
assert.Equal(t, config.DefaultTimeout, conf.Timeout())
}

func TestTokens(t *testing.T) {
tokens := &types.Tokens{Access: "foobar"}
conf := &Config{Cluster: Cluster{Tokens: tokens}}
Expand Down
8 changes: 8 additions & 0 deletions cli/client/config/basic/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"time"

"github.com/sensu/sensu-go/types"
)
Expand Down Expand Up @@ -37,6 +38,13 @@ func (c *Config) SaveNamespace(namespace string) error {
return write(c.Profile, filepath.Join(c.path, profileFilename))
}

// SaveTimeout saves the user's timeout to a configuration file
func (c *Config) SaveTimeout(timeout time.Duration) error {
c.Cluster.Timeout = timeout

return write(c.Cluster, filepath.Join(c.path, clusterFilename))
}

// SaveTokens saves the JWT into a configuration file
func (c *Config) SaveTokens(tokens *types.Tokens) error {
// Update the configuration loaded in memory
Expand Down
16 changes: 16 additions & 0 deletions cli/client/config/basic/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"testing"
"time"

"github.com/sensu/sensu-go/types"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -75,6 +76,21 @@ func TestSaveNamespace(t *testing.T) {
assert.Equal(t, namespace, config.Namespace())
}

func TestSaveTimeout(t *testing.T) {
dir, cleanup := tmpDir(t)
defer cleanup()

// Set flags
flags := pflag.NewFlagSet("config-dir", pflag.ContinueOnError)
flags.String("config-dir", dir, "")

config := Load(flags)

timeout := 30 * time.Second
require.NoError(t, config.SaveTimeout(timeout))
assert.Equal(t, timeout, config.Timeout())
}

func TestSaveTokens(t *testing.T) {
dir, cleanup := tmpDir(t)
defer cleanup()
Expand Down
7 changes: 7 additions & 0 deletions cli/client/config/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import (
"time"

"github.com/sensu/sensu-go/types"
)

Expand All @@ -11,6 +13,9 @@ const (
// DefaultFormat is the default format output for printers.
DefaultFormat = FormatTabular

// DefaultTimeout is the default timeout
DefaultTimeout = 15 * time.Second

// FormatTabular indicates tabular format for printers.
FormatTabular = "tabular"

Expand Down Expand Up @@ -38,6 +43,7 @@ type Read interface {
InsecureSkipTLSVerify() bool
Namespace() string
Tokens() *types.Tokens
Timeout() time.Duration
TrustedCAFile() string
}

Expand All @@ -49,4 +55,5 @@ type Write interface {
SaveNamespace(string) error
SaveTokens(*types.Tokens) error
SaveTrustedCAFile(string) error
SaveTimeout(time.Duration) error
}
14 changes: 14 additions & 0 deletions cli/client/config/inmemory/inmemory.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package inmemory

import (
"time"

"github.com/sensu/sensu-go/cli/client/config"
"github.com/sensu/sensu-go/types"
)
Expand All @@ -10,6 +12,7 @@ type Config struct {
url string
format string
namespace string
timeout time.Duration
tokens *types.Tokens
}

Expand Down Expand Up @@ -39,6 +42,11 @@ func (c *Config) Namespace() string {
return c.namespace
}

// Timeout describes the timeout for communicating with the backend
func (c *Config) Timeout() time.Duration {
return c.timeout
}

// Tokens describes the authorization tokens used to make requests
func (c *Config) Tokens() *types.Tokens {
return c.tokens
Expand All @@ -62,6 +70,12 @@ func (c *Config) SaveNamespace(val string) error {
return nil
}

// SaveTimeout updates the current timeout value
func (c *Config) SaveTimeout(val time.Duration) error {
c.timeout = val
return nil
}

// SaveTokens updates the current value
func (c *Config) SaveTokens(val *types.Tokens) error {
c.tokens = val
Expand Down
16 changes: 16 additions & 0 deletions cli/client/config/mock.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import (
"time"

corev2 "github.com/sensu/sensu-go/api/core/v2"

"github.com/stretchr/testify/mock"
Expand Down Expand Up @@ -38,6 +40,14 @@ func (m *MockConfig) Namespace() string {
return args.String(0)
}

// Timeout mocks the timeout config
func (m *MockConfig) Timeout() time.Duration {
args := m.Called()
timeoutString := args.String(0)
d, _ := time.ParseDuration(timeoutString)
return d
naemono marked this conversation as resolved.
Show resolved Hide resolved
}

// TrustedCAFile mocks the trusted CA file config
func (m *MockConfig) TrustedCAFile() string {
args := m.Called()
Expand Down Expand Up @@ -68,6 +78,12 @@ func (m *MockConfig) SaveNamespace(namespace string) error {
return args.Error(0)
}

// SaveTimeout mocks saving the timeout
func (m *MockConfig) SaveTimeout(timeout time.Duration) error {
args := m.Called(timeout)
return args.Error(0)
}

// SaveTokens mocks saving the tokens
func (m *MockConfig) SaveTokens(tokens *corev2.Tokens) error {
args := m.Called(tokens)
Expand Down
16 changes: 16 additions & 0 deletions cli/client/testing/mock_config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package testing

import (
"time"

"github.com/sensu/sensu-go/types"
"github.com/stretchr/testify/mock"
)
Expand Down Expand Up @@ -43,6 +45,14 @@ func (m *MockConfig) TrustedCAFile() string {
return args.String(0)
}

// Timeout mocks the timeout config
func (m *MockConfig) Timeout() time.Duration {
args := m.Called()
timeoutString := args.String(0)
d, _ := time.ParseDuration(timeoutString)
return d
naemono marked this conversation as resolved.
Show resolved Hide resolved
}

// SaveAPIUrl mocks saving the API URL
func (m *MockConfig) SaveAPIUrl(url string) error {
args := m.Called(url)
Expand All @@ -67,6 +77,12 @@ func (m *MockConfig) SaveNamespace(namespace string) error {
return args.Error(0)
}

// SaveTimeout mocks saving the timeout
func (m *MockConfig) SaveTimeout(timeout time.Duration) error {
args := m.Called(timeout)
return args.Error(0)
}

// SaveTokens mocks saving the tokens
func (m *MockConfig) SaveTokens(tokens *types.Tokens) error {
args := m.Called(tokens)
Expand Down
1 change: 1 addition & 0 deletions cli/commands/config/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ func HelpCommand(cli *cli.SensuCli) *cobra.Command {
cmd.AddCommand(
SetFormatCommand(cli),
SetNamespaceCommand(cli),
SetTimeoutCommand(cli),
ViewCommand(cli),
)

Expand Down
52 changes: 52 additions & 0 deletions cli/commands/config/set_timeout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package config

import (
"errors"
"fmt"
"time"

"github.com/sensu/sensu-go/cli"
"github.com/sensu/sensu-go/cli/commands/hooks"
"github.com/spf13/cobra"
)

// SetTimeoutCommand given argument changes timeout for active profile
func SetTimeoutCommand(cli *cli.SensuCli) *cobra.Command {
return &cobra.Command{
Use: "set-timeout [TIMEOUT]",
Short: "Set timeout for active profile in duration format (ex: 15s)",
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
_ = cmd.Help()
return errors.New("invalid argument(s) received")
}

newTimeout := args[0]
newTimeoutDuration, err := time.ParseDuration(newTimeout)
if err != nil {
fmt.Fprintf(
cmd.OutOrStderr(),
"Unable to parse new timeout with error: %s\n",
err,
)
return err
}
if err := cli.Config.SaveTimeout(newTimeoutDuration); err != nil {
fmt.Fprintf(
cmd.OutOrStderr(),
"Unable to write new configuration file with error: %s\n",
err,
)
}

fmt.Fprintln(cmd.OutOrStdout(), "Updated")
return nil
},
Annotations: map[string]string{
// We want to be able to run this command regardless of whether the CLI
// has been configured.
hooks.ConfigurationRequirement: hooks.ConfigurationNotRequired,
},
}
}
Loading