Class: ChefZero::RestBase
- Inherits:
-
Object
- Object
- ChefZero::RestBase
show all
- Defined in:
- lib/chef_zero/rest_base.rb
Direct Known Subclasses
Endpoints::AclEndpoint, Endpoints::AclsEndpoint, Endpoints::ActorDefaultKeyEndpoint, Endpoints::ActorKeyEndpoint, Endpoints::ActorKeysEndpoint, Endpoints::AuthenticateUserEndpoint, Endpoints::ControlsEndpoint, Endpoints::CookbookArtifactEndpoint, Endpoints::CookbookArtifactsEndpoint, Endpoints::CookbooksBase, Endpoints::DummyEndpoint, Endpoints::EnvironmentCookbookVersionsEndpoint, Endpoints::EnvironmentNodesEndpoint, Endpoints::FileStoreFileEndpoint, Endpoints::LicenseEndpoint, Endpoints::NodeIdentifiersEndpoint, Endpoints::OrganizationAssociationRequestEndpoint, Endpoints::OrganizationAssociationRequestsEndpoint, Endpoints::OrganizationAuthenticateUserEndpoint, Endpoints::OrganizationEndpoint, Endpoints::OrganizationUserDefaultKeyEndpoint, Endpoints::OrganizationUserEndpoint, Endpoints::OrganizationUserKeyEndpoint, Endpoints::OrganizationUserKeysEndpoint, Endpoints::OrganizationUsersEndpoint, Endpoints::OrganizationValidatorKeyEndpoint, Endpoints::OrganizationsEndpoint, Endpoints::PoliciesEndpoint, Endpoints::PolicyEndpoint, Endpoints::PolicyGroupEndpoint, Endpoints::PolicyGroupPolicyEndpoint, Endpoints::PolicyGroupsEndpoint, Endpoints::PolicyRevisionEndpoint, Endpoints::PolicyRevisionsEndpoint, Endpoints::PrincipalEndpoint, Endpoints::RestListEndpoint, Endpoints::RestObjectEndpoint, Endpoints::RoleEnvironmentsEndpoint, Endpoints::SandboxEndpoint, Endpoints::SandboxesEndpoint, Endpoints::SearchEndpoint, Endpoints::SearchesEndpoint, Endpoints::ServerAPIVersionEndpoint, Endpoints::SystemRecoveryEndpoint, Endpoints::UserAssociationRequestEndpoint, Endpoints::UserAssociationRequestsCountEndpoint, Endpoints::UserAssociationRequestsEndpoint, Endpoints::UserOrganizationsEndpoint, Endpoints::VersionEndpoint
Constant Summary
collapse
- DEFAULT_REQUEST_VERSION =
0
- DEFAULT_RESPONSE_VERSION =
0
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#accepts?(request, category, type) ⇒ Boolean
-
#already_json_response(response_code, json_text, options = {}) ⇒ Array(Fixnum, Hash{String => String}, String)
Returns an Array with the response code, HTTP headers, and JSON body.
-
#build_uri(base_uri, rest_path) ⇒ Object
To be called from inside rest endpoints.
-
#call(request) ⇒ Object
-
#check_api_version(request) ⇒ Object
-
#create_data(request, rest_path, name, data, *options) ⇒ Object
-
#create_data_dir(request, rest_path, name, *options) ⇒ Object
-
#data_store ⇒ Object
-
#delete_data(request, rest_path = nil, *options) ⇒ Object
-
#delete_data_dir(request, rest_path, *options) ⇒ Object
-
#error(response_code, error, opts = {}) ⇒ Object
-
#exists_data?(request, rest_path = nil) ⇒ Boolean
-
#exists_data_dir?(request, rest_path = nil) ⇒ Boolean
-
#get_data(request, rest_path = nil, *options) ⇒ Object
-
#get_data_or_else(request, path, or_else_value) ⇒ Object
-
#hashify_list(list) ⇒ Object
-
#head_request(request) ⇒ Array(Fixnum, Hash{String => String}, String)
rfc090 returns 404 error or 200 with an emtpy body.
-
#initialize(server) ⇒ RestBase
constructor
A new instance of RestBase.
-
#json_only ⇒ Object
-
#json_response(response_code, data, options = {}) ⇒ Array(Fixnum, Hash{String => String}, String)
Serializes ‘data` to JSON and returns an Array with the response code, HTTP headers and JSON body.
-
#list_data(request, rest_path = nil, *options) ⇒ Object
-
#list_data_or_else(request, path, or_else_value) ⇒ Object
-
#parse_json(json) ⇒ Object
-
#policy_name_invalid?(name) ⇒ Boolean
-
#populate_defaults(request, response) ⇒ Object
-
#set_data(request, rest_path, data, *options) ⇒ Object
-
#text_response(response_code, text) ⇒ Object
-
#to_json(data) ⇒ Object
Constructor Details
#initialize(server) ⇒ RestBase
Returns a new instance of RestBase.
11
12
13
|
# File 'lib/chef_zero/rest_base.rb', line 11
def initialize(server)
@server = server
end
|
Instance Attribute Details
#server ⇒ Object
Returns the value of attribute server.
15
16
17
|
# File 'lib/chef_zero/rest_base.rb', line 15
def server
@server
end
|
Class Method Details
.build_uri(base_uri, rest_path) ⇒ Object
286
287
288
|
# File 'lib/chef_zero/rest_base.rb', line 286
def self.build_uri(base_uri, rest_path)
"#{base_uri}/#{rest_path.map { |v| rfc2396_parser.escape(v) }.join("/")}"
end
|
.rfc2396_parser ⇒ Object
328
329
330
|
# File 'lib/chef_zero/rest_base.rb', line 328
def self.rfc2396_parser
@parser ||= URI::RFC2396_Parser.new
end
|
Instance Method Details
#accepts?(request, category, type) ⇒ Boolean
69
70
71
72
73
74
75
76
|
# File 'lib/chef_zero/rest_base.rb', line 69
def accepts?(request, category, type)
return true unless request.env["HTTP_ACCEPT"]
accepts = request.env["HTTP_ACCEPT"].split(/,\s*/).map { |x| x.split(";", 2)[0].strip }
accepts.include?("#{category}/#{type}") || accepts.include?("#{category}/*") || accepts.include?("*/*")
end
|
#already_json_response(response_code, json_text, options = {}) ⇒ Array(Fixnum, Hash{String => String}, String)
Returns an Array with the response code, HTTP headers, and JSON body.
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
|
# File 'lib/chef_zero/rest_base.rb', line 255
def already_json_response(response_code, json_text, options = {})
= FFI_Yajl::Encoder.encode(
"min_version" => MIN_API_VERSION.to_s,
"max_version" => MAX_API_VERSION.to_s,
"request_version" => options[:request_version] || DEFAULT_REQUEST_VERSION.to_s,
"response_version" => options[:response_version] || DEFAULT_RESPONSE_VERSION.to_s
)
= {
"Content-Type" => "application/json",
"X-Ops-Server-API-Version" => ,
}
.merge!(options[:headers]) if options[:headers]
[ response_code, , json_text ]
end
|
#build_uri(base_uri, rest_path) ⇒ Object
To be called from inside rest endpoints
273
274
275
276
277
278
279
280
281
282
283
284
|
# File 'lib/chef_zero/rest_base.rb', line 273
def build_uri(base_uri, rest_path)
if server.options[:single_org]
if rest_path[0..1] != [ "organizations", server.options[:single_org] ]
raise "Unexpected URL #{rest_path[0..1]} passed to build_uri in single org mode"
end
return self.class.build_uri(base_uri, rest_path[2..-1])
end
self.class.build_uri(base_uri, rest_path)
end
|
#call(request) ⇒ Object
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
# File 'lib/chef_zero/rest_base.rb', line 42
def call(request)
response = check_api_version(request)
return response unless response.nil?
method = request.method.downcase.to_sym
unless respond_to?(method)
accept_methods = %i{get put post delete}.select { |m| respond_to?(m) }
accept_methods_str = accept_methods.map { |m| m.to_s.upcase }.join(", ")
return [405, { "Content-Type" => "text/plain", "Allow" => accept_methods_str }, "Bad request method for '#{request.env["REQUEST_PATH"]}': #{request.env["REQUEST_METHOD"]}"]
end
if json_only && !accepts?(request, "application", "json")
return [406, { "Content-Type" => "text/plain" }, "Must accept application/json"]
end
begin
send(method, request)
rescue RestErrorResponse => e
ChefZero::Log.debug("#{e.inspect}\n#{e.backtrace.join("\n")}")
error(e.response_code, e.error)
end
end
|
#check_api_version(request) ⇒ Object
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
# File 'lib/chef_zero/rest_base.rb', line 21
def check_api_version(request)
version = request.api_version
if version > MAX_API_VERSION || version < MIN_API_VERSION
response = {
"error" => "invalid-x-ops-server-api-version",
"message" => "Specified version #{version} not supported",
"min_api_version" => MIN_API_VERSION,
"max_api_version" => MAX_API_VERSION,
}
return json_response(406,
response,
request_version: version, response_version: -1)
end
rescue ArgumentError
json_response(406,
{ "username" => request.requestor },
request_version: -1, response_version: -1)
end
|
#create_data(request, rest_path, name, data, *options) ⇒ Object
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
|
# File 'lib/chef_zero/rest_base.rb', line 177
def create_data(request, rest_path, name, data, *options)
rest_path ||= request.rest_path
begin
data_store.create(rest_path, name, data, *options, requestor: request.requestor)
rescue DataStore::DataNotFoundError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(404, "Parent not found: #{build_uri(request.base_uri, rest_path)}")
end
rescue DataStore::DataAlreadyExistsError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(409, "Object already exists: #{build_uri(request.base_uri, rest_path + [name])}")
end
end
end
|
#create_data_dir(request, rest_path, name, *options) ⇒ Object
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
# File 'lib/chef_zero/rest_base.rb', line 158
def create_data_dir(request, rest_path, name, *options)
rest_path ||= request.rest_path
begin
data_store.create_dir(rest_path, name, *options, requestor: request.requestor)
rescue DataStore::DataNotFoundError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(404, "Parent not found: #{build_uri(request.base_uri, rest_path)}")
end
rescue DataStore::DataAlreadyExistsError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(409, "Object already exists: #{build_uri(request.base_uri, rest_path + [name])}")
end
end
end
|
#data_store ⇒ Object
17
18
19
|
# File 'lib/chef_zero/rest_base.rb', line 17
def data_store
server.data_store
end
|
#delete_data(request, rest_path = nil, *options) ⇒ Object
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# File 'lib/chef_zero/rest_base.rb', line 107
def delete_data(request, rest_path = nil, *options)
rest_path ||= request.rest_path
begin
data_store.delete(rest_path, *options)
rescue DataStore::DataNotFoundError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
end
end
begin
acl_path = ChefData::AclPath.get_acl_data_path(rest_path)
data_store.delete(acl_path) if acl_path
rescue DataStore::DataNotFoundError
end
end
|
#delete_data_dir(request, rest_path, *options) ⇒ Object
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
# File 'lib/chef_zero/rest_base.rb', line 126
def delete_data_dir(request, rest_path, *options)
rest_path ||= request.rest_path
begin
data_store.delete_dir(rest_path, *options)
rescue DataStore::DataNotFoundError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
end
end
begin
acl_path = ChefData::AclPath.get_acl_data_path(rest_path)
data_store.delete(acl_path) if acl_path
rescue DataStore::DataNotFoundError
end
end
|
#error(response_code, error, opts = {}) ⇒ Object
206
207
208
|
# File 'lib/chef_zero/rest_base.rb', line 206
def error(response_code, error, opts = {})
json_response(response_code, { "error" => [ error ] }, opts)
end
|
#exists_data?(request, rest_path = nil) ⇒ Boolean
196
197
198
199
|
# File 'lib/chef_zero/rest_base.rb', line 196
def exists_data?(request, rest_path = nil)
rest_path ||= request.rest_path
data_store.exists?(rest_path)
end
|
#exists_data_dir?(request, rest_path = nil) ⇒ Boolean
201
202
203
204
|
# File 'lib/chef_zero/rest_base.rb', line 201
def exists_data_dir?(request, rest_path = nil)
rest_path ||= request.rest_path
data_store.exists_dir?(rest_path)
end
|
#get_data(request, rest_path = nil, *options) ⇒ Object
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/chef_zero/rest_base.rb', line 78
def get_data(request, rest_path = nil, *options)
rest_path ||= request.rest_path
rest_path = rest_path.map { |v| self.class.rfc2396_parser.unescape(v) }
begin
data_store.get(rest_path, request)
rescue DataStore::DataNotFoundError
if options.include?(:nil)
nil
elsif options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
end
end
end
|
#get_data_or_else(request, path, or_else_value) ⇒ Object
302
303
304
305
306
307
308
|
# File 'lib/chef_zero/rest_base.rb', line 302
def get_data_or_else(request, path, or_else_value)
if exists_data?(request, path)
parse_json(get_data(request, path))
else
or_else_value
end
end
|
#hashify_list(list) ⇒ Object
318
319
320
|
# File 'lib/chef_zero/rest_base.rb', line 318
def hashify_list(list)
list.reduce({}) { |acc, obj| acc.merge( obj => {} ) }
end
|
#head_request(request) ⇒ Array(Fixnum, Hash{String => String}, String)
rfc090 returns 404 error or 200 with an emtpy body
239
240
241
242
|
# File 'lib/chef_zero/rest_base.rb', line 239
def head_request(request)
get_data(request) json_response(200, nil)
end
|
#json_only ⇒ Object
65
66
67
|
# File 'lib/chef_zero/rest_base.rb', line 65
def json_only
true
end
|
#json_response(response_code, data, options = {}) ⇒ Array(Fixnum, Hash{String => String}, String)
Serializes ‘data` to JSON and returns an Array with the response code, HTTP headers and JSON body.
223
224
225
226
227
228
|
# File 'lib/chef_zero/rest_base.rb', line 223
def json_response(response_code, data, options = {})
options = { pretty: true }.merge(options)
do_pretty_json = !!options.delete(:pretty) json = FFI_Yajl::Encoder.encode(data, pretty: do_pretty_json)
already_json_response(response_code, json, options)
end
|
#list_data(request, rest_path = nil, *options) ⇒ Object
94
95
96
97
98
99
100
101
102
103
104
105
|
# File 'lib/chef_zero/rest_base.rb', line 94
def list_data(request, rest_path = nil, *options)
rest_path ||= request.rest_path
begin
data_store.list(rest_path)
rescue DataStore::DataNotFoundError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
end
end
end
|
#list_data_or_else(request, path, or_else_value) ⇒ Object
310
311
312
313
314
315
316
|
# File 'lib/chef_zero/rest_base.rb', line 310
def list_data_or_else(request, path, or_else_value)
if exists_data_dir?(request, path)
list_data(request, path)
else
or_else_value
end
end
|
#parse_json(json) ⇒ Object
294
295
296
|
# File 'lib/chef_zero/rest_base.rb', line 294
def parse_json(json)
FFI_Yajl::Parser.parse(json)
end
|
#policy_name_invalid?(name) ⇒ Boolean
322
323
324
325
326
|
# File 'lib/chef_zero/rest_base.rb', line 322
def policy_name_invalid?(name)
!name.is_a?(String) ||
name.size > 255 ||
name =~ /[+ !]/
end
|
#populate_defaults(request, response) ⇒ Object
290
291
292
|
# File 'lib/chef_zero/rest_base.rb', line 290
def populate_defaults(request, response)
response
end
|
#set_data(request, rest_path, data, *options) ⇒ Object
145
146
147
148
149
150
151
152
153
154
155
156
|
# File 'lib/chef_zero/rest_base.rb', line 145
def set_data(request, rest_path, data, *options)
rest_path ||= request.rest_path
begin
data_store.set(rest_path, data, *options, requestor: request.requestor)
rescue DataStore::DataNotFoundError
if options.include?(:data_store_exceptions)
raise
else
raise RestErrorResponse.new(404, "Object not found: #{build_uri(request.base_uri, rest_path)}")
end
end
end
|
#text_response(response_code, text) ⇒ Object
230
231
232
|
# File 'lib/chef_zero/rest_base.rb', line 230
def text_response(response_code, text)
[response_code, { "Content-Type" => "text/plain" }, text]
end
|
#to_json(data) ⇒ Object
298
299
300
|
# File 'lib/chef_zero/rest_base.rb', line 298
def to_json(data)
FFI_Yajl::Encoder.encode(data, pretty: true)
end
|