summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/chef_zero/endpoints/authenticate_user_endpoint.rb8
-rw-r--r--lib/chef_zero/endpoints/cookbook_endpoint.rb8
-rw-r--r--lib/chef_zero/endpoints/cookbook_version_endpoint.rb31
-rw-r--r--lib/chef_zero/endpoints/cookbooks_base.rb11
-rw-r--r--lib/chef_zero/endpoints/cookbooks_endpoint.rb2
-rw-r--r--lib/chef_zero/endpoints/data_bag_endpoint.rb7
-rw-r--r--lib/chef_zero/endpoints/data_bags_endpoint.rb5
-rw-r--r--lib/chef_zero/endpoints/environment_cookbook_endpoint.rb4
-rw-r--r--lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb24
-rw-r--r--lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb2
-rw-r--r--lib/chef_zero/endpoints/environment_nodes_endpoint.rb4
-rw-r--r--lib/chef_zero/endpoints/environment_recipes_endpoint.rb4
-rw-r--r--lib/chef_zero/endpoints/environment_role_endpoint.rb1
-rw-r--r--lib/chef_zero/endpoints/file_store_file_endpoint.rb2
-rw-r--r--lib/chef_zero/endpoints/principal_endpoint.rb4
-rw-r--r--lib/chef_zero/endpoints/rest_list_endpoint.rb7
-rw-r--r--lib/chef_zero/endpoints/rest_object_endpoint.rb22
-rw-r--r--lib/chef_zero/endpoints/sandbox_endpoint.rb8
-rw-r--r--lib/chef_zero/endpoints/sandboxes_endpoint.rb13
-rw-r--r--lib/chef_zero/endpoints/search_endpoint.rb16
-rw-r--r--lib/chef_zero/endpoints/searches_endpoint.rb2
-rw-r--r--lib/chef_zero/rest_base.rb60
-rw-r--r--lib/chef_zero/server.rb56
23 files changed, 176 insertions, 125 deletions
diff --git a/lib/chef_zero/endpoints/authenticate_user_endpoint.rb b/lib/chef_zero/endpoints/authenticate_user_endpoint.rb
index ce044c7..37e56a9 100644
--- a/lib/chef_zero/endpoints/authenticate_user_endpoint.rb
+++ b/lib/chef_zero/endpoints/authenticate_user_endpoint.rb
@@ -9,8 +9,12 @@ module ChefZero
request_json = JSON.parse(request.body, :create_additions => false)
name = request_json['name']
password = request_json['password']
- user = data['users'][name]
- verified = user && JSON.parse(user, :create_additions => false)['password'] == password
+ begin
+ user = data_store.get(['users', name])
+ verified = JSON.parse(user, :create_additions => false)['password'] == password
+ rescue DataStore::DataNotFoundError
+ verified = false
+ end
json_response(200, {
'name' => name,
'verified' => !!verified
diff --git a/lib/chef_zero/endpoints/cookbook_endpoint.rb b/lib/chef_zero/endpoints/cookbook_endpoint.rb
index d910e9c..215a21e 100644
--- a/lib/chef_zero/endpoints/cookbook_endpoint.rb
+++ b/lib/chef_zero/endpoints/cookbook_endpoint.rb
@@ -9,7 +9,7 @@ module ChefZero
case filter
when '_latest'
result = {}
- filter_cookbooks(data['cookbooks'], {}, 1) do |name, versions|
+ filter_cookbooks(all_cookbooks_list, {}, 1) do |name, versions|
if versions.size > 0
result[name] = build_uri(request.base_uri, ['cookbooks', name, versions[0]])
end
@@ -17,15 +17,15 @@ module ChefZero
json_response(200, result)
when '_recipes'
result = []
- filter_cookbooks(data['cookbooks'], {}, 1) do |name, versions|
+ filter_cookbooks(all_cookbooks_list, {}, 1) do |name, versions|
if versions.size > 0
- cookbook = JSON.parse(data['cookbooks'][name][versions[0]], :create_additions => false)
+ cookbook = JSON.parse(get_data(['cookbooks', name, versions[0]]), :create_additions => false)
result += recipe_names(name, cookbook)
end
end
json_response(200, result.sort)
else
- cookbook_list = { filter => get_data(request, request.rest_path) }
+ cookbook_list = { filter => list_data(request, request.rest_path) }
json_response(200, format_cookbooks_list(request, cookbook_list))
end
end
diff --git a/lib/chef_zero/endpoints/cookbook_version_endpoint.rb b/lib/chef_zero/endpoints/cookbook_version_endpoint.rb
index 0cde0ec..c9a115a 100644
--- a/lib/chef_zero/endpoints/cookbook_version_endpoint.rb
+++ b/lib/chef_zero/endpoints/cookbook_version_endpoint.rb
@@ -9,7 +9,7 @@ module ChefZero
class CookbookVersionEndpoint < RestObjectEndpoint
def get(request)
if request.rest_path[2] == "_latest" || request.rest_path[2] == "latest"
- request.rest_path[2] = latest_version(get_data(request, request.rest_path[0..1]).keys)
+ request.rest_path[2] = latest_version(list_data(request, request.rest_path[0..1]))
end
super(request)
end
@@ -17,9 +17,8 @@ module ChefZero
def put(request)
name = request.rest_path[1]
version = request.rest_path[2]
- data['cookbooks'][name] = {} if !data['cookbooks'][name]
- existing_cookbook = data['cookbooks'][name][version]
-
+ existing_cookbook = get_data(request, request.rest_path, :nil)
+
# Honor frozen
if existing_cookbook
existing_cookbook_json = JSON.parse(existing_cookbook, :create_additions => false)
@@ -37,7 +36,7 @@ module ChefZero
end
# Set the cookbook
- data['cookbooks'][name][version] = request.body
+ set_data(request, ['cookbooks', name, version], request.body, :create_dir, :create)
# If the cookbook was updated, check for deleted files and clean them up
if existing_cookbook
@@ -47,18 +46,22 @@ module ChefZero
end
end
- already_json_response(existing_cookbook ? 200 : 201, populate_defaults(request, data['cookbooks'][name][version]))
+ already_json_response(existing_cookbook ? 200 : 201, populate_defaults(request, request.body))
end
def delete(request)
if request.rest_path[2] == "_latest" || request.rest_path[2] == "latest"
- request.rest_path[2] = latest_version(get_data(request, request.rest_path[0..1]).keys)
+ request.rest_path[2] = latest_version(list_data(request, request.rest_path[0..1]))
end
- deleted_cookbook = get_data(request, request.rest_path)
+ deleted_cookbook = get_data(request)
response = super(request)
cookbook_name = request.rest_path[1]
- data['cookbooks'].delete(cookbook_name) if data['cookbooks'][cookbook_name].size == 0
+ begin
+ data_store.delete(['cookbooks', cookbook_name]) if data_store.list(['cookbooks', cookbook_name]).size == 0
+ rescue DataStore::DataNotFoundError
+ # This is just a race.
+ end
# Hoover deleted files, if they exist
hoover_unused_checksums(get_checksums(deleted_cookbook))
@@ -79,14 +82,18 @@ module ChefZero
result
end
+ private
+
def hoover_unused_checksums(deleted_checksums)
- data['cookbooks'].each_pair do |cookbook_name, versions|
- versions.each_pair do |cookbook_version, cookbook|
+ data_store.list(['cookbooks']).each do |cookbook_name|
+ data_store.list(['cookbooks', cookbook_name]).each do |version|
+ cookbook = data_store.get(['cookbooks', cookbook_name, version])
deleted_checksums = deleted_checksums - get_checksums(cookbook)
end
end
deleted_checksums.each do |checksum|
- data['file_store'].delete(checksum)
+ # There can be a race here if multiple cookbooks are uploading.
+ data_store.delete(['file_store', checksum])
end
end
diff --git a/lib/chef_zero/endpoints/cookbooks_base.rb b/lib/chef_zero/endpoints/cookbooks_base.rb
index 68db3a1..2df1dde 100644
--- a/lib/chef_zero/endpoints/cookbooks_base.rb
+++ b/lib/chef_zero/endpoints/cookbooks_base.rb
@@ -23,11 +23,20 @@ module ChefZero
results
end
+ def all_cookbooks_list
+ result = {}
+ # Race conditions exist here (if someone deletes while listing). I don't care.
+ data_store.list(['cookbooks']).each do |name|
+ result[name] = data_store.list(['cookbooks', name])
+ end
+ result
+ end
+
def filter_cookbooks(cookbooks_list, constraints = {}, num_versions = nil)
cookbooks_list.keys.sort.each do |name|
constraint = Gem::Requirement.new(constraints[name])
versions = []
- cookbooks_list[name].keys.sort_by { |version| Gem::Version.new(version.dup) }.reverse.each do |version|
+ cookbooks_list[name].sort_by { |version| Gem::Version.new(version.dup) }.reverse.each do |version|
break if num_versions && versions.size >= num_versions
if constraint.satisfied_by?(Gem::Version.new(version.dup))
versions << version
diff --git a/lib/chef_zero/endpoints/cookbooks_endpoint.rb b/lib/chef_zero/endpoints/cookbooks_endpoint.rb
index a595718..587862d 100644
--- a/lib/chef_zero/endpoints/cookbooks_endpoint.rb
+++ b/lib/chef_zero/endpoints/cookbooks_endpoint.rb
@@ -5,7 +5,7 @@ module ChefZero
# /cookbooks
class CookbooksEndpoint < CookbooksBase
def get(request)
- json_response(200, format_cookbooks_list(request, data['cookbooks']))
+ json_response(200, format_cookbooks_list(request, all_cookbooks_list))
end
end
end
diff --git a/lib/chef_zero/endpoints/data_bag_endpoint.rb b/lib/chef_zero/endpoints/data_bag_endpoint.rb
index 6f3d204..9287d8d 100644
--- a/lib/chef_zero/endpoints/data_bag_endpoint.rb
+++ b/lib/chef_zero/endpoints/data_bag_endpoint.rb
@@ -32,12 +32,7 @@ module ChefZero
def delete(request)
key = request.rest_path[1]
- container = data['data']
- if !container.has_key?(key)
- raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
- end
- result = container[key]
- container.delete(key)
+ delete_data(request)
json_response(200, {
'chef_type' => 'data_bag',
'json_class' => 'Chef::DataBag',
diff --git a/lib/chef_zero/endpoints/data_bags_endpoint.rb b/lib/chef_zero/endpoints/data_bags_endpoint.rb
index b400fda..f1bb6a8 100644
--- a/lib/chef_zero/endpoints/data_bags_endpoint.rb
+++ b/lib/chef_zero/endpoints/data_bags_endpoint.rb
@@ -6,15 +6,14 @@ module ChefZero
# /data
class DataBagsEndpoint < RestListEndpoint
def post(request)
- container = get_data(request)
contents = request.body
name = JSON.parse(contents, :create_additions => false)[identity_key]
if name.nil?
error(400, "Must specify '#{identity_key}' in JSON")
- elsif container[name]
+ elsif exists_data?(request, ['data', name])
error(409, "Object already exists")
else
- container[name] = {}
+ data_store.create_dir(['data'], name, :keep_existing)
json_response(201, {"uri" => "#{build_uri(request.base_uri, request.rest_path + [name])}"})
end
end
diff --git a/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb b/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb
index 3360cd5..f9bb6b1 100644
--- a/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb
+++ b/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb
@@ -9,7 +9,7 @@ module ChefZero
cookbook_name = request.rest_path[3]
environment = JSON.parse(get_data(request, request.rest_path[0..1]), :create_additions => false)
constraints = environment['cookbook_versions'] || {}
- cookbook = get_data(request, request.rest_path[2..3])
+ cookbook_versions = list_data(request, request.rest_path[2..3])
if request.query_params['num_versions'] == 'all'
num_versions = nil
elsif request.query_params['num_versions']
@@ -17,7 +17,7 @@ module ChefZero
else
num_versions = nil
end
- json_response(200, format_cookbooks_list(request, { cookbook_name => cookbook }, constraints, num_versions))
+ json_response(200, format_cookbooks_list(request, { cookbook_name => cookbook_versions }, constraints, num_versions))
end
end
end
diff --git a/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb b/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb
index 2874e47..5ce8afb 100644
--- a/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb
+++ b/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb
@@ -6,27 +6,21 @@ module ChefZero
module Endpoints
# /environments/NAME/cookbook_versions
class EnvironmentCookbookVersionsEndpoint < RestBase
- def cookbooks
- data['cookbooks']
- end
-
- def environments
- data['environments']
- end
-
def post(request)
+ cookbook_names = list_data(request, ['cookbooks'])
+
# Get the list of cookbooks and versions desired by the runlist
desired_versions = {}
run_list = JSON.parse(request.body, :create_additions => false)['run_list']
run_list.each do |run_list_entry|
if run_list_entry =~ /(.+)(::.+)?\@(.+)/
- raise RestErrorResponse.new(412, "No such cookbook: #{$1}") if !cookbooks[$1]
- raise RestErrorResponse.new(412, "No such cookbook version for cookbook #{$1}: #{$2}") if !cookbooks[$1][$2]
+ raise RestErrorResponse.new(412, "No such cookbook: #{$1}") if !cookbook_names.include?($1)
+ raise RestErrorResponse.new(412, "No such cookbook version for cookbook #{$1}: #{$3}") if !list_data(request, ['cookbooks', $1]).include?($3)
desired_versions[$1] = [ $3 ]
else
desired_cookbook = run_list_entry.split('::')[0]
- raise RestErrorResponse.new(412, "No such cookbook: #{desired_cookbook}") if !cookbooks[desired_cookbook]
- desired_versions[desired_cookbook] = cookbooks[desired_cookbook].keys
+ raise RestErrorResponse.new(412, "No such cookbook: #{desired_cookbook}") if !cookbook_names.include?(desired_cookbook)
+ desired_versions[desired_cookbook] = list_data(request, ['cookbooks', desired_cookbook])
end
end
@@ -46,7 +40,7 @@ module ChefZero
result = {}
solved.each_pair do |name, versions|
- cookbook = JSON.parse(data['cookbooks'][name][versions[0]], :create_additions => false)
+ cookbook = JSON.parse(get_data(request, ['cookbooks', name, versions[0]]), :create_additions => false)
result[name] = DataNormalizer.normalize_cookbook(cookbook, name, versions[0], request.base_uri, 'GET')
end
json_response(200, result)
@@ -67,7 +61,7 @@ module ChefZero
new_unsolved = unsolved[1..-1]
# Pick this cookbook, and add dependencies
- cookbook_obj = JSON.parse(cookbooks[solve_for][desired_version], :create_additions => false)
+ cookbook_obj = JSON.parse(get_data(request, ['cookbooks', solve_for, desired_version]), create_additions => false)
cookbook_metadata = cookbook_obj['metadata'] || {}
cookbook_dependencies = cookbook_metadata['dependencies'] || {}
dep_not_found = false
@@ -81,7 +75,7 @@ module ChefZero
dep_not_found = true
break
end
- new_desired_versions[dep_name] = cookbooks[dep_name].keys
+ new_desired_versions[dep_name] = list_data(request, ['cookbooks', dep_name])
new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, environment_constraints[dep_name])
end
new_desired_versions = filter_by_constraint(new_desired_versions, dep_name, dep_constraint)
diff --git a/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb b/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb
index 591f43f..1222b94 100644
--- a/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb
+++ b/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb
@@ -15,7 +15,7 @@ module ChefZero
else
num_versions = 1
end
- json_response(200, format_cookbooks_list(request, data['cookbooks'], constraints, num_versions))
+ json_response(200, format_cookbooks_list(request, all_cookbooks_list, constraints, num_versions))
end
end
end
diff --git a/lib/chef_zero/endpoints/environment_nodes_endpoint.rb b/lib/chef_zero/endpoints/environment_nodes_endpoint.rb
index 31a4044..6d0ca76 100644
--- a/lib/chef_zero/endpoints/environment_nodes_endpoint.rb
+++ b/lib/chef_zero/endpoints/environment_nodes_endpoint.rb
@@ -10,8 +10,8 @@ module ChefZero
get_data(request, request.rest_path[0..1])
result = {}
- data['nodes'].each_pair do |name, node|
- node_json = JSON.parse(node, :create_additions => false)
+ list_data(request, ['nodes']).each do |name|
+ node = JSON.parse(get_data(request, ['nodes', name]), :create_additions => false)
if node['chef_environment'] == request.rest_path[1]
result[name] = build_uri(request.base_uri, 'nodes', name)
end
diff --git a/lib/chef_zero/endpoints/environment_recipes_endpoint.rb b/lib/chef_zero/endpoints/environment_recipes_endpoint.rb
index 0bbaa8b..67d48f3 100644
--- a/lib/chef_zero/endpoints/environment_recipes_endpoint.rb
+++ b/lib/chef_zero/endpoints/environment_recipes_endpoint.rb
@@ -9,9 +9,9 @@ module ChefZero
environment = JSON.parse(get_data(request, request.rest_path[0..1]), :create_additions => false)
constraints = environment['cookbook_versions'] || {}
result = []
- filter_cookbooks(data['cookbooks'], constraints, 1) do |name, versions|
+ filter_cookbooks(all_cookbooks_list, constraints, 1) do |name, versions|
if versions.size > 0
- cookbook = JSON.parse(data['cookbooks'][name][versions[0]], :create_additions => false)
+ cookbook = JSON.parse(get_data(request, ['cookbooks', name, versions[0]]), :create_additions => false)
result += recipe_names(name, cookbook)
end
end
diff --git a/lib/chef_zero/endpoints/environment_role_endpoint.rb b/lib/chef_zero/endpoints/environment_role_endpoint.rb
index 94be3ab..474376b 100644
--- a/lib/chef_zero/endpoints/environment_role_endpoint.rb
+++ b/lib/chef_zero/endpoints/environment_role_endpoint.rb
@@ -15,6 +15,7 @@ module ChefZero
environment_path = request.rest_path[2..3]
role_path = request.rest_path[0..1]
end
+ # Verify that the environment exists
get_data(request, environment_path)
role = JSON.parse(get_data(request, role_path), :create_additions => false)
diff --git a/lib/chef_zero/endpoints/file_store_file_endpoint.rb b/lib/chef_zero/endpoints/file_store_file_endpoint.rb
index 98cea4d..fdae771 100644
--- a/lib/chef_zero/endpoints/file_store_file_endpoint.rb
+++ b/lib/chef_zero/endpoints/file_store_file_endpoint.rb
@@ -14,7 +14,7 @@ module ChefZero
end
def put(request)
- data['file_store'][request.rest_path[1]] = request.body
+ data_store.set(request.rest_path, request.body, :create)
json_response(200, {})
end
end
diff --git a/lib/chef_zero/endpoints/principal_endpoint.rb b/lib/chef_zero/endpoints/principal_endpoint.rb
index 1833592..dde9219 100644
--- a/lib/chef_zero/endpoints/principal_endpoint.rb
+++ b/lib/chef_zero/endpoints/principal_endpoint.rb
@@ -8,11 +8,11 @@ module ChefZero
class PrincipalEndpoint < RestBase
def get(request)
name = request.rest_path[-1]
- json = data['users'][name]
+ json = get_data(request, [ 'users', name ], :nil)
if json
type = 'user'
else
- json = data['clients'][name]
+ json = get_data(request, [ 'clients', name ], :nil)
type = 'client'
end
if json
diff --git a/lib/chef_zero/endpoints/rest_list_endpoint.rb b/lib/chef_zero/endpoints/rest_list_endpoint.rb
index 6cdf739..4fa277b 100644
--- a/lib/chef_zero/endpoints/rest_list_endpoint.rb
+++ b/lib/chef_zero/endpoints/rest_list_endpoint.rb
@@ -15,22 +15,19 @@ module ChefZero
def get(request)
# Get the result
result_hash = {}
- get_data(request).keys.sort.each do |name|
+ list_data(request).sort.each do |name|
result_hash[name] = "#{build_uri(request.base_uri, request.rest_path + [name])}"
end
json_response(200, result_hash)
end
def post(request)
- container = get_data(request)
contents = request.body
key = get_key(contents)
if key.nil?
error(400, "Must specify '#{identity_key}' in JSON")
- elsif container[key]
- error(409, 'Object already exists')
else
- container[key] = contents
+ create_data(request, request.rest_path, key, contents)
json_response(201, {'uri' => "#{build_uri(request.base_uri, request.rest_path + [key])}"})
end
end
diff --git a/lib/chef_zero/endpoints/rest_object_endpoint.rb b/lib/chef_zero/endpoints/rest_object_endpoint.rb
index bd45afe..f301a99 100644
--- a/lib/chef_zero/endpoints/rest_object_endpoint.rb
+++ b/lib/chef_zero/endpoints/rest_object_endpoint.rb
@@ -22,33 +22,29 @@ module ChefZero
old_body = get_data(request)
request_json = JSON.parse(request.body, :create_additions => false)
key = request_json[identity_key] || request.rest_path[-1]
- container = get_data(request, request.rest_path[0..-2])
# If it's a rename, check for conflict and delete the old value
rename = key != request.rest_path[-1]
if rename
- if container.has_key?(key)
+ begin
+ data_store.create(request.rest_path[0..-2] + [key], request.body)
+ rescue DataStore::DataAlreadyExistsError
return error(409, "Cannot rename '#{request.rest_path[-1]}' to '#{key}': '#{key}' already exists")
end
- container.delete(request.rest_path[-1])
+ delete_data(request)
+ else
+ set_data(request, request.rest_path, request.body)
end
- container[key] = request.body
already_json_response(200, populate_defaults(request, request.body))
end
def delete(request)
- key = request.rest_path[-1]
- container = get_data(request, request.rest_path[0..-2])
- if !container.has_key?(key)
- raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
- end
- result = container[key]
- container.delete(key)
+ result = get_data(request)
+ delete_data(request)
already_json_response(200, populate_defaults(request, result))
end
def patch_request_body(request)
- container = get_data(request, request.rest_path[0..-2])
- existing_value = container[request.rest_path[-1]]
+ existing_value = get_data(request, nil, :nil)
if existing_value
request_json = JSON.parse(request.body, :create_additions => false)
existing_json = JSON.parse(existing_value, :create_additions => false)
diff --git a/lib/chef_zero/endpoints/sandbox_endpoint.rb b/lib/chef_zero/endpoints/sandbox_endpoint.rb
index 09cb180..680f0ef 100644
--- a/lib/chef_zero/endpoints/sandbox_endpoint.rb
+++ b/lib/chef_zero/endpoints/sandbox_endpoint.rb
@@ -5,15 +5,13 @@ module ChefZero
# /sandboxes/ID
class SandboxEndpoint < RestBase
def put(request)
- existing_sandbox = get_data(request, request.rest_path)
- data['sandboxes'].delete(request.rest_path[1])
- time_str = existing_sandbox[:create_time].strftime('%Y-%m-%dT%H:%M:%S%z')
- time_str = "#{time_str[0..21]}:#{time_str[22..23]}"
+ existing_sandbox = JSON.parse(get_data(request), :create_additions => false)
+ delete_data(request)
json_response(200, {
:guid => request.rest_path[1],
:name => request.rest_path[1],
:checksums => existing_sandbox[:checksums],
- :create_time => time_str,
+ :create_time => existing_sandbox[:create_time],
:is_completed => true
})
end
diff --git a/lib/chef_zero/endpoints/sandboxes_endpoint.rb b/lib/chef_zero/endpoints/sandboxes_endpoint.rb
index 698564f..561c94f 100644
--- a/lib/chef_zero/endpoints/sandboxes_endpoint.rb
+++ b/lib/chef_zero/endpoints/sandboxes_endpoint.rb
@@ -16,7 +16,7 @@ module ChefZero
needed_checksums = JSON.parse(request.body, :create_additions => false)['checksums']
result_checksums = {}
needed_checksums.keys.each do |needed_checksum|
- if data['file_store'].has_key?(needed_checksum)
+ if list_data(request, ['file_store']).include?(needed_checksum)
result_checksums[needed_checksum] = { :needs_upload => false }
else
result_checksums[needed_checksum] = {
@@ -27,13 +27,20 @@ module ChefZero
end
end
+ # There is an obvious race condition here.
id = @next_id.to_s
@next_id+=1
- data['sandboxes'][id] = { :create_time => Time.now.utc, :checksums => sandbox_checksums }
+ time_str = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%S%z')
+ time_str = "#{time_str[0..21]}:#{time_str[22..23]}"
+
+ create_data(request, request.rest_path, id, JSON.pretty_generate({
+ :create_time => time_str,
+ :checksums => sandbox_checksums
+ }))
json_response(201, {
- :uri => build_uri(request.base_uri, request.rest_path + [id.to_s]),
+ :uri => build_uri(request.base_uri, request.rest_path + [id]),
:checksums => result_checksums,
:sandbox_id => id
})
diff --git a/lib/chef_zero/endpoints/search_endpoint.rb b/lib/chef_zero/endpoints/search_endpoint.rb
index 4440c7a..d698b45 100644
--- a/lib/chef_zero/endpoints/search_endpoint.rb
+++ b/lib/chef_zero/endpoints/search_endpoint.rb
@@ -48,15 +48,15 @@ module ChefZero
def search_container(request, index)
case index
when 'client'
- [ data['clients'], Proc.new { |client, name| DataNormalizer.normalize_client(client, name) }, build_uri(request.base_uri, [ 'clients' ]) ]
+ [ ['clients'], Proc.new { |client, name| DataNormalizer.normalize_client(client, name) }, build_uri(request.base_uri, [ 'clients' ]) ]
when 'node'
- [ data['nodes'], Proc.new { |node, name| DataNormalizer.normalize_node(node, name) }, build_uri(request.base_uri, [ 'nodes' ]) ]
+ [ ['nodes'], Proc.new { |node, name| DataNormalizer.normalize_node(node, name) }, build_uri(request.base_uri, [ 'nodes' ]) ]
when 'environment'
- [ data['environments'], Proc.new { |environment, name| DataNormalizer.normalize_environment(environment, name) }, build_uri(request.base_uri, [ 'environments' ]) ]
+ [ ['environments'], Proc.new { |environment, name| DataNormalizer.normalize_environment(environment, name) }, build_uri(request.base_uri, [ 'environments' ]) ]
when 'role'
- [ data['roles'], Proc.new { |role, name| DataNormalizer.normalize_role(role, name) }, build_uri(request.base_uri, [ 'roles' ]) ]
+ [ ['roles'], Proc.new { |role, name| DataNormalizer.normalize_role(role, name) }, build_uri(request.base_uri, [ 'roles' ]) ]
else
- [ data['data'][index], Proc.new { |data_bag_item, id| DataNormalizer.normalize_data_bag_item(data_bag_item, index, id, 'DELETE') }, build_uri(request.base_uri, [ 'data', index ]) ]
+ [ ['data', index], Proc.new { |data_bag_item, id| DataNormalizer.normalize_data_bag_item(data_bag_item, index, id, 'DELETE') }, build_uri(request.base_uri, [ 'data', index ]) ]
end
end
@@ -101,13 +101,11 @@ module ChefZero
# Get the search container
container, expander, base_uri = search_container(request, index)
- if container.nil?
- raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
- end
# Search!
result = []
- container.each_pair do |name,value|
+ list_data(request, container).each do |name|
+ value = get_data(request, container + [name])
expanded = expander.call(JSON.parse(value, :create_additions => false), name)
result << [ name, build_uri(base_uri, [name]), expanded, expand_for_indexing(expanded, index, name) ]
end
diff --git a/lib/chef_zero/endpoints/searches_endpoint.rb b/lib/chef_zero/endpoints/searches_endpoint.rb
index d7ab451..dabe164 100644
--- a/lib/chef_zero/endpoints/searches_endpoint.rb
+++ b/lib/chef_zero/endpoints/searches_endpoint.rb
@@ -7,7 +7,7 @@ module ChefZero
def get(request)
# Get the result
result_hash = {}
- indices = (%w(client environment node role) + data['data'].keys).sort
+ indices = (%w(client environment node role) + data_store.list(['data'])).sort
indices.each do |index|
result_hash[index] = build_uri(request.base_uri, request.rest_path + [index])
end
diff --git a/lib/chef_zero/rest_base.rb b/lib/chef_zero/rest_base.rb
index f219ff1..5371a0a 100644
--- a/lib/chef_zero/rest_base.rb
+++ b/lib/chef_zero/rest_base.rb
@@ -1,5 +1,6 @@
require 'chef_zero/rest_request'
require 'chef_zero/rest_error_response'
+require 'chef_zero/data_store/data_not_found_error'
module ChefZero
class RestBase
@@ -9,8 +10,8 @@ module ChefZero
attr_reader :server
- def data
- server.data
+ def data_store
+ server.data_store
end
def call(request)
@@ -35,17 +36,58 @@ module ChefZero
true
end
- def get_data(request, rest_path=nil)
+ def get_data(request, rest_path=nil, *options)
rest_path ||= request.rest_path
- # Grab the value we're looking for
- value = data
- rest_path.each do |path_part|
- if !value.has_key?(path_part)
+ begin
+ data_store.get(rest_path)
+ rescue DataStore::DataNotFoundError
+ if options.include?(:nil)
+ nil
+ else
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
end
- value = value[path_part]
end
- value
+ end
+
+ def list_data(request, rest_path=nil)
+ rest_path ||= request.rest_path
+ begin
+ data_store.list(rest_path)
+ rescue DataStore::DataNotFoundError
+ raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
+ end
+ end
+
+ def delete_data(request, rest_path=nil)
+ rest_path ||= request.rest_path
+ begin
+ data_store.delete(rest_path)
+ rescue DataStore::DataNotFoundError
+ raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
+ end
+ end
+
+ def set_data(request, rest_path, data, *options)
+ rest_path ||= request.rest_path
+ begin
+ data_store.set(rest_path, request.body, *options)
+ rescue DataStore::DataNotFoundError
+ raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
+ end
+ end
+
+ def create_data(request, rest_path, name, data, *options)
+ rest_path ||= request.rest_path
+ begin
+ data_store.create(rest_path, name, data, *options)
+ rescue DataStore::DataAlreadyExistsError
+ raise RestErrorResponse.new(409, "Object already exists: #{build_uri(request.base_uri, request.rest_path + [name])}")
+ end
+ end
+
+ def exists_data?(request, rest_path=nil)
+ rest_path ||= request.rest_path
+ data_store.exists?(rest_path)
end
def error(response_code, error)
diff --git a/lib/chef_zero/server.rb b/lib/chef_zero/server.rb
index d8f2c7d..50f016a 100644
--- a/lib/chef_zero/server.rb
+++ b/lib/chef_zero/server.rb
@@ -24,6 +24,7 @@ require 'timeout'
require 'chef_zero'
require 'chef_zero/cookbook_data'
require 'chef_zero/rest_router'
+require 'chef_zero/data_store/memory_store'
require 'chef_zero/version'
require 'chef_zero/endpoints/authenticate_user_endpoint'
@@ -77,7 +78,7 @@ module ChefZero
end
attr_reader :server
- attr_reader :data
+ attr_reader :data_store
attr_reader :url
include ChefZero::Endpoints
@@ -180,15 +181,18 @@ module ChefZero
def load_data(contents)
%w(clients environments nodes roles users).each do |data_type|
if contents[data_type]
- data[data_type].merge!(dejsonize_children(contents[data_type]))
+ dejsonize_children(contents[data_type]).each_pair do |name, data|
+ data_store.create([data_type], name, data)
+ end
end
end
if contents['data']
- new_data = {}
contents['data'].each_pair do |key, data_bag|
- new_data[key] = dejsonize_children(data_bag)
+ data_store.create_dir(['data'], key, :keep_existing)
+ dejsonize_children(data_bag).each do |item_name, item|
+ data_store.set(['data', key], item_name, item, :create)
+ end
end
- data['data'].merge!(new_data)
end
if contents['cookbooks']
contents['cookbooks'].each_pair do |name_version, cookbook|
@@ -198,12 +202,12 @@ module ChefZero
cookbook_data = CookbookData.to_hash(cookbook, name_version)
end
raise "No version specified" if !cookbook_data[:version]
- data['cookbooks'][cookbook_data[:cookbook_name]] = {} if !data['cookbooks'][cookbook_data[:cookbook_name]]
- data['cookbooks'][cookbook_data[:cookbook_name]][cookbook_data[:version]] = JSON.pretty_generate(cookbook_data)
+ data_store.create_dir(['cookbooks'], cookbook_data[:cookbook_name], :keep_existing)
+ data_store.set(['cookbooks', cookbook_data[:cookbook_name], cookbook_data[:version]], JSON.pretty_generate(cookbook_data), :create)
cookbook_data.values.each do |files|
next unless files.is_a? Array
files.each do |file|
- data['file_store'][file[:checksum]] = get_file(cookbook, file[:path])
+ data_store.set(['file_store', file[:checksum]], get_file(cookbook, file[:path]), :create)
end
end
end
@@ -211,24 +215,24 @@ module ChefZero
end
def clear_data
- @data = {
- 'clients' => {
- 'chef-validator' => '{ "validator": true }',
- 'chef-webui' => '{ "admin": true }'
- },
- 'cookbooks' => {},
- 'data' => {},
- 'environments' => {
- '_default' => '{ "description": "The default Chef environment" }'
- },
- 'file_store' => {},
- 'nodes' => {},
- 'roles' => {},
- 'sandboxes' => {},
- 'users' => {
- 'admin' => '{ "admin": true }'
- }
- }
+ @data_store = DataStore::MemoryStore.new
+
+ # Create containers
+ data_store.create_dir([], 'clients')
+ data_store.create_dir([], 'cookbooks')
+ data_store.create_dir([], 'data')
+ data_store.create_dir([], 'environments')
+ data_store.create_dir([], 'file_store')
+ data_store.create_dir([], 'nodes')
+ data_store.create_dir([], 'roles')
+ data_store.create_dir([], 'sandboxes')
+ data_store.create_dir([], 'users')
+
+ # Set defaults
+ data_store.create(['clients'], 'chef-validator', '{ "validator": true }')
+ data_store.create(['clients'], 'chef-webui', '{ "admin": true }')
+ data_store.create(['environments'], '_default', '{ "description": "The default Chef environment" }')
+ data_store.create(['users'], 'admin', '{ "admin": true }')
end
def request_handler(&block)