github.com/sym3tri/etcd@v0.2.1-0.20140422215517-a563d82f95d6/Documentation/api.md (about) 1 # etcd API 2 3 ## Running a Single Machine Cluster 4 5 These examples will use a single machine cluster to show you the basics of the etcd REST API. 6 Let's start etcd: 7 8 ```sh 9 ./bin/etcd -data-dir machine0 -name machine0 10 ``` 11 12 This will bring up etcd listening on default ports (4001 for client communication and 7001 for server-to-server communication). 13 The `-data-dir machine0` argument tells etcd to write machine configuration, logs and snapshots to the `./machine0/` directory. 14 The `-name machine0` tells the rest of the cluster that this machine is named machine0. 15 16 ## Key Space Operations 17 18 The primary API of etcd is a hierarchical key space. 19 The key space consists of directories and keys which are generically referred to as "nodes". 20 21 22 ### Setting the value of a key 23 24 Let's set the first key-value pair in the datastore. 25 In this case the key is `/message` and the value is `Hello world`. 26 27 ```sh 28 curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello world" 29 ``` 30 31 ```json 32 { 33 "action": "set", 34 "node": { 35 "createdIndex": 2, 36 "key": "/message", 37 "modifiedIndex": 2, 38 "value": "Hello world" 39 } 40 } 41 ``` 42 43 The response object contains several attributes: 44 45 1. `action`: the action of the request that was just made. 46 The request attempted to modify `node.value` via a `PUT` HTTP request, thus the value of action is `set`. 47 48 2. `node.key`: the HTTP path to which the request was made. 49 We set `/message` to `Hello world`, so the key field is `/message`. 50 etcd uses a file-system-like structure to represent the key-value pairs, therefore all keys start with `/`. 51 52 3. `node.value`: the value of the key after resolving the request. 53 In this case, a successful request was made that attempted to change the node's value to `Hello world`. 54 55 4. `node.createdIndex`: an index is a unique, monotonically-incrementing integer created for each change to etcd. 56 This specific index reflects the point in the etcd state machine at which a given key was created. 57 You may notice that in this example the index is `2` even though it is the first request you sent to the server. 58 This is because there are internal commands that also change the state behind the scenes, like adding and syncing servers. 59 60 5. `node.modifiedIndex`: like `node.createdIndex`, this attribute is also an etcd index. 61 Actions that cause the value to change include `set`, `delete`, `update`, `create`, `compareAndSwap` and `compareAndDelete`. 62 Since the `get` and `watch` commands do not change state in the store, they do not change the value of `node.modifiedIndex`. 63 64 65 ### Response Headers 66 67 etcd includes a few HTTP headers in responses that provide global information about the etcd cluster that serviced a request: 68 69 ``` 70 X-Etcd-Index: 35 71 X-Raft-Index: 5398 72 X-Raft-Term: 0 73 ``` 74 75 - `X-Etcd-Index` is the current etcd index as explained above. 76 - `X-Raft-Index` is similar to the etcd index but is for the underlying raft protocol 77 - `X-Raft-Term` is an integer that will increase whenever an etcd master election happens in the cluster. If this number is increasing rapidly, you may need to tune the election timeout. See the [tuning][tuning] section for details. 78 79 [tuning]: #tuning 80 81 82 ### Get the value of a key 83 84 We can get the value that we just set in `/message` by issuing a `GET` request: 85 86 ```sh 87 curl -L http://127.0.0.1:4001/v2/keys/message 88 ``` 89 90 ```json 91 { 92 "action": "get", 93 "node": { 94 "createdIndex": 2, 95 "key": "/message", 96 "modifiedIndex": 2, 97 "value": "Hello world" 98 } 99 } 100 ``` 101 102 103 ### Changing the value of a key 104 105 You can change the value of `/message` from `Hello world` to `Hello etcd` with another `PUT` request to the key: 106 107 ```sh 108 curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello etcd" 109 ``` 110 111 ```json 112 { 113 "action": "set", 114 "node": { 115 "createdIndex": 3, 116 "key": "/message", 117 "modifiedIndex": 3, 118 "value": "Hello etcd" 119 }, 120 "prevNode": { 121 "createdIndex": 2 122 "key": "/message", 123 "value": "Hello world", 124 "modifiedIndex": 2, 125 } 126 } 127 ``` 128 129 Here we introduce a new field: `prevNode`. The `prevNode` field represents what the state of a given node was before resolving the request at hand. The `prevNode` field follows the same format as the `node`, and is omitted in the event that there was no previous state for a given node. 130 131 ### Deleting a key 132 133 You can remove the `/message` key with a `DELETE` request: 134 135 ```sh 136 curl -L http://127.0.0.1:4001/v2/keys/message -XDELETE 137 ``` 138 139 ```json 140 { 141 "action": "delete", 142 "node": { 143 "createdIndex": 3, 144 "key": "/message", 145 "modifiedIndex": 4 146 }, 147 "prevNode": { 148 "key": "/message", 149 "value": "Hello etcd", 150 "modifiedIndex": 3, 151 "createdIndex": 3 152 } 153 } 154 ``` 155 156 157 ### Using key TTL 158 159 Keys in etcd can be set to expire after a specified number of seconds. 160 You can do this by setting a TTL (time to live) on the key when sending a `PUT` request: 161 162 ```sh 163 curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -d ttl=5 164 ``` 165 166 ```json 167 { 168 "action": "set", 169 "node": { 170 "createdIndex": 5, 171 "expiration": "2013-12-04T12:01:21.874888581-08:00", 172 "key": "/foo", 173 "modifiedIndex": 5, 174 "ttl": 5, 175 "value": "bar" 176 } 177 } 178 ``` 179 180 Note the two new fields in response: 181 182 1. The `expiration` is the time at which this key will expire and be deleted. 183 184 2. The `ttl` is the specified time to live for the key, in seconds. 185 186 _NOTE_: Keys can only be expired by a cluster leader, so if a machine gets disconnected from the cluster, its keys will not expire until it rejoins. 187 188 Now you can try to get the key by sending a `GET` request: 189 190 ```sh 191 curl -L http://127.0.0.1:4001/v2/keys/foo 192 ``` 193 194 If the TTL has expired, the key will have been deleted, and you will be returned a 100. 195 196 ```json 197 { 198 "cause": "/foo", 199 "errorCode": 100, 200 "index": 6, 201 "message": "Key Not Found" 202 } 203 ``` 204 205 The TTL could be unset to avoid expiration through update operation: 206 207 ```sh 208 curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar -d ttl= -d prevExist=true 209 ``` 210 211 ```json 212 { 213 "action": "update", 214 "node": { 215 "createdIndex": 5, 216 "key": "/foo", 217 "modifiedIndex": 6, 218 "value": "bar" 219 } 220 "prevNode": { 221 "createdIndex": 5, 222 "expiration": "2013-12-04T12:01:21.874888581-08:00", 223 "key": "/foo", 224 "modifiedIndex": 5, 225 "ttl": 3, 226 "value": "bar" 227 } 228 } 229 ``` 230 231 232 ### Waiting for a change 233 234 We can watch for a change on a key and receive a notification by using long polling. 235 This also works for child keys by passing `recursive=true` in curl. 236 237 In one terminal, we send a `GET` with `wait=true` : 238 239 ```sh 240 curl -L http://127.0.0.1:4001/v2/keys/foo?wait=true 241 ``` 242 243 Now we are waiting for any changes at path `/foo`. 244 245 In another terminal, we set a key `/foo` with value `bar`: 246 247 ```sh 248 curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=bar 249 ``` 250 251 The first terminal should get the notification and return with the same response as the set request: 252 253 ```json 254 { 255 "action": "set", 256 "node": { 257 "createdIndex": 7, 258 "key": "/foo", 259 "modifiedIndex": 7, 260 "value": "bar" 261 }, 262 "prevNode": { 263 "createdIndex": 6, 264 "key": "/foo", 265 "modifiedIndex": 6, 266 "value": "bar" 267 } 268 } 269 ``` 270 271 However, the watch command can do more than this. 272 Using the index, we can watch for commands that have happened in the past. 273 This is useful for ensuring you don't miss events between watch commands. 274 275 Let's try to watch for the set command of index 7 again: 276 277 ```sh 278 curl -L 'http://127.0.0.1:4001/v2/keys/foo?wait=true&waitIndex=7' 279 ``` 280 281 The watch command returns immediately with the same response as previously. 282 283 284 ### Atomically Creating In-Order Keys 285 286 Using `POST` on a directory, you can create keys with key names that are created in-order. 287 This can be used in a variety of useful patterns, like implementing queues of keys which need to be processed in strict order. 288 An example use case is the [locking module][lockmod] which uses it to ensure clients get fair access to a mutex. 289 290 Creating an in-order key is easy: 291 292 ```sh 293 curl http://127.0.0.1:4001/v2/keys/queue -XPOST -d value=Job1 294 ``` 295 296 ```json 297 { 298 "action": "create", 299 "node": { 300 "createdIndex": 6, 301 "key": "/queue/6", 302 "modifiedIndex": 6, 303 "value": "Job1" 304 } 305 } 306 ``` 307 308 If you create another entry some time later, it is guaranteed to have a key name that is greater than the previous key. 309 Also note the key names use the global etcd index, so the next key can be more than `previous + 1`. 310 311 ```sh 312 curl http://127.0.0.1:4001/v2/keys/queue -XPOST -d value=Job2 313 ``` 314 315 ```json 316 { 317 "action": "create", 318 "node": { 319 "createdIndex": 29, 320 "key": "/queue/29", 321 "modifiedIndex": 29, 322 "value": "Job2" 323 } 324 } 325 ``` 326 327 To enumerate the in-order keys as a sorted list, use the "sorted" parameter. 328 329 ```sh 330 curl -s 'http://127.0.0.1:4001/v2/keys/queue?recursive=true&sorted=true' 331 ``` 332 333 ```json 334 { 335 "action": "get", 336 "node": { 337 "createdIndex": 2, 338 "dir": true, 339 "key": "/queue", 340 "modifiedIndex": 2, 341 "nodes": [ 342 { 343 "createdIndex": 2, 344 "key": "/queue/2", 345 "modifiedIndex": 2, 346 "value": "Job1" 347 }, 348 { 349 "createdIndex": 3, 350 "key": "/queue/3", 351 "modifiedIndex": 3, 352 "value": "Job2" 353 } 354 ] 355 } 356 } 357 ``` 358 359 [lockmod]: #lock 360 361 362 ### Using a directory TTL 363 364 Like keys, directories in etcd can be set to expire after a specified number of seconds. 365 You can do this by setting a TTL (time to live) on a directory when it is created with a `PUT`: 366 367 ```sh 368 curl -L http://127.0.0.1:4001/v2/keys/dir -XPUT -d ttl=30 -d dir=true 369 ``` 370 371 ```json 372 { 373 "action": "set", 374 "node": { 375 "createdIndex": 17, 376 "dir": true, 377 "expiration": "2013-12-11T10:37:33.689275857-08:00", 378 "key": "/newdir", 379 "modifiedIndex": 17, 380 "ttl": 30 381 } 382 } 383 ``` 384 385 The directory's TTL can be refreshed by making an update. 386 You can do this by making a PUT with `prevExist=true` and a new TTL. 387 388 ```sh 389 curl -L http://127.0.0.1:4001/v2/keys/dir -XPUT -d ttl=30 -d dir=true -d prevExist=true 390 ``` 391 392 Keys that are under this directory work as usual, but when the directory expires, a watcher on a key under the directory will get an expire event: 393 394 ```sh 395 curl 'http://127.0.0.1:4001/v2/keys/dir/asdf?consistent=true&wait=true' 396 ``` 397 398 ```json 399 { 400 "action": "expire", 401 "node": { 402 "createdIndex": 8, 403 "key": "/dir", 404 "modifiedIndex": 15 405 }, 406 "prevNode": { 407 "createdIndex": 8, 408 "key": "/dir", 409 "dir":true, 410 "modifiedIndex": 17, 411 "expiration": "2013-12-11T10:39:35.689275857-08:00" 412 }, 413 } 414 ``` 415 416 417 ### Atomic Compare-and-Swap 418 419 etcd can be used as a centralized coordination service in a cluster, and `CompareAndSwap` (CAS) is the most basic operation used to build a distributed lock service. 420 421 This command will set the value of a key only if the client-provided conditions are equal to the current conditions. 422 423 The current comparable conditions are: 424 425 1. `prevValue` - checks the previous value of the key. 426 427 2. `prevIndex` - checks the previous modifiedIndex of the key. 428 429 3. `prevExist` - checks existence of the key: if `prevExist` is true, it is an `update` request; if prevExist is `false`, it is a `create` request. 430 431 Here is a simple example. 432 Let's create a key-value pair first: `foo=one`. 433 434 ```sh 435 curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=one 436 ``` 437 438 Now let's try some invalid `CompareAndSwap` commands. 439 440 Trying to set this existing key with `prevExist=false` fails as expected: 441 ```sh 442 curl -L http://127.0.0.1:4001/v2/keys/foo?prevExist=false -XPUT -d value=three 443 ``` 444 445 The error code explains the problem: 446 447 ```json 448 { 449 "cause": "/foo", 450 "errorCode": 105, 451 "index": 39776, 452 "message": "Already exists" 453 } 454 ``` 455 456 Now let's provide a `prevValue` parameter: 457 458 ```sh 459 curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=two -XPUT -d value=three 460 ``` 461 462 This will try to compare the previous value of the key and the previous value we provided. If they are equal, the value of the key will change to three. 463 464 ```json 465 { 466 "cause": "[two != one]", 467 "errorCode": 101, 468 "index": 8, 469 "message": "Test Failed" 470 } 471 ``` 472 473 which means `CompareAndSwap` failed. `cause` explains why the test failed. 474 Note: the condition prevIndex=0 always passes. 475 476 Let's try a valid condition: 477 478 ```sh 479 curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=one -XPUT -d value=two 480 ``` 481 482 The response should be: 483 484 ```json 485 { 486 "action": "compareAndSwap", 487 "node": { 488 "createdIndex": 8, 489 "key": "/foo", 490 "modifiedIndex": 9, 491 "value": "two" 492 }, 493 "prevNode": { 494 "createdIndex": 8, 495 "key": "/foo", 496 "modifiedIndex": 8, 497 "value": "one" 498 } 499 } 500 ``` 501 502 We successfully changed the value from "one" to "two" since we gave the correct previous value. 503 504 ### Atomic Compare-and-Delete 505 506 This command will delete a key only if the client-provided conditions are equal to the current conditions. 507 508 The current comparable conditions are: 509 510 1. `prevValue` - checks the previous value of the key. 511 512 2. `prevIndex` - checks the previous modifiedIndex of the key. 513 514 Here is a simple example. Let's first create a key: `foo=one`. 515 516 ```sh 517 curl -L http://127.0.0.1:4001/v2/keys/foo -XPUT -d value=one 518 ``` 519 520 Now let's try some `CompareAndDelete` commands. 521 522 Trying to delete the key with `prevValue=two` fails as expected: 523 ```sh 524 curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=two -XDELETE 525 ``` 526 527 The error code explains the problem: 528 529 ```json 530 { 531 "errorCode": 101, 532 "message": "Compare failed", 533 "cause": "[two != one]", 534 "index": 8 535 } 536 ``` 537 538 As does a `CompareAndDelete` with a mismatched `prevIndex`: 539 540 ```sh 541 curl -L http://127.0.0.1:4001/v2/keys/foo?prevIndex=1 -XDELETE 542 ``` 543 544 ```json 545 { 546 "errorCode": 101, 547 "message": "Compare failed", 548 "cause": "[1 != 8]", 549 "index": 8 550 } 551 ``` 552 553 And now a valid `prevValue` condition: 554 555 ```sh 556 curl -L http://127.0.0.1:4001/v2/keys/foo?prevValue=one -XDELETE 557 ``` 558 559 The successful response will look something like: 560 561 ```json 562 { 563 "action": "compareAndDelete", 564 "node": { 565 "key": "/foo", 566 "modifiedIndex": 9, 567 "createdIndex": 8 568 }, 569 "prevNode": { 570 "key": "/foo", 571 "value": "one", 572 "modifiedIndex": 8, 573 "createdIndex": 8 574 } 575 } 576 ``` 577 578 ### Creating Directories 579 580 In most cases, directories for a key are automatically created. 581 But there are cases where you will want to create a directory or remove one. 582 583 Creating a directory is just like a key except you cannot provide a value and must add the `dir=true` parameter. 584 585 ```sh 586 curl -L http://127.0.0.1:4001/v2/keys/dir -XPUT -d dir=true 587 ``` 588 ```json 589 { 590 "action": "set", 591 "node": { 592 "createdIndex": 30, 593 "dir": true, 594 "key": "/dir", 595 "modifiedIndex": 30 596 } 597 } 598 ``` 599 600 601 ### Listing a directory 602 603 In etcd we can store two types of things: keys and directories. 604 Keys store a single string value. 605 Directories store a set of keys and/or other directories. 606 607 In this example, let's first create some keys: 608 609 We already have `/foo=two` so now we'll create another one called `/foo_dir/foo` with the value of `bar`: 610 611 ```sh 612 curl -L http://127.0.0.1:4001/v2/keys/foo_dir/foo -XPUT -d value=bar 613 ``` 614 615 ```json 616 { 617 "action": "set", 618 "node": { 619 "createdIndex": 2, 620 "key": "/foo_dir/foo", 621 "modifiedIndex": 2, 622 "value": "bar" 623 } 624 } 625 ``` 626 627 Now we can list the keys under root `/`: 628 629 ```sh 630 curl -L http://127.0.0.1:4001/v2/keys/ 631 ``` 632 633 We should see the response as an array of items: 634 635 ```json 636 { 637 "action": "get", 638 "node": { 639 "dir": true, 640 "key": "/", 641 "nodes": [ 642 { 643 "createdIndex": 2, 644 "dir": true, 645 "key": "/foo_dir", 646 "modifiedIndex": 2 647 } 648 ] 649 } 650 } 651 ``` 652 653 Here we can see `/foo` is a key-value pair under `/` and `/foo_dir` is a directory. 654 We can also recursively get all the contents under a directory by adding `recursive=true`. 655 656 ```sh 657 curl -L http://127.0.0.1:4001/v2/keys/?recursive=true 658 ``` 659 660 ```json 661 { 662 "action": "get", 663 "node": { 664 "dir": true, 665 "key": "/", 666 "nodes": [ 667 { 668 "createdIndex": 2, 669 "dir": true, 670 "key": "/foo_dir", 671 "modifiedIndex": 2, 672 "nodes": [ 673 { 674 "createdIndex": 2, 675 "key": "/foo_dir/foo", 676 "modifiedIndex": 2, 677 "value": "bar" 678 } 679 ] 680 } 681 ] 682 } 683 } 684 ``` 685 686 687 ### Deleting a Directory 688 689 Now let's try to delete the directory `/foo_dir`. 690 691 You can remove an empty directory using the `DELETE` verb and the `dir=true` parameter. 692 693 ```sh 694 curl -L 'http://127.0.0.1:4001/v2/keys/foo_dir?dir=true' -XDELETE 695 ``` 696 ```json 697 { 698 "action": "delete", 699 "node": { 700 "createdIndex": 30, 701 "dir": true, 702 "key": "/foo_dir", 703 "modifiedIndex": 31 704 }, 705 "prevNode": { 706 "createdIndex": 30, 707 "key": "/foo_dir", 708 "dir": true, 709 "modifiedIndex": 30 710 } 711 } 712 ``` 713 714 To delete a directory that holds keys, you must add `recursive=true`. 715 716 ```sh 717 curl -L http://127.0.0.1:4001/v2/keys/dir?recursive=true -XDELETE 718 ``` 719 720 ```json 721 { 722 "action": "delete", 723 "node": { 724 "createdIndex": 10, 725 "dir": true, 726 "key": "/dir", 727 "modifiedIndex": 11 728 }, 729 "prevNode": { 730 "createdIndex": 10, 731 "dir": true, 732 "key": "/dir", 733 "modifiedIndex": 10 734 } 735 } 736 ``` 737 738 739 ### Creating a hidden node 740 741 We can create a hidden key-value pair or directory by add a `_` prefix. 742 The hidden item will not be listed when sending a `GET` request for a directory. 743 744 First we'll add a hidden key named `/_message`: 745 746 ```sh 747 curl -L http://127.0.0.1:4001/v2/keys/_message -XPUT -d value="Hello hidden world" 748 ``` 749 750 ```json 751 { 752 "action": "set", 753 "node": { 754 "createdIndex": 3, 755 "key": "/_message", 756 "modifiedIndex": 3, 757 "value": "Hello hidden world" 758 } 759 } 760 ``` 761 762 Next we'll add a regular key named `/message`: 763 764 ```sh 765 curl -L http://127.0.0.1:4001/v2/keys/message -XPUT -d value="Hello world" 766 ``` 767 768 ```json 769 { 770 "action": "set", 771 "node": { 772 "createdIndex": 4, 773 "key": "/message", 774 "modifiedIndex": 4, 775 "value": "Hello world" 776 } 777 } 778 ``` 779 780 Now let's try to get a listing of keys under the root directory, `/`: 781 782 ```sh 783 curl -L http://127.0.0.1:4001/v2/keys/ 784 ``` 785 786 ```json 787 { 788 "action": "get", 789 "node": { 790 "dir": true, 791 "key": "/", 792 "nodes": [ 793 { 794 "createdIndex": 2, 795 "dir": true, 796 "key": "/foo_dir", 797 "modifiedIndex": 2 798 }, 799 { 800 "createdIndex": 4, 801 "key": "/message", 802 "modifiedIndex": 4, 803 "value": "Hello world" 804 } 805 ] 806 } 807 } 808 ``` 809 810 Here we see the `/message` key but our hidden `/_message` key is not returned. 811 812 ### Setting a key from a file 813 814 You can also use etcd to store small configuration files, json documents, XML documents, etc directly. 815 For example you can use curl to upload a simple text file and encode it: 816 817 ``` 818 echo "Hello\nWorld" > afile.txt 819 curl -L http://127.0.0.1:4001/v2/keys/afile -XPUT --data-urlencode value@afile.txt 820 ``` 821 822 ```json 823 { 824 "action": "get", 825 "node": { 826 "createdIndex": 2, 827 "key": "/afile", 828 "modifiedIndex": 2, 829 "value": "Hello\nWorld\n" 830 } 831 } 832 ``` 833 834 ### Read Consistency 835 836 Followers in a cluster can be behind the leader in their copy of the keyspace. 837 If your application wants or needs the most up-to-date version of a key then it should ensure it reads from the current leader. 838 By using the `consistent=true` flag in your GET requests, etcd will make sure you are talking to the current master. 839 840 As an example of how a machine can be behind the leader let's start with a three machine cluster: L, F1, and F2. 841 A client makes a write to L and F1 acknowledges the request. 842 The client is told the write was successful and the keyspace is updated. 843 Meanwhile F2 has partitioned from the network and will have an out-of-date version of the keyspace until the partition resolves. 844 Since F2 missed the most recent write, a client reading from F2 will have an out-of-date version of the keyspace. 845 846 ## Lock Module (*Deprecated*) 847 848 The lock module is used to serialize access to resources used by clients. 849 Multiple clients can attempt to acquire a lock but only one can have it at a time. 850 Once the lock is released, the next client waiting for the lock will receive it. 851 852 **Warning:** This module is deprecated at v0.4. See [Modules][modules] for more details. 853 854 855 ### Acquiring a Lock 856 857 To acquire a lock, simply send a `POST` request to the lock module with the lock name and TTL: 858 859 ```sh 860 curl -L http://127.0.0.1:4001/mod/v2/lock/mylock -XPOST -d ttl=20 861 ``` 862 863 You will receive the lock index when you acquire the lock: 864 865 ``` 866 2 867 ``` 868 869 If the TTL is not specified or is not a number then you'll receive the following error: 870 871 ```json 872 { 873 "errorCode": 202, 874 "message": "The given TTL in POST form is not a number", 875 "cause": "Acquire", 876 } 877 ``` 878 879 If you specify a timeout that is not a number then you'll receive the following error: 880 881 ```json 882 { 883 "errorCode": 205, 884 "message": "The given timeout in POST form is not a number", 885 "cause": "Acquire", 886 } 887 ``` 888 889 890 ### Renewing a Lock 891 892 To extend the TTL of an already acquired lock, simply repeat your original request but with a `PUT` and the lock index instead: 893 894 ```sh 895 curl -L http://127.0.0.1:4001/mod/v2/lock/mylock -XPUT -d index=5 -d ttl=20 896 ``` 897 898 If the index or value is not specified then you'll receive the following error: 899 900 ```json 901 { 902 "errorCode": 207, 903 "message": "Index or value is required", 904 "cause": "Renew", 905 } 906 ``` 907 908 If the index or value does not exist then you'll receive the following error with a `404 Not Found` HTTP code: 909 910 ```json 911 { 912 "errorCode": 100, 913 "message": "Key not found", 914 "index": 1 915 } 916 ``` 917 918 If the TTL is not specified or is not a number then you'll receive the following error: 919 920 ```json 921 { 922 "errorCode": 202, 923 "message": "The given TTL in POST form is not a number", 924 "cause": "Renew", 925 } 926 ``` 927 928 929 ### Releasing a Lock 930 931 When the client is finished with the lock, simply send a `DELETE` request to release the lock: 932 933 ```sh 934 curl -L http://127.0.0.1:4001/mod/v2/lock/mylock?index=5 -XDELETE 935 ``` 936 937 If the index or value is not specified then you'll receive the following error: 938 939 ```json 940 { 941 "errorCode": 207, 942 "message": "Index or value is required", 943 "cause": "Release", 944 } 945 ``` 946 947 If the index and value are both specified then you'll receive the following error: 948 949 ```json 950 { 951 "errorCode": 208, 952 "message": "Index and value cannot both be specified", 953 "cause": "Release", 954 } 955 ``` 956 957 If the index or value does not exist then you'll receive the following error with a `404 Not Found` HTTP code: 958 959 ```json 960 { 961 "errorCode": 100, 962 "message": "Key not found", 963 "index": 1 964 } 965 ``` 966 967 968 ### Retrieving a Lock 969 970 To determine the current value or index of a lock, send a `GET` request to the lock. 971 You can specify a `field` of `index` or `value`. 972 The default is `value`. 973 974 ```sh 975 curl -L http://127.0.0.1:4001/mod/v2/lock/mylock?field=index 976 ``` 977 978 Will return the current index: 979 980 ```sh 981 2 982 ``` 983 984 If you specify a field other than `index` or `value` then you'll receive the following error: 985 986 ```json 987 { 988 "errorCode": 209, 989 "message": "Invalid field", 990 "cause": "Get", 991 } 992 ``` 993 994 995 ## Leader Module (*Deprecated*) 996 997 The leader module wraps the lock module to provide a simple interface for electing a single leader in a cluster. 998 999 **Warning:** This module is deprecated at v0.4. See [Modules][modules] for more details. 1000 [modules]: https://github.com/coreos/etcd/blob/master/Documentation/modules.md 1001 1002 1003 ### Setting the Leader 1004 1005 A client can attempt to become leader by sending a `PUT` request to the leader module with the name of the leader to elect: 1006 1007 ```sh 1008 curl -L http://127.0.0.1:4001/mod/v2/leader/myclustername -XPUT -d ttl=300 -d name=foo.mydomain.com 1009 ``` 1010 1011 You will receive a successful `200` HTTP response code when the leader is elected. 1012 1013 If the name is not specified then you'll receive the following error: 1014 1015 ```json 1016 { 1017 "errorCode": 206, 1018 "message": "Name is required in POST form", 1019 "cause": "Set", 1020 } 1021 ``` 1022 1023 You can also receive any errors specified by the Lock module. 1024 1025 1026 ### Retrieving the Current Leader 1027 1028 A client can check to determine if there is a current leader by sending a `GET` request to the leader module: 1029 1030 ```sh 1031 curl -L http://127.0.0.1:4001/mod/v2/leader/myclustername 1032 ``` 1033 1034 You will receive the name of the current leader: 1035 1036 ```sh 1037 foo.mydomain.com 1038 ``` 1039 1040 1041 ### Relinquishing Leadership 1042 1043 A client can give up leadership by sending a `DELETE` request with the leader name: 1044 1045 ```sh 1046 curl -L http://127.0.0.1:4001/mod/v2/leader/myclustername?name=foo.mydomain.com -XDELETE 1047 ``` 1048 1049 If the name is not specified then you'll receive the following error: 1050 1051 ```json 1052 { 1053 "errorCode": 206, 1054 "message": "Name is required in POST form", 1055 "cause": "Set", 1056 } 1057 ``` 1058 1059 1060 ## Statistics 1061 1062 An etcd cluster keeps track of a number of statistics including latency, bandwidth and uptime. 1063 These statistics are used in the `/mod/dashboard` endpoint to generate tables and graphs about the cluster state. 1064 1065 1066 ### Leader Statistics 1067 1068 The leader has a view of the entire cluster and keeps track of two interesting statistics: latency to each peer in the cluster, and the number of failed and successful Raft RPC requests. 1069 You can grab these statistics from the `/v2/stats/leader` endpoint: 1070 1071 ```sh 1072 curl -L http://127.0.0.1:4001/v2/stats/leader 1073 ``` 1074 1075 ```json 1076 { 1077 "followers": { 1078 "etcd-node1": { 1079 "counts": { 1080 "fail": 1212, 1081 "success": 4163176 1082 }, 1083 "latency": { 1084 "average": 2.7206299430775007, 1085 "current": 1.486487, 1086 "maximum": 2018.410279, 1087 "minimum": 1.011763, 1088 "standardDeviation": 6.246990702203536 1089 } 1090 }, 1091 "etcd-node3": { 1092 "counts": { 1093 "fail": 1378, 1094 "success": 4164598 1095 }, 1096 "latency": { 1097 "average": 2.707100125761001, 1098 "current": 1.666258, 1099 "maximum": 1409.054765, 1100 "minimum": 0.998415, 1101 "standardDeviation": 5.910089773061448 1102 } 1103 } 1104 }, 1105 "leader": "etcd-node2" 1106 } 1107 ``` 1108 1109 1110 ### Self Statistics 1111 1112 Each node keeps a number of internal statistics: 1113 1114 - `leaderInfo.leader`: name of the current leader machine 1115 - `leaderInfo.uptime`: amount of time the leader has been leader 1116 - `name`: this machine's name 1117 - `recvAppendRequestCnt`: number of append requests this node has processed 1118 - `recvBandwidthRate`: number of bytes per second this node is receiving (follower only) 1119 - `recvPkgRate`: number of requests per second this node is receiving (follower only) 1120 - `sendAppendRequestCnt`: number of requests that this node has sent 1121 - `sendBandwidthRate`: number of bytes per second this node is receiving (leader only). This value is undefined on single machine clusters. 1122 - `sendPkgRate`: number of requests per second this node is receiving (leader only). This value is undefined on single machine clusters. 1123 - `state`: either leader or follower 1124 - `startTime`: the time when this node was started 1125 1126 This is an example response from a follower machine: 1127 1128 ```sh 1129 curl -L http://127.0.0.1:4001/v2/stats/self 1130 ``` 1131 1132 ```json 1133 { 1134 "leaderInfo": { 1135 "leader": "machine1", 1136 "uptime": "1m18.544996775s" 1137 }, 1138 "name": "machine0", 1139 "recvAppendRequestCnt": 5871307, 1140 "recvBandwidthRate": 630.3121596542599, 1141 "recvPkgRate": 19.272654323628185, 1142 "sendAppendRequestCnt": 3175763, 1143 "startTime": "2014-01-01T15:26:24.96569404Z", 1144 "state": "follower" 1145 } 1146 ``` 1147 1148 And this is an example response from a leader machine: 1149 1150 ```sh 1151 curl -L http://127.0.0.1:4001/v2/stats/self 1152 ``` 1153 1154 ```json 1155 { 1156 "leaderInfo": { 1157 "leader": "machine0", 1158 "uptime": "24.648619798s" 1159 }, 1160 "name": "machine0", 1161 "recvAppendRequestCnt": 5901116, 1162 "sendAppendRequestCnt": 3212344, 1163 "sendBandwidthRate": 1254.3151237301615, 1164 "sendPkgRate": 38.71342974475808, 1165 "startTime": "2014-01-01T15:26:24.96569404Z", 1166 "state": "leader" 1167 } 1168 ``` 1169 1170 1171 ### Store Statistics 1172 1173 The store statistics include information about the operations that this node has handled. 1174 1175 Operations that modify the store's state like create, delete, set and update are seen by the entire cluster and the number will increase on all nodes. 1176 Operations like get and watch are node local and will only be seen on this node. 1177 1178 ```sh 1179 curl -L http://127.0.0.1:4001/v2/stats/store 1180 ``` 1181 1182 ```json 1183 { 1184 "compareAndSwapFail": 0, 1185 "compareAndSwapSuccess": 0, 1186 "createFail": 0, 1187 "createSuccess": 2, 1188 "deleteFail": 0, 1189 "deleteSuccess": 0, 1190 "expireCount": 0, 1191 "getsFail": 4, 1192 "getsSuccess": 75, 1193 "setsFail": 2, 1194 "setsSuccess": 4, 1195 "updateFail": 0, 1196 "updateSuccess": 0, 1197 "watchers": 0 1198 } 1199 ```