summaryrefslogtreecommitdiff
path: root/lib/chef_zero/endpoints/rest_object_endpoint.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chef_zero/endpoints/rest_object_endpoint.rb')
-rw-r--r--lib/chef_zero/endpoints/rest_object_endpoint.rb42
1 files changed, 36 insertions, 6 deletions
diff --git a/lib/chef_zero/endpoints/rest_object_endpoint.rb b/lib/chef_zero/endpoints/rest_object_endpoint.rb
index 9e978b4..efadf82 100644
--- a/lib/chef_zero/endpoints/rest_object_endpoint.rb
+++ b/lib/chef_zero/endpoints/rest_object_endpoint.rb
@@ -21,12 +21,11 @@ module ChefZero
def put(request)
# We grab the old body to trigger a 404 if it doesn't exist
old_body = get_data(request)
- request_json = FFI_Yajl::Parser.parse(request.body, :create_additions => false)
- key = identity_keys.map { |k| request_json[k] }.select { |v| v }.first
- key ||= request.rest_path[-1]
+
# If it's a rename, check for conflict and delete the old value
- rename = key != request.rest_path[-1]
- if rename
+ if is_rename?(request)
+ key = identity_key_value(request)
+
begin
create_data(request, request.rest_path[0..-2], key, request.body, :data_store_exceptions)
rescue DataStore::DataAlreadyExistsError
@@ -46,18 +45,49 @@ module ChefZero
already_json_response(200, populate_defaults(request, result))
end
- def patch_request_body(request)
+ # Merge the request body with the existing data, if one exists in
+ # the data store
+ #
+ # @param [ChefZero::RestRequest] request
+ # @param [Hash] options
+ # @option options [Symbol, Array<Symbol>] :except (nil) Key(s) from
+ # the existing data to discard
+ def patch_request_body(request, options={})
existing_value = get_data(request, nil, :nil)
+
if existing_value
request_json = FFI_Yajl::Parser.parse(request.body, :create_additions => false)
existing_json = FFI_Yajl::Parser.parse(existing_value, :create_additions => false)
+
+ if options[:except]
+ Array(options[:except]).each do |except_key|
+ existing_json.delete(except_key)
+ end
+ end
+
merged_json = existing_json.merge(request_json)
+
if merged_json.size > request_json.size
return FFI_Yajl::Encoder.encode(merged_json, :pretty => true)
end
end
+
request.body
end
+
+ private
+
+ # Get the value of the (first existing) identity key from the request body or nil
+ def identity_key_value(request)
+ request_json = FFI_Yajl::Parser.parse(request.body, :create_additions => false)
+ identity_keys.map { |k| request_json[k] }.compact.first
+ end
+
+ # Does this request change the value of the identity key?
+ def is_rename?(request)
+ return false unless key = identity_key_value(request)
+ key != request.rest_path[-1]
+ end
end
end
end