From 4a74fda8ce0ea7f9e30557b2e5fe89099f377704 Mon Sep 17 00:00:00 2001 From: Juliano Martinez Date: Tue, 1 Oct 2024 21:44:36 +0200 Subject: [PATCH] Allow client template config block to be parsed when using json config (#24007) - Adds tests - Adds sample test data for parsing hcl and json - Adds changelog --- .changelog/24007.txt | 3 ++ client/config/config.go | 12 ++++---- command/agent/config_parse.go | 8 +++++- command/agent/config_parse_test.go | 41 ++++++++++++++++++++++++++++ command/agent/testdata/template.hcl | 37 +++++++++++++++++++++++++ command/agent/testdata/template.json | 33 ++++++++++++++++++++++ 6 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 .changelog/24007.txt create mode 100644 command/agent/testdata/template.hcl create mode 100644 command/agent/testdata/template.json diff --git a/.changelog/24007.txt b/.changelog/24007.txt new file mode 100644 index 00000000000..edf07b18819 --- /dev/null +++ b/.changelog/24007.txt @@ -0,0 +1,3 @@ +```release-note:bug +bug: Allow client template config block to be parsed when using json config +``` diff --git a/client/config/config.go b/client/config/config.go index a0290709ecb..86e28c2cbbc 100644 --- a/client/config/config.go +++ b/client/config/config.go @@ -401,14 +401,14 @@ type ClientTemplateConfig struct { // time to wait for the Consul cluster to reach a consistent state before rendering a // template. This is useful to enable in systems where Consul is experiencing // a lot of flapping because it will reduce the number of times a template is rendered. - Wait *WaitConfig `hcl:"wait,optional" json:"-"` + Wait *WaitConfig `hcl:"wait,optional"` // WaitBounds allows operators to define boundaries on individual template wait // configuration overrides. If set, this ensures that if a job author specifies // a wait configuration with values the cluster operator does not allow, the // cluster operator's boundary will be applied rather than the job author's // out of bounds configuration. - WaitBounds *WaitConfig `hcl:"wait_bounds,optional" json:"-"` + WaitBounds *WaitConfig `hcl:"wait_bounds,optional"` // This controls the retry behavior when an error is returned from Consul. // Consul Template is highly fault tolerant, meaning it does not exit in the @@ -566,9 +566,9 @@ func (c *ClientTemplateConfig) Merge(o *ClientTemplateConfig) *ClientTemplateCon // to maintain parity with the external subsystem, not to establish a new standard. type WaitConfig struct { Min *time.Duration `hcl:"-"` - MinHCL string `hcl:"min,optional" json:"-"` + MinHCL string `hcl:"min,optional"` Max *time.Duration `hcl:"-"` - MaxHCL string `hcl:"max,optional" json:"-"` + MaxHCL string `hcl:"max,optional"` } // Copy returns a deep copy of the receiver. @@ -696,11 +696,11 @@ type RetryConfig struct { // Backoff is the base of the exponential backoff. This number will be // multiplied by the next power of 2 on each iteration. Backoff *time.Duration `hcl:"-"` - BackoffHCL string `hcl:"backoff,optional" json:"-"` + BackoffHCL string `hcl:"backoff,optional"` // MaxBackoff is an upper limit to the sleep time between retries // A MaxBackoff of 0 means there is no limit to the exponential growth of the backoff. MaxBackoff *time.Duration `hcl:"-"` - MaxBackoffHCL string `hcl:"max_backoff,optional" json:"-"` + MaxBackoffHCL string `hcl:"max_backoff,optional"` } func (rc *RetryConfig) Copy() *RetryConfig { diff --git a/command/agent/config_parse.go b/command/agent/config_parse.go index 06dcec37adc..d5bb7b54932 100644 --- a/command/agent/config_parse.go +++ b/command/agent/config_parse.go @@ -295,7 +295,7 @@ func extraKeys(c *Config) error { helper.RemoveEqualFold(&c.ExtraKeysHCL, "plugin") } - for _, k := range []string{"options", "meta", "chroot_env", "servers", "server_join"} { + for _, k := range []string{"options", "meta", "chroot_env", "servers", "server_join", "template"} { helper.RemoveEqualFold(&c.ExtraKeysHCL, k) helper.RemoveEqualFold(&c.ExtraKeysHCL, "client") } @@ -315,6 +315,12 @@ func extraKeys(c *Config) error { helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, "host_network") } + // Remove Template extra keys + for _, t := range []string{"function_denylist", "disable_file_sandbox", "max_stale", "wait", "wait_bounds", "block_query_wait", "consul_retry", "vault_retry", "nomad_retry"} { + helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, t) + helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, "template") + } + // Remove AuditConfig extra keys for _, f := range c.Audit.Filters { helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, f.Name) diff --git a/command/agent/config_parse_test.go b/command/agent/config_parse_test.go index 2cf544e2522..34904ffa89c 100644 --- a/command/agent/config_parse_test.go +++ b/command/agent/config_parse_test.go @@ -1146,3 +1146,44 @@ func TestConfig_Telemetry(t *testing.T) { must.Eq(t, mergedTelemetry2.inMemoryCollectionInterval, 1*time.Second) must.Eq(t, mergedTelemetry2.inMemoryRetentionPeriod, 10*time.Second) } + +func TestConfig_Template(t *testing.T) { + ci.Parallel(t) + + for _, suffix := range []string{"hcl", "json"} { + t.Run(suffix, func(t *testing.T) { + cfg := DefaultConfig() + fc, err := LoadConfig("testdata/template." + suffix) + must.NoError(t, err) + cfg = cfg.Merge(fc) + + must.Eq(t, []string{"plugin"}, cfg.Client.TemplateConfig.FunctionDenylist) + must.True(t, cfg.Client.TemplateConfig.DisableSandbox) + must.Eq(t, pointer.Of(7600*time.Hour), cfg.Client.TemplateConfig.MaxStale) + must.Eq(t, pointer.Of(10*time.Minute), cfg.Client.TemplateConfig.BlockQueryWaitTime) + + must.NotNil(t, cfg.Client.TemplateConfig.Wait) + must.Eq(t, pointer.Of(10*time.Second), cfg.Client.TemplateConfig.Wait.Min) + must.Eq(t, pointer.Of(10*time.Minute), cfg.Client.TemplateConfig.Wait.Max) + + must.NotNil(t, cfg.Client.TemplateConfig.WaitBounds) + must.Eq(t, pointer.Of(1*time.Second), cfg.Client.TemplateConfig.WaitBounds.Min) + must.Eq(t, pointer.Of(10*time.Hour), cfg.Client.TemplateConfig.WaitBounds.Max) + + must.NotNil(t, cfg.Client.TemplateConfig.ConsulRetry) + must.Eq(t, 6, *cfg.Client.TemplateConfig.ConsulRetry.Attempts) + must.Eq(t, pointer.Of(550*time.Millisecond), cfg.Client.TemplateConfig.ConsulRetry.Backoff) + must.Eq(t, pointer.Of(10*time.Minute), cfg.Client.TemplateConfig.ConsulRetry.MaxBackoff) + + must.NotNil(t, cfg.Client.TemplateConfig.VaultRetry) + must.Eq(t, 6, *cfg.Client.TemplateConfig.VaultRetry.Attempts) + must.Eq(t, pointer.Of(550*time.Millisecond), cfg.Client.TemplateConfig.VaultRetry.Backoff) + must.Eq(t, pointer.Of(10*time.Minute), cfg.Client.TemplateConfig.VaultRetry.MaxBackoff) + + must.NotNil(t, cfg.Client.TemplateConfig.NomadRetry) + must.Eq(t, 6, *cfg.Client.TemplateConfig.NomadRetry.Attempts) + must.Eq(t, pointer.Of(550*time.Millisecond), cfg.Client.TemplateConfig.NomadRetry.Backoff) + must.Eq(t, pointer.Of(10*time.Minute), cfg.Client.TemplateConfig.NomadRetry.MaxBackoff) + }) + } +} diff --git a/command/agent/testdata/template.hcl b/command/agent/testdata/template.hcl new file mode 100644 index 00000000000..f6849300060 --- /dev/null +++ b/command/agent/testdata/template.hcl @@ -0,0 +1,37 @@ +client { + template { + function_denylist = ["plugin"] + disable_file_sandbox = true + max_stale = "7600h" + + wait { + min = "10s" + max = "10m" + } + + wait_bounds { + min = "1s" + max = "10h" + } + + block_query_wait = "10m" + + consul_retry { + attempts = 6 + backoff = "550ms" + max_backoff = "10m" + } + + vault_retry { + attempts = 6 + backoff = "550ms" + max_backoff = "10m" + } + + nomad_retry { + attempts = 6 + backoff = "550ms" + max_backoff = "10m" + } + } +} diff --git a/command/agent/testdata/template.json b/command/agent/testdata/template.json new file mode 100644 index 00000000000..6c523827904 --- /dev/null +++ b/command/agent/testdata/template.json @@ -0,0 +1,33 @@ +{ + "client": { + "template": { + "function_denylist": ["plugin"], + "disable_file_sandbox": true, + "max_stale": "7600h", + "wait": { + "min": "10s", + "max": "10m" + }, + "wait_bounds": { + "min": "1s", + "max": "10h" + }, + "block_query_wait": "10m", + "consul_retry": { + "attempts": 6, + "backoff": "550ms", + "max_backoff": "10m" + }, + "vault_retry": { + "attempts": 6, + "backoff": "550ms", + "max_backoff": "10m" + }, + "nomad_retry": { + "attempts": 6, + "backoff": "550ms", + "max_backoff": "10m" + } + } + } +}