Package Model¶
Here we discuss package model of EtcdClient
Package model contains case classes for dealing with etcd HTTP responses and building correct HTTP requests to etcd. Most of the case classes are self-explanatory, once the Responses and Errors section below is read. Those that are not are discussed in more detail in this documentation. They are mostly used by handlers or by the client to extract information from JSON objects or write information to JSON objects sent in requests.
Also, package model contains an object for properly building instances of EtcdKey, EtcdDirectory, or EtcdValue case classes. There is also a method for creating hidden nodes, a special case of EtcdKey.
Finally, it contains JSON4S custom serializers for JSON parsing support. All the custom serializers contained in this package are contained in the EtcdJsonFormat object, which in turn is used by handlers in package handlers to parse responses from etcd to HTTP requests.
Results, Responses and Errors¶
All requests can return either a response or an error.
In order to deal with this two possible situations, the outcome of each request is represented by a Result sealed trait in this package.
These traits are extended by case classes representing an error or a response in the manner described bellow.
The naming convention for Result sealed traits is the following: Etcd<NameOfTheEtcdClientMethod>Result
.
For example EtcdGetKeyReslut
.
There are two types of error that etcd could return. For EtcdClient, they are represented in the EtcdStandardError and EtcdRequestError. One of these case classes extends each Result sealed trait representing the outcome of a request sent by the client.
On the other hand, responses are dealt with using Response case classes.
They contain all the necessary fields used to deserialize the information contained in the HTTP response received from etcd.
Response case classes also extend Result sealed traits. The naming convention is similar: Etcd<NameOfTheEtcdClientMethod>Response
.
For example EtcdGetKeyResponse
.
Both Response and Error case classes contain the relevant information about etcd that can be found in headers and in the response body.
A more involved case, which is delt with a callback, is EtcdWaitForKeyResult. We discuss it bellow.
Also, note that each Reslut used by EtcdClient is wrapped around a Future.
Result sealed traits¶
A common feature of Result sealed traits is that they have an accepted method. Response case classes extending such sealed traits override this method and set it to true, while Error case classes set it to false.
The following table illustrates the relation between Result seald traits and Error and Response case classes.
Sealed trait | Response case class extending trait | Type of error extending trait |
---|---|---|
EtcdSetKeyResult | EtcdSetKeyResponse | EtcdRequestError |
EtcdGetKeyResult | EtcdGetKeyResponse | |
EtcdWaitForKeyResult | EtcdWaitForKeyAccepted | |
EtcdCreateDirResult | EtcdCreateDirResponse | |
EtcdDeleteResult | EtcdDeleteResponse | |
EtcdListDirResult | EtcdListDirResponse | |
EtcdGetVersionResult | EtcdGetVersionResponse | EtcdStandardError |
EtcdGetHealthResult | EtcdGetHealthResponse | |
EtcdGetLeaderStatsResult | EtcdGetLeaderStatsResponse | |
EtcdGetSelfStatsResult | EtcdGetSelfStatsResponse | |
EtcdGetStoreStatsResult | EtcdGetStoreStatsResponse | |
EtcdGetAuthenticationStatusResult | EtcdGetAuthenticationStatusResponse | |
EtcdAddUpdateUserResult | EtcdAddUpdateUserResponse | |
EtcdGetUsersResult | EtcdGetUsersResponse | |
EtcdGetUserDetailsResult | EtcdGetUserDetailsResponse | |
EtcdAddUpdateRoleResult | EtcdAddUpdateRoleResponse | |
EtcdGetRolesResult | EtcdGetRolesResponse | |
EtcdGetRoleDetailsResult | EtcdGetRoleDetailsResponse | |
EtcdGetMembersResult | EtcdGetMembersResponse | |
EtcdAddMemberResult | EtcdAddMemberResponse | |
EtcdConfirmationResult | EtcdConfirmationResponse |
It is also important to note that the outcome of some operations to etcd is the same as the outcome of other case classes. Therefore, it is not the case that there is one Result sealed trait for each of EtcdClient’s methods. Instead, some Result sealed traits are reused. The following table shows exactly this:
EtcdClient method | Result sealed trait returned (wrapped around a Future) |
---|---|
setKey | EtcdSetKeyResult |
refreshTTL | |
createKeyFromCurrentEtcdIndex | |
waitForKey | EtcdWaitForKeyResult |
getKey | EtcdGetKeyResult |
deleteKey | EtcdDeleteKeyResult |
createDir | EtcdCreateDirResult |
deleteDir | |
refreshDirTTL | |
listDir | EtcdListDirResult |
getLeaderStats | EtcdGetLeaderStatsResult |
getHealth | EtcdGetHealthResult |
getSelfStats | EtcdGetSelfStatsResult |
getStoreStats | EtcdGetStoreStatsResult |
getVersion | EtcdGetVersionResult |
getAuthenticationStatus | EtcdGetAuthenticationStatusResult |
enableAuthentication | EtcdConfirmationResult |
disableAuthentication | |
deleteUser | |
deleteRole | |
deleteMember | |
changePeerURLs | |
addUpdateUser | EtcdAddUpdateUserResult |
getUsers | EtcdGetUsersResult |
getUserDetails | EtcdGetUserDetailsResult |
addUpdateRole | EtcdAddUpdateRoleResult |
getRoles | EtcdGetRolesResult |
getRoleDetails | EtcdGetRoleDetailsResult |
getMembers | EtcdGetMembersResult |
addMember | EtcdAddMemberResult |
Response and Error case classes¶
As mentioned above, Response case classes contain all the necessary fields used to deserialize the information contained in the HTTP response received from etcd, while Error case classes also contain fields to deserialize information returned by etcd explaining the cause of the error.
The information returned by etcd responses is different in each case. Therefore, each case class contains different information, depending on the outcome of the request. A good place to see exactly what information is contained in a Response or Error case class is the EtcdClient scaladoc.
EtcdWaitForKeyResult¶
The wait operation is handled in a special manner. It is implemented using a callback. Therefore, instead of returning Response case class whenever the request sent is valid, it returns a EtcdWaitForKeyAccepted containing the headers of the response. EtcdWaitForKeyAccepted also overrides EtcdWaitForKeyResult‘s accepted method, setting it to true. In the case there has not been any change in etcd since the watch has been set, etcd returns a HTTP response with an empty body, but with headers confirming the wait has been set (see Waiting for a change).
The callback is implemented using a trait (EtcdWaitCallback) and a class extending it (FutureBasedEtcdWaitCallback). FutureBasedEtcdWaitCallback has a method (.future) for returning a Future wrapped around a EtcdGetKeyResponse if the request is valid. It also has a method (.isCompleted) which returns a Boolean. It is set to true when the callback is completed (i.e. the watch has been notified that a change occurred modifying the key on watch). It returns false otherwise.
Model Case Classes and Traits¶
In this section we discuss some other case classes contained in package model. In particular, we discuss how we deal with keys, directories and values. These are the basic objects used in the key space of etcd.
EtcdKey¶
A key’s name is a full path name that is placed in etcd’s key space. The key space is the node found at the /v2/keys directory and all its sub nodes.
The key’s name should start with a ‘/’. If the path contains many nodes, it should separate each of them with ‘/’. Finally, the last node should not contain ‘/’.
The following example shows a key named using randomly generated strings:
EtcdKey("/k6/tq6eo3Wntsy7qymj3kwSply0xuqxrmysl9p5i/bsnhuen7o")
An instance of a GET request for such a key made using curl
would look as follows:
curl http://127.0.0.1:2379/v2/keys/k6/tq6eo3Wntsy7qymj3kwSply0xuqxrmysl9p5i/bsnhuen7o
The idea of using such a path to name a key is to associate a value to it.
The recommended way to create keys and perform operations on them is by using the EtcdModel object.
Parameters:
- key: the string representation of the key.
EtcdDirectory¶
Like a key, a directory is a full path, but it has a trailing ‘/’.
The directory’s name should start with a ‘/’. If the path contains many nodes, it should separate each of them with ‘/’. Finally, the last node should contain ‘/’.
The same example as above shows that a key can be viewed as a directory by adding a trailing ‘/’:
EtcdDirectory("/k6/tq6eo3Wntsy7qymj3kwSply0xuqxrmysl9p5i/bsnhuen7o/")
The idea of using such a path to name a directory is to put other keys and directories into it.
In our model, we make a difference between keys and directories, since operations made on keys return different responses than operations made on directories.
Again, the recommended way to create directories and perform operations on them is by using the EtcdModel object.
Parameters:
- dir: the string representation of the directory.
EtcdValue¶
A value is any data being stored under a key.
Parameters:
- value: the string representation of the value.
CompareAndSwapCondition¶
A sealed trait used to represent the conditions that can be imposed on the EtcdClient.setKey method.
It can be either KeyMustExist, KeyMustHaveIndex or KeyMustHaveValue.
ConditionalDeleteCondition¶
A sealed trait used to represent the conditions that can be imposed on the EtcdClient.deleteKey method.
It can be either KeyMustHaveIndex or KeyMustHaveValue.
KeyMustExist¶
This case class is used as input for a compare-and-swap operation:
case class KeyMustExist(state: Boolean)
extends CompareAndSwapCondition
Parameters:
- state: Requires that the key already exist, when set to true. When set to false, requires for the key to not exist.
KeyMustHaveIndex¶
This case class is used as input for a compare-and-swap operation or for a conditional delete:
case class KeyMustHaveIndex(index: EtcdIndex)
extends CompareAndSwapCondition with ConditionalDeleteCondition
Parameters:
- index: Requires for the key to have this modified index associated to its last operation.
KeyMustHaveValue¶
This case class is used as input for a compare-and-swap operation or for a conditional delete:
case class KeyMustHaveValue(value: EtcdValue)
extends CompareAndSwapCondition with ConditionalDeleteCondition
Parameters:
- value: Requires for the key to have this value at the time of the request.
EtcdIndex¶
Index associated to the last operation performed in etcd.
See “Response Headers”.
Parameters:
- index: Integer representation of the etcd index.
EtcdTTL¶
Life span in seconds of a key or directory.
Parameters:
- ttl: Integer representing the time to live in seconds.
EtcdResponseCode¶
HTTP response code to a request.
Parameters:
- code: Integer representation of the response code.
RaftTerm¶
An integer that will increase whenever an etcd master election happens in the cluster.
See “Response Headers”.
Parameters:
- term: Integer representation of the raft term.
EtcdHeaders¶
This case class contains the most relevant information returned in headers of responses to requests performed by key-value methods:
case class EtcdHeaders(
xEtcdClusterId: EtcdClusterId,
xEtcdIndex: EtcdIndex,
xRaftIndex: RaftIndex,
xRaftTerm: RaftTerm
)
EtcdMember¶
Case class representing the information that a member of a cluster may have of another member.
Parameters:
- id: String identifying a member of an etcd cluster.
- name: String identifying a member of an etcd cluster by name.
- peerURLs: List of URLs (represented as strings) used for communication between peers in an etcd cluster.
- clientURLs: List of URLs (represented as strings) used for communication with clients.
EtcdMemberForm¶
Form used to update the peer URLs of a member of a cluster.
Parameters:
- peerURLs: List of strings representing the peer URLs.
EtcdUserRequestForm¶
Form that needs to be filled to use as input for EtcdClient.addUpdateUser and EtcdClient.deleteUser methods. Sometimes the only parameter needed is the user field.
Parameters:
- user: String identifying a user.
- password: Password that the user will use for authentication.
- roles: List of roles that a user has when it gets created.
- grant: List of roles to be granted when performing an update.
- revoke: List of roles to be revoked when performing an update.
EtcdUserAuthenticationData¶
Data used to get authorization when authentication is enabled.
Parameters:
- userLogin: String representing a login.
- password: String representing a password.
EtcdUser¶
Data representing a user in etcd.
Parameters:
- user: String representing the name of the user.
- password: String representing the password of the user.
- roles: List of instances of EtcdRole, which specify the permissions the user has.
EtcdRole¶
Data specifying what write and read privileges are granted or revoked to the users in possession of it.
Parameters:
- role: String representing the name of the role.
- permissions: List of permissions that the possession of the role grants.
- grant: Used for granting a permission when a role is updated.
- revoke: Used for revoking a permission when a role is updated.
EtcdPermission¶
Data specifying the read and write access to the key-value and authentication spaces.
Parameters:
- kv: Instance of EtcdKV.
EtcdKV¶
Data specifying the read and write access to the key-value and authentication spaces.
Parameters:
- read: List of strings specifying read access to a certain domain of the key-value and authentication spaces.
- write: List of strings specifying write access to a certain domain of the key-value and authentication spaces.
The EtcdModel Object¶
The EtcdModel object contains methods for getting well-formed instances of EtcdKey, EtcdDirectory, or EtcdValue case classes. It also includes a method for creating hidden nodes, a type of EtcdKey.
key(key: String)¶
Creates a well-formed instance of EtcdKey from a String that represents a path to an etcd node. In general, this method is used to check that an input string will not produce errors while sending requests. It creates instances of keys that conform to the description of keys given in EtcdKey.
Parameters:
- key: the String representation of the key
The following examples show the outcome of some operations using this method:
//returns EtcdKey(/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj)
EtcdModel.key("/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj")
//returns java.lang.IllegalArgumentException: key name must not end with '/'.
EtcdModel.key("/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/")
//returns java.lang.IllegalArgumentException: key name must start with '/'.
EtcdModel.key("model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj")
//returns java.lang.IllegalArgumentException: key name can not be null.
EtcdModel.key("")
//returns java.lang.IllegalArgumentException: key name can not be null.
EtcdModel.key(null)
key(dir: EtcdDirectory, key: String)¶
Creates a well-formed instance of EtcdKey from a String that represents a path to an etcd node and a String that represents the name of the node.
Parameters:
- dir: the string representation of the directory.
- key: the string representation of the key.
The following is an instance of how this method could be used:
val someDir = EtcdModel.directory(
"/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/"
)
val someName = "foo"
// returns EtcdKey(/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/foo)
EtcdModel.key(someDir, someName)
directory(dir: String)¶
Creates a well-formed instance of EtcdDirectory from a String that represents a path. It creates instances of directories that conform to the description of keys given in EtcdDirectory.
Parameters:
- dir: the string representation of the directory.
The following examples show the outcome of some operations using this method:
//returns EtcdDirectory(/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/)
EtcdModel.directory("/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/")
//returns java.lang.IllegalArgumentException: Directory name must start with '/'.
EtcdModel.directory("model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/")
//returns java.lang.IllegalArgumentException: Directory must end with '/'.
EtcdModel.directory("/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj")
//returns java.lang.IllegalArgumentException: Directory name must start with '/'.
EtcdModel.directory("")
//returns java.lang.IllegalArgumentException: Directory name can not be null.
EtcdModel.directory(null)
value(value: String)¶
Creates a well-formed instance of EtcdValue.
Parameters:
- value: the string representation of the value
The following is an instance of how this method could be used:
val str = "foo"
//returns EtcdValue(foo)
EtcdModel.value(str)
keyOfDirectory(dir: EtcdDirectory)¶
Returns an instance of EtcdKey from a EtcdDirectory.
An EtcdDirectory can be treated as an EtcdKey by dropping the closing ‘/’.
Parameters:
- dir: the EtcdDirectory that is to be treated as a key.
The following is an instance of how this method could be used:
val someDir = EtcdModel.directory(
"/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/"
)
//returns EtcdKey(/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj)
EtcdModel.keyOfDirectory(someDir)
directoryOfKey(key: EtcdKey)¶
Returns an instance of EtcdDirectory from a EtcdKey.
An EtcdDirectory can be treated as an EtcdKey by adding a closing ‘/’.
Parameters:
- key: the EtcdKey that is to be treated as a directory.
The following is an instance of how this method could be used:
val someKey = EtcdModel.key(
"/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj"
)
//returns EtcdDirectory(/model/k1/rprpxoyqupvqyxg/iaqzqj/sIbn3vouscjabdtgh/v9elcFp0ySUykKa0yhkj/)
EtcdModel.directoryOfKey(someKey)
fromPath(path: List[String])¶
Returns an instance of EtcdKey from a list of node names.
The key preserves the order of the list given as input.
Parameters:
- path: A list of strings not containing “/”, which are to be used as node names.
The following examples show the outcome of some operations using this method:
val listOfNodes: List[String] = List("path", "leading", "to", "node")
//returns EtcdKey(/path/leading/to/node)
EtcdModel.fromPath(listOfNodes)
val listOfNodes2: List[String] = List("path", "leading/to", "node")
//returns java.lang.IllegalArgumentException: node names cannot contain '/'
EtcdModel.fromPath(listOfNodes2)
One restriction on this method ist that the strings included on the list cannot contain “/”.
toPath(key: EtcdKey)¶
Returns a list of all node names in order.
Parameters:
- key: An EtcdKey which is to be split in node names and placed in order into a list.
The following is an instance of how this method could be used:
val someKey = EtcdKey("/path/leading/to/node")
//returns List(path, leading, to, node)
EtcdModel.toPath(someKey)