chef-zero 4.5.0 → 4.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,11 +1,11 @@
1
1
  module ChefZero
2
2
  class RestErrorResponse < StandardError
3
+ attr_reader :response_code, :error
4
+
3
5
  def initialize(response_code, error)
4
6
  @response_code = response_code
5
7
  @error = error
8
+ super "#{response_code}: #{error}"
6
9
  end
7
-
8
- attr_reader :response_code
9
- attr_reader :error
10
10
  end
11
11
  end
@@ -2,6 +2,9 @@ require 'rack/request'
2
2
 
3
3
  module ChefZero
4
4
  class RestRequest
5
+
6
+ ZERO = "0".freeze
7
+
5
8
  def initialize(env, rest_base_prefix = [])
6
9
  @env = env
7
10
  @rest_base_prefix = rest_base_prefix
@@ -19,7 +22,11 @@ module ChefZero
19
22
  end
20
23
 
21
24
  def api_version
22
- @env['HTTP_X_OPS_SERVER_API_VERSION'] || 0
25
+ @env['HTTP_X_OPS_SERVER_API_VERSION'] || ZERO
26
+ end
27
+
28
+ def api_v0?
29
+ api_version == ZERO
23
30
  end
24
31
 
25
32
  def requestor
@@ -34,6 +41,10 @@ module ChefZero
34
41
  @rest_path ||= rest_base_prefix + env['PATH_INFO'].split('/').select { |part| part != "" }
35
42
  end
36
43
 
44
+ def rest_path=(rest_path)
45
+ @rest_path = rest_path
46
+ end
47
+
37
48
  def body=(body)
38
49
  @body = body
39
50
  end
@@ -1,3 +1,5 @@
1
+ require 'pp'
2
+
1
3
  module ChefZero
2
4
  class RestRouter
3
5
  def initialize(routes)
@@ -15,24 +17,18 @@ module ChefZero
15
17
  attr_accessor :not_found
16
18
 
17
19
  def call(request)
18
- begin
19
- ChefZero::Log.debug(request)
20
- ChefZero::Log.debug(request.body) if request.body
21
-
22
- clean_path = "/" + request.rest_path.join("/")
23
-
24
- response = find_endpoint(clean_path).call(request)
25
- ChefZero::Log.debug([
26
- "",
27
- "--- RESPONSE (#{response[0]}) ---",
28
- response[2],
29
- "--- END RESPONSE ---",
30
- ].join("\n"))
31
- return response
32
- rescue
33
- ChefZero::Log.error("#{$!.inspect}\n#{$!.backtrace.join("\n")}")
34
- [500, {"Content-Type" => "text/plain"}, "Exception raised! #{$!.inspect}\n#{$!.backtrace.join("\n")}"]
20
+ log_request(request)
21
+
22
+ clean_path = "/" + request.rest_path.join("/")
23
+
24
+ find_endpoint(clean_path).call(request).tap do |response|
25
+ log_response(response)
35
26
  end
27
+ rescue => ex
28
+ exception = "#{ex.inspect}\n#{ex.backtrace.join("\n")}"
29
+
30
+ ChefZero::Log.error(exception)
31
+ [ 500, { "Content-Type" => "text/plain" }, "Exception raised! #{exception}" ]
36
32
  end
37
33
 
38
34
  private
@@ -41,5 +37,36 @@ module ChefZero
41
37
  _, endpoint = routes.find { |route, endpoint| route.match(clean_path) }
42
38
  endpoint || not_found
43
39
  end
40
+
41
+ def log_request(request)
42
+ ChefZero::Log.info do
43
+ "#{request.method} /#{request.rest_path.join("/")}".tap do |msg|
44
+ next unless request.method =~ /^(POST|PUT)$/
45
+
46
+ if request.body.nil? || request.body.empty?
47
+ msg << " (no body)"
48
+ else
49
+ msg << [
50
+ "",
51
+ "--- #{request.method} BODY ---",
52
+ request.body.chomp,
53
+ "--- END #{request.method} BODY ---"
54
+ ].join("\n")
55
+ end
56
+ end
57
+ end
58
+
59
+ ChefZero::Log.debug { request.pretty_inspect }
60
+ end
61
+
62
+ def log_response(response)
63
+ ChefZero::Log.info {
64
+ [ "",
65
+ "--- RESPONSE (#{response[0]}) ---",
66
+ response[2].chomp,
67
+ "--- END RESPONSE ---",
68
+ ].join("\n")
69
+ }
70
+ end
44
71
  end
45
72
  end
@@ -67,7 +67,7 @@ module ChefZero
67
67
  if chef_server_options[:server_scope] != self.class.chef_server_options[:server_scope]
68
68
  raise "server_scope: #{chef_server_options[:server_scope]} will not be honored: it can only be set on when_the_chef_server!"
69
69
  end
70
- Log.debug("Starting Chef server with options #{chef_server_options}")
70
+ Log.info("Starting Chef server with options #{chef_server_options}")
71
71
 
72
72
  ChefZero::RSpec.set_server_options(chef_server_options)
73
73
 
@@ -40,8 +40,14 @@ require 'chef_zero/endpoints/rest_list_endpoint'
40
40
  require 'chef_zero/endpoints/authenticate_user_endpoint'
41
41
  require 'chef_zero/endpoints/acls_endpoint'
42
42
  require 'chef_zero/endpoints/acl_endpoint'
43
- require 'chef_zero/endpoints/actors_endpoint'
44
43
  require 'chef_zero/endpoints/actor_endpoint'
44
+ require 'chef_zero/endpoints/actors_endpoint'
45
+ require 'chef_zero/endpoints/actor_key_endpoint'
46
+ require 'chef_zero/endpoints/organization_user_key_endpoint'
47
+ require 'chef_zero/endpoints/organization_user_default_key_endpoint'
48
+ require 'chef_zero/endpoints/organization_user_keys_endpoint'
49
+ require 'chef_zero/endpoints/actor_default_key_endpoint'
50
+ require 'chef_zero/endpoints/actor_keys_endpoint'
45
51
  require 'chef_zero/endpoints/cookbooks_endpoint'
46
52
  require 'chef_zero/endpoints/cookbook_endpoint'
47
53
  require 'chef_zero/endpoints/cookbook_version_endpoint'
@@ -105,9 +111,9 @@ module ChefZero
105
111
  class Server
106
112
 
107
113
  DEFAULT_OPTIONS = {
108
- :host => '127.0.0.1',
114
+ :host => ['127.0.0.1'],
109
115
  :port => 8889,
110
- :log_level => :info,
116
+ :log_level => :warn,
111
117
  :generate_real_keys => true,
112
118
  :single_org => 'chef',
113
119
  :ssl => false
@@ -136,6 +142,7 @@ module ChefZero
136
142
  def port
137
143
  if @port
138
144
  @port
145
+ # If options[:port] is not an Array or an Enumerable, it is just an Integer.
139
146
  elsif !options[:port].respond_to?(:each)
140
147
  options[:port]
141
148
  else
@@ -158,10 +165,11 @@ module ChefZero
158
165
  #
159
166
  def url
160
167
  sch = @options[:ssl] ? 'https' : 'http'
161
- @url ||= if @options[:host].include?(':')
162
- URI("#{sch}://[#{@options[:host]}]:#{port}").to_s
168
+ hosts = Array(@options[:host])
169
+ @url ||= if hosts.first.include?(':')
170
+ URI("#{sch}://[#{hosts.first}]:#{port}").to_s
163
171
  else
164
- URI("#{sch}://#{@options[:host]}:#{port}").to_s
172
+ URI("#{sch}://#{hosts.first}:#{port}").to_s
165
173
  end
166
174
  end
167
175
 
@@ -259,6 +267,18 @@ module ChefZero
259
267
  # @return [Thread]
260
268
  # the thread the background process is running in
261
269
  #
270
+ def listen(hosts, port)
271
+ hosts.each do |host|
272
+ @server.listen(host, port)
273
+ end
274
+ true
275
+ rescue Errno::EADDRINUSE
276
+ ChefZero::Log.warn("Port #{port} not available")
277
+ @server.listeners.each { |l| l.close }
278
+ @server.listeners.clear
279
+ false
280
+ end
281
+
262
282
  def start_background(wait = 5)
263
283
  @server = WEBrick::HTTPServer.new(
264
284
  :DoNotListen => true,
@@ -274,22 +294,17 @@ module ChefZero
274
294
  @server.mount('/', Rack::Handler::WEBrick, app)
275
295
 
276
296
  # Pick a port
277
- if options[:port].respond_to?(:each)
278
- options[:port].each do |port|
279
- begin
280
- @server.listen(options[:host], port)
281
- @port = port
282
- break
283
- rescue Errno::EADDRINUSE
284
- ChefZero::Log.info("Port #{port} in use: #{$!}")
285
- end
286
- end
287
- if !@port
288
- raise Errno::EADDRINUSE, "No port in :port range #{options[:port]} is available"
297
+ # If options[:port] can be an Enumerator, an Array, or an Integer,
298
+ # we need something that can respond to .each (Enum and Array can already).
299
+ Array(options[:port]).each do |port|
300
+ if listen(Array(options[:host]), port)
301
+ @port = port
302
+ break
289
303
  end
290
- else
291
- @server.listen(options[:host], options[:port])
292
- @port = options[:port]
304
+ end
305
+ if !@port
306
+ raise Errno::EADDRINUSE,
307
+ "No port in :port range #{options[:port]} is available"
293
308
  end
294
309
 
295
310
  # Start the server in the background
@@ -523,7 +538,7 @@ module ChefZero
523
538
  [
524
539
  [ "/organizations/*/users", ActorsEndpoint.new(self) ],
525
540
  [ "/organizations/*/users/*", ActorEndpoint.new(self) ],
526
- [ "/organizations/*/authenticate_user", OrganizationAuthenticateUserEndpoint.new(self) ],
541
+ [ "/organizations/*/authenticate_user", OrganizationAuthenticateUserEndpoint.new(self) ]
527
542
  ]
528
543
  else
529
544
  # EC-only
@@ -537,11 +552,13 @@ module ChefZero
537
552
  [ "/users/*/association_requests", UserAssociationRequestsEndpoint.new(self) ],
538
553
  [ "/users/*/association_requests/count", UserAssociationRequestsCountEndpoint.new(self) ],
539
554
  [ "/users/*/association_requests/*", UserAssociationRequestEndpoint.new(self) ],
555
+ [ "/users/*/keys", ActorKeysEndpoint.new(self) ],
556
+ [ "/users/*/keys/default", ActorDefaultKeyEndpoint.new(self) ],
557
+ [ "/users/*/keys/*", ActorKeyEndpoint.new(self) ],
540
558
  [ "/users/*/organizations", UserOrganizationsEndpoint.new(self) ],
541
559
  [ "/authenticate_user", AuthenticateUserEndpoint.new(self) ],
542
560
  [ "/system_recovery", SystemRecoveryEndpoint.new(self) ],
543
561
  [ "/license", LicenseEndpoint.new(self) ],
544
-
545
562
  [ "/organizations", OrganizationsEndpoint.new(self) ],
546
563
  [ "/organizations/*", OrganizationEndpoint.new(self) ],
547
564
  [ "/organizations/*/_validator_key", OrganizationValidatorKeyEndpoint.new(self) ],
@@ -564,6 +581,12 @@ module ChefZero
564
581
  [ "/dummy", DummyEndpoint.new(self) ],
565
582
  [ "/organizations/*/clients", ActorsEndpoint.new(self) ],
566
583
  [ "/organizations/*/clients/*", ActorEndpoint.new(self) ],
584
+ [ "/organizations/*/clients/*/keys", ActorKeysEndpoint.new(self) ],
585
+ [ "/organizations/*/clients/*/keys/default", ActorDefaultKeyEndpoint.new(self) ],
586
+ [ "/organizations/*/clients/*/keys/*", ActorKeyEndpoint.new(self) ],
587
+ [ "/organizations/*/users/*/keys", OrganizationUserKeysEndpoint.new(self) ],
588
+ [ "/organizations/*/users/*/keys/default", OrganizationUserDefaultKeyEndpoint.new(self) ],
589
+ [ "/organizations/*/users/*/keys/*", OrganizationUserKeyEndpoint.new(self) ],
567
590
  [ "/organizations/*/controls", ControlsEndpoint.new(self) ],
568
591
  [ "/organizations/*/cookbooks", CookbooksEndpoint.new(self) ],
569
592
  [ "/organizations/*/cookbooks/*", CookbookEndpoint.new(self) ],
@@ -1,3 +1,3 @@
1
1
  module ChefZero
2
- VERSION = '4.5.0'
2
+ VERSION = '4.6.0'
3
3
  end
@@ -5,6 +5,42 @@ require 'bundler/setup'
5
5
  require 'chef_zero/server'
6
6
  require 'rspec/core'
7
7
 
8
+ # This file runs oc-chef-pedant specs and is invoked by `rake pedant`
9
+ # and other Rake tasks. Run `rake -T` to list tasks.
10
+ #
11
+ # Options for oc-chef-pedant and rspec can be specified via
12
+ # ENV['PEDANT_OPTS'] and ENV['RSPEC_OPTS'], respectively.
13
+ #
14
+ # The log level can be specified via ENV['LOG_LEVEL'].
15
+ #
16
+ # Example:
17
+ #
18
+ # $ PEDANT_OPTS="--focus-users --skip-keys" \
19
+ # > RSPEC_OPTS="--fail-fast --profile 5" \
20
+ # > LOG_LEVEL=debug \
21
+ # > rake pedant
22
+ #
23
+
24
+ DEFAULT_SERVER_OPTIONS = {
25
+ port: 8889,
26
+ single_org: false,
27
+ }.freeze
28
+
29
+ DEFAULT_LOG_LEVEL = :warn
30
+
31
+ def log_level
32
+ return ENV['LOG_LEVEL'].downcase.to_sym if ENV['LOG_LEVEL']
33
+ return :debug if ENV['DEBUG']
34
+ DEFAULT_LOG_LEVEL
35
+ end
36
+
37
+ def start_chef_server(opts={})
38
+ opts = DEFAULT_SERVER_OPTIONS.merge(opts)
39
+ opts[:log_level] = log_level
40
+
41
+ ChefZero::Server.new(opts).tap {|server| server.start_background }
42
+ end
43
+
8
44
  def start_cheffs_server(chef_repo_path)
9
45
  require 'chef/version'
10
46
  require 'chef/config'
@@ -34,37 +70,42 @@ def start_cheffs_server(chef_repo_path)
34
70
  data_store.set(%w(organizations pedant-testorg groups admins), '{ "users": [ "pivotal" ] }')
35
71
  data_store.set(%w(organizations pedant-testorg groups users), '{ "users": [ "pivotal" ] }')
36
72
 
37
- server = ChefZero::Server.new(
38
- port: 8889,
39
- data_store: data_store,
40
- single_org: false,
41
- #log_level: :debug
42
- )
43
- server.start_background
44
- server
73
+ start_chef_server(data_store: data_store)
45
74
  end
46
75
 
47
- tmpdir = nil
76
+ def pedant_args_from_env
77
+ args_from_env('PEDANT_OPTS')
78
+ end
79
+
80
+ def rspec_args_from_env
81
+ args_from_env('RSPEC_OPTS')
82
+ end
83
+
84
+ def args_from_env(key)
85
+ return [] unless ENV[key]
86
+ ENV[key].split
87
+ end
48
88
 
49
89
  begin
50
- if ENV['FILE_STORE']
51
- require 'tmpdir'
52
- require 'chef_zero/data_store/raw_file_store'
53
- tmpdir = Dir.mktmpdir
54
- data_store = ChefZero::DataStore::RawFileStore.new(tmpdir, true)
55
- data_store = ChefZero::DataStore::DefaultFacade.new(data_store, false, false)
56
- server = ChefZero::Server.new(:port => 8889, :single_org => false, :data_store => data_store)
57
- server.start_background
58
-
59
- elsif ENV['CHEF_FS']
60
- require 'tmpdir'
61
- tmpdir = Dir.mktmpdir
62
- server = start_cheffs_server(tmpdir)
90
+ tmpdir = nil
91
+ server =
92
+ if ENV['FILE_STORE']
93
+ require 'tmpdir'
94
+ require 'chef_zero/data_store/raw_file_store'
95
+ tmpdir = Dir.mktmpdir
96
+ data_store = ChefZero::DataStore::RawFileStore.new(tmpdir, true)
97
+ data_store = ChefZero::DataStore::DefaultFacade.new(data_store, false, false)
98
+
99
+ start_chef_server(data_store: data_store)
100
+
101
+ elsif ENV['CHEF_FS']
102
+ require 'tmpdir'
103
+ tmpdir = Dir.mktmpdir
104
+ start_cheffs_server(tmpdir)
63
105
 
64
- else
65
- server = ChefZero::Server.new(:port => 8889, :single_org => false)#, :log_level => :debug)
66
- server.start_background
67
- end
106
+ else
107
+ start_chef_server
108
+ end
68
109
 
69
110
  require 'rspec/core'
70
111
  require 'pedant'
@@ -83,6 +124,7 @@ begin
83
124
  '--skip-users',
84
125
  '--skip-organizations',
85
126
  '--skip-multiuser',
127
+ '--skip-user-keys',
86
128
 
87
129
  # chef-zero has some non-removable quirks, such as the fact that files
88
130
  # with 255-character names cannot be stored in local mode. This is
@@ -98,13 +140,17 @@ begin
98
140
  chef_fs_skips << '--skip-cookbook-artifacts'
99
141
  chef_fs_skips << '--skip-policies'
100
142
 
143
+ # Multi-keys don't work prior to 12.8
144
+ unless Gem::Requirement.new(">= 12.8.0").satisfied_by?(Gem::Version.new(Chef::VERSION))
145
+ chef_fs_skips << '--skip-keys'
146
+ end
147
+
101
148
  # These things aren't supported by Chef Zero in any mode of operation:
102
149
  default_skips = [
103
150
  # "the goal is that only authorization, authentication and validation tests
104
151
  # are turned off" - @jkeiser
105
152
  #
106
153
  # ...but we're not there yet
107
- '--skip-keys',
108
154
 
109
155
  # Chef Zero does not intend to support validation the way erchef does.
110
156
  '--skip-validation',
@@ -128,7 +174,6 @@ begin
128
174
  '--skip-usags',
129
175
 
130
176
  # Chef 12 features not yet 100% supported by Chef Zero
131
- '--skip-api-v1',
132
177
 
133
178
  # The universe endpoint is unlikely to ever make sense for Chef Zero
134
179
  '--skip-universe',
@@ -143,12 +188,10 @@ begin
143
188
  default_skips + chef_fs_skips + %w{ --skip-knife }
144
189
  end
145
190
 
146
- Pedant.setup(pedant_args)
147
-
148
- fail_fast = %w()#--fail-fast)
149
- #fail_fast = ["--fail-fast"]
191
+ Pedant.setup(pedant_args + pedant_args_from_env)
150
192
 
151
- result = RSpec::Core::Runner.run(Pedant.config.rspec_args + fail_fast)
193
+ rspec_args = Pedant.config.rspec_args + rspec_args_from_env
194
+ result = RSpec::Core::Runner.run(rspec_args)
152
195
 
153
196
  server.stop if server.running?
154
197
  ensure
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: 4.5.0
4
+ version: 4.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-29 00:00:00.000000000 Z
11
+ date: 2016-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-log
@@ -156,20 +156,6 @@ dependencies:
156
156
  - - ">="
157
157
  - !ruby/object:Gem::Version
158
158
  version: '0'
159
- - !ruby/object:Gem::Dependency
160
- name: github_changelog_generator
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - ">="
164
- - !ruby/object:Gem::Version
165
- version: '0'
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - ">="
171
- - !ruby/object:Gem::Version
172
- version: '0'
173
159
  - !ruby/object:Gem::Dependency
174
160
  name: chef
175
161
  requirement: !ruby/object:Gem::Requirement
@@ -216,7 +202,10 @@ files:
216
202
  - lib/chef_zero/data_store/v2_to_v1_adapter.rb
217
203
  - lib/chef_zero/endpoints/acl_endpoint.rb
218
204
  - lib/chef_zero/endpoints/acls_endpoint.rb
205
+ - lib/chef_zero/endpoints/actor_default_key_endpoint.rb
219
206
  - lib/chef_zero/endpoints/actor_endpoint.rb
207
+ - lib/chef_zero/endpoints/actor_key_endpoint.rb
208
+ - lib/chef_zero/endpoints/actor_keys_endpoint.rb
220
209
  - lib/chef_zero/endpoints/actors_endpoint.rb
221
210
  - lib/chef_zero/endpoints/authenticate_user_endpoint.rb
222
211
  - lib/chef_zero/endpoints/container_endpoint.rb
@@ -253,7 +242,10 @@ files:
253
242
  - lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb
254
243
  - lib/chef_zero/endpoints/organization_endpoint.rb
255
244
  - lib/chef_zero/endpoints/organization_user_base.rb
245
+ - lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb
256
246
  - lib/chef_zero/endpoints/organization_user_endpoint.rb
247
+ - lib/chef_zero/endpoints/organization_user_key_endpoint.rb
248
+ - lib/chef_zero/endpoints/organization_user_keys_endpoint.rb
257
249
  - lib/chef_zero/endpoints/organization_users_endpoint.rb
258
250
  - lib/chef_zero/endpoints/organization_validator_key_endpoint.rb
259
251
  - lib/chef_zero/endpoints/organizations_endpoint.rb
@@ -316,7 +308,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
316
308
  requirements:
317
309
  - - ">="
318
310
  - !ruby/object:Gem::Version
319
- version: '0'
311
+ version: 2.1.0
320
312
  required_rubygems_version: !ruby/object:Gem::Requirement
321
313
  requirements:
322
314
  - - ">="