WeAreFarmGeek/diplomat: A HTTP Ruby API for Consul

admin 0
WeAreFarmGeek/diplomat: A HTTP Ruby API for Consul

Build Status
Gem Version Gem Code Climate Inline docs

A HTTP Ruby API for Consul

Diplomacy Board Game


What’s Diplomat for?

Diplomat permits any ruby software to work together with Consul’s distributed key worth retailer, and in addition obtain details about companies at the moment accessible within the Consul cluster.

Does it work in rails?

Yup! In actual fact, we’re utilizing it in all of our rails manufacturing apps as a substitute of any earlier case the place it would be proper to make use of atmosphere variables in line with 12Issue configuration principals. This offers us the power to scale up with out making any modifications to the precise venture codebase, and to maneuver purposes across the cluster with ease.

This is what a manufacturing database.yml file would possibly appear to be:

<% if Rails.env.manufacturing? %>
  adapter:            postgresql
  encoding:           unicode
  host:               <%= Diplomat::Service.get('postgres').Handle %>
  database:           <%= Diplomat::Kv.get('venture/db/identify') %>
  pool:               5
  username:           <%= Diplomat::Kv.get('venture/db/person') %>
  password:           <%= Diplomat::Kv.get('venture/db/cross') %>
  port:               <%= Diplomat::Service.get('postgres').ServicePort %>
<% finish %>

Why would I exploit Consul over ZooKeeper, Doozerd, etcd, Nagios, Sensu, SmartStack, SkyDNS, Chef, Puppet, Ansible, and so on?

Learn up what makes Consul completely different right here

How do I set up Consul?

See right here. I managed to roll it out on my manufacturing machines with the assistance of Ansible in a single working day.

Which variations of Ruby does Diplomat assist? The place did my ruby 1.9 compatibility go?

Try GitHub Actions to see which variations of ruby we at the moment check after we’re making builds.

We have dropped ruby 1.9 assist. You’ll be able to nonetheless rely on Diplomat by instantly utilizing the ruby-1.9-compatible department on github, though be suggested it is not actively maintained anymore.

ERB templating

It’s attainable to inject diplomat information into .erb information (comparable to in chef), however you would additionally take a look at
consul-templaterb that’s extremely optimized for ERB templating
with very hello parallelism and good optimized efficiency for big clusters.


The hottest place to learn concerning the API is right here.

This is a number of examples of how diplomat works:

Key Values


Setting the worth of a key’s straightforward as pie:

foo = Diplomat::Kv.put('foo', 'bar')
# => "bar"


Getting the worth of a key’s simply as easy:

foo = Diplomat::Kv.get('foo')
# => "bar"

Or retrieve a price from one other datacenter:

foo = Diplomat::Kv.get('foo', :dc => 'dc-west')
# => "baz"

You may as well retrieve values recursively:

Diplomat::Kv.put('foo/a', 'lorem')
Diplomat::Kv.put('foo/b', 'ipsum')
Diplomat::Kv.put('foo/c', 'dolor')

Diplomat::Kv.get('foo/', recurse: true)
# => [{:key=>"foo/a", :value=>"lorem"}, {:key=>"foo/b", :value=>"ipsum"}, {:key=>"foo/c", :value=>"dolor"}]

You may as well use get_all to retrieve values recursively with a constant return sort:

Diplomat::Kv.put('foo/a', 'lorem')
Diplomat::Kv.put('foo/b', 'ipsum')
Diplomat::Kv.put('foo/c', 'dolor')

Diplomat::Kv.get('foo/', recurse: true)
# => [{:key=>"foo/a", :value=>"lorem"}, {:key=>"foo/b", :value=>"ipsum"}, {:key=>"foo/c", :value=>"dolor"}]
# => [{:key=>"foo/a", :value=>"lorem"}, {:key=>"foo/b", :value=>"ipsum"}, {:key=>"foo/c", :value=>"dolor"}]

Diplomat::Kv.put('bar/a', 'lorem')

Diplomat::Kv.get('bar/', recurse: true)
# => "lorem"
# => [{:key=>"bar/a", :value=>"lorem"}]

Or record all accessible keys:

Diplomat::Kv.get('/', :keys => true) # => ['foo/a', 'foo/b']

You’ll be able to convert the consul information to a ruby hash

Diplomat::Kv.put('foo/a', 'lorem')
Diplomat::Kv.put('foo/b', 'ipsum')
Diplomat::Kv.put('foo/c', 'dolor')

Diplomat::Kv.get('foo/', recurse: true, convert_to_hash: true)
# => {"foo"=>{"a"=>"lorem", "b"=>"ipsum", "c"=>"dolor"}}



Lookup a node:

foo_service = Diplomat::Node.get('foo')
# => {"Node"=>{"Node"=>"foobar", "Handle"=>""}, "Providers"=>{"consul"=>{"ID"=>"consul", "Service"=>"consul", "Tags"=>nil, "Port"=>8300}, "redis"=>{"ID"=>"redis", "Service"=>"redis", "Tags"=>["v1"], "Port"=>8000}}}

Get all nodes:

nodes = Diplomat::Node.get_all
# => [#, #]

Get all nodes for a specific datacenter

nodes = Diplomat::Node.get_all({ :dc => 'My_Datacenter' })
# => [#, #]

Register a node:

Diplomat::Node.register({ :Node => "app1", :Handle => "" })
# => true

De-register a node:

Diplomat::Node.deregister({ :Node => "app1", :Handle => "" })
# => true



Wanting up a service is simple as pie:

foo_service = Diplomat::Service.get('foo')
# => #

Or in case you have a number of nodes per service:

foo_service = Diplomat::Service.get('foo', :all)
# => [#,#]

Or if you wish to discover companies for a specific datacenter

foo_service = Diplomat::Service.get('foo', :all, { :dc => 'My_Datacenter'})
# => [#,#]

In case you want to record all of the companies on consul:

companies = Diplomat::Service.get_all
# => #

In case you want to record all of the companies for a particular datacenter:

companies = Diplomat::Service.get_all({ :dc => 'My_Datacenter' })
# => #


Getting a listing of datacenters is kind of easy and offers you the choice to extract all companies out of
all accessible datacenters if it’s essential.

datacenters = Diplomat::Datacenter.get()
# => ["DC1", "DC2"]


Making a session:

sessionid = Diplomat::Session.create({:Node => "server1", :Title => "my-lock"})
# => "fc5ca01a-c317-39ea-05e8-221da00d3a12"

Or destroying a session:


Renew a session:


Record periods:

Diplomat::Session.record.every {|session| places "#{session["ID"]} #{session["Name"]}"}


Purchase a lock:

sessionid = Diplomat::Session.create({:Node => "server1", :Title => "my-lock"})
lock_acquired = Diplomat::Lock.purchase("/key/to/lock", sessionid)
# => true

Or look ahead to a lock to be acquired:

sessionid = Diplomat::Session.create({:hostname => "server1", :ipaddress => ""})
lock_acquired = Diplomat::Lock.wait_to_acquire("/key/to/lock", sessionid)

Launch a lock:

Diplomat::Lock.launch("/key/to/lock", sessionid )


Fireplace an occasion:

Diplomat::Occasion.fireplace('do_something', 'payload')

Record all occasions with a sure identify obtained by the native agent:


Get the newest occasion with a sure identify obtained by the native agent:


Iterate by way of the occasions with a sure identify obtained by the native agent:

occasions = Enumerator.new do |y|
  ret = {token: :first}
  whereas ret = start Diplomat::Occasion.get('do_something', ret[:token], :reject) rescue nil finish

occasions.every places e 


Returns details about the standing of the Consul cluster.

Get the raft chief for the datacenter wherein the native consul agent is working


Get an array of Raft friends for the datacenter wherein the agent is working


Returns details about the autopilot configuration of the Consul cluster

Get the present autopilot configuration


Get the well being standing from autopilot


Upkeep mode

Allow upkeep mode on a bunch, with non-obligatory cause and DC (requires entry to native agent)

Diplomat::Upkeep.allow(true, 'doing stuff', :dc => 'abc')

Decide if a bunch has upkeep mode enabled

# => { :enabled => true, :cause => 'doing stuff' }

Customized configuration

You’ll be able to create a customized configuration utilizing the next syntax:

Diplomat.configure do |config|
  # Arrange a customized Consul URL
  config.url = "http://localhost:8888"
  # Arrange a customized Faraday Middleware
  config.middleware = MyCustomMiddleware
  # Set additional Faraday configuration choices and customized entry token (ACL)
  config.choices = {ssl: {model: :TLSv1_2}, headers: {"X-Consul-Token" => "xxxxxxxx-yyyy-zzzz-1111-222222222222"}}

That is historically saved contained in the config/initializers listing for those who’re utilizing rails. The middleware means that you can customise what occurs when faraday sends and receives information. This may be helpful if you wish to instrument your use of diplomat, for instance. You’ll be able to learn extra about Faraday’s customized middleware right here.

Alternatively, configuration settings might be overriden at every methodology name permitting as an example to handle completely different consul brokers, with another token.

Diplomat::Service.get('foo', { http_addr: 'http://consu01:8500' })
Diplomat::Service.get('foo', { http_addr: 'http://consu02:8500' })
Diplomat::Kv.put('key/path', 'worth', { http_addr: 'http://localhost:8500', dc: 'dc1', token: '111-222-333-444-555' })

Commonest choices are:

  • dc: goal datacenter
  • token: id used to carry out the corresponding motion
  • http_addr: to focus on a distant consul node
  • stale: use consistency mode that enables any server to service the learn no matter whether or not it’s the chief


Get pleasure from!

Photo Copyright

Leave a Reply

Your email address will not be published. Required fields are marked *