Add multiple service definition support

This change-set adds another key to the configuration decoding called
`services`, which is expected to be a list of service definitions. It
follows the established convention of only allowing one of the keys:
`service`, `check`, `services`. For every entry in the list it calls
the corresponding decode method and appends it to the Servics of the
resulting Config.

While a similar result could be achieved with changing the Services
member of the Config struct to have named mapstruct tag it lacks the
proper time conversions provided by DecodeServiceDefinition.
This commit is contained in:
Alexander Simmerl 2014-10-23 22:22:25 -04:00
parent df43c42c94
commit ad4598959e
3 changed files with 131 additions and 2 deletions

View File

@ -392,9 +392,20 @@ func DecodeConfig(r io.Reader) (*Config, error) {
// Check the result type
if obj, ok := raw.(map[string]interface{}); ok {
// Check for a "service" or "check" key, meaning
// Check for a "services", "service" or "check" key, meaning
// this is actually a definition entry
if sub, ok := obj["service"]; ok {
if sub, ok := obj["services"]; ok {
if list, ok := sub.([]interface{}); ok {
for _, srv := range list {
service, err := DecodeServiceDefinition(srv)
if err != nil {
return nil, err
}
result.Services = append(result.Services, service)
}
return &result, nil
}
} else if sub, ok := obj["service"]; ok {
service, err := DecodeServiceDefinition(sub)
result.Services = append(result.Services, service)
return &result, err

View File

@ -516,6 +516,86 @@ func TestDecodeConfig(t *testing.T) {
}
}
func TestDecodeConfig_Services(t *testing.T) {
input := `{
"services": [
{
"id": "red0",
"name": "redis",
"tags": [
"master"
],
"port": 6000,
"check": {
"script": "/bin/check_redis -p 6000",
"interval": "5s",
"ttl": "20s"
}
},
{
"id": "red1",
"name": "redis",
"tags": [
"delayed",
"slave"
],
"port": 7000,
"check": {
"script": "/bin/check_redis -p 7000",
"interval": "30s",
"ttl": "60s"
}
}
]
}`
config, err := DecodeConfig(bytes.NewReader([]byte(input)))
if err != nil {
t.Fatalf("err: %s", err)
}
if len(config.Services) != 2 {
t.Fatalf("missing services")
}
expected := &ServiceDefinition{
Check: CheckType{
Interval: 5 * time.Second,
Script: "/bin/check_redis -p 6000",
TTL: 20 * time.Second,
},
ID: "red0",
Name: "redis",
Tags: []string{
"master",
},
Port: 6000,
}
if !reflect.DeepEqual(config.Services[0], expected) {
t.Fatalf("services do not match:\n%+v\n%+v", config.Services[0], expected)
}
expected = &ServiceDefinition{
Check: CheckType{
Interval: 30 * time.Second,
Script: "/bin/check_redis -p 7000",
TTL: 60 * time.Second,
},
ID: "red1",
Name: "redis",
Tags: []string{
"delayed",
"slave",
},
Port: 7000,
}
if !reflect.DeepEqual(config.Services[1], expected) {
t.Fatalf("services do not match:\n%+v\n%+v", config.Services[1], expected)
}
}
func TestDecodeConfig_Service(t *testing.T) {
// Basics
input := `{"service": {"id": "red1", "name": "redis", "tags": ["master"], "port":8000, "check": {"script": "/bin/check_redis", "interval": "10s", "ttl": "15s" }}}`

View File

@ -62,3 +62,41 @@ end in the ".json" extension to be loaded by Consul. Check definitions can
also be updated by sending a `SIGHUP` to the agent. Alternatively, the
service can be registered dynamically using the [HTTP API](/docs/agent/http.html).
## Multiple Service Definitions
Multiple services definitions can be provided at once. Single and mutiple service definitions can't be provided together in one configuration file.
```javascript
{
"services": [
{
"id": "red0",
"name": "redis",
"tags": [
"master"
],
"port": 6000,
"check": {
"script": "/bin/check_redis -p 6000",
"interval": "5s",
"ttl": "20s"
}
},
{
"id": "red1",
"name": "redis",
"tags": [
"delayed",
"slave"
],
"port": 7000,
"check": {
"script": "/bin/check_redis -p 7000",
"interval": "30s",
"ttl": "60s"
}
},
...
]
}
```