diff --git a/lib/diplomat/kv.rb b/lib/diplomat/kv.rb index 4e2b121..0db4498 100644 --- a/lib/diplomat/kv.rb +++ b/lib/diplomat/kv.rb @@ -11,11 +11,15 @@ class Kv < Diplomat::RestClient # @param options [Hash] the query params # @option options [String] :consistency The read consistency type # @option options [String] :dc Target datacenter + # @option options [String] :recurse indicates that we're performing a recursive get # @param not_found [Symbol] behaviour if the key doesn't exist; # :reject with exception, :return degenerate value, or :wait for it to appear # @param found [Symbol] behaviour if the key does exist; # :reject with exception, :return its current value, or :wait for its next value - # @return [String] The base64-decoded value associated with the key + # @return [String|Array] a string equal to the value if it was a regular get and there is + # a result, otherwise, an array of hashes, where the hash contains + # :key & :value entries. When nothing was found, either for a recursive + # search or for a regular one, we return an empty array # @note # When trying to access a key, there are two possibilites: # - The key doesn't (yet) exist @@ -42,6 +46,11 @@ def get key, options=nil, not_found=:reject, found=:return url += use_consistency(@options) url += dc(@options) + # We need to know if this is a recursive search so we know how to parse the output. But + # the user can invoke a recursive get in two ways: (1) by adding '?recurse' to the key + # string or by adding a {:recurse => true} to the options hash. + is_recurse = key.end_with?('?recurse') || ( options && options[:recurse] ) + # 404s OK using this connection raw = @conn_no_err.get concat_url url if raw.status == 404 @@ -60,7 +69,7 @@ def get key, options=nil, not_found=:reject, found=:return when :return @raw = raw parse_body - return return_value + return return_value is_recurse when :wait index = raw.headers["x-consul-index"] end @@ -75,7 +84,7 @@ def get key, options=nil, not_found=:reject, found=:return req.options.timeout = 86400 end parse_body - return_value + return_value is_recurse end # Associate a value with a key diff --git a/lib/diplomat/rest_client.rb b/lib/diplomat/rest_client.rb index 8a85df7..c15f630 100644 --- a/lib/diplomat/rest_client.rb +++ b/lib/diplomat/rest_client.rb @@ -75,8 +75,16 @@ def parse_body end # Get the key/value(s) from the raw output - def return_value - if @raw.count == 1 + # + # + # + # @param [bool] is_recurse, true if we're handling the result of a recursive search + # @returns [String|Array] a string equal to the value if it was a regular get and there is + # a result, otherwise, an array of hashes, where the hash contains + # :key & :value entries. When nothing was found, either for a recursive + # search or for a regular one, we return an empty array + def return_value is_recurse + if @raw.count == 1 && !is_recurse @value = @raw.first["Value"] @value = Base64.decode64(@value) unless @value.nil? else diff --git a/spec/kv_spec.rb b/spec/kv_spec.rb index 67c4a28..eb6fd49 100644 --- a/spec/kv_spec.rb +++ b/spec/kv_spec.rb @@ -50,6 +50,18 @@ { key: 'key', value: "toast" } ]) end + + it "Recursive GET with one response should return an array" do + json = JSON.generate([ + { + "Key" => key + 'dewfr', + "Value" => Base64.encode64(key_params), + "Flags" => 0 + }]) + faraday.stub(:get).and_return(OpenStruct.new({ status: 200, body: json })) + kv = Diplomat::Kv.new(faraday) + expect(kv.get("key", {:recurse=>true})).to eql([{ key: 'keydewfr', value: "toast" }]) + end end context "ACLs NOT enabled" do