Ruby client for Etcd V3
To install etcdv3, run the following command:
geminstalletcdv3require'etcdv3'# Insecure connectionconn=Etcdv3.new(endpoints: 'http://127.0.0.1:2379, http://127.0.0.1:2389, http://127.0.0.1:2399')# Secure connection using default certificatesconn=Etcdv3.new(endpoints: 'https://hostname:port')# Secure connection with Authconn=Etcdv3.new(endpoints: 'https://hostname:port',user: 'root',password: 'mysecretpassword')# Scope CRUD operations to a specific keyspace. conn=Etcdv3.new(endpoints: 'https://hostname:port',namespace: "/target_keyspace/")# Secure connection specifying custom certificates# Coming soon...High Availability
In the event of a failure, the client will work to restore connectivity by cycling through the specified endpoints until a connection can be established. With that being said, it is encouraged to specify multiple endpoints when available.
However, sometimes this is not what you want. If you need more control over failures, you can suppress this mechanism by using
conn=Etcdv3.new(endpoints: 'https://hostname:port',allow_reconnect: false)This will still rotate the endpoints, but it will raise an exception so you can
handle the failure yourself. On next call to the new endpoint (since they were
rotated) is tried. One thing you need to keep in mind if auth is enabled, you
need to take care of GRPC::Unauthenticated exception and manually re-authenticate
when token expires. To reiterate, you are responsible for handling the errors, so
some understanding of how this gem and etcd works is recommended.
Namespacing is a convenience feature used to scope CRUD based operations to a specific keyspace.
# Establish connectionconn=Etcdv3.new(endpoints: 'https://hostname:port',namespace: '/service-a/')# Write key to /service-a/test_keyconn.put("test_key","value").# Get the key we just wrote.conn.get("test_key")# Retrieve everything under the namespace.conn.get("","\0")# Delete everything under the namespace.conn.del("","\0")Note: Namespaces are stripped from responses.
# Putconn.put('foo','bar')# Getconn.get('my')# Get actual valuevalue=conn.get('my').kvs.first.value# Get Key Rangeconn.get('foo',range_end: 'foo80')# Delete Keyconn.del('foo')# Delete Key Rangeconn.del('foo',range_end: 'foo80')# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list# Add Roleconn.role_add('admin')# Grant Permission to Roleconn.role_grant_permission('admin',:readwrite,'foo','foo99')# Delete Roleconn.role_delete('admin')# List Rolesconn.role_list# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enableAfter you enable authentication, you must authenticate.
# This will generate and assign an auth token that will be used in future requests.conn.authenticate('root','mysecretpassword')Disabling auth will clear the auth token and all previously attached user information
conn.auth_disable
# Grant a lease with a 100 second TTLconn.lease_grant(100)# Attach key to leaseconn.put('foo','bar',lease: 1234566789)# Get information about lease and its attached keysconn.lease_ttl(1234566789)# Revoke lease and delete all keys attachedconn.lease_revoke(1234566789)Transactions provide an easy way to process multiple requests in a single transaction.
Note: You cannot modify the same key multiple times within a single transaction.
# https://github.com/davissp14/etcdv3-ruby/blob/master/lib/etcdv3/kv/transaction.rbconn.transactiondo |txn|
txn.compare=[# Is the value of 'target_key' equal to 'compare_value'txn.value('target_key',:equal,'compare_value'),# Is the version of 'target_key' greater than 10txn.version('target_key',:greater,10)]txn.success=[txn.put('txn1','success')]txn.failure=[txn.put('txn1','failed',lease: lease_id)]end# Watch for changes on a specified key for at most 10 seconds and returnevents=conn.watch('foo',timeout: 10)# Watch for changes on a specified key range and returnevents=conn.watch('foo',range_end: 'fop')# Watch for changes since a given revisionevents=conn.watch('foo',start_revision: 42)# Watches for changes continuously until killed.event_count=0conn.watch('boom')do |events|
putseventsevent_count=event_count + 1breakifevent_count >= 10end# First, get yourself a leaselease_id=conn.lease_grant(100)['ID']# Attempt to lock distibuted lock 'foo', wait at most 10 secondslock_key=conn.lock('foo',lease_id,timeout: 10).key# Unlock the 'foo' lock using the key returned from `lock`conn.unlock(key)# Perform a critical section while holding the lock 'hello'conn.with_lock('hello',lease_id)doputs"kitty!"end# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivateThe default timeout for all requests is 120 seconds.
# Specify `command_timeout` to override the default global timeout.conn=Etcdv3.new(endpoints: 'https://hostname:port',command_timeout: 5)# 5 seconds# You can also specify request specific timeouts.conn.get("foo",timeout: 2)Timeouts apply to and can be set when:
- Adding, Fetching and Deleting keys
- User, Role, and Authentication Management
- Leases
- Transactions
Note: Timeouts currently do not affect Watch or Maintenance related commands.
If you're looking to get involved, Fork the project and send pull requests.