Update client api and docs for node metadata
This commit is contained in:
parent
561d6c71e0
commit
15f008b3e3
10
api/api.go
10
api/api.go
|
@ -74,6 +74,11 @@ type QueryOptions struct {
|
||||||
// that node. Setting this to "_agent" will use the agent's node
|
// that node. Setting this to "_agent" will use the agent's node
|
||||||
// for the sort.
|
// for the sort.
|
||||||
Near string
|
Near string
|
||||||
|
|
||||||
|
// NodeMeta is used to filter results by nodes with the given
|
||||||
|
// metadata key/value pairs. Currently, only one key/value pair can
|
||||||
|
// be provided for filtering.
|
||||||
|
NodeMeta map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteOptions are used to parameterize a write
|
// WriteOptions are used to parameterize a write
|
||||||
|
@ -386,6 +391,11 @@ func (r *request) setQueryOptions(q *QueryOptions) {
|
||||||
if q.Near != "" {
|
if q.Near != "" {
|
||||||
r.params.Set("near", q.Near)
|
r.params.Set("near", q.Near)
|
||||||
}
|
}
|
||||||
|
if len(q.NodeMeta) > 0 {
|
||||||
|
for key, value := range q.NodeMeta {
|
||||||
|
r.params.Add("node-meta", key+":"+value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// durToMsec converts a duration to a millisecond specified string. If the
|
// durToMsec converts a duration to a millisecond specified string. If the
|
||||||
|
|
|
@ -4,12 +4,14 @@ type Node struct {
|
||||||
Node string
|
Node string
|
||||||
Address string
|
Address string
|
||||||
TaggedAddresses map[string]string
|
TaggedAddresses map[string]string
|
||||||
|
Meta map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
type CatalogService struct {
|
type CatalogService struct {
|
||||||
Node string
|
Node string
|
||||||
Address string
|
Address string
|
||||||
TaggedAddresses map[string]string
|
TaggedAddresses map[string]string
|
||||||
|
NodeMeta map[string]string
|
||||||
ServiceID string
|
ServiceID string
|
||||||
ServiceName string
|
ServiceName string
|
||||||
ServiceAddress string
|
ServiceAddress string
|
||||||
|
@ -29,6 +31,7 @@ type CatalogRegistration struct {
|
||||||
Node string
|
Node string
|
||||||
Address string
|
Address string
|
||||||
TaggedAddresses map[string]string
|
TaggedAddresses map[string]string
|
||||||
|
NodeMeta map[string]string
|
||||||
Datacenter string
|
Datacenter string
|
||||||
Service *AgentService
|
Service *AgentService
|
||||||
Check *AgentCheck
|
Check *AgentCheck
|
||||||
|
|
|
@ -60,6 +60,64 @@ func TestCatalog_Nodes(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCatalog_Nodes_MetaFilter(t *testing.T) {
|
||||||
|
meta := map[string]string{"somekey": "somevalue"}
|
||||||
|
c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
|
||||||
|
conf.NodeMeta = meta
|
||||||
|
})
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
catalog := c.Catalog()
|
||||||
|
|
||||||
|
// Make sure we get the node back when filtering by its metadata
|
||||||
|
testutil.WaitForResult(func() (bool, error) {
|
||||||
|
nodes, meta, err := catalog.Nodes(&QueryOptions{NodeMeta: meta})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(nodes) == 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := nodes[0].TaggedAddresses["wan"]; !ok {
|
||||||
|
return false, fmt.Errorf("Bad: %v", nodes[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := nodes[0].Meta["somekey"]; !ok || v != "somevalue" {
|
||||||
|
return false, fmt.Errorf("Bad: %v", nodes[0].Meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}, func(err error) {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Get nothing back when we use an invalid filter
|
||||||
|
testutil.WaitForResult(func() (bool, error) {
|
||||||
|
nodes, meta, err := catalog.Nodes(&QueryOptions{NodeMeta: map[string]string{"nope":"nope"}})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(nodes) != 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", nodes)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}, func(err error) {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestCatalog_Services(t *testing.T) {
|
func TestCatalog_Services(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
c, s := makeClient(t)
|
c, s := makeClient(t)
|
||||||
|
@ -87,6 +145,56 @@ func TestCatalog_Services(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCatalog_Services_NodeMetaFilter(t *testing.T) {
|
||||||
|
meta := map[string]string{"somekey": "somevalue"}
|
||||||
|
c, s := makeClientWithConfig(t, nil, func(conf *testutil.TestServerConfig) {
|
||||||
|
conf.NodeMeta = meta
|
||||||
|
})
|
||||||
|
defer s.Stop()
|
||||||
|
|
||||||
|
catalog := c.Catalog()
|
||||||
|
|
||||||
|
// Make sure we get the service back when filtering by the node's metadata
|
||||||
|
testutil.WaitForResult(func() (bool, error) {
|
||||||
|
services, meta, err := catalog.Services(&QueryOptions{NodeMeta: meta})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(services) == 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", services)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}, func(err error) {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Get nothing back when using an invalid filter
|
||||||
|
testutil.WaitForResult(func() (bool, error) {
|
||||||
|
services, meta, err := catalog.Services(&QueryOptions{NodeMeta: map[string]string{"nope":"nope"}})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if meta.LastIndex == 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(services) != 0 {
|
||||||
|
return false, fmt.Errorf("Bad: %v", services)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}, func(err error) {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestCatalog_Service(t *testing.T) {
|
func TestCatalog_Service(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
c, s := makeClient(t)
|
c, s := makeClient(t)
|
||||||
|
@ -173,6 +281,7 @@ func TestCatalog_Registration(t *testing.T) {
|
||||||
Datacenter: "dc1",
|
Datacenter: "dc1",
|
||||||
Node: "foobar",
|
Node: "foobar",
|
||||||
Address: "192.168.10.10",
|
Address: "192.168.10.10",
|
||||||
|
NodeMeta: map[string]string{"somekey": "somevalue"},
|
||||||
Service: service,
|
Service: service,
|
||||||
Check: check,
|
Check: check,
|
||||||
}
|
}
|
||||||
|
@ -200,6 +309,10 @@ func TestCatalog_Registration(t *testing.T) {
|
||||||
return false, fmt.Errorf("missing checkid service:redis1")
|
return false, fmt.Errorf("missing checkid service:redis1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if v, ok := node.Node.Meta["somekey"]; !ok || v != "somevalue" {
|
||||||
|
return false, fmt.Errorf("missing node meta pair somekey:somevalue")
|
||||||
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}, func(err error) {
|
}, func(err error) {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
|
|
|
@ -53,6 +53,7 @@ type TestAddressConfig struct {
|
||||||
// TestServerConfig is the main server configuration struct.
|
// TestServerConfig is the main server configuration struct.
|
||||||
type TestServerConfig struct {
|
type TestServerConfig struct {
|
||||||
NodeName string `json:"node_name"`
|
NodeName string `json:"node_name"`
|
||||||
|
NodeMeta map[string]string `json:"node_meta"`
|
||||||
Performance *TestPerformanceConfig `json:"performance,omitempty"`
|
Performance *TestPerformanceConfig `json:"performance,omitempty"`
|
||||||
Bootstrap bool `json:"bootstrap,omitempty"`
|
Bootstrap bool `json:"bootstrap,omitempty"`
|
||||||
Server bool `json:"server,omitempty"`
|
Server bool `json:"server,omitempty"`
|
||||||
|
|
|
@ -128,6 +128,8 @@ This endpoint is used to return the configuration and member information of the
|
||||||
|
|
||||||
Consul 0.7.0 and later also includes a snapshot of various operating statistics under the `Stats` key. These statistics are intended to help human operators for debugging and may change over time, so this part of the interface should not be consumed programmatically.
|
Consul 0.7.0 and later also includes a snapshot of various operating statistics under the `Stats` key. These statistics are intended to help human operators for debugging and may change over time, so this part of the interface should not be consumed programmatically.
|
||||||
|
|
||||||
|
Consul 0.7.3 and later also includes a block of user-defined node metadata values under the `Meta` key. These are arbitrary key/value pairs defined in the [node meta](/docs/agent/options.html#_node_meta) section of the agent configuration.
|
||||||
|
|
||||||
It returns a JSON body like this:
|
It returns a JSON body like this:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
@ -194,6 +196,10 @@ It returns a JSON body like this:
|
||||||
"DelegateMin": 2,
|
"DelegateMin": 2,
|
||||||
"DelegateMax": 4,
|
"DelegateMax": 4,
|
||||||
"DelegateCur": 4
|
"DelegateCur": 4
|
||||||
|
},
|
||||||
|
"Meta": {
|
||||||
|
"instance_type": "i2.xlarge",
|
||||||
|
"os_version": "ubuntu_16.04",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -44,6 +44,9 @@ body must look something like:
|
||||||
"lan": "192.168.10.10",
|
"lan": "192.168.10.10",
|
||||||
"wan": "10.0.10.10"
|
"wan": "10.0.10.10"
|
||||||
},
|
},
|
||||||
|
"NodeMeta": {
|
||||||
|
"somekey": "somevalue"
|
||||||
|
},
|
||||||
"Service": {
|
"Service": {
|
||||||
"ID": "redis1",
|
"ID": "redis1",
|
||||||
"Service": "redis",
|
"Service": "redis",
|
||||||
|
@ -73,6 +76,10 @@ the node with the catalog. `TaggedAddresses` can be used in conjunction with the
|
||||||
option and the `wan` address. The `lan` address was added in Consul 0.7 to help find
|
option and the `wan` address. The `lan` address was added in Consul 0.7 to help find
|
||||||
the LAN address if address translation is enabled.
|
the LAN address if address translation is enabled.
|
||||||
|
|
||||||
|
The `Meta` block was added in Consul 0.7.3 to enable associating arbitrary metadata
|
||||||
|
key/value pairs with a node for filtering purposes. For more information on node metadata,
|
||||||
|
see the [node meta](/docs/agent/options.html#_node_meta) section of the configuration page.
|
||||||
|
|
||||||
If the `Service` key is provided, the service will also be registered. If
|
If the `Service` key is provided, the service will also be registered. If
|
||||||
`ID` is not provided, it will be defaulted to the value of the `Service.Service` property.
|
`ID` is not provided, it will be defaulted to the value of the `Service.Service` property.
|
||||||
Only one service with a given `ID` may be present per node. The service `Tags`, `Address`,
|
Only one service with a given `ID` may be present per node. The service `Tags`, `Address`,
|
||||||
|
@ -191,9 +198,9 @@ the node list in ascending order based on the estimated round trip
|
||||||
time from that node. Passing `?near=_agent` will use the agent's
|
time from that node. Passing `?near=_agent` will use the agent's
|
||||||
node for the sort.
|
node for the sort.
|
||||||
|
|
||||||
Adding the optional `?node-meta=` parameter with a desired node
|
In Consul 0.7.3 and later, the optional `?node-meta=` parameter can be
|
||||||
metadata key/value pair of the form `key:value` will filter the
|
provided with a desired node metadata key/value pair of the form `key:value`.
|
||||||
results to nodes with that pair present.
|
This will filter the results to nodes with that pair present.
|
||||||
|
|
||||||
It returns a JSON body like this:
|
It returns a JSON body like this:
|
||||||
|
|
||||||
|
@ -205,6 +212,9 @@ It returns a JSON body like this:
|
||||||
"TaggedAddresses": {
|
"TaggedAddresses": {
|
||||||
"lan": "10.1.10.11",
|
"lan": "10.1.10.11",
|
||||||
"wan": "10.1.10.11"
|
"wan": "10.1.10.11"
|
||||||
|
},
|
||||||
|
"Meta": {
|
||||||
|
"instance_type": "t2.medium"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -213,6 +223,9 @@ It returns a JSON body like this:
|
||||||
"TaggedAddresses": {
|
"TaggedAddresses": {
|
||||||
"lan": "10.1.10.11",
|
"lan": "10.1.10.11",
|
||||||
"wan": "10.1.10.12"
|
"wan": "10.1.10.12"
|
||||||
|
},
|
||||||
|
"Meta": {
|
||||||
|
"instance_type": "t2.large"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -226,9 +239,9 @@ This endpoint is hit with a `GET` and returns the services registered
|
||||||
in a given DC. By default, the datacenter of the agent is queried;
|
in a given DC. By default, the datacenter of the agent is queried;
|
||||||
however, the `dc` can be provided using the `?dc=` query parameter.
|
however, the `dc` can be provided using the `?dc=` query parameter.
|
||||||
|
|
||||||
Adding the optional `?node-meta=` parameter with a desired node
|
In Consul 0.7.3 and later, the optional `?node-meta=` parameter can be
|
||||||
metadata key/value pair of the form `key:value` will filter the
|
provided with a desired node metadata key/value pair of the form `key:value`.
|
||||||
results to services with that pair present.
|
This will filter the results to services with that pair present.
|
||||||
|
|
||||||
It returns a JSON body like this:
|
It returns a JSON body like this:
|
||||||
|
|
||||||
|
@ -273,6 +286,9 @@ It returns a JSON body like this:
|
||||||
"lan": "192.168.10.10",
|
"lan": "192.168.10.10",
|
||||||
"wan": "10.0.10.10"
|
"wan": "10.0.10.10"
|
||||||
},
|
},
|
||||||
|
"Meta": {
|
||||||
|
"instance_type": "t2.medium"
|
||||||
|
}
|
||||||
"CreateIndex": 51,
|
"CreateIndex": 51,
|
||||||
"ModifyIndex": 51,
|
"ModifyIndex": 51,
|
||||||
"Node": "foobar",
|
"Node": "foobar",
|
||||||
|
@ -294,6 +310,7 @@ The returned fields are as follows:
|
||||||
|
|
||||||
- `Address`: IP address of the Consul node on which the service is registered
|
- `Address`: IP address of the Consul node on which the service is registered
|
||||||
- `TaggedAddresses`: List of explicit LAN and WAN IP addresses for the agent
|
- `TaggedAddresses`: List of explicit LAN and WAN IP addresses for the agent
|
||||||
|
- `Meta`: Added in Consul 0.7.3, a list of user-defined metadata key/value pairs for the node
|
||||||
- `CreateIndex`: Internal index value representing when the service was created
|
- `CreateIndex`: Internal index value representing when the service was created
|
||||||
- `ModifyIndex`: Last index that modified the service
|
- `ModifyIndex`: Last index that modified the service
|
||||||
- `Node`: Node name of the Consul node on which the service is registered
|
- `Node`: Node name of the Consul node on which the service is registered
|
||||||
|
@ -321,6 +338,9 @@ It returns a JSON body like this:
|
||||||
"TaggedAddresses": {
|
"TaggedAddresses": {
|
||||||
"lan": "10.1.10.12",
|
"lan": "10.1.10.12",
|
||||||
"wan": "10.1.10.12"
|
"wan": "10.1.10.12"
|
||||||
|
},
|
||||||
|
"Meta": {
|
||||||
|
"instance_type": "t2.medium"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Services": {
|
"Services": {
|
||||||
|
|
|
@ -131,6 +131,9 @@ It returns a JSON body like this:
|
||||||
"TaggedAddresses": {
|
"TaggedAddresses": {
|
||||||
"lan": "10.1.10.12",
|
"lan": "10.1.10.12",
|
||||||
"wan": "10.1.10.12"
|
"wan": "10.1.10.12"
|
||||||
|
},
|
||||||
|
"Meta": {
|
||||||
|
"instance_type": "t2.medium"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Service": {
|
"Service": {
|
||||||
|
|
|
@ -251,9 +251,9 @@ will exit with an error at startup.
|
||||||
* <a name="_node"></a><a href="#_node">`-node`</a> - The name of this node in the cluster.
|
* <a name="_node"></a><a href="#_node">`-node`</a> - The name of this node in the cluster.
|
||||||
This must be unique within the cluster. By default this is the hostname of the machine.
|
This must be unique within the cluster. By default this is the hostname of the machine.
|
||||||
|
|
||||||
* <a name="_node_meta"></a><a href="#_node_meta">`-node-meta`</a> - An arbitrary metadata key/value pair
|
* <a name="_node_meta"></a><a href="#_node_meta">`-node-meta`</a> - Available in Consul 0.7.3 and later,
|
||||||
to associate with the node, of the form `key:value`. This can be specified multiple times. Node metadata
|
this specifies an arbitrary metadata key/value pair to associate with the node, of the form `key:value`.
|
||||||
pairs have the following restrictions:
|
This can be specified multiple times. Node metadata pairs have the following restrictions:
|
||||||
- A maximum of 64 key/value pairs can be registered per node.
|
- A maximum of 64 key/value pairs can be registered per node.
|
||||||
- Metadata keys must be between 1 and 128 characters (inclusive) in length
|
- Metadata keys must be between 1 and 128 characters (inclusive) in length
|
||||||
- Metadata keys must contain only alphanumeric, `-`, and `_` characters.
|
- Metadata keys must contain only alphanumeric, `-`, and `_` characters.
|
||||||
|
@ -667,9 +667,18 @@ Consul will not enable TLS for the HTTP API unless the `https` port has been ass
|
||||||
* <a name="node_name"></a><a href="#node_name">`node_name`</a> Equivalent to the
|
* <a name="node_name"></a><a href="#node_name">`node_name`</a> Equivalent to the
|
||||||
[`-node` command-line flag](#_node).
|
[`-node` command-line flag](#_node).
|
||||||
|
|
||||||
* <a name="node_meta"></a><a href="#node_meta">`node_meta`</a> This object allows associating arbitrary
|
* <a name="node_meta"></a><a href="#node_meta">`node_meta`</a> Available in Consul 0.7.3 and later,
|
||||||
metadata key/value pairs with the local node, which can then be used for filtering results from certain
|
This object allows associating arbitrary metadata key/value pairs with the local node, which can
|
||||||
catalog endpoints. See the [`-node-meta` command-line flag](#_node_meta) for more information.
|
then be used for filtering results from certain catalog endpoints. See the
|
||||||
|
[`-node-meta` command-line flag](#_node_meta) for more information.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"node_meta": {
|
||||||
|
"instance_type": "t2.medium"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
* <a name="performance"></a><a href="#performance">`performance`</a> Available in Consul 0.7 and
|
* <a name="performance"></a><a href="#performance">`performance`</a> Available in Consul 0.7 and
|
||||||
later, this is a nested object that allows tuning the performance of different subsystems in
|
later, this is a nested object that allows tuning the performance of different subsystems in
|
||||||
|
|
Loading…
Reference in New Issue