Skip to content

Commit

Permalink
feat(agent): add retry configuration for vault agent (#10644)
Browse files Browse the repository at this point in the history
* feat(agent): add retry configuration for vault agent

* feat(agent): add test fixtures for retry

* fix(retry): move retry stanza to top level as template_retry

* fix(retry): add retry config to ServerConfig struct

* fix(retry): point config parser to parse template_retry instead of retry

* remove netlify config (#10711)

* Fix build (#10749)

* Move the declaration to a OSS build tag file to not have it collide w… (#10750)

* Move the declaration to a OSS build tag file to not have it collide with ent declarations

* Add comment

* Remove comment to trigger ci

* Unconditionally use the root namespace when calling sys/seal-status. (#10742)

* feat(agent): add retry configuration for vault agent

* feat(agent): add test fixtures for retry

* fix(retry): move retry stanza to top level as template_retry

* fix(retry): add retry config to ServerConfig struct

* fix(retry): point config parser to parse template_retry instead of retry

Co-authored-by: Hridoy Roy <roy@hashicorp.com>
Co-authored-by: Jeff Escalante <jescalan@users.noreply.github.com>
Co-authored-by: Vishal Nayak <vishalnayak@users.noreply.github.com>
Co-authored-by: Mark Gritter <mgritter@hashicorp.com>
  • Loading branch information
5 people committed Jan 25, 2021
1 parent f61280b commit 8c304ed
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 5 deletions.
1 change: 1 addition & 0 deletions command/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ func (c *AgentCommand) Run(args []string) int {
LogLevel: level,
LogWriter: c.logWriter,
VaultConf: config.Vault,
TemplateRetry: config.TemplateRetry,
Namespace: namespace,
ExitAfterAuth: exitAfterAuth,
})
Expand Down
62 changes: 62 additions & 0 deletions command/agent/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Config struct {
Cache *Cache `hcl:"cache"`
Vault *Vault `hcl:"vault"`
Templates []*ctconfig.TemplateConfig `hcl:"templates"`
TemplateRetry *TemplateRetry `hcl:"template_retry"`
}

// Vault contains configuration for connecting to Vault servers
Expand Down Expand Up @@ -82,6 +83,15 @@ type Sink struct {
Config map[string]interface{}
}

type TemplateRetry struct {
Enabled bool `hcl:"enabled"`
Attempts int `hcl:"attempts"`
BackoffRaw interface{} `hcl:"backoff"`
Backoff time.Duration `hcl:"-"`
MaxBackoffRaw interface{} `hcl:"max_backoff"`
MaxBackoff time.Duration `hcl:"-"`
}

func NewConfig() *Config {
return &Config{
SharedConfig: new(configutil.SharedConfig),
Expand Down Expand Up @@ -169,6 +179,10 @@ func LoadConfig(path string) (*Config, error) {
return nil, errwrap.Wrapf("error parsing 'vault':{{err}}", err)
}

if err := parseRetry(result, list); err != nil {
return nil, errwrap.Wrapf("error parsing 'retry': {{err}}", err)
}

return result, nil
}

Expand Down Expand Up @@ -204,6 +218,54 @@ func parseVault(result *Config, list *ast.ObjectList) error {
return nil
}

func parseRetry(result *Config, list *ast.ObjectList) error {
name := "template_retry"

retryList := list.Filter(name)
if len(retryList.Items) == 0 {
return nil
}

if len(retryList.Items) > 1 {
return fmt.Errorf("one and only one %q block is required", name)
}

item := retryList.Items[0]

var r TemplateRetry
err := hcl.DecodeObject(&r, item.Val)
if err != nil {
return err
}

// Set defaults
if r.Attempts < 1 {
r.Attempts = ctconfig.DefaultRetryAttempts
}
r.Backoff = ctconfig.DefaultRetryBackoff
r.MaxBackoff = ctconfig.DefaultRetryMaxBackoff

if r.BackoffRaw != nil {
var err error
if r.Backoff, err = parseutil.ParseDurationSecond(r.BackoffRaw); err != nil {
return err
}
r.BackoffRaw = nil
}

if r.MaxBackoffRaw != nil {
var err error
if r.MaxBackoff, err = parseutil.ParseDurationSecond(r.MaxBackoffRaw); err != nil {
return err
}
r.MaxBackoffRaw = nil
}

result.TemplateRetry = &r

return nil
}

func parseCache(result *Config, list *ast.ObjectList) error {
name := "cache"

Expand Down
98 changes: 98 additions & 0 deletions command/agent/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -642,3 +642,101 @@ func TestLoadConfigFile_Template_NoSinks(t *testing.T) {
})
}
}

func TestLoadConfigFile_Vault_Retry(t *testing.T) {
config, err := LoadConfig("./test-fixtures/config-vault-retry.hcl")
if err != nil {
t.Fatal(err)
}

expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
Config: map[string]interface{}{
"role": "foobar",
},
},
Sinks: []*Sink{
{
Type: "file",
DHType: "curve25519",
DHPath: "/tmp/file-foo-dhpath",
AAD: "foobar",
Config: map[string]interface{}{
"path": "/tmp/file-foo",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
},
TemplateRetry: &TemplateRetry{
Enabled: true,
Attempts: 5,
BackoffRaw: nil,
Backoff: 100 * time.Millisecond,
MaxBackoffRaw: nil,
MaxBackoff: 400 * time.Millisecond,
},
}

if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}

func TestLoadConfigFile_Vault_Retry_Empty(t *testing.T) {
config, err := LoadConfig("./test-fixtures/config-vault-retry-empty.hcl")
if err != nil {
t.Fatal(err)
}

expected := &Config{
SharedConfig: &configutil.SharedConfig{
PidFile: "./pidfile",
},
AutoAuth: &AutoAuth{
Method: &Method{
Type: "aws",
MountPath: "auth/aws",
Namespace: "my-namespace/",
Config: map[string]interface{}{
"role": "foobar",
},
},
Sinks: []*Sink{
{
Type: "file",
DHType: "curve25519",
DHPath: "/tmp/file-foo-dhpath",
AAD: "foobar",
Config: map[string]interface{}{
"path": "/tmp/file-foo",
},
},
},
},
Vault: &Vault{
Address: "http://127.0.0.1:1111",
},
TemplateRetry: &TemplateRetry{
Enabled: false,
Attempts: ctconfig.DefaultRetryAttempts,
BackoffRaw: nil,
Backoff: ctconfig.DefaultRetryBackoff,
MaxBackoffRaw: nil,
MaxBackoff: ctconfig.DefaultRetryMaxBackoff,
},
}

if diff := deep.Equal(config, expected); diff != nil {
t.Fatal(diff)
}
}
28 changes: 28 additions & 0 deletions command/agent/config/test-fixtures/config-vault-retry-empty.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
pid_file = "./pidfile"

auto_auth {
method {
type = "aws"
namespace = "my-namespace/"

config = {
role = "foobar"
}
}

sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}

vault {
address = "http://127.0.0.1:1111"
}

template_retry {}
33 changes: 33 additions & 0 deletions command/agent/config/test-fixtures/config-vault-retry.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
pid_file = "./pidfile"

auto_auth {
method {
type = "aws"
namespace = "my-namespace/"

config = {
role = "foobar"
}
}

sink {
type = "file"
config = {
path = "/tmp/file-foo"
}
aad = "foobar"
dh_type = "curve25519"
dh_path = "/tmp/file-foo-dhpath"
}
}

vault {
address = "http://127.0.0.1:1111"
}

template_retry {
enabled = true
attempts = 5
backoff = "100ms"
max_backoff = "400ms"
}
17 changes: 12 additions & 5 deletions command/agent/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ type ServerConfig struct {
// Client *api.Client
VaultConf *config.Vault
ExitAfterAuth bool

Namespace string
TemplateRetry *config.TemplateRetry
Namespace string

// LogLevel is needed to set the internal Consul Template Runner's log level
// to match the log level of Vault Agent. The internal Runner creates it's own
Expand Down Expand Up @@ -164,9 +164,16 @@ func (ts *Server) Run(ctx context.Context, incoming chan string, templates []*ct
},
}

// If we're testing, limit retries to 3 attempts to avoid
// long test runs from exponential back-offs
if ts.testingLimitRetry != 0 {
if ts.config.TemplateRetry != nil && ts.config.TemplateRetry.Enabled {
ctv.Vault.Retry = &ctconfig.RetryConfig{
Attempts: &ts.config.TemplateRetry.Attempts,
Backoff: &ts.config.TemplateRetry.Backoff,
MaxBackoff: &ts.config.TemplateRetry.MaxBackoff,
Enabled: &ts.config.TemplateRetry.Enabled,
}
} else if ts.testingLimitRetry != 0 {
// If we're testing, limit retries to 3 attempts to avoid
// long test runs from exponential back-offs
ctv.Vault.Retry = &ctconfig.RetryConfig{Attempts: &ts.testingLimitRetry}
}

Expand Down

0 comments on commit 8c304ed

Please sign in to comment.