chef-zero 4.2.3 → 4.3.0

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.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +201 -201
  3. data/README.md +155 -150
  4. data/Rakefile +31 -31
  5. data/bin/chef-zero +100 -100
  6. data/lib/chef_zero.rb +10 -7
  7. data/lib/chef_zero/chef_data/acl_path.rb +139 -139
  8. data/lib/chef_zero/chef_data/cookbook_data.rb +240 -240
  9. data/lib/chef_zero/chef_data/data_normalizer.rb +207 -207
  10. data/lib/chef_zero/chef_data/default_creator.rb +446 -446
  11. data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
  12. data/lib/chef_zero/data_store/data_error.rb +31 -31
  13. data/lib/chef_zero/data_store/data_not_found_error.rb +28 -28
  14. data/lib/chef_zero/data_store/default_facade.rb +149 -149
  15. data/lib/chef_zero/data_store/interface_v1.rb +67 -67
  16. data/lib/chef_zero/data_store/interface_v2.rb +18 -18
  17. data/lib/chef_zero/data_store/memory_store.rb +33 -33
  18. data/lib/chef_zero/data_store/memory_store_v2.rb +155 -155
  19. data/lib/chef_zero/data_store/raw_file_store.rb +147 -147
  20. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +142 -142
  21. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +107 -107
  22. data/lib/chef_zero/endpoints/acl_endpoint.rb +38 -38
  23. data/lib/chef_zero/endpoints/acls_endpoint.rb +29 -29
  24. data/lib/chef_zero/endpoints/actor_endpoint.rb +94 -88
  25. data/lib/chef_zero/endpoints/actors_endpoint.rb +64 -64
  26. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +31 -31
  27. data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
  28. data/lib/chef_zero/endpoints/containers_endpoint.rb +13 -13
  29. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
  30. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +119 -119
  31. data/lib/chef_zero/endpoints/cookbooks_base.rb +65 -65
  32. data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
  33. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
  34. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
  35. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
  36. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
  37. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +123 -123
  38. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
  39. data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
  40. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
  41. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
  42. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
  43. data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
  44. data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
  45. data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
  46. data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
  47. data/lib/chef_zero/endpoints/node_endpoint.rb +17 -17
  48. data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -0
  49. data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
  50. data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
  51. data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -29
  52. data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
  53. data/lib/chef_zero/endpoints/organization_endpoint.rb +46 -41
  54. data/lib/chef_zero/endpoints/organization_user_base.rb +15 -0
  55. data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -48
  56. data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -14
  57. data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
  58. data/lib/chef_zero/endpoints/organizations_endpoint.rb +62 -55
  59. data/lib/chef_zero/endpoints/policies_endpoint.rb +151 -154
  60. data/lib/chef_zero/endpoints/principal_endpoint.rb +42 -42
  61. data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
  62. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +63 -63
  63. data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
  64. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
  65. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
  66. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +50 -50
  67. data/lib/chef_zero/endpoints/search_endpoint.rb +194 -192
  68. data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
  69. data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -0
  70. data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
  71. data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +40 -40
  72. data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
  73. data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
  74. data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
  75. data/lib/chef_zero/endpoints/version_endpoint.rb +12 -12
  76. data/lib/chef_zero/log.rb +7 -7
  77. data/lib/chef_zero/rest_base.rb +242 -214
  78. data/lib/chef_zero/rest_error_response.rb +11 -11
  79. data/lib/chef_zero/rest_request.rb +69 -65
  80. data/lib/chef_zero/rest_router.rb +45 -45
  81. data/lib/chef_zero/rspec.rb +308 -308
  82. data/lib/chef_zero/server.rb +642 -637
  83. data/lib/chef_zero/socketless_server_map.rb +92 -92
  84. data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
  85. data/lib/chef_zero/solr/query/phrase.rb +23 -23
  86. data/lib/chef_zero/solr/query/range_query.rb +46 -46
  87. data/lib/chef_zero/solr/query/regexpable_query.rb +29 -29
  88. data/lib/chef_zero/solr/query/subquery.rb +37 -37
  89. data/lib/chef_zero/solr/query/term.rb +45 -45
  90. data/lib/chef_zero/solr/query/unary_operator.rb +43 -43
  91. data/lib/chef_zero/solr/solr_doc.rb +53 -53
  92. data/lib/chef_zero/solr/solr_parser.rb +203 -203
  93. data/lib/chef_zero/version.rb +3 -3
  94. data/spec/run_oc_pedant.rb +63 -56
  95. data/spec/search_spec.rb +32 -32
  96. data/spec/server_spec.rb +92 -91
  97. data/spec/socketless_server_map_spec.rb +76 -76
  98. data/spec/support/oc_pedant.rb +132 -134
  99. data/spec/support/stickywicket.pem +27 -27
  100. metadata +10 -15
  101. data/spec/run_pedant.rb +0 -103
  102. data/spec/support/pedant.rb +0 -129
@@ -1,11 +1,11 @@
1
- module ChefZero
2
- class RestErrorResponse < StandardError
3
- def initialize(response_code, error)
4
- @response_code = response_code
5
- @error = error
6
- end
7
-
8
- attr_reader :response_code
9
- attr_reader :error
10
- end
11
- end
1
+ module ChefZero
2
+ class RestErrorResponse < StandardError
3
+ def initialize(response_code, error)
4
+ @response_code = response_code
5
+ @error = error
6
+ end
7
+
8
+ attr_reader :response_code
9
+ attr_reader :error
10
+ end
11
+ end
@@ -1,65 +1,69 @@
1
- require 'rack/request'
2
-
3
- module ChefZero
4
- class RestRequest
5
- def initialize(env, rest_base_prefix = [])
6
- @env = env
7
- @rest_base_prefix = rest_base_prefix
8
- end
9
-
10
- attr_reader :env
11
- attr_accessor :rest_base_prefix
12
-
13
- def base_uri
14
- @base_uri ||= "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['SCRIPT_NAME']}"
15
- end
16
-
17
- def base_uri=(value)
18
- @base_uri = value
19
- end
20
-
21
- def requestor
22
- @env['HTTP_X_OPS_USERID']
23
- end
24
-
25
- def method
26
- @env['REQUEST_METHOD']
27
- end
28
-
29
- def rest_path
30
- @rest_path ||= rest_base_prefix + env['PATH_INFO'].split('/').select { |part| part != "" }
31
- end
32
-
33
- def body=(body)
34
- @body = body
35
- end
36
-
37
- def body
38
- @body ||= env['rack.input'].read
39
- end
40
-
41
- def query_params
42
- @query_params ||= begin
43
- params = Rack::Request.new(env).GET
44
- params.keys.each do |key|
45
- params[key] = URI.unescape(params[key])
46
- end
47
- params
48
- end
49
- end
50
-
51
- def to_s
52
- result = "#{method} #{rest_path.join('/')}"
53
- if query_params.size > 0
54
- result << "?#{query_params.map { |k,v| "#{k}=#{v}" }.join('&') }"
55
- end
56
- if body.chomp != ''
57
- result << "\n--- #{method} BODY ---\n"
58
- result << body
59
- result << "\n" if !body.end_with?("\n")
60
- result << "--- END #{method} BODY ---"
61
- end
62
- result
63
- end
64
- end
65
- end
1
+ require 'rack/request'
2
+
3
+ module ChefZero
4
+ class RestRequest
5
+ def initialize(env, rest_base_prefix = [])
6
+ @env = env
7
+ @rest_base_prefix = rest_base_prefix
8
+ end
9
+
10
+ attr_reader :env
11
+ attr_accessor :rest_base_prefix
12
+
13
+ def base_uri
14
+ @base_uri ||= "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['SCRIPT_NAME']}"
15
+ end
16
+
17
+ def base_uri=(value)
18
+ @base_uri = value
19
+ end
20
+
21
+ def api_version
22
+ @env['HTTP_X_OPS_SERVER_API_VERSION'] || 0
23
+ end
24
+
25
+ def requestor
26
+ @env['HTTP_X_OPS_USERID']
27
+ end
28
+
29
+ def method
30
+ @env['REQUEST_METHOD']
31
+ end
32
+
33
+ def rest_path
34
+ @rest_path ||= rest_base_prefix + env['PATH_INFO'].split('/').select { |part| part != "" }
35
+ end
36
+
37
+ def body=(body)
38
+ @body = body
39
+ end
40
+
41
+ def body
42
+ @body ||= env['rack.input'].read
43
+ end
44
+
45
+ def query_params
46
+ @query_params ||= begin
47
+ params = Rack::Request.new(env).GET
48
+ params.keys.each do |key|
49
+ params[key] = URI.unescape(params[key])
50
+ end
51
+ params
52
+ end
53
+ end
54
+
55
+ def to_s
56
+ result = "#{method} #{rest_path.join('/')}"
57
+ if query_params.size > 0
58
+ result << "?#{query_params.map { |k,v| "#{k}=#{v}" }.join('&') }"
59
+ end
60
+ if body.chomp != ''
61
+ result << "\n--- #{method} BODY ---\n"
62
+ result << body
63
+ result << "\n" if !body.end_with?("\n")
64
+ result << "--- END #{method} BODY ---"
65
+ end
66
+ result
67
+ end
68
+ end
69
+ end
@@ -1,45 +1,45 @@
1
- module ChefZero
2
- class RestRouter
3
- def initialize(routes)
4
- @routes = routes.map do |route, endpoint|
5
- if route =~ /\*\*$/
6
- pattern = Regexp.new("^#{route[0..-3].gsub('*', '[^/]*')}")
7
- else
8
- pattern = Regexp.new("^#{route.gsub('*', '[^/]*')}$")
9
- end
10
- [ pattern, endpoint ]
11
- end
12
- end
13
-
14
- attr_reader :routes
15
- attr_accessor :not_found
16
-
17
- 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")}"]
35
- end
36
- end
37
-
38
- private
39
-
40
- def find_endpoint(clean_path)
41
- _, endpoint = routes.find { |route, endpoint| route.match(clean_path) }
42
- endpoint || not_found
43
- end
44
- end
45
- end
1
+ module ChefZero
2
+ class RestRouter
3
+ def initialize(routes)
4
+ @routes = routes.map do |route, endpoint|
5
+ if route =~ /\*\*$/
6
+ pattern = Regexp.new("^#{route[0..-3].gsub('*', '[^/]*')}")
7
+ else
8
+ pattern = Regexp.new("^#{route.gsub('*', '[^/]*')}$")
9
+ end
10
+ [ pattern, endpoint ]
11
+ end
12
+ end
13
+
14
+ attr_reader :routes
15
+ attr_accessor :not_found
16
+
17
+ 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")}"]
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def find_endpoint(clean_path)
41
+ _, endpoint = routes.find { |route, endpoint| route.match(clean_path) }
42
+ endpoint || not_found
43
+ end
44
+ end
45
+ end
@@ -1,308 +1,308 @@
1
- require 'tempfile'
2
- require 'chef_zero/server'
3
- require 'chef_zero/rest_request'
4
-
5
- module ChefZero
6
- module RSpec
7
- module RSpecClassMethods
8
- attr_accessor :server
9
- attr_accessor :client_key
10
- attr_reader :request_log
11
-
12
- def clear_request_log
13
- @request_log = []
14
- end
15
-
16
- def set_server_options(chef_server_options)
17
- if server && chef_server_options != server.options
18
- server.stop
19
- self.server = nil
20
- end
21
-
22
- unless server
23
- # TODO: can this be logged easily?
24
- # pp :zero_opts => chef_server_options
25
-
26
- # Set up configuration so that clients will point to the server
27
- self.server = ChefZero::Server.new(chef_server_options)
28
- self.client_key = Tempfile.new(['chef_zero_client_key', '.pem'])
29
- client_key.write(ChefZero::PRIVATE_KEY)
30
- client_key.close
31
- # Start the server
32
- server.start_background
33
- server.on_response do |request, response|
34
- request_log << [ request, response ]
35
- end
36
- else
37
- server.clear_data
38
- end
39
- clear_request_log
40
- end
41
- end
42
- extend RSpecClassMethods
43
-
44
- def when_the_chef_server(description, *tags, &block)
45
- context "When the Chef server #{description}", *tags do
46
- extend WhenTheChefServerClassMethods
47
- include WhenTheChefServerInstanceMethods
48
-
49
- # Take the passed-in options
50
-
51
- define_singleton_method(:chef_server_options) {
52
- @chef_server_options ||= begin
53
- _chef_server_options = { port: 8900, signals: false, log_requests: true }
54
- _chef_server_options = _chef_server_options.merge(tags.last) if tags.last.is_a?(Hash)
55
- _chef_server_options = _chef_server_options.freeze
56
- end
57
- }
58
-
59
- # Merge in chef_server_options from let(:chef_server_options)
60
- def chef_server_options
61
- chef_server_options = self.class.chef_server_options.dup
62
- chef_server_options = chef_server_options.merge(chef_zero_opts) if self.respond_to?(:chef_zero_opts)
63
- chef_server_options
64
- end
65
-
66
- before chef_server_options[:server_scope] do
67
- if chef_server_options[:server_scope] != self.class.chef_server_options[:server_scope]
68
- raise "server_scope: #{chef_server_options[:server_scope]} will not be honored: it can only be set on when_the_chef_server!"
69
- end
70
- Log.debug("Starting Chef server with options #{chef_server_options}")
71
-
72
- ChefZero::RSpec.set_server_options(chef_server_options)
73
-
74
- if chef_server_options[:organization]
75
- organization chef_server_options[:organization]
76
- end
77
-
78
- if defined?(Chef::Config)
79
- @old_chef_server_url = Chef::Config.chef_server_url
80
- @old_node_name = Chef::Config.node_name
81
- @old_client_key = Chef::Config.client_key
82
- if chef_server_options[:organization]
83
- Chef::Config.chef_server_url = "#{ChefZero::RSpec.server.url}/organizations/#{chef_server_options[:organization]}"
84
- else
85
- Chef::Config.chef_server_url = ChefZero::RSpec.server.url
86
- end
87
- Chef::Config.node_name = 'admin'
88
- Chef::Config.client_key = ChefZero::RSpec.client_key.path
89
- Chef::Config.http_retry_count = 0
90
- end
91
- end
92
-
93
- if defined?(Chef::Config)
94
- after chef_server_options[:server_scope] do
95
- Chef::Config.chef_server_url = @old_chef_server_url
96
- Chef::Config.node_name = @old_node_name
97
- Chef::Config.client_key = @old_client_key
98
- end
99
- end
100
-
101
- instance_eval(&block)
102
- end
103
- end
104
-
105
- module WhenTheChefServerClassMethods
106
- def organization(name, org = '{}', &block)
107
- before(chef_server_options[:server_scope]) { organization(name, org, &block) }
108
- end
109
-
110
- def acl_for(path, data)
111
- before(chef_server_options[:server_scope]) { acl_for(path, data) }
112
- end
113
-
114
- def client(name, data, &block)
115
- before(chef_server_options[:server_scope]) { client(name, data, &block) }
116
- end
117
-
118
- def container(name, data, &block)
119
- before(chef_server_options[:server_scope]) { container(name, data, &block) }
120
- end
121
-
122
- def cookbook(name, version, data = {}, options = {}, &block)
123
- before(chef_server_options[:server_scope]) do
124
- cookbook(name, version, data, &block)
125
- end
126
- end
127
-
128
- def data_bag(name, data, &block)
129
- before(chef_server_options[:server_scope]) { data_bag(name, data, &block) }
130
- end
131
-
132
- def environment(name, data, &block)
133
- before(chef_server_options[:server_scope]) { environment(name, data, &block) }
134
- end
135
-
136
- def group(name, data, &block)
137
- before(chef_server_options[:server_scope]) { group(name, data, &block) }
138
- end
139
-
140
- def node(name, data, &block)
141
- before(chef_server_options[:server_scope]) { node(name, data, &block) }
142
- end
143
-
144
- def org_invite(*usernames)
145
- before(chef_server_options[:server_scope]) { org_invite(*usernames) }
146
- end
147
-
148
- def org_member(*usernames)
149
- before(chef_server_options[:server_scope]) { org_member(*usernames) }
150
- end
151
-
152
- def role(name, data, &block)
153
- before(chef_server_options[:server_scope]) { role(name, data, &block) }
154
- end
155
-
156
- def sandbox(name, data, &block)
157
- before(chef_server_options[:server_scope]) { sandbox(name, data, &block) }
158
- end
159
-
160
- def user(name, data, &block)
161
- before(chef_server_options[:server_scope]) { user(name, data, &block) }
162
- end
163
- end
164
-
165
- module WhenTheChefServerInstanceMethods
166
- def organization(name, org = '{}', &block)
167
- ChefZero::RSpec.server.data_store.set([ 'organizations', name, 'org' ], dejsonize(org), :create_dir, :create)
168
- prev_org_name = @current_org
169
- @current_org = name
170
- prev_object_path = @current_object_path
171
- @current_object_path = "organizations/#{name}"
172
- if block_given?
173
- begin
174
- instance_eval(&block)
175
- ensure
176
- @current_org = prev_org_name
177
- @current_object_path = prev_object_path
178
- end
179
- end
180
- end
181
-
182
- def acl_for(path, data)
183
- ChefZero::RSpec.server.load_data({ 'acls' => { path => data } }, current_org)
184
- end
185
-
186
- def acl(data)
187
- acl_for(@current_object_path, data)
188
- end
189
-
190
- def client(name, data, &block)
191
- with_object_path("clients/#{name}") do
192
- ChefZero::RSpec.server.load_data({ 'clients' => { name => data } }, current_org)
193
- instance_eval(&block) if block_given?
194
- end
195
- end
196
-
197
- def container(name, data, &block)
198
- with_object_path("containers/#{name}") do
199
- ChefZero::RSpec.server.load_data({ 'containers' => { name => data } }, current_org)
200
- instance_eval(&block) if block_given?
201
- end
202
- end
203
-
204
- def cookbook(name, version, data = {}, options = {}, &block)
205
- with_object_path("cookbooks/#{name}") do
206
- if data.has_key?('metadata.rb')
207
- if data['metadata.rb'].nil?
208
- data.delete('metadata.rb')
209
- end
210
- else
211
- data['metadata.rb'] = "name #{name.inspect}; version #{version.inspect}"
212
- end
213
- ChefZero::RSpec.server.load_data({ 'cookbooks' => { "#{name}-#{version}" => data.merge(options) }}, current_org)
214
- instance_eval(&block) if block_given?
215
- end
216
- end
217
-
218
- def data_bag(name, data, &block)
219
- with_object_path("data/#{name}") do
220
- ChefZero::RSpec.server.load_data({ 'data' => { name => data }}, current_org)
221
- instance_eval(&block) if block_given?
222
- end
223
- end
224
-
225
- def environment(name, data, &block)
226
- with_object_path("environments/#{name}") do
227
- ChefZero::RSpec.server.load_data({ 'environments' => { name => data } }, current_org)
228
- instance_eval(&block) if block_given?
229
- end
230
- end
231
-
232
- def group(name, data, &block)
233
- with_object_path("groups/#{name}") do
234
- ChefZero::RSpec.server.load_data({ 'groups' => { name => data } }, current_org)
235
- instance_eval(&block) if block_given?
236
- end
237
- end
238
-
239
- def node(name, data, &block)
240
- with_object_path("nodes/#{name}") do
241
- ChefZero::RSpec.server.load_data({ 'nodes' => { name => data } }, current_org)
242
- instance_eval(&block) if block_given?
243
- end
244
- end
245
-
246
- def org_invite(*usernames)
247
- ChefZero::RSpec.server.load_data({ 'invites' => usernames }, current_org)
248
- end
249
-
250
- def org_member(*usernames)
251
- ChefZero::RSpec.server.load_data({ 'members' => usernames }, current_org)
252
- end
253
-
254
- def role(name, data, &block)
255
- with_object_path("roles/#{name}") do
256
- ChefZero::RSpec.server.load_data({ 'roles' => { name => data } }, current_org)
257
- instance_eval(&block) if block_given?
258
- end
259
- end
260
-
261
- def sandbox(name, data, &block)
262
- with_object_path("sandboxes/#{name}") do
263
- ChefZero::RSpec.server.load_data({ 'sandboxes' => { name => data } }, current_org)
264
- instance_eval(&block) if block_given?
265
- end
266
- end
267
-
268
- def user(name, data, &block)
269
- if ChefZero::RSpec.server.options[:osc_compat]
270
- with_object_path("users/#{name}") do
271
- ChefZero::RSpec.server.load_data({ 'users' => { name => data }}, current_org)
272
- instance_eval(&block) if block_given?
273
- end
274
- else
275
- old_object_path = @current_object_path
276
- @current_object_path = "users/#{name}"
277
- begin
278
- ChefZero::RSpec.server.load_data({ 'users' => { name => data }}, current_org)
279
- instance_eval(&block) if block_given?
280
- ensure
281
- @current_object_path = old_object_path
282
- end
283
- end
284
- end
285
-
286
- def dejsonize(data)
287
- if data.is_a?(String)
288
- data
289
- else
290
- FFI_Yajl::Encoder.encode(data, :pretty => true)
291
- end
292
- end
293
-
294
- def current_org
295
- @current_org || ChefZero::RSpec.server.options[:single_org] || nil
296
- end
297
-
298
- def with_object_path(object_path)
299
- old_object_path = @current_object_path
300
- @current_object_path = object_path
301
- begin
302
- yield if block_given?
303
- end
304
- @current_object_path = old_object_path
305
- end
306
- end
307
- end
308
- end
1
+ require 'tempfile'
2
+ require 'chef_zero/server'
3
+ require 'chef_zero/rest_request'
4
+
5
+ module ChefZero
6
+ module RSpec
7
+ module RSpecClassMethods
8
+ attr_accessor :server
9
+ attr_accessor :client_key
10
+ attr_reader :request_log
11
+
12
+ def clear_request_log
13
+ @request_log = []
14
+ end
15
+
16
+ def set_server_options(chef_server_options)
17
+ if server && chef_server_options != server.options
18
+ server.stop
19
+ self.server = nil
20
+ end
21
+
22
+ unless server
23
+ # TODO: can this be logged easily?
24
+ # pp :zero_opts => chef_server_options
25
+
26
+ # Set up configuration so that clients will point to the server
27
+ self.server = ChefZero::Server.new(chef_server_options)
28
+ self.client_key = Tempfile.new(['chef_zero_client_key', '.pem'])
29
+ client_key.write(ChefZero::PRIVATE_KEY)
30
+ client_key.close
31
+ # Start the server
32
+ server.start_background
33
+ server.on_response do |request, response|
34
+ request_log << [ request, response ]
35
+ end
36
+ else
37
+ server.clear_data
38
+ end
39
+ clear_request_log
40
+ end
41
+ end
42
+ extend RSpecClassMethods
43
+
44
+ def when_the_chef_server(description, *tags, &block)
45
+ context "When the Chef server #{description}", *tags do
46
+ extend WhenTheChefServerClassMethods
47
+ include WhenTheChefServerInstanceMethods
48
+
49
+ # Take the passed-in options
50
+
51
+ define_singleton_method(:chef_server_options) {
52
+ @chef_server_options ||= begin
53
+ _chef_server_options = { port: 8900, signals: false, log_requests: true }
54
+ _chef_server_options = _chef_server_options.merge(tags.last) if tags.last.is_a?(Hash)
55
+ _chef_server_options = _chef_server_options.freeze
56
+ end
57
+ }
58
+
59
+ # Merge in chef_server_options from let(:chef_server_options)
60
+ def chef_server_options
61
+ chef_server_options = self.class.chef_server_options.dup
62
+ chef_server_options = chef_server_options.merge(chef_zero_opts) if self.respond_to?(:chef_zero_opts)
63
+ chef_server_options
64
+ end
65
+
66
+ before chef_server_options[:server_scope] do
67
+ if chef_server_options[:server_scope] != self.class.chef_server_options[:server_scope]
68
+ raise "server_scope: #{chef_server_options[:server_scope]} will not be honored: it can only be set on when_the_chef_server!"
69
+ end
70
+ Log.debug("Starting Chef server with options #{chef_server_options}")
71
+
72
+ ChefZero::RSpec.set_server_options(chef_server_options)
73
+
74
+ if chef_server_options[:organization]
75
+ organization chef_server_options[:organization]
76
+ end
77
+
78
+ if defined?(Chef::Config)
79
+ @old_chef_server_url = Chef::Config.chef_server_url
80
+ @old_node_name = Chef::Config.node_name
81
+ @old_client_key = Chef::Config.client_key
82
+ if chef_server_options[:organization]
83
+ Chef::Config.chef_server_url = "#{ChefZero::RSpec.server.url}/organizations/#{chef_server_options[:organization]}"
84
+ else
85
+ Chef::Config.chef_server_url = ChefZero::RSpec.server.url
86
+ end
87
+ Chef::Config.node_name = 'admin'
88
+ Chef::Config.client_key = ChefZero::RSpec.client_key.path
89
+ Chef::Config.http_retry_count = 0
90
+ end
91
+ end
92
+
93
+ if defined?(Chef::Config)
94
+ after chef_server_options[:server_scope] do
95
+ Chef::Config.chef_server_url = @old_chef_server_url
96
+ Chef::Config.node_name = @old_node_name
97
+ Chef::Config.client_key = @old_client_key
98
+ end
99
+ end
100
+
101
+ instance_eval(&block)
102
+ end
103
+ end
104
+
105
+ module WhenTheChefServerClassMethods
106
+ def organization(name, org = '{}', &block)
107
+ before(chef_server_options[:server_scope]) { organization(name, org, &block) }
108
+ end
109
+
110
+ def acl_for(path, data)
111
+ before(chef_server_options[:server_scope]) { acl_for(path, data) }
112
+ end
113
+
114
+ def client(name, data, &block)
115
+ before(chef_server_options[:server_scope]) { client(name, data, &block) }
116
+ end
117
+
118
+ def container(name, data, &block)
119
+ before(chef_server_options[:server_scope]) { container(name, data, &block) }
120
+ end
121
+
122
+ def cookbook(name, version, data = {}, options = {}, &block)
123
+ before(chef_server_options[:server_scope]) do
124
+ cookbook(name, version, data, &block)
125
+ end
126
+ end
127
+
128
+ def data_bag(name, data, &block)
129
+ before(chef_server_options[:server_scope]) { data_bag(name, data, &block) }
130
+ end
131
+
132
+ def environment(name, data, &block)
133
+ before(chef_server_options[:server_scope]) { environment(name, data, &block) }
134
+ end
135
+
136
+ def group(name, data, &block)
137
+ before(chef_server_options[:server_scope]) { group(name, data, &block) }
138
+ end
139
+
140
+ def node(name, data, &block)
141
+ before(chef_server_options[:server_scope]) { node(name, data, &block) }
142
+ end
143
+
144
+ def org_invite(*usernames)
145
+ before(chef_server_options[:server_scope]) { org_invite(*usernames) }
146
+ end
147
+
148
+ def org_member(*usernames)
149
+ before(chef_server_options[:server_scope]) { org_member(*usernames) }
150
+ end
151
+
152
+ def role(name, data, &block)
153
+ before(chef_server_options[:server_scope]) { role(name, data, &block) }
154
+ end
155
+
156
+ def sandbox(name, data, &block)
157
+ before(chef_server_options[:server_scope]) { sandbox(name, data, &block) }
158
+ end
159
+
160
+ def user(name, data, &block)
161
+ before(chef_server_options[:server_scope]) { user(name, data, &block) }
162
+ end
163
+ end
164
+
165
+ module WhenTheChefServerInstanceMethods
166
+ def organization(name, org = '{}', &block)
167
+ ChefZero::RSpec.server.data_store.set([ 'organizations', name, 'org' ], dejsonize(org), :create_dir, :create)
168
+ prev_org_name = @current_org
169
+ @current_org = name
170
+ prev_object_path = @current_object_path
171
+ @current_object_path = "organizations/#{name}"
172
+ if block_given?
173
+ begin
174
+ instance_eval(&block)
175
+ ensure
176
+ @current_org = prev_org_name
177
+ @current_object_path = prev_object_path
178
+ end
179
+ end
180
+ end
181
+
182
+ def acl_for(path, data)
183
+ ChefZero::RSpec.server.load_data({ 'acls' => { path => data } }, current_org)
184
+ end
185
+
186
+ def acl(data)
187
+ acl_for(@current_object_path, data)
188
+ end
189
+
190
+ def client(name, data, &block)
191
+ with_object_path("clients/#{name}") do
192
+ ChefZero::RSpec.server.load_data({ 'clients' => { name => data } }, current_org)
193
+ instance_eval(&block) if block_given?
194
+ end
195
+ end
196
+
197
+ def container(name, data, &block)
198
+ with_object_path("containers/#{name}") do
199
+ ChefZero::RSpec.server.load_data({ 'containers' => { name => data } }, current_org)
200
+ instance_eval(&block) if block_given?
201
+ end
202
+ end
203
+
204
+ def cookbook(name, version, data = {}, options = {}, &block)
205
+ with_object_path("cookbooks/#{name}") do
206
+ if data.has_key?('metadata.rb')
207
+ if data['metadata.rb'].nil?
208
+ data.delete('metadata.rb')
209
+ end
210
+ else
211
+ data['metadata.rb'] = "name #{name.inspect}; version #{version.inspect}"
212
+ end
213
+ ChefZero::RSpec.server.load_data({ 'cookbooks' => { "#{name}-#{version}" => data.merge(options) }}, current_org)
214
+ instance_eval(&block) if block_given?
215
+ end
216
+ end
217
+
218
+ def data_bag(name, data, &block)
219
+ with_object_path("data/#{name}") do
220
+ ChefZero::RSpec.server.load_data({ 'data' => { name => data }}, current_org)
221
+ instance_eval(&block) if block_given?
222
+ end
223
+ end
224
+
225
+ def environment(name, data, &block)
226
+ with_object_path("environments/#{name}") do
227
+ ChefZero::RSpec.server.load_data({ 'environments' => { name => data } }, current_org)
228
+ instance_eval(&block) if block_given?
229
+ end
230
+ end
231
+
232
+ def group(name, data, &block)
233
+ with_object_path("groups/#{name}") do
234
+ ChefZero::RSpec.server.load_data({ 'groups' => { name => data } }, current_org)
235
+ instance_eval(&block) if block_given?
236
+ end
237
+ end
238
+
239
+ def node(name, data, &block)
240
+ with_object_path("nodes/#{name}") do
241
+ ChefZero::RSpec.server.load_data({ 'nodes' => { name => data } }, current_org)
242
+ instance_eval(&block) if block_given?
243
+ end
244
+ end
245
+
246
+ def org_invite(*usernames)
247
+ ChefZero::RSpec.server.load_data({ 'invites' => usernames }, current_org)
248
+ end
249
+
250
+ def org_member(*usernames)
251
+ ChefZero::RSpec.server.load_data({ 'members' => usernames }, current_org)
252
+ end
253
+
254
+ def role(name, data, &block)
255
+ with_object_path("roles/#{name}") do
256
+ ChefZero::RSpec.server.load_data({ 'roles' => { name => data } }, current_org)
257
+ instance_eval(&block) if block_given?
258
+ end
259
+ end
260
+
261
+ def sandbox(name, data, &block)
262
+ with_object_path("sandboxes/#{name}") do
263
+ ChefZero::RSpec.server.load_data({ 'sandboxes' => { name => data } }, current_org)
264
+ instance_eval(&block) if block_given?
265
+ end
266
+ end
267
+
268
+ def user(name, data, &block)
269
+ if ChefZero::RSpec.server.options[:osc_compat]
270
+ with_object_path("users/#{name}") do
271
+ ChefZero::RSpec.server.load_data({ 'users' => { name => data }}, current_org)
272
+ instance_eval(&block) if block_given?
273
+ end
274
+ else
275
+ old_object_path = @current_object_path
276
+ @current_object_path = "users/#{name}"
277
+ begin
278
+ ChefZero::RSpec.server.load_data({ 'users' => { name => data }}, current_org)
279
+ instance_eval(&block) if block_given?
280
+ ensure
281
+ @current_object_path = old_object_path
282
+ end
283
+ end
284
+ end
285
+
286
+ def dejsonize(data)
287
+ if data.is_a?(String)
288
+ data
289
+ else
290
+ FFI_Yajl::Encoder.encode(data, :pretty => true)
291
+ end
292
+ end
293
+
294
+ def current_org
295
+ @current_org || ChefZero::RSpec.server.options[:single_org] || nil
296
+ end
297
+
298
+ def with_object_path(object_path)
299
+ old_object_path = @current_object_path
300
+ @current_object_path = object_path
301
+ begin
302
+ yield if block_given?
303
+ end
304
+ @current_object_path = old_object_path
305
+ end
306
+ end
307
+ end
308
+ end