Skip to content

Commit

Permalink
Converting data to a ruby hash (WeAreFarmGeek#95)
Browse files Browse the repository at this point in the history
* Adding the ability to specify the kv data to be returned as a ruby hash

* Fixing whitespace

* Updating readme

* Moving to_hash inside the class
  • Loading branch information
kendrickm authored and johnhamelink committed Oct 5, 2016
1 parent fe1efde commit effa540
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 2 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
- 2016-08-02 John Hamelink <[email protected]> Improve ACL and Event endpoints by uniformly raising an error for statuscodes which aren't 200.
- 2016-08-02 Sandstrom <[email protected]> Add documentation for listing all keys
- 2016-08-02 Alexander Vagin <[email protected]> Add state option to Health service
- 2016-08-02 John Hamelink <[email protected]> Removed Ruby 1.x support. Added check to raise error for ruby versions < 2.0.0
- 2016-08-02 John Hamelink <[email protected]> Removed Ruby 1.x support. Added check to raise error for ruby versions <
- 2016-07-27 Kendrick Martin <[email protected]> Added the ability to return k/v data as ruby hash

## 0.18.0

Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ foo = Diplomat::Kv.get('foo', :dc => 'dc-west')
```

You can also retrieve values recursively:

```ruby
Diplomat::Kv.put('foo/a', 'lorem')
Diplomat::Kv.put('foo/b', 'ipsum')
Expand All @@ -88,11 +87,21 @@ Diplomat::Kv.get('foo/', recurse: true)
# => [{:key=>"foo/a", :value=>"lorem"}, {:key=>"foo/b", :value=>"ipsum"}, {:key=>"foo/c", :value=>"dolor"}]
```


Or list all available keys:

```ruby
Diplomat::Kv.get('/', :keys => true) # => ['foo/a', 'foo/b']
```
You can convert the consul data to a ruby hash
```ruby
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"}}
```

### Nodes

Expand Down
4 changes: 4 additions & 0 deletions lib/diplomat/kv.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Kv < Diplomat::RestClient
# @option options [Boolean] :decode_values Return consul response with decoded values.
# @option options [String] :separator List only up to a given separator. Only applies when combined with :keys option.
# @option options [Boolean] :nil_values If to return keys/dirs with nil values
# @option options [Boolean] :convert_to_hash Take the data returned from consul and build a hash
# @option options [Callable] :transformation funnction to invoke on keys values
# @param not_found [Symbol] behaviour if the key doesn't exist;
# :reject with exception, :return degenerate value, or :wait for it to appear
Expand Down Expand Up @@ -81,6 +82,9 @@ def get key, options=nil, not_found=:reject, found=:return
if @options and @options[:decode_values]
return decode_values
end
if @options and @options[:convert_to_hash]
return convert_to_hash(return_value(return_nil_values, transformation))
end
return return_value(return_nil_values, transformation)
when :wait
index = raw.headers["x-consul-index"]
Expand Down
38 changes: 38 additions & 0 deletions lib/diplomat/rest_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,44 @@ def build_connection(api_connection, raise_error=false)
end
end

#Converts k/v data into ruby hash
def convert_to_hash(data)
collection = []
master = {}
data.each do |item|
split_up = item[:key].split ?/
sub_hash = {}
temp = nil
real_size = split_up.size - 1
for i in 0..real_size do
if i == 0
temp = {}
sub_hash[split_up[i]] = temp
next
end
if i == real_size
temp[split_up[i]] = item[:value]
else
new_h = {}
temp[split_up[i]] = new_h
temp = new_h
end
end
collection << sub_hash
end

collection.each do |h|
n = deep_merge(master, h)
master = n
end
master
end

def deep_merge(first, second)
merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
first.merge(second, &merger)
end

# Parse the body, apply it to the raw attribute
def parse_body
return JSON.parse(@raw.body) if @raw.status == 200
Expand Down
39 changes: 39 additions & 0 deletions spec/kv_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,45 @@
])
end
end

context "ACLs NOT enabled, recurse option ON, convert_to_hash option ON" do
let(:json) { JSON.generate([
{
"Key" => key + '/dewfr',
"Value" => Base64.encode64(key_params),
"Flags" => 0
},
{
"Key" => key,
"Value" => Base64.encode64(key_params),
"Flags" => 0
},
{
"Key" => key + '/iamnil',
"Value" => nil,
"Flags" => 0
}])
}

it "GET" do
faraday.stub(:get).and_return(OpenStruct.new({ status: 200, body: json }))
kv = Diplomat::Kv.new(faraday)
answer = {}
answer[key] = {}
answer[key]['dewfr'] = 'toast'
expect(kv.get(key, recurse: true, convert_to_hash: true)).to eql(answer)
end
it "GET with nil values" do
faraday.stub(:get).and_return(OpenStruct.new({ status: 200, body: json }))
kv = Diplomat::Kv.new(faraday)
answer = {}
answer[key] = {}
answer[key]['dewfr'] = 'toast'
answer[key]['iamnil'] = nil
expect(kv.get(key, recurse: true, convert_to_hash: true, nil_values: true)).to eql(answer)
end
end

context "ACLs NOT enabled, keys option ON" do
let(:json) { JSON.generate([ key, key + "ring", key + "tar" ]) }
it "GET" do
Expand Down

0 comments on commit effa540

Please sign in to comment.