2016-03-12 02:24:58 +00:00
|
|
|
package agent
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2016-06-16 20:30:29 +00:00
|
|
|
"time"
|
2016-03-12 02:24:58 +00:00
|
|
|
|
|
|
|
"github.com/hashicorp/hcl"
|
2020-03-06 15:09:10 +00:00
|
|
|
"github.com/hashicorp/nomad/helper"
|
2016-05-22 03:15:58 +00:00
|
|
|
"github.com/hashicorp/nomad/nomad/structs/config"
|
2016-03-12 02:24:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func ParseConfigFile(path string) (*Config, error) {
|
2019-04-04 19:06:05 +00:00
|
|
|
// slurp
|
|
|
|
var buf bytes.Buffer
|
|
|
|
path, err := filepath.Abs(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
if _, err := io.Copy(&buf, f); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// parse
|
|
|
|
c := &Config{
|
|
|
|
Client: &ClientConfig{ServerJoin: &ServerJoin{}},
|
|
|
|
ACL: &ACLConfig{},
|
2020-03-22 16:17:33 +00:00
|
|
|
Audit: &config.AuditConfig{},
|
2019-04-04 19:06:05 +00:00
|
|
|
Server: &ServerConfig{ServerJoin: &ServerJoin{}},
|
2019-06-11 19:14:24 +00:00
|
|
|
Consul: &config.ConsulConfig{},
|
|
|
|
Autopilot: &config.AutopilotConfig{},
|
2019-04-04 19:06:05 +00:00
|
|
|
Telemetry: &Telemetry{},
|
2019-06-11 19:14:24 +00:00
|
|
|
Vault: &config.VaultConfig{},
|
2019-04-04 19:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
err = hcl.Decode(c, buf.String())
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert strings to time.Durations
|
2020-03-22 16:17:33 +00:00
|
|
|
tds := []td{
|
2019-04-04 19:06:05 +00:00
|
|
|
{"gc_interval", &c.Client.GCInterval, &c.Client.GCIntervalHCL},
|
|
|
|
{"acl.token_ttl", &c.ACL.TokenTTL, &c.ACL.TokenTTLHCL},
|
|
|
|
{"acl.policy_ttl", &c.ACL.PolicyTTL, &c.ACL.PolicyTTLHCL},
|
|
|
|
{"client.server_join.retry_interval", &c.Client.ServerJoin.RetryInterval, &c.Client.ServerJoin.RetryIntervalHCL},
|
|
|
|
{"server.heartbeat_grace", &c.Server.HeartbeatGrace, &c.Server.HeartbeatGraceHCL},
|
|
|
|
{"server.min_heartbeat_ttl", &c.Server.MinHeartbeatTTL, &c.Server.MinHeartbeatTTLHCL},
|
|
|
|
{"server.retry_interval", &c.Server.RetryInterval, &c.Server.RetryIntervalHCL},
|
|
|
|
{"server.server_join.retry_interval", &c.Server.ServerJoin.RetryInterval, &c.Server.ServerJoin.RetryIntervalHCL},
|
|
|
|
{"consul.timeout", &c.Consul.Timeout, &c.Consul.TimeoutHCL},
|
|
|
|
{"autopilot.server_stabilization_time", &c.Autopilot.ServerStabilizationTime, &c.Autopilot.ServerStabilizationTimeHCL},
|
|
|
|
{"autopilot.last_contact_threshold", &c.Autopilot.LastContactThreshold, &c.Autopilot.LastContactThresholdHCL},
|
|
|
|
{"telemetry.collection_interval", &c.Telemetry.collectionInterval, &c.Telemetry.CollectionInterval},
|
2020-03-22 16:17:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add enterprise audit sinks for time.Duration parsing
|
|
|
|
for i, sink := range c.Audit.Sinks {
|
|
|
|
tds = append(tds, td{
|
|
|
|
fmt.Sprintf("audit.sink.%d", i), &sink.RotateDuration, &sink.RotateDurationHCL,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// convert strings to time.Durations
|
|
|
|
err = durations(tds)
|
2019-04-04 19:06:05 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// report unexpected keys
|
|
|
|
err = extraKeys(c)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return c, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// td holds args for one duration conversion
|
|
|
|
type td struct {
|
|
|
|
path string
|
|
|
|
td *time.Duration
|
|
|
|
str *string
|
|
|
|
}
|
|
|
|
|
|
|
|
// durations parses the duration strings specified in the config files
|
|
|
|
// into time.Durations
|
|
|
|
func durations(xs []td) error {
|
|
|
|
for _, x := range xs {
|
|
|
|
if x.td != nil && x.str != nil && "" != *x.str {
|
|
|
|
d, err := time.ParseDuration(*x.str)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("%s can't parse time duration %s", x.path, *x.str)
|
|
|
|
}
|
|
|
|
|
|
|
|
*x.td = d
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func extraKeys(c *Config) error {
|
|
|
|
// hcl leaves behind extra keys when parsing JSON. These keys
|
|
|
|
// are kept on the top level, taken from slices or the keys of
|
|
|
|
// structs contained in slices. Clean up before looking for
|
|
|
|
// extra keys.
|
|
|
|
for range c.HTTPAPIResponseHeaders {
|
2020-03-06 15:09:10 +00:00
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, "http_api_response_headers")
|
2019-04-04 19:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, p := range c.Plugins {
|
2020-03-06 15:09:10 +00:00
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, p.Name)
|
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, "config")
|
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, "plugin")
|
2019-04-04 19:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, k := range []string{"options", "meta", "chroot_env", "servers", "server_join"} {
|
2020-03-06 15:09:10 +00:00
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, k)
|
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, "client")
|
2019-04-04 19:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// stats is an unused key, continue to silently ignore it
|
2020-03-06 15:09:10 +00:00
|
|
|
helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, "stats")
|
2019-04-04 19:06:05 +00:00
|
|
|
|
2019-07-25 14:45:41 +00:00
|
|
|
// Remove HostVolume extra keys
|
|
|
|
for _, hv := range c.Client.HostVolumes {
|
2020-03-06 15:09:10 +00:00
|
|
|
helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, hv.Name)
|
|
|
|
helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, "host_volume")
|
2019-07-25 14:45:41 +00:00
|
|
|
}
|
|
|
|
|
2020-06-16 15:53:10 +00:00
|
|
|
// Remove HostNetwork extra keys
|
|
|
|
for _, hn := range c.Client.HostNetworks {
|
|
|
|
helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, hn.Name)
|
|
|
|
helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, "host_network")
|
|
|
|
}
|
|
|
|
|
2020-03-22 16:17:33 +00:00
|
|
|
// Remove AuditConfig extra keys
|
|
|
|
for _, f := range c.Audit.Filters {
|
2020-03-23 18:30:53 +00:00
|
|
|
helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, f.Name)
|
|
|
|
helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, "filter")
|
2020-03-22 16:17:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, s := range c.Audit.Sinks {
|
2020-03-23 18:30:53 +00:00
|
|
|
helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, s.Name)
|
|
|
|
helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, "sink")
|
2020-03-22 16:17:33 +00:00
|
|
|
}
|
|
|
|
|
2019-04-04 19:06:05 +00:00
|
|
|
for _, k := range []string{"enabled_schedulers", "start_join", "retry_join", "server_join"} {
|
2020-03-06 15:09:10 +00:00
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, k)
|
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, "server")
|
2019-04-04 19:06:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, k := range []string{"datadog_tags"} {
|
2020-03-06 15:09:10 +00:00
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, k)
|
|
|
|
helper.RemoveEqualFold(&c.ExtraKeysHCL, "telemetry")
|
2019-04-04 19:06:05 +00:00
|
|
|
}
|
|
|
|
|
2020-03-06 15:09:10 +00:00
|
|
|
return helper.UnusedKeys(c)
|
2019-04-04 19:06:05 +00:00
|
|
|
}
|