Class: ChefZero::RestBase

Inherits:
Object
  • Object
show all
Defined in:
lib/chef_zero/rest_base.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(server) ⇒ RestBase

Returns a new instance of RestBase


8
9
10
# File 'lib/chef_zero/rest_base.rb', line 8

def initialize(server)
  @server = server
end

Instance Attribute Details

#serverObject (readonly)

Returns the value of attribute server


12
13
14
# File 'lib/chef_zero/rest_base.rb', line 12

def server
  @server
end

Class Method Details

.build_uri(base_uri, rest_path) ⇒ Object


206
207
208
# File 'lib/chef_zero/rest_base.rb', line 206

def self.build_uri(base_uri, rest_path)
  "#{base_uri}/#{rest_path.join('/')}"
end

Instance Method Details

#accepts?(request, category, type) ⇒ Boolean

Returns:

  • (Boolean)

41
42
43
44
45
46
47
# File 'lib/chef_zero/rest_base.rb', line 41

def accepts?(request, category, type)
  # If HTTP_ACCEPT is not sent at all, assume it accepts anything
  # This parses as per http://tools.ietf.org/html/rfc7231#section-5.3
  return true if !request.env['HTTP_ACCEPT']
  accepts = request.env['HTTP_ACCEPT'].split(/,\s*/).map { |x| x.split(';',2)[0].strip }
  return accepts.include?("#{category}/#{type}") || accepts.include?("#{category}/*") || accepts.include?('*/*')
end

#already_json_response(response_code, json_text) ⇒ Object


188
189
190
# File 'lib/chef_zero/rest_base.rb', line 188

def already_json_response(response_code, json_text)
  [response_code, {"Content-Type" => "application/json"}, json_text]
end

#build_uri(base_uri, rest_path) ⇒ Object

To be called from inside rest endpoints


193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/chef_zero/rest_base.rb', line 193

def build_uri(base_uri, rest_path)
  if server.options[:single_org]
    # Strip off /organizations/chef if we are in single org mode
    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"
    else
      "#{base_uri}/#{rest_path[2..-1].join('/')}"
    end
  else
    "#{base_uri}/#{rest_path.join('/')}"
  end
end

#call(request) ⇒ Object


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/chef_zero/rest_base.rb', line 18

def call(request)
  method = request.method.downcase.to_sym
  if !self.respond_to?(method)
    accept_methods = [:get, :put, :post, :delete].select { |m| self.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
  # Dispatch to get()/post()/put()/delete()
  begin
    self.send(method, request)
  rescue RestErrorResponse => e
    ChefZero::Log.debug("#{e.inspect}\n#{e.backtrace.join("\n")}")
    error(e.response_code, e.error)
  end
end

#create_data(request, rest_path, name, data, *options) ⇒ Object


147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/chef_zero/rest_base.rb', line 147

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, request.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, request.rest_path + [name])}")
    end
  end
end

#create_data_dir(request, rest_path, name, *options) ⇒ Object


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/chef_zero/rest_base.rb', line 128

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, request.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, request.rest_path + [name])}")
    end
  end
end

#data_storeObject


14
15
16
# File 'lib/chef_zero/rest_base.rb', line 14

def data_store
  server.data_store
end

#delete_data(request, rest_path = nil, *options) ⇒ Object


77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/chef_zero/rest_base.rb', line 77

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, request.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


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/chef_zero/rest_base.rb', line 96

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, request.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) ⇒ Object


176
177
178
# File 'lib/chef_zero/rest_base.rb', line 176

def error(response_code, error)
  json_response(response_code, {"error" => [error]})
end

#exists_data?(request, rest_path = nil) ⇒ Boolean

Returns:

  • (Boolean)

166
167
168
169
# File 'lib/chef_zero/rest_base.rb', line 166

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

Returns:

  • (Boolean)

171
172
173
174
# File 'lib/chef_zero/rest_base.rb', line 171

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


49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/chef_zero/rest_base.rb', line 49

def get_data(request, rest_path=nil, *options)
  rest_path ||= request.rest_path
  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

#json_onlyObject


37
38
39
# File 'lib/chef_zero/rest_base.rb', line 37

def json_only
  true
end

#json_response(response_code, json) ⇒ Object


180
181
182
# File 'lib/chef_zero/rest_base.rb', line 180

def json_response(response_code, json)
  already_json_response(response_code, FFI_Yajl::Encoder.encode(json, :pretty => true))
end

#list_data(request, rest_path = nil, *options) ⇒ Object


64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/chef_zero/rest_base.rb', line 64

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

#populate_defaults(request, response) ⇒ Object


210
211
212
# File 'lib/chef_zero/rest_base.rb', line 210

def populate_defaults(request, response)
  response
end

#set_data(request, rest_path, data, *options) ⇒ Object


115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/chef_zero/rest_base.rb', line 115

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, request.rest_path)}")
    end
  end
end

#text_response(response_code, text) ⇒ Object


184
185
186
# File 'lib/chef_zero/rest_base.rb', line 184

def text_response(response_code, text)
  [response_code, {"Content-Type" => "text/plain"}, text]
end