chef-zero 0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +201 -0
- data/README.rdoc +79 -0
- data/Rakefile +19 -0
- data/bin/chef-zero +40 -0
- data/lib/chef_zero.rb +5 -0
- data/lib/chef_zero/cookbook_data.rb +110 -0
- data/lib/chef_zero/data_normalizer.rb +129 -0
- data/lib/chef_zero/endpoints/actor_endpoint.rb +68 -0
- data/lib/chef_zero/endpoints/actors_endpoint.rb +32 -0
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +21 -0
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -0
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +106 -0
- data/lib/chef_zero/endpoints/cookbooks_base.rb +59 -0
- data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +12 -0
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +50 -0
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -0
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +21 -0
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -0
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +114 -0
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -0
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -0
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +35 -0
- data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/node_endpoint.rb +17 -0
- data/lib/chef_zero/endpoints/not_found_endpoint.rb +9 -0
- data/lib/chef_zero/endpoints/principal_endpoint.rb +30 -0
- data/lib/chef_zero/endpoints/rest_list_endpoint.rb +41 -0
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +65 -0
- data/lib/chef_zero/endpoints/role_endpoint.rb +16 -0
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -0
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +44 -0
- data/lib/chef_zero/endpoints/search_endpoint.rb +139 -0
- data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -0
- data/lib/chef_zero/rest_base.rb +82 -0
- data/lib/chef_zero/rest_error_response.rb +11 -0
- data/lib/chef_zero/rest_request.rb +42 -0
- data/lib/chef_zero/router.rb +26 -0
- data/lib/chef_zero/server.rb +255 -0
- data/lib/chef_zero/solr/query/binary_operator.rb +53 -0
- data/lib/chef_zero/solr/query/phrase.rb +23 -0
- data/lib/chef_zero/solr/query/range_query.rb +34 -0
- data/lib/chef_zero/solr/query/regexpable_query.rb +29 -0
- data/lib/chef_zero/solr/query/subquery.rb +35 -0
- data/lib/chef_zero/solr/query/term.rb +45 -0
- data/lib/chef_zero/solr/query/unary_operator.rb +43 -0
- data/lib/chef_zero/solr/solr_doc.rb +62 -0
- data/lib/chef_zero/solr/solr_parser.rb +194 -0
- data/lib/chef_zero/version.rb +3 -0
- metadata +132 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef_zero'
|
3
|
+
require 'chef_zero/rest_base'
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
module Endpoints
|
7
|
+
# /principals/NAME
|
8
|
+
class PrincipalEndpoint < RestBase
|
9
|
+
def get(request)
|
10
|
+
name = request.rest_path[-1]
|
11
|
+
json = data['users'][name]
|
12
|
+
if json
|
13
|
+
type = 'user'
|
14
|
+
else
|
15
|
+
json = data['clients'][name]
|
16
|
+
type = 'client'
|
17
|
+
end
|
18
|
+
if json
|
19
|
+
json_response(200, {
|
20
|
+
'name' => name,
|
21
|
+
'type' => type,
|
22
|
+
'public_key' => JSON.parse(json)['public_key'] || PUBLIC_KEY
|
23
|
+
})
|
24
|
+
else
|
25
|
+
error(404, 'Principal not found')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef_zero/rest_base'
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# Typical REST list endpoint (/roles or /data/BAG)
|
7
|
+
class RestListEndpoint < RestBase
|
8
|
+
def initialize(server, identity_key = 'name')
|
9
|
+
super(server)
|
10
|
+
@identity_key = identity_key
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :identity_key
|
14
|
+
|
15
|
+
def get(request)
|
16
|
+
# Get the result
|
17
|
+
result_hash = {}
|
18
|
+
get_data(request).keys.sort.each do |name|
|
19
|
+
result_hash[name] = "#{build_uri(request.base_uri, request.rest_path + [name])}"
|
20
|
+
end
|
21
|
+
json_response(200, result_hash)
|
22
|
+
end
|
23
|
+
|
24
|
+
def post(request)
|
25
|
+
container = get_data(request)
|
26
|
+
contents = request.body
|
27
|
+
key = get_key(contents)
|
28
|
+
if container[key]
|
29
|
+
error(409, 'Object already exists')
|
30
|
+
else
|
31
|
+
container[key] = contents
|
32
|
+
json_response(201, {'uri' => "#{build_uri(request.base_uri, request.rest_path + [key])}"})
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_key(contents)
|
37
|
+
JSON.parse(contents, :create_additions => false)[identity_key]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef_zero/rest_base'
|
3
|
+
require 'chef_zero/rest_error_response'
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
module Endpoints
|
7
|
+
# Typical REST leaf endpoint (/roles/NAME or /data/BAG/NAME)
|
8
|
+
class RestObjectEndpoint < RestBase
|
9
|
+
def initialize(server, identity_key = 'name')
|
10
|
+
super(server)
|
11
|
+
@identity_key = identity_key
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :identity_key
|
15
|
+
|
16
|
+
def get(request)
|
17
|
+
already_json_response(200, populate_defaults(request, get_data(request)))
|
18
|
+
end
|
19
|
+
|
20
|
+
def put(request)
|
21
|
+
# We grab the old body to trigger a 404 if it doesn't exist
|
22
|
+
old_body = get_data(request)
|
23
|
+
request_json = JSON.parse(request.body, :create_additions => false)
|
24
|
+
key = request_json[identity_key] || request.rest_path[-1]
|
25
|
+
container = get_data(request, request.rest_path[0..-2])
|
26
|
+
# If it's a rename, check for conflict and delete the old value
|
27
|
+
rename = key != request.rest_path[-1]
|
28
|
+
if rename
|
29
|
+
if container.has_key?(key)
|
30
|
+
return error(409, "Cannot rename '#{request.rest_path[-1]}' to '#{key}': '#{key}' already exists")
|
31
|
+
end
|
32
|
+
container.delete(request.rest_path[-1])
|
33
|
+
end
|
34
|
+
container[key] = request.body
|
35
|
+
already_json_response(200, populate_defaults(request, request.body))
|
36
|
+
end
|
37
|
+
|
38
|
+
def delete(request)
|
39
|
+
key = request.rest_path[-1]
|
40
|
+
container = get_data(request, request.rest_path[0..-2])
|
41
|
+
if !container.has_key?(key)
|
42
|
+
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
|
43
|
+
end
|
44
|
+
result = container[key]
|
45
|
+
container.delete(key)
|
46
|
+
already_json_response(200, populate_defaults(request, result))
|
47
|
+
end
|
48
|
+
|
49
|
+
def patch_request_body(request)
|
50
|
+
container = get_data(request, request.rest_path[0..-2])
|
51
|
+
existing_value = container[request.rest_path[-1]]
|
52
|
+
if existing_value
|
53
|
+
request_json = JSON.parse(request.body, :create_additions => false)
|
54
|
+
existing_json = JSON.parse(existing_value, :create_additions => false)
|
55
|
+
merged_json = existing_json.merge(request_json)
|
56
|
+
if merged_json.size > request_json.size
|
57
|
+
return JSON.pretty_generate(merged_json)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
request.body
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef_zero/endpoints/rest_object_endpoint'
|
3
|
+
require 'chef_zero/data_normalizer'
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
module Endpoints
|
7
|
+
# /roles/NAME
|
8
|
+
class RoleEndpoint < RestObjectEndpoint
|
9
|
+
def populate_defaults(request, response_json)
|
10
|
+
role = JSON.parse(response_json, :create_additions => false)
|
11
|
+
role = DataNormalizer.normalize_role(role, request.rest_path[1])
|
12
|
+
JSON.pretty_generate(role)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef_zero/rest_base'
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /roles/NAME/environments
|
7
|
+
class RoleEnvironmentsEndpoint < RestBase
|
8
|
+
def get(request)
|
9
|
+
role = JSON.parse(get_data(request, request.rest_path[0..1]), :create_additions => false)
|
10
|
+
json_response(200, [ '_default' ] + (role['env_run_lists'].keys || []))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'chef_zero/rest_base'
|
2
|
+
|
3
|
+
module ChefZero
|
4
|
+
module Endpoints
|
5
|
+
# /sandboxes/ID
|
6
|
+
class SandboxEndpoint < RestBase
|
7
|
+
def put(request)
|
8
|
+
existing_sandbox = get_data(request, request.rest_path)
|
9
|
+
data['sandboxes'].delete(request.rest_path[1])
|
10
|
+
time_str = existing_sandbox[:create_time].strftime('%Y-%m-%dT%H:%M:%S%z')
|
11
|
+
time_str = "#{time_str[0..21]}:#{time_str[22..23]}"
|
12
|
+
json_response(200, {
|
13
|
+
:guid => request.rest_path[1],
|
14
|
+
:name => request.rest_path[1],
|
15
|
+
:checksums => existing_sandbox[:checksums],
|
16
|
+
:create_time => time_str,
|
17
|
+
:is_completed => true
|
18
|
+
})
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef_zero/rest_base'
|
3
|
+
|
4
|
+
module ChefZero
|
5
|
+
module Endpoints
|
6
|
+
# /sandboxes
|
7
|
+
class SandboxesEndpoint < RestBase
|
8
|
+
def initialize(server)
|
9
|
+
super(server)
|
10
|
+
@next_id = 1
|
11
|
+
end
|
12
|
+
|
13
|
+
def post(request)
|
14
|
+
sandbox_checksums = []
|
15
|
+
|
16
|
+
needed_checksums = JSON.parse(request.body, :create_additions => false)['checksums']
|
17
|
+
result_checksums = {}
|
18
|
+
needed_checksums.keys.each do |needed_checksum|
|
19
|
+
if data['file_store'].has_key?(needed_checksum)
|
20
|
+
result_checksums[needed_checksum] = { :needs_upload => false }
|
21
|
+
else
|
22
|
+
result_checksums[needed_checksum] = {
|
23
|
+
:needs_upload => true,
|
24
|
+
:url => build_uri(request.base_uri, ['file_store', needed_checksum])
|
25
|
+
}
|
26
|
+
sandbox_checksums << needed_checksum
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
id = @next_id.to_s
|
31
|
+
@next_id+=1
|
32
|
+
|
33
|
+
data['sandboxes'][id] = { :create_time => Time.now.utc, :checksums => sandbox_checksums }
|
34
|
+
|
35
|
+
json_response(201, {
|
36
|
+
:uri => build_uri(request.base_uri, request.rest_path + [id.to_s]),
|
37
|
+
:checksums => result_checksums,
|
38
|
+
:sandbox_id => id
|
39
|
+
})
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'chef/mixin/deep_merge'
|
3
|
+
require 'chef_zero/endpoints/rest_object_endpoint'
|
4
|
+
require 'chef_zero/data_normalizer'
|
5
|
+
require 'chef_zero/rest_error_response'
|
6
|
+
require 'chef_zero/solr/solr_parser'
|
7
|
+
require 'chef_zero/solr/solr_doc'
|
8
|
+
|
9
|
+
module ChefZero
|
10
|
+
module Endpoints
|
11
|
+
# /search/INDEX
|
12
|
+
class SearchEndpoint < RestBase
|
13
|
+
def get(request)
|
14
|
+
results = search(request)
|
15
|
+
results['rows'] = results['rows'].map { |name,uri,value,search_value| value }
|
16
|
+
json_response(200, results)
|
17
|
+
end
|
18
|
+
|
19
|
+
def post(request)
|
20
|
+
full_results = search(request)
|
21
|
+
keys = JSON.parse(request.body, :create_additions => false)
|
22
|
+
partial_results = full_results['rows'].map do |name, uri, doc, search_value|
|
23
|
+
data = {}
|
24
|
+
keys.each_pair do |key, path|
|
25
|
+
if path.size > 0
|
26
|
+
value = search_value
|
27
|
+
path.each do |path_part|
|
28
|
+
value = value[path_part] if !value.nil?
|
29
|
+
end
|
30
|
+
data[key] = value
|
31
|
+
else
|
32
|
+
data[key] = nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
{
|
36
|
+
'url' => uri,
|
37
|
+
'data' => data
|
38
|
+
}
|
39
|
+
end
|
40
|
+
json_response(200, {
|
41
|
+
'rows' => partial_results,
|
42
|
+
'start' => full_results['start'],
|
43
|
+
'total' => full_results['total']
|
44
|
+
})
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def search_container(request, index)
|
50
|
+
case index
|
51
|
+
when 'client'
|
52
|
+
[ data['clients'], Proc.new { |client, name| DataNormalizer.normalize_client(client, name) }, build_uri(request.base_uri, [ 'clients' ]) ]
|
53
|
+
when 'node'
|
54
|
+
[ data['nodes'], Proc.new { |node, name| DataNormalizer.normalize_node(node, name) }, build_uri(request.base_uri, [ 'nodes' ]) ]
|
55
|
+
when 'environment'
|
56
|
+
[ data['environments'], Proc.new { |environment, name| DataNormalizer.normalize_environment(environment, name) }, build_uri(request.base_uri, [ 'environments' ]) ]
|
57
|
+
when 'role'
|
58
|
+
[ data['roles'], Proc.new { |role, name| DataNormalizer.normalize_role(role, name) }, build_uri(request.base_uri, [ 'roles' ]) ]
|
59
|
+
else
|
60
|
+
[ 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 ]) ]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def expand_for_indexing(value, index, id)
|
65
|
+
if index == 'node'
|
66
|
+
result = {}
|
67
|
+
Chef::Mixin::DeepMerge.deep_merge!(value['default'] || {}, result)
|
68
|
+
Chef::Mixin::DeepMerge.deep_merge!(value['normal'] || {}, result)
|
69
|
+
Chef::Mixin::DeepMerge.deep_merge!(value['override'] || {}, result)
|
70
|
+
Chef::Mixin::DeepMerge.deep_merge!(value['automatic'] || {}, result)
|
71
|
+
result['recipe'] = []
|
72
|
+
result['role'] = []
|
73
|
+
if value['run_list']
|
74
|
+
value['run_list'].each do |run_list_entry|
|
75
|
+
if run_list_entry =~ /^(recipe|role)\[(.*)\]/
|
76
|
+
result[$1] << $2
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
value.each_pair do |key, value|
|
81
|
+
result[key] = value unless %w(default normal override automatic).include?(key)
|
82
|
+
end
|
83
|
+
result
|
84
|
+
|
85
|
+
elsif !%w(client environment role).include?(index)
|
86
|
+
DataNormalizer.normalize_data_bag_item(value, index, id, 'GET')
|
87
|
+
else
|
88
|
+
value
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def search(request)
|
93
|
+
# Extract parameters
|
94
|
+
index = request.rest_path[1]
|
95
|
+
query_string = request.query_params['q'] || '*:*'
|
96
|
+
solr_query = ChefZero::Solr::SolrParser.new(query_string).parse
|
97
|
+
sort_string = request.query_params['sort']
|
98
|
+
start = request.query_params['start']
|
99
|
+
start = start.to_i if start
|
100
|
+
rows = request.query_params['rows']
|
101
|
+
rows = rows.to_i if rows
|
102
|
+
|
103
|
+
# Get the search container
|
104
|
+
container, expander, base_uri = search_container(request, index)
|
105
|
+
if container.nil?
|
106
|
+
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, request.rest_path)}")
|
107
|
+
end
|
108
|
+
|
109
|
+
# Search!
|
110
|
+
result = []
|
111
|
+
container.each_pair do |name,value|
|
112
|
+
expanded = expander.call(JSON.parse(value, :create_additions => false), name)
|
113
|
+
result << [ name, build_uri(base_uri, [name]), expanded, expand_for_indexing(expanded, index, name) ]
|
114
|
+
end
|
115
|
+
result = result.select do |name, uri, value, search_value|
|
116
|
+
solr_query.matches_doc?(ChefZero::Solr::SolrDoc.new(search_value, name))
|
117
|
+
end
|
118
|
+
total = result.size
|
119
|
+
|
120
|
+
# Sort
|
121
|
+
if sort_string
|
122
|
+
sort_key, sort_order = sort_string.split(/\s+/, 2)
|
123
|
+
result = result.sort_by { |name,uri,value,search_value| ChefZero::Solr::SolrDoc.new(search_value, name)[sort_key] }
|
124
|
+
result = result.reverse if sort_order == "DESC"
|
125
|
+
end
|
126
|
+
|
127
|
+
# Paginate
|
128
|
+
if start
|
129
|
+
result = result[start..start+(rows||-1)]
|
130
|
+
end
|
131
|
+
{
|
132
|
+
'rows' => result,
|
133
|
+
'start' => start || 0,
|
134
|
+
'total' => total
|
135
|
+
}
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'chef_zero/rest_base'
|
2
|
+
|
3
|
+
module ChefZero
|
4
|
+
module Endpoints
|
5
|
+
# /search
|
6
|
+
class SearchesEndpoint < RestBase
|
7
|
+
def get(request)
|
8
|
+
# Get the result
|
9
|
+
result_hash = {}
|
10
|
+
indices = (%w(client environment node role) + data['data'].keys).sort
|
11
|
+
indices.each do |index|
|
12
|
+
result_hash[index] = build_uri(request.base_uri, request.rest_path + [index])
|
13
|
+
end
|
14
|
+
json_response(200, result_hash)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'chef_zero/rest_request'
|
2
|
+
require 'chef_zero/rest_error_response'
|
3
|
+
require 'chef/log'
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
class RestBase
|
7
|
+
def initialize(server)
|
8
|
+
@server = server
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :server
|
12
|
+
|
13
|
+
def data
|
14
|
+
server.data
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
begin
|
19
|
+
rest_path = env['PATH_INFO'].split('/').select { |part| part != "" }
|
20
|
+
method = env['REQUEST_METHOD'].downcase.to_sym
|
21
|
+
if !self.respond_to?(method)
|
22
|
+
accept_methods = [:get, :put, :post, :delete].select { |m| self.respond_to?(m) }
|
23
|
+
accept_methods_str = accept_methods.map { |m| m.to_s.upcase }.join(', ')
|
24
|
+
return [405, {"Content-Type" => "text/plain", "Allow" => accept_methods_str}, "Bad request method for '#{env['REQUEST_PATH']}': #{env['REQUEST_METHOD']}"]
|
25
|
+
end
|
26
|
+
if json_only && !env['HTTP_ACCEPT'].split(';').include?('application/json')
|
27
|
+
return [406, {"Content-Type" => "text/plain"}, "Must accept application/json"]
|
28
|
+
end
|
29
|
+
# Dispatch to get()/post()/put()/delete()
|
30
|
+
begin
|
31
|
+
self.send(method, RestRequest.new(env))
|
32
|
+
rescue RestErrorResponse => e
|
33
|
+
error(e.response_code, e.error)
|
34
|
+
end
|
35
|
+
rescue
|
36
|
+
Chef::Log.error("#{$!.inspect}\n#{$!.backtrace.join("\n")}")
|
37
|
+
raise
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def json_only
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_data(request, rest_path=nil)
|
46
|
+
rest_path ||= request.rest_path
|
47
|
+
# Grab the value we're looking for
|
48
|
+
value = data
|
49
|
+
rest_path.each do |path_part|
|
50
|
+
if !value.has_key?(path_part)
|
51
|
+
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
|
52
|
+
end
|
53
|
+
value = value[path_part]
|
54
|
+
end
|
55
|
+
value
|
56
|
+
end
|
57
|
+
|
58
|
+
def error(response_code, error)
|
59
|
+
json_response(response_code, {"error" => [error]})
|
60
|
+
end
|
61
|
+
|
62
|
+
def json_response(response_code, json)
|
63
|
+
already_json_response(response_code, JSON.pretty_generate(json))
|
64
|
+
end
|
65
|
+
|
66
|
+
def already_json_response(response_code, json_text)
|
67
|
+
[response_code, {"Content-Type" => "application/json"}, json_text]
|
68
|
+
end
|
69
|
+
|
70
|
+
def build_uri(base_uri, rest_path)
|
71
|
+
RestBase::build_uri(base_uri, rest_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.build_uri(base_uri, rest_path)
|
75
|
+
"#{base_uri}/#{rest_path.join('/')}"
|
76
|
+
end
|
77
|
+
|
78
|
+
def populate_defaults(request, response)
|
79
|
+
response
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|