Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

etcdv3-ruby Gem VersionBuild Statuscodecov

Ruby client for Etcd V3

Getting Started

RubyDocs

To install etcdv3, run the following command:

geminstalletcdv3

Establishing a connection

require'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.

Namespace support

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.

Adding, Fetching and Deleting Keys

# 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')

User Management

# Add Userconn.user_add('admin','secret')# Delete Userconn.user_delete('admin')# Get Userconn.user_get('admin')# List Usersconn.user_list

Role Management

# 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

Authentication Management

# Configure a root userconn.user_add('root','mysecretpassword')# Grant root role to root userconn.user_grant_role('root','root')# Enable Authenticationconn.auth_enable

After 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

Leases

# 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)

Transaction

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

# 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

Locks

# 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

Alarms

# List all active Alarmsconn.alarm_list# Deactivate ALL active Alarmsconn.alarm_deactivate

Timeouts

The 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.

Contributing

If you're looking to get involved, Fork the project and send pull requests.

About

Etcd v3 Ruby Client

Topics

Resources

Stars

55 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages