diff --git a/agent/structs/structs.go b/agent/structs/structs.go index a699c9e4a3..e1d9c0cdf4 100644 --- a/agent/structs/structs.go +++ b/agent/structs/structs.go @@ -906,7 +906,7 @@ type HealthCheckDefinition struct { func (d *HealthCheckDefinition) MarshalJSON() ([]byte, error) { type Alias HealthCheckDefinition - return json.Marshal(&struct { + exported := &struct { Interval string Timeout string DeregisterCriticalServiceAfter string @@ -916,7 +916,18 @@ func (d *HealthCheckDefinition) MarshalJSON() ([]byte, error) { Timeout: d.Timeout.String(), DeregisterCriticalServiceAfter: d.DeregisterCriticalServiceAfter.String(), Alias: (*Alias)(d), - }) + } + if d.Interval == 0 { + exported.Interval = "" + } + if d.Timeout == 0 { + exported.Timeout = "" + } + if d.DeregisterCriticalServiceAfter == 0 { + exported.DeregisterCriticalServiceAfter = "" + } + + return json.Marshal(exported) } func (d *HealthCheckDefinition) UnmarshalJSON(data []byte) error { diff --git a/agent/structs/txn.go b/agent/structs/txn.go index 5d136ccf71..87d247bd02 100644 --- a/agent/structs/txn.go +++ b/agent/structs/txn.go @@ -112,10 +112,10 @@ type TxnErrors []*TxnError // TxnResult is used to define the result of a given operation inside a // transaction. Only one of the types should be filled out per entry. type TxnResult struct { - KV TxnKVResult - Node TxnNodeResult - Service TxnServiceResult - Check TxnCheckResult + KV TxnKVResult `json:",omitempty"` + Node TxnNodeResult `json:",omitempty"` + Service TxnServiceResult `json:",omitempty"` + Check TxnCheckResult `json:",omitempty"` } // TxnResults is a list of TxnResult entries. diff --git a/agent/txn_endpoint.go b/agent/txn_endpoint.go index 33f361a435..d11958ebd8 100644 --- a/agent/txn_endpoint.go +++ b/agent/txn_endpoint.go @@ -195,17 +195,17 @@ func (s *HTTPServer) convertOps(resp http.ResponseWriter, req *http.Request) (st Verb: in.Service.Verb, Node: in.Service.Node, Service: structs.NodeService{ - ID: svc.ServiceID, - Service: svc.ServiceName, - Tags: svc.ServiceTags, - Address: svc.ServiceAddress, - Meta: svc.ServiceMeta, - Port: svc.ServicePort, + ID: svc.ID, + Service: svc.Service, + Tags: svc.Tags, + Address: svc.Address, + Meta: svc.Meta, + Port: svc.Port, Weights: &structs.Weights{ - Passing: svc.ServiceWeights.Passing, - Warning: svc.ServiceWeights.Warning, + Passing: svc.Weights.Passing, + Warning: svc.Weights.Warning, }, - EnableTagOverride: svc.ServiceEnableTagOverride, + EnableTagOverride: svc.EnableTagOverride, RaftIndex: structs.RaftIndex{ ModifyIndex: svc.ModifyIndex, }, diff --git a/api/txn.go b/api/txn.go index 02ae66252f..65d7a16ea0 100644 --- a/api/txn.go +++ b/api/txn.go @@ -125,7 +125,7 @@ const ( type ServiceTxnOp struct { Verb ServiceOp Node string - Service CatalogService + Service AgentService } // CheckOp constants give possible operations available in a transaction. diff --git a/api/txn_test.go b/api/txn_test.go index 74a9cfdf9a..c164ebe92b 100644 --- a/api/txn_test.go +++ b/api/txn_test.go @@ -84,7 +84,7 @@ func TestAPI_ClientTxn(t *testing.T) { Service: &ServiceTxnOp{ Verb: ServiceGet, Node: "foo", - Service: CatalogService{ServiceID: "foo1"}, + Service: AgentService{ID: "foo1"}, }, }, &TxnOp{ diff --git a/website/source/api/txn.html.md b/website/source/api/txn.html.md index 17bce978f5..23e28b0d20 100644 --- a/website/source/api/txn.html.md +++ b/website/source/api/txn.html.md @@ -3,19 +3,18 @@ layout: api page_title: Transaction - HTTP API sidebar_current: api-txn description: |- - The /txn endpoints manage updates or fetches of multiple keys inside a single, - atomic transaction. + The /txn endpoint manages multiple operations in Consul, including catalog updates and fetches of multiple KV entries inside a single, atomic transaction. --- # Transactions HTTP API -The `/txn` endpoints manage updates or fetches of multiple keys inside a single, -atomic transaction. It is important to note that each datacenter has its own KV -store, and there is no built-in replication between datacenters. +The `/txn` endpoint manages multiple operations in Consul, including catalog +updates and fetches of multiple KV entries inside a single, atomic +transaction. ## Create Transaction -This endpoint permits submitting a list of operations to apply to the KV store +This endpoint permits submitting a list of operations to apply to Consul inside of a transaction. If any operation fails, the transaction is rolled back and none of the changes are applied. @@ -43,7 +42,7 @@ The table below shows this endpoint's support for | Blocking Queries | Consistency Modes | Agent Caching | ACL Required | | ---------------- | ----------------- | ------------- | ------------ | -| `NO` | `all`1 | `none` | `key:read,key:write`2 | +| `NO` | `all`1 | `none` | `key:read,key:write`
`node:read,node:write`
`service:read,service:write`2 1 For read-only transactions
@@ -55,7 +54,7 @@ The table below shows this endpoint's support for to the datacenter of the agent being queried. This is specified as part of the URL as a query parameter. -- `KV` is the only available operation type, though other types may be added in the future. +- `KV` operations have the following fields: - `Verb` `(string: )` - Specifies the type of operation to perform. Please see the table below for available verbs. @@ -74,7 +73,32 @@ The table below shows this endpoint's support for - `Session` `(string: "")` - Specifies a session. See the table below for more information. + +- `Node` operations have the following fields: + - `Verb` `(string: )` - Specifies the type of operation to perform. + + - `Node` `(Node: )` - Specifies the node information to use + for the operation. See the [catalog endpoint](/api/catalog.html#parameters) for the fields in this object. Note the only the node can be specified here, not any services or checks - separate service or check operations must be used for those. + +- `Service` operations have the following fields: + + - `Verb` `(string: )` - Specifies the type of operation to perform. + + - `Node` `(string: )` = Specifies the name of the node to use for + this service operation. + + - `Service` `(Service: )` - Specifies the service instance information to use + for the operation. See the [catalog endpoint](/api/catalog.html#parameters) for the fields in this object. + +- `Check` operations have the following fields: + + - `Verb` `(string: )` - Specifies the type of operation to perform. + + - `Service` `(Service: )` - Specifies the check to use + for the operation. See the [catalog endpoint](/api/catalog.html#parameters) for the fields in this object. + + Please see the table below for available verbs. ### Sample Payload The body of the request should be a list of operations to perform inside the @@ -91,6 +115,48 @@ atomic transaction. Up to 64 operations may be present in a single transaction. "Index": , "Session": "" } + }, + { + "Node": { + "Verb": "set", + "Node": { + "ID": "67539c9d-b948-ba67-edd4-d07a676d6673", + "Node": "bar", + "Address": "192.168.0.1", + "Datacenter": "dc1", + "Meta": { + "instance_type": "m2.large" + } + } + } + }, + { + "Service": { + "Verb": "delete", + "Node": "foo", + "Service": { + "ID": "db1" + } + } + }, + { + "Check": { + "Verb": "cas", + "Check": { + "Node": "bar", + "CheckID": "service:web1", + "Name": "Web HTTP Check", + "Status": "critical", + "ServiceID": "web1", + "ServiceName": "web", + "ServiceTags": null, + "Definition": { + "HTTP": "http://localhost:8080", + "Interval": "10s" + }, + "ModifyIndex": 22 + } + } } ] ``` @@ -123,6 +189,39 @@ look like this: "CreateIndex": , "ModifyIndex": } + }, + { + "Node": { + "ID": "67539c9d-b948-ba67-edd4-d07a676d6673", + "Node": "bar", + "Address": "192.168.0.1", + "Datacenter": "dc1", + "TaggedAddresses": null, + "Meta": { + "instance_type": "m2.large" + }, + "CreateIndex": 32, + "ModifyIndex": 32 + } + }, + { + "Check": { + "Node": "bar", + "CheckID": "service:web1", + "Name": "Web HTTP Check", + "Status": "critical", + "Notes": "", + "Output": "", + "ServiceID": "web1", + "ServiceName": "web", + "ServiceTags": null, + "Definition": { + "HTTP": "http://localhost:8080", + "Interval": "10s" + }, + "CreateIndex": 22, + "ModifyIndex": 35 + } } ], "Errors": [ @@ -130,12 +229,13 @@ look like this: "OpIndex": , "What": "" }, + ... ] } ``` - `Results` has entries for some operations if the transaction was successful. - To save space, the `Value` will be `null` for any `Verb` other than "get" or + To save space, the `Value` for KV results will be `null` for any `Verb` other than "get" or "get-tree". Like the `/v1/kv/` endpoint, `Value` will be Base64-encoded if it is present. Also, no result entries will be added for verbs that delete keys. @@ -145,10 +245,12 @@ look like this: transaction, and `What` is a string with an error message about why that operation failed. -### Table of Operations +### Tables of Operations -The following table summarizes the available verbs and the fields that apply to -that operation ("X" means a field is required and "O" means it is optional): +#### KV Operations + +The following tables summarize the available verbs and the fields that apply to +those operations ("X" means a field is required and "O" means it is optional): | Verb | Operation | Key | Value | Flags | Index | Session | | ------------------ | -------------------------------------------- | :--: | :---: | :---: | :---: | :-----: | @@ -164,3 +266,42 @@ that operation ("X" means a field is required and "O" means it is optional): | `delete` | Delete the key | `x` | | | | | | `delete-tree` | Delete all keys with a prefix | `x` | | | | | | `delete-cas` | Delete, but with CAS semantics | `x` | | | `x` | | + +#### Node Operations + +Node operations act on an individual node and require either a Node ID or name, giving precedence +to the ID if both are set. Delete operations will not return a result on success. + +| Verb | Operation | +| ------------------ | -------------------------------------------- | +| `set` | Sets the node to the given state | +| `cas` | Sets, but with CAS semantics using the given ModifyIndex | +| `get` | Get the node, fails if it does not exist | +| `delete` | Delete the node | +| `delete-cas` | Delete, but with CAS semantics | + +#### Service Operations + +Service operations act on an individual service instance on the given node name. Both a node name +and valid service name are required. Delete operations will not return a result on success. + +| Verb | Operation | +| ------------------ | -------------------------------------------- | +| `set` | Sets the service to the given state | +| `cas` | Sets, but with CAS semantics using the given ModifyIndex | +| `get` | Get the service, fails if it does not exist | +| `delete` | Delete the service | +| `delete-cas` | Delete, but with CAS semantics | + +#### Check Operations + +Check operations act on an individual health check instance on the given node name. Both a node name +and valid check ID are required. Delete operations will not return a result on success. + +| Verb | Operation | +| ------------------ | -------------------------------------------- | +| `set` | Sets the health check to the given state | +| `cas` | Sets, but with CAS semantics using the given ModifyIndex | +| `get` | Get the check, fails if it does not exist | +| `delete` | Delete the check | +| `delete-cas` | Delete, but with CAS semantics | \ No newline at end of file