diff --git a/agent/config/builder.go b/agent/config/builder.go index d2fa6a888f..a98ab39585 100644 --- a/agent/config/builder.go +++ b/agent/config/builder.go @@ -232,6 +232,19 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) { if err != nil { return RuntimeConfig{}, fmt.Errorf("Error parsing %s: %s", s.Name, err) } + + // if we have a single 'check' or 'service' we need to add them to the + // list of checks and services first since we cannot merge them + // generically and later values would clobber earlier ones. + if c2.Check != nil { + c2.Checks = append(c2.Checks, *c2.Check) + c2.Check = nil + } + if c2.Service != nil { + c2.Services = append(c2.Services, *c2.Service) + c2.Service = nil + } + c = Merge(c, c2) } diff --git a/agent/config/runtime_test.go b/agent/config/runtime_test.go index 4d81de850b..29c3fb1f1e 100644 --- a/agent/config/runtime_test.go +++ b/agent/config/runtime_test.go @@ -1657,6 +1657,48 @@ func TestConfigFlagsAndEdgecases(t *testing.T) { }, warns: []string{`WARNING: WAN keyring exists but -encrypt given, using keyring`}, }, + { + desc: "multiple check files", + flags: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "check": { "name": "a", "script": "/bin/true" } }`, + `{ "check": { "name": "b", "script": "/bin/false" } }`, + }, + hcl: []string{ + `check = { name = "a" script = "/bin/true" }`, + `check = { name = "b" script = "/bin/false" }`, + }, + patch: func(rt *RuntimeConfig) { + rt.Checks = []*structs.CheckDefinition{ + &structs.CheckDefinition{Name: "a", Script: "/bin/true"}, + &structs.CheckDefinition{Name: "b", Script: "/bin/false"}, + } + rt.DataDir = dataDir + }, + }, + { + desc: "multiple service files", + flags: []string{ + `-data-dir=` + dataDir, + }, + json: []string{ + `{ "service": { "name": "a", "port": 80 } }`, + `{ "service": { "name": "b", "port": 90 } }`, + }, + hcl: []string{ + `service = { name = "a" port = 80 }`, + `service = { name = "b" port = 90 }`, + }, + patch: func(rt *RuntimeConfig) { + rt.Services = []*structs.ServiceDefinition{ + &structs.ServiceDefinition{Name: "a", Port: 80}, + &structs.ServiceDefinition{Name: "b", Port: 90}, + } + rt.DataDir = dataDir + }, + }, } testConfig(t, tests, dataDir) @@ -2831,29 +2873,6 @@ func TestFullConfig(t *testing.T) { CAPath: "mQEN1Mfp", CertFile: "7s4QAzDk", Checks: []*structs.CheckDefinition{ - &structs.CheckDefinition{ - ID: "fZaCAXww", - Name: "OOM2eo0f", - Notes: "zXzXI9Gt", - ServiceID: "L8G0QNmR", - Token: "oo4BCTgJ", - Status: "qLykAl5u", - Script: "dhGfIF8n", - HTTP: "29B93haH", - Header: map[string][]string{ - "hBq0zn1q": {"2a9o9ZKP", "vKwA5lR6"}, - "f3r6xFtM": {"RyuIdDWv", "QbxEcIUM"}, - }, - Method: "Dou0nGT5", - TCP: "JY6fTTcw", - Interval: 18714 * time.Second, - DockerContainerID: "qF66POS9", - Shell: "sOnDy228", - TLSSkipVerify: true, - Timeout: 5954 * time.Second, - TTL: 30044 * time.Second, - DeregisterCriticalServiceAfter: 13209 * time.Second, - }, &structs.CheckDefinition{ ID: "uAjE6m9Z", Name: "QsZRGpYr", @@ -2900,6 +2919,29 @@ func TestFullConfig(t *testing.T) { TTL: 31006 * time.Second, DeregisterCriticalServiceAfter: 2366 * time.Second, }, + &structs.CheckDefinition{ + ID: "fZaCAXww", + Name: "OOM2eo0f", + Notes: "zXzXI9Gt", + ServiceID: "L8G0QNmR", + Token: "oo4BCTgJ", + Status: "qLykAl5u", + Script: "dhGfIF8n", + HTTP: "29B93haH", + Header: map[string][]string{ + "hBq0zn1q": {"2a9o9ZKP", "vKwA5lR6"}, + "f3r6xFtM": {"RyuIdDWv", "QbxEcIUM"}, + }, + Method: "Dou0nGT5", + TCP: "JY6fTTcw", + Interval: 18714 * time.Second, + DockerContainerID: "qF66POS9", + Shell: "sOnDy228", + TLSSkipVerify: true, + Timeout: 5954 * time.Second, + TTL: 30044 * time.Second, + DeregisterCriticalServiceAfter: 13209 * time.Second, + }, }, CheckUpdateInterval: 16507 * time.Second, ClientAddrs: []*net.IPAddr{ipAddr("93.83.18.19")},