github.com/janma/nomad@v0.11.3/command/agent/config_parse.go (about) 1 package agent 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "path/filepath" 9 "time" 10 11 "github.com/hashicorp/hcl" 12 "github.com/hashicorp/nomad/helper" 13 "github.com/hashicorp/nomad/nomad/structs/config" 14 ) 15 16 func ParseConfigFile(path string) (*Config, error) { 17 // slurp 18 var buf bytes.Buffer 19 path, err := filepath.Abs(path) 20 if err != nil { 21 return nil, err 22 } 23 24 f, err := os.Open(path) 25 if err != nil { 26 return nil, err 27 } 28 defer f.Close() 29 if _, err := io.Copy(&buf, f); err != nil { 30 return nil, err 31 } 32 33 // parse 34 c := &Config{ 35 Client: &ClientConfig{ServerJoin: &ServerJoin{}}, 36 ACL: &ACLConfig{}, 37 Audit: &config.AuditConfig{}, 38 Server: &ServerConfig{ServerJoin: &ServerJoin{}}, 39 Consul: &config.ConsulConfig{}, 40 Autopilot: &config.AutopilotConfig{}, 41 Telemetry: &Telemetry{}, 42 Vault: &config.VaultConfig{}, 43 } 44 45 err = hcl.Decode(c, buf.String()) 46 if err != nil { 47 return nil, err 48 } 49 50 // convert strings to time.Durations 51 tds := []td{ 52 {"gc_interval", &c.Client.GCInterval, &c.Client.GCIntervalHCL}, 53 {"acl.token_ttl", &c.ACL.TokenTTL, &c.ACL.TokenTTLHCL}, 54 {"acl.policy_ttl", &c.ACL.PolicyTTL, &c.ACL.PolicyTTLHCL}, 55 {"client.server_join.retry_interval", &c.Client.ServerJoin.RetryInterval, &c.Client.ServerJoin.RetryIntervalHCL}, 56 {"server.heartbeat_grace", &c.Server.HeartbeatGrace, &c.Server.HeartbeatGraceHCL}, 57 {"server.min_heartbeat_ttl", &c.Server.MinHeartbeatTTL, &c.Server.MinHeartbeatTTLHCL}, 58 {"server.retry_interval", &c.Server.RetryInterval, &c.Server.RetryIntervalHCL}, 59 {"server.server_join.retry_interval", &c.Server.ServerJoin.RetryInterval, &c.Server.ServerJoin.RetryIntervalHCL}, 60 {"consul.timeout", &c.Consul.Timeout, &c.Consul.TimeoutHCL}, 61 {"autopilot.server_stabilization_time", &c.Autopilot.ServerStabilizationTime, &c.Autopilot.ServerStabilizationTimeHCL}, 62 {"autopilot.last_contact_threshold", &c.Autopilot.LastContactThreshold, &c.Autopilot.LastContactThresholdHCL}, 63 {"telemetry.collection_interval", &c.Telemetry.collectionInterval, &c.Telemetry.CollectionInterval}, 64 } 65 66 // Add enterprise audit sinks for time.Duration parsing 67 for i, sink := range c.Audit.Sinks { 68 tds = append(tds, td{ 69 fmt.Sprintf("audit.sink.%d", i), &sink.RotateDuration, &sink.RotateDurationHCL, 70 }) 71 } 72 73 // convert strings to time.Durations 74 err = durations(tds) 75 if err != nil { 76 return nil, err 77 } 78 79 // report unexpected keys 80 err = extraKeys(c) 81 if err != nil { 82 return nil, err 83 } 84 85 return c, nil 86 } 87 88 // td holds args for one duration conversion 89 type td struct { 90 path string 91 td *time.Duration 92 str *string 93 } 94 95 // durations parses the duration strings specified in the config files 96 // into time.Durations 97 func durations(xs []td) error { 98 for _, x := range xs { 99 if x.td != nil && x.str != nil && "" != *x.str { 100 d, err := time.ParseDuration(*x.str) 101 if err != nil { 102 return fmt.Errorf("%s can't parse time duration %s", x.path, *x.str) 103 } 104 105 *x.td = d 106 } 107 } 108 109 return nil 110 } 111 112 func extraKeys(c *Config) error { 113 // hcl leaves behind extra keys when parsing JSON. These keys 114 // are kept on the top level, taken from slices or the keys of 115 // structs contained in slices. Clean up before looking for 116 // extra keys. 117 for range c.HTTPAPIResponseHeaders { 118 helper.RemoveEqualFold(&c.ExtraKeysHCL, "http_api_response_headers") 119 } 120 121 for _, p := range c.Plugins { 122 helper.RemoveEqualFold(&c.ExtraKeysHCL, p.Name) 123 helper.RemoveEqualFold(&c.ExtraKeysHCL, "config") 124 helper.RemoveEqualFold(&c.ExtraKeysHCL, "plugin") 125 } 126 127 for _, k := range []string{"options", "meta", "chroot_env", "servers", "server_join"} { 128 helper.RemoveEqualFold(&c.ExtraKeysHCL, k) 129 helper.RemoveEqualFold(&c.ExtraKeysHCL, "client") 130 } 131 132 // stats is an unused key, continue to silently ignore it 133 helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, "stats") 134 135 // Remove HostVolume extra keys 136 for _, hv := range c.Client.HostVolumes { 137 helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, hv.Name) 138 helper.RemoveEqualFold(&c.Client.ExtraKeysHCL, "host_volume") 139 } 140 141 // Remove AuditConfig extra keys 142 for _, f := range c.Audit.Filters { 143 helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, f.Name) 144 helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, "filter") 145 } 146 147 for _, s := range c.Audit.Sinks { 148 helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, s.Name) 149 helper.RemoveEqualFold(&c.Audit.ExtraKeysHCL, "sink") 150 } 151 152 for _, k := range []string{"enabled_schedulers", "start_join", "retry_join", "server_join"} { 153 helper.RemoveEqualFold(&c.ExtraKeysHCL, k) 154 helper.RemoveEqualFold(&c.ExtraKeysHCL, "server") 155 } 156 157 for _, k := range []string{"datadog_tags"} { 158 helper.RemoveEqualFold(&c.ExtraKeysHCL, k) 159 helper.RemoveEqualFold(&c.ExtraKeysHCL, "telemetry") 160 } 161 162 return helper.UnusedKeys(c) 163 }