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
|
||||
// for the sort.
|
||||
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
|
||||
|
@ -386,6 +391,11 @@ func (r *request) setQueryOptions(q *QueryOptions) {
|
|||
if 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
|
||||
|
|
|
@ -4,12 +4,14 @@ type Node struct {
|
|||
Node string
|
||||
Address string
|
||||
TaggedAddresses map[string]string
|
||||
Meta map[string]string
|
||||
}
|
||||
|
||||
type CatalogService struct {
|
||||
Node string
|
||||
Address string
|
||||
TaggedAddresses map[string]string
|
||||
NodeMeta map[string]string
|
||||
ServiceID string
|
||||
ServiceName string
|
||||
ServiceAddress string
|
||||
|
@ -29,6 +31,7 @@ type CatalogRegistration struct {
|
|||
Node string
|
||||
Address string
|
||||
TaggedAddresses map[string]string
|
||||
NodeMeta map[string]string
|
||||
Datacenter string
|
||||
Service *AgentService
|
||||
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) {
|
||||
t.Parallel()
|
||||
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) {
|
||||
t.Parallel()
|
||||
c, s := makeClient(t)
|
||||
|
@ -173,6 +281,7 @@ func TestCatalog_Registration(t *testing.T) {
|
|||
Datacenter: "dc1",
|
||||
Node: "foobar",
|
||||
Address: "192.168.10.10",
|
||||
NodeMeta: map[string]string{"somekey": "somevalue"},
|
||||
Service: service,
|
||||
Check: check,
|
||||
}
|
||||
|
@ -200,6 +309,10 @@ func TestCatalog_Registration(t *testing.T) {
|
|||
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
|
||||
}, func(err error) {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
|
|
@ -53,6 +53,7 @@ type TestAddressConfig struct {
|
|||
// TestServerConfig is the main server configuration struct.
|
||||
type TestServerConfig struct {
|
||||
NodeName string `json:"node_name"`
|
||||
NodeMeta map[string]string `json:"node_meta"`
|
||||
Performance *TestPerformanceConfig `json:"performance,omitempty"`
|
||||
Bootstrap bool `json:"bootstrap,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.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:
|
||||
|
||||
```javascript
|
||||
|
@ -194,6 +196,10 @@ It returns a JSON body like this:
|
|||
"DelegateMin": 2,
|
||||
"DelegateMax": 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",
|
||||
"wan": "10.0.10.10"
|
||||
},
|
||||
"NodeMeta": {
|
||||
"somekey": "somevalue"
|
||||
},
|
||||
"Service": {
|
||||
"ID": "redis1",
|
||||
"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
|
||||
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
|
||||
`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`,
|
||||
|
@ -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
|
||||
node for the sort.
|
||||
|
||||
Adding the optional `?node-meta=` parameter with a desired node
|
||||
metadata key/value pair of the form `key:value` will filter the
|
||||
results to nodes with that pair present.
|
||||
In Consul 0.7.3 and later, the optional `?node-meta=` parameter can be
|
||||
provided with a desired node metadata key/value pair of the form `key:value`.
|
||||
This will filter the results to nodes with that pair present.
|
||||
|
||||
It returns a JSON body like this:
|
||||
|
||||
|
@ -205,6 +212,9 @@ It returns a JSON body like this:
|
|||
"TaggedAddresses": {
|
||||
"lan": "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": {
|
||||
"lan": "10.1.10.11",
|
||||
"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;
|
||||
however, the `dc` can be provided using the `?dc=` query parameter.
|
||||
|
||||
Adding the optional `?node-meta=` parameter with a desired node
|
||||
metadata key/value pair of the form `key:value` will filter the
|
||||
results to services with that pair present.
|
||||
In Consul 0.7.3 and later, the optional `?node-meta=` parameter can be
|
||||
provided with a desired node metadata key/value pair of the form `key:value`.
|
||||
This will filter the results to services with that pair present.
|
||||
|
||||
It returns a JSON body like this:
|
||||
|
||||
|
@ -273,6 +286,9 @@ It returns a JSON body like this:
|
|||
"lan": "192.168.10.10",
|
||||
"wan": "10.0.10.10"
|
||||
},
|
||||
"Meta": {
|
||||
"instance_type": "t2.medium"
|
||||
}
|
||||
"CreateIndex": 51,
|
||||
"ModifyIndex": 51,
|
||||
"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
|
||||
- `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
|
||||
- `ModifyIndex`: Last index that modified the service
|
||||
- `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": {
|
||||
"lan": "10.1.10.12",
|
||||
"wan": "10.1.10.12"
|
||||
},
|
||||
"Meta": {
|
||||
"instance_type": "t2.medium"
|
||||
}
|
||||
},
|
||||
"Services": {
|
||||
|
|
|
@ -131,6 +131,9 @@ It returns a JSON body like this:
|
|||
"TaggedAddresses": {
|
||||
"lan": "10.1.10.12",
|
||||
"wan": "10.1.10.12"
|
||||
},
|
||||
"Meta": {
|
||||
"instance_type": "t2.medium"
|
||||
}
|
||||
},
|
||||
"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.
|
||||
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
|
||||
to associate with the node, of the form `key:value`. This can be specified multiple times. Node metadata
|
||||
pairs have the following restrictions:
|
||||
* <a name="_node_meta"></a><a href="#_node_meta">`-node-meta`</a> - Available in Consul 0.7.3 and later,
|
||||
this specifies an arbitrary metadata key/value pair to associate with the node, of the form `key:value`.
|
||||
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.
|
||||
- Metadata keys must be between 1 and 128 characters (inclusive) in length
|
||||
- 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
|
||||
[`-node` command-line flag](#_node).
|
||||
|
||||
* <a name="node_meta"></a><a href="#node_meta">`node_meta`</a> This object allows associating arbitrary
|
||||
metadata key/value pairs with the local node, which can then be used for filtering results from certain
|
||||
catalog endpoints. See the [`-node-meta` command-line flag](#_node_meta) for more information.
|
||||
* <a name="node_meta"></a><a href="#node_meta">`node_meta`</a> Available in Consul 0.7.3 and later,
|
||||
This object allows associating arbitrary metadata key/value pairs with the local node, which can
|
||||
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
|
||||
later, this is a nested object that allows tuning the performance of different subsystems in
|
||||
|
|
Loading…
Reference in New Issue