chef-zero 2.0.2 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/chef_zero/data_normalizer.rb +6 -2
  3. data/lib/chef_zero/data_store/interface_v1.rb +49 -0
  4. data/lib/chef_zero/data_store/interface_v2.rb +18 -0
  5. data/lib/chef_zero/data_store/memory_store.rb +6 -141
  6. data/lib/chef_zero/data_store/memory_store_v2.rb +188 -0
  7. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +190 -0
  8. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +107 -0
  9. data/lib/chef_zero/endpoints/actor_endpoint.rb +6 -12
  10. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +1 -1
  11. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +5 -5
  12. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +16 -16
  13. data/lib/chef_zero/endpoints/cookbooks_base.rb +5 -5
  14. data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +1 -1
  15. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +2 -2
  16. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +1 -1
  17. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +2 -2
  18. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +3 -3
  19. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +9 -9
  20. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +2 -2
  21. data/lib/chef_zero/endpoints/environment_endpoint.rb +3 -3
  22. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +5 -5
  23. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +3 -3
  24. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +6 -6
  25. data/lib/chef_zero/endpoints/node_endpoint.rb +1 -1
  26. data/lib/chef_zero/endpoints/principal_endpoint.rb +2 -2
  27. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +3 -3
  28. data/lib/chef_zero/endpoints/role_endpoint.rb +1 -1
  29. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +1 -1
  30. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +3 -3
  31. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +2 -3
  32. data/lib/chef_zero/endpoints/search_endpoint.rb +13 -9
  33. data/lib/chef_zero/endpoints/searches_endpoint.rb +1 -1
  34. data/lib/chef_zero/rest_base.rb +10 -2
  35. data/lib/chef_zero/rest_request.rb +4 -3
  36. data/lib/chef_zero/server.rb +83 -52
  37. data/lib/chef_zero/version.rb +1 -1
  38. data/spec/run.rb +72 -25
  39. data/spec/support/pedant.rb +4 -0
  40. metadata +10 -5
@@ -2,11 +2,13 @@ require 'rack/request'
2
2
 
3
3
  module ChefZero
4
4
  class RestRequest
5
- def initialize(env)
5
+ def initialize(env, rest_base_prefix = [])
6
6
  @env = env
7
+ @rest_base_prefix = rest_base_prefix
7
8
  end
8
9
 
9
10
  attr_reader :env
11
+ attr_reader :rest_base_prefix
10
12
 
11
13
  def base_uri
12
14
  @base_uri ||= "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['SCRIPT_NAME']}"
@@ -17,7 +19,7 @@ module ChefZero
17
19
  end
18
20
 
19
21
  def rest_path
20
- @rest_path ||= env['PATH_INFO'].split('/').select { |part| part != "" }
22
+ @rest_path ||= rest_base_prefix + env['PATH_INFO'].split('/').select { |part| part != "" }
21
23
  end
22
24
 
23
25
  def body=(body)
@@ -53,4 +55,3 @@ module ChefZero
53
55
  end
54
56
  end
55
57
  end
56
-
@@ -28,7 +28,8 @@ require 'webrick'
28
28
  require 'chef_zero'
29
29
  require 'chef_zero/cookbook_data'
30
30
  require 'chef_zero/rest_router'
31
- require 'chef_zero/data_store/memory_store'
31
+ require 'chef_zero/data_store/memory_store_v2'
32
+ require 'chef_zero/data_store/v1_to_v2_adapter'
32
33
  require 'chef_zero/version'
33
34
 
34
35
  require 'chef_zero/endpoints/authenticate_user_endpoint'
@@ -65,7 +66,8 @@ module ChefZero
65
66
  :host => '127.0.0.1',
66
67
  :port => 8889,
67
68
  :log_level => :info,
68
- :generate_real_keys => true
69
+ :generate_real_keys => true,
70
+ :single_org => 'chef'
69
71
  }.freeze
70
72
 
71
73
  def initialize(options = {})
@@ -102,10 +104,25 @@ module ChefZero
102
104
  #
103
105
  # The data store for this server (default is in-memory).
104
106
  #
105
- # @return [~ChefZero::DataStore]
107
+ # @return [ChefZero::DataStore]
106
108
  #
107
109
  def data_store
108
- @data_store ||= @options[:data_store] || DataStore::MemoryStore.new
110
+ @data_store ||= begin
111
+ result = @options[:data_store] || DataStore::MemoryStoreV2.new
112
+ if options[:single_org]
113
+ if result.respond_to?(:interface_version) && result.interface_version >= 2 && result.interface_version < 3
114
+ result.create_dir([ 'organizations' ], options[:single_org])
115
+ else
116
+ result = ChefZero::DataStore::V1ToV2Adapter.new(result, options[:single_org])
117
+ end
118
+ else
119
+ if !(result.respond_to?(:interface_version) && result.interface_version >= 2 && result.interface_version < 3)
120
+ raise "Multi-org not supported by data store #{result}!"
121
+ end
122
+ end
123
+
124
+ result
125
+ end
109
126
  end
110
127
 
111
128
  #
@@ -123,8 +140,8 @@ module ChefZero
123
140
  # Start a Chef Zero server in the current thread. You can stop this server
124
141
  # by canceling the current thread.
125
142
  #
126
- # @param [Boolean] publish
127
- # publish the server information to STDOUT
143
+ # @param [Boolean|IO] publish
144
+ # publish the server information to the publish parameter or to STDOUT if it's "true"
128
145
  #
129
146
  # @return [nil]
130
147
  # this method will block the main thread until interrupted
@@ -133,7 +150,8 @@ module ChefZero
133
150
  publish = publish[:publish] if publish.is_a?(Hash) # Legacy API
134
151
 
135
152
  if publish
136
- puts <<-EOH.gsub(/^ {10}/, '')
153
+ output = publish.respond_to?(:puts) ? publish : STDOUT
154
+ output.puts <<-EOH.gsub(/^ {10}/, '')
137
155
  >> Starting Chef Zero (v#{ChefZero::VERSION})...
138
156
  >> WEBrick (v#{WEBrick::VERSION}) on Rack (v#{Rack.release}) is listening at #{url}
139
157
  >> Press CTRL+C to stop
@@ -208,9 +226,9 @@ module ChefZero
208
226
  # server
209
227
  #
210
228
  def stop(wait = 5)
211
- Timeout.timeout(wait) do
229
+ if @thread
212
230
  @server.shutdown
213
- @thread.join(wait) if @thread
231
+ @thread.join(wait)
214
232
  end
215
233
  rescue Timeout::Error
216
234
  if @thread
@@ -265,19 +283,20 @@ module ChefZero
265
283
  # }
266
284
  # }
267
285
  # }
268
- def load_data(contents)
286
+ def load_data(contents, org_name = 'chef')
287
+ data_store.create_dir('organizations', org_name)
269
288
  %w(clients environments nodes roles users).each do |data_type|
270
289
  if contents[data_type]
271
290
  dejsonize_children(contents[data_type]).each_pair do |name, data|
272
- data_store.set([data_type, name], data, :create)
291
+ data_store.set(['organizations', org_name, data_type, name], data, :create)
273
292
  end
274
293
  end
275
294
  end
276
295
  if contents['data']
277
296
  contents['data'].each_pair do |key, data_bag|
278
- data_store.create_dir(['data'], key, :recursive)
297
+ data_store.create_dir(['organizations', org_name, 'data'], key, :recursive)
279
298
  dejsonize_children(data_bag).each do |item_name, item|
280
- data_store.set(['data', key, item_name], item, :create)
299
+ data_store.set(['organizations', org_name, 'data', key, item_name], item, :create)
281
300
  end
282
301
  end
283
302
  end
@@ -289,12 +308,12 @@ module ChefZero
289
308
  cookbook_data = CookbookData.to_hash(cookbook, name_version)
290
309
  end
291
310
  raise "No version specified" if !cookbook_data[:version]
292
- data_store.create_dir(['cookbooks'], cookbook_data[:cookbook_name], :recursive)
293
- data_store.set(['cookbooks', cookbook_data[:cookbook_name], cookbook_data[:version]], JSON.pretty_generate(cookbook_data), :create)
311
+ data_store.create_dir(['organizations', org_name, 'cookbooks'], cookbook_data[:cookbook_name], :recursive)
312
+ data_store.set(['organizations', org_name, 'cookbooks', cookbook_data[:cookbook_name], cookbook_data[:version]], JSON.pretty_generate(cookbook_data), :create)
294
313
  cookbook_data.values.each do |files|
295
314
  next unless files.is_a? Array
296
315
  files.each do |file|
297
- data_store.set(['file_store', 'checksums', file[:checksum]], get_file(cookbook, file[:path]), :create)
316
+ data_store.set(['organizations', org_name, 'file_store', 'checksums', file[:checksum]], get_file(cookbook, file[:path]), :create)
298
317
  end
299
318
  end
300
319
  end
@@ -303,6 +322,9 @@ module ChefZero
303
322
 
304
323
  def clear_data
305
324
  data_store.clear
325
+ if options[:single_org]
326
+ data_store.create_dir([ 'organizations' ], options[:single_org])
327
+ end
306
328
  end
307
329
 
308
330
  def request_handler(&block)
@@ -319,45 +341,54 @@ module ChefZero
319
341
 
320
342
  private
321
343
 
344
+ def open_source_endpoints
345
+ [
346
+ [ "/organizations/*/authenticate_user", AuthenticateUserEndpoint.new(self) ],
347
+ [ "/organizations/*/clients", ActorsEndpoint.new(self) ],
348
+ [ "/organizations/*/clients/*", ActorEndpoint.new(self) ],
349
+ [ "/organizations/*/cookbooks", CookbooksEndpoint.new(self) ],
350
+ [ "/organizations/*/cookbooks/*", CookbookEndpoint.new(self) ],
351
+ [ "/organizations/*/cookbooks/*/*", CookbookVersionEndpoint.new(self) ],
352
+ [ "/organizations/*/data", DataBagsEndpoint.new(self) ],
353
+ [ "/organizations/*/data/*", DataBagEndpoint.new(self) ],
354
+ [ "/organizations/*/data/*/*", DataBagItemEndpoint.new(self) ],
355
+ [ "/organizations/*/environments", RestListEndpoint.new(self) ],
356
+ [ "/organizations/*/environments/*", EnvironmentEndpoint.new(self) ],
357
+ [ "/organizations/*/environments/*/cookbooks", EnvironmentCookbooksEndpoint.new(self) ],
358
+ [ "/organizations/*/environments/*/cookbooks/*", EnvironmentCookbookEndpoint.new(self) ],
359
+ [ "/organizations/*/environments/*/cookbook_versions", EnvironmentCookbookVersionsEndpoint.new(self) ],
360
+ [ "/organizations/*/environments/*/nodes", EnvironmentNodesEndpoint.new(self) ],
361
+ [ "/organizations/*/environments/*/recipes", EnvironmentRecipesEndpoint.new(self) ],
362
+ [ "/organizations/*/environments/*/roles/*", EnvironmentRoleEndpoint.new(self) ],
363
+ [ "/organizations/*/nodes", RestListEndpoint.new(self) ],
364
+ [ "/organizations/*/nodes/*", NodeEndpoint.new(self) ],
365
+ [ "/organizations/*/principals/*", PrincipalEndpoint.new(self) ],
366
+ [ "/organizations/*/roles", RestListEndpoint.new(self) ],
367
+ [ "/organizations/*/roles/*", RoleEndpoint.new(self) ],
368
+ [ "/organizations/*/roles/*/environments", RoleEnvironmentsEndpoint.new(self) ],
369
+ [ "/organizations/*/roles/*/environments/*", EnvironmentRoleEndpoint.new(self) ],
370
+ [ "/organizations/*/sandboxes", SandboxesEndpoint.new(self) ],
371
+ [ "/organizations/*/sandboxes/*", SandboxEndpoint.new(self) ],
372
+ [ "/organizations/*/search", SearchesEndpoint.new(self) ],
373
+ [ "/organizations/*/search/*", SearchEndpoint.new(self) ],
374
+ [ "/organizations/*/users", ActorsEndpoint.new(self) ],
375
+ [ "/organizations/*/users/*", ActorEndpoint.new(self) ],
376
+
377
+ [ "/organizations/*/file_store/**", FileStoreFileEndpoint.new(self) ],
378
+ ]
379
+ end
380
+
322
381
  def app
323
- router = RestRouter.new([
324
- [ '/authenticate_user', AuthenticateUserEndpoint.new(self) ],
325
- [ '/clients', ActorsEndpoint.new(self) ],
326
- [ '/clients/*', ActorEndpoint.new(self) ],
327
- [ '/cookbooks', CookbooksEndpoint.new(self) ],
328
- [ '/cookbooks/*', CookbookEndpoint.new(self) ],
329
- [ '/cookbooks/*/*', CookbookVersionEndpoint.new(self) ],
330
- [ '/data', DataBagsEndpoint.new(self) ],
331
- [ '/data/*', DataBagEndpoint.new(self) ],
332
- [ '/data/*/*', DataBagItemEndpoint.new(self) ],
333
- [ '/environments', RestListEndpoint.new(self) ],
334
- [ '/environments/*', EnvironmentEndpoint.new(self) ],
335
- [ '/environments/*/cookbooks', EnvironmentCookbooksEndpoint.new(self) ],
336
- [ '/environments/*/cookbooks/*', EnvironmentCookbookEndpoint.new(self) ],
337
- [ '/environments/*/cookbook_versions', EnvironmentCookbookVersionsEndpoint.new(self) ],
338
- [ '/environments/*/nodes', EnvironmentNodesEndpoint.new(self) ],
339
- [ '/environments/*/recipes', EnvironmentRecipesEndpoint.new(self) ],
340
- [ '/environments/*/roles/*', EnvironmentRoleEndpoint.new(self) ],
341
- [ '/nodes', RestListEndpoint.new(self) ],
342
- [ '/nodes/*', NodeEndpoint.new(self) ],
343
- [ '/principals/*', PrincipalEndpoint.new(self) ],
344
- [ '/roles', RestListEndpoint.new(self) ],
345
- [ '/roles/*', RoleEndpoint.new(self) ],
346
- [ '/roles/*/environments', RoleEnvironmentsEndpoint.new(self) ],
347
- [ '/roles/*/environments/*', EnvironmentRoleEndpoint.new(self) ],
348
- [ '/sandboxes', SandboxesEndpoint.new(self) ],
349
- [ '/sandboxes/*', SandboxEndpoint.new(self) ],
350
- [ '/search', SearchesEndpoint.new(self) ],
351
- [ '/search/*', SearchEndpoint.new(self) ],
352
- [ '/users', ActorsEndpoint.new(self) ],
353
- [ '/users/*', ActorEndpoint.new(self) ],
354
-
355
- [ '/file_store/**', FileStoreFileEndpoint.new(self) ],
356
- ])
382
+ router = RestRouter.new(open_source_endpoints)
357
383
  router.not_found = NotFoundEndpoint.new
358
384
 
385
+ if options[:single_org]
386
+ rest_base_prefix = [ 'organizations', 'chef' ]
387
+ else
388
+ rest_base_prefix = []
389
+ end
359
390
  return proc do |env|
360
- request = RestRequest.new(env)
391
+ request = RestRequest.new(env, rest_base_prefix)
361
392
  if @on_request_proc
362
393
  @on_request_proc.call(request)
363
394
  end
@@ -387,7 +418,7 @@ module ChefZero
387
418
  def dejsonize_children(hash)
388
419
  result = {}
389
420
  hash.each_pair do |key, value|
390
- result[key] = value.is_a?(Hash) ? JSON.pretty_generate(value) : value
421
+ result[key] = value.is_a?(Hash) ? JSON.pretty_generate(value) : value
391
422
  end
392
423
  result
393
424
  end
@@ -1,3 +1,3 @@
1
1
  module ChefZero
2
- VERSION = '2.0.2'
2
+ VERSION = '2.1'
3
3
  end
data/spec/run.rb CHANGED
@@ -5,33 +5,80 @@ require 'bundler/setup'
5
5
  require 'chef_zero/server'
6
6
  require 'rspec/core'
7
7
 
8
- server = ChefZero::Server.new(:port => 8889)
9
- server.start_background
10
-
11
- unless ENV['SKIP_PEDANT']
12
- require 'pedant'
13
- require 'pedant/opensource'
14
-
15
- Pedant.config.suite = 'api'
16
- Pedant.config[:config_file] = 'spec/support/pedant.rb'
17
- Pedant.setup([
18
- '--skip-validation',
19
- '--skip-authentication',
20
- '--skip-authorization',
21
- '--skip-omnibus'
22
- ])
23
-
24
- result = RSpec::Core::Runner.run(Pedant.config.rspec_args)
25
- else
26
- require 'net/http'
27
- response = Net::HTTP.new('127.0.0.1', 8889).get("/environments", { 'Accept' => 'application/json'}).body
28
- if response =~ /_default/
29
- result = 0
8
+ tmpdir = nil
9
+
10
+ def start_server(chef_repo_path)
11
+ Dir.mkdir(chef_repo_path) if !File.exists?(chef_repo_path)
12
+
13
+ # 11.6 and below had a bug where it couldn't create the repo children automatically
14
+ if Chef::VERSION.to_f < 11.8
15
+ %w(clients cookbooks data_bags environments nodes roles users).each do |child|
16
+ Dir.mkdir("#{chef_repo_path}/#{child}") if !File.exists?("#{chef_repo_path}/#{child}")
17
+ end
18
+ end
19
+
20
+ # Start the new server
21
+ Chef::Config.repo_mode = 'everything'
22
+ Chef::Config.chef_repo_path = chef_repo_path
23
+ Chef::Config.versioned_cookbooks = true
24
+ chef_fs = Chef::ChefFS::Config.new.local_fs
25
+ data_store = Chef::ChefFS::ChefFSDataStore.new(chef_fs)
26
+ server = ChefZero::Server.new(:port => 8889, :data_store => data_store)#, :log_level => :debug)
27
+ server.start_background
28
+ server
29
+ end
30
+
31
+ begin
32
+ if ENV['CHEF_FS']
33
+ require 'chef/chef_fs/chef_fs_data_store'
34
+ require 'chef/chef_fs/config'
35
+ require 'tmpdir'
36
+ require 'fileutils'
37
+ require 'chef/version'
38
+
39
+ # Create chef repository
40
+ tmpdir = Dir.mktmpdir
41
+ chef_repo_path = "#{tmpdir}/repo"
42
+
43
+ # Capture setup data into master_chef_repo_path
44
+ server = start_server(chef_repo_path)
45
+
46
+ else
47
+ server = ChefZero::Server.new(:port => 8889)
48
+ server.start_background
49
+ end
50
+
51
+ unless ENV['SKIP_PEDANT']
52
+ require 'pedant'
53
+ require 'pedant/opensource'
54
+
55
+ #Pedant::Config.rerun = true
56
+
57
+ Pedant.config.suite = 'api'
58
+ Pedant.config[:config_file] = 'spec/support/pedant.rb'
59
+ Pedant.setup([
60
+ '--skip-knife',
61
+ '--skip-validation',
62
+ '--skip-authentication',
63
+ '--skip-authorization',
64
+ '--skip-omnibus'
65
+ ])
66
+
67
+ result = RSpec::Core::Runner.run(Pedant.config.rspec_args)
30
68
  else
31
- puts "GET /environments returned #{response}. Expected _default!"
32
- result = 1
69
+ require 'net/http'
70
+ response = Net::HTTP.new('127.0.0.1', 8889).get("/environments", { 'Accept' => 'application/json'}).body
71
+ if response =~ /_default/
72
+ result = 0
73
+ else
74
+ puts "GET /environments returned #{response}. Expected _default!"
75
+ result = 1
76
+ end
33
77
  end
78
+
79
+ server.stop if server.running?
80
+ ensure
81
+ FileUtils.remove_entry_secure(tmpdir) if tmpdir
34
82
  end
35
83
 
36
- server.stop
37
84
  exit(result)
@@ -41,6 +41,10 @@ chef_server 'http://127.0.0.1:8889'
41
41
  # differs significantly from this.
42
42
  maximum_search_time 0
43
43
 
44
+ # OSC sends erchef a host header with a port, so this option needs
45
+ # # to be enabled for Pedant tests to work correctly
46
+ explicit_port_url true
47
+
44
48
  # We're starting to break tests up into groups based on different
45
49
  # criteria. The proper API tests (the results of which are viewable
46
50
  # to OPC customers) should be the only ones run by Pedant embedded in
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-zero
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: '2.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-21 00:00:00.000000000 Z
11
+ date: 2014-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-log
@@ -105,14 +105,17 @@ files:
105
105
  - LICENSE
106
106
  - README.md
107
107
  - Rakefile
108
- - bin/chef-zero
109
- - lib/chef_zero.rb
110
108
  - lib/chef_zero/cookbook_data.rb
111
109
  - lib/chef_zero/data_normalizer.rb
112
110
  - lib/chef_zero/data_store/data_already_exists_error.rb
113
111
  - lib/chef_zero/data_store/data_error.rb
114
112
  - lib/chef_zero/data_store/data_not_found_error.rb
113
+ - lib/chef_zero/data_store/interface_v1.rb
114
+ - lib/chef_zero/data_store/interface_v2.rb
115
115
  - lib/chef_zero/data_store/memory_store.rb
116
+ - lib/chef_zero/data_store/memory_store_v2.rb
117
+ - lib/chef_zero/data_store/v1_to_v2_adapter.rb
118
+ - lib/chef_zero/data_store/v2_to_v1_adapter.rb
116
119
  - lib/chef_zero/endpoints/actor_endpoint.rb
117
120
  - lib/chef_zero/endpoints/actors_endpoint.rb
118
121
  - lib/chef_zero/endpoints/authenticate_user_endpoint.rb
@@ -159,10 +162,12 @@ files:
159
162
  - lib/chef_zero/solr/solr_doc.rb
160
163
  - lib/chef_zero/solr/solr_parser.rb
161
164
  - lib/chef_zero/version.rb
165
+ - lib/chef_zero.rb
162
166
  - spec/run.rb
163
167
  - spec/search_spec.rb
164
168
  - spec/support/pedant.rb
165
169
  - spec/support/stickywicket.pem
170
+ - bin/chef-zero
166
171
  homepage: http://www.opscode.com
167
172
  licenses:
168
173
  - Apache 2.0
@@ -183,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
188
  version: '0'
184
189
  requirements: []
185
190
  rubyforge_project:
186
- rubygems_version: 2.2.1
191
+ rubygems_version: 2.0.3
187
192
  signing_key:
188
193
  specification_version: 4
189
194
  summary: Self-contained, easy-setup, fast-start in-memory Chef server for testing