chef-zero 2.2.1 → 3.0.0.rc.1

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 (77) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/Rakefile +5 -1
  4. data/bin/chef-zero +17 -0
  5. data/lib/chef_zero/chef_data/acl_path.rb +139 -0
  6. data/lib/chef_zero/chef_data/cookbook_data.rb +240 -0
  7. data/lib/chef_zero/chef_data/data_normalizer.rb +207 -0
  8. data/lib/chef_zero/chef_data/default_creator.rb +446 -0
  9. data/lib/chef_zero/data_store/default_facade.rb +149 -0
  10. data/lib/chef_zero/data_store/interface_v1.rb +18 -0
  11. data/lib/chef_zero/data_store/memory_store.rb +2 -1
  12. data/lib/chef_zero/data_store/memory_store_v2.rb +3 -36
  13. data/lib/chef_zero/data_store/raw_file_store.rb +147 -0
  14. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +39 -103
  15. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +1 -1
  16. data/lib/chef_zero/endpoints/acl_endpoint.rb +38 -0
  17. data/lib/chef_zero/endpoints/acls_endpoint.rb +29 -0
  18. data/lib/chef_zero/endpoints/actor_endpoint.rb +36 -10
  19. data/lib/chef_zero/endpoints/actors_endpoint.rb +38 -6
  20. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +15 -9
  21. data/lib/chef_zero/endpoints/container_endpoint.rb +22 -0
  22. data/lib/chef_zero/endpoints/containers_endpoint.rb +13 -0
  23. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +1 -1
  24. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +15 -14
  25. data/lib/chef_zero/endpoints/cookbooks_base.rb +2 -2
  26. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +4 -4
  27. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +5 -5
  28. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +5 -4
  29. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +2 -2
  30. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +6 -6
  31. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +2 -2
  32. data/lib/chef_zero/endpoints/environment_endpoint.rb +5 -5
  33. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +2 -2
  34. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +3 -3
  35. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +2 -2
  36. data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +1 -1
  37. data/lib/chef_zero/endpoints/group_endpoint.rb +20 -0
  38. data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -0
  39. data/lib/chef_zero/endpoints/license_endpoint.rb +25 -0
  40. data/lib/chef_zero/endpoints/node_endpoint.rb +5 -5
  41. data/lib/chef_zero/endpoints/not_found_endpoint.rb +2 -2
  42. data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -0
  43. data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +29 -0
  44. data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -0
  45. data/lib/chef_zero/endpoints/organization_endpoint.rb +41 -0
  46. data/lib/chef_zero/endpoints/organization_user_endpoint.rb +48 -0
  47. data/lib/chef_zero/endpoints/organization_users_endpoint.rb +14 -0
  48. data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -0
  49. data/lib/chef_zero/endpoints/organizations_endpoint.rb +55 -0
  50. data/lib/chef_zero/endpoints/principal_endpoint.rb +15 -3
  51. data/lib/chef_zero/endpoints/rest_list_endpoint.rb +8 -6
  52. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +12 -10
  53. data/lib/chef_zero/endpoints/role_endpoint.rb +5 -5
  54. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +2 -2
  55. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +2 -2
  56. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +4 -4
  57. data/lib/chef_zero/endpoints/search_endpoint.rb +10 -10
  58. data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -0
  59. data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +40 -0
  60. data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -0
  61. data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -0
  62. data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -0
  63. data/lib/chef_zero/rest_base.rb +79 -13
  64. data/lib/chef_zero/rest_error_response.rb +1 -1
  65. data/lib/chef_zero/rest_request.rb +4 -0
  66. data/lib/chef_zero/rest_router.rb +1 -0
  67. data/lib/chef_zero/rspec.rb +55 -8
  68. data/lib/chef_zero/server.rb +87 -21
  69. data/lib/chef_zero/version.rb +1 -1
  70. data/spec/run_oc_pedant.rb +53 -0
  71. data/spec/{run.rb → run_pedant.rb} +13 -4
  72. data/spec/server_spec.rb +54 -0
  73. data/spec/support/oc_pedant.rb +134 -0
  74. data/spec/support/pedant.rb +1 -1
  75. metadata +54 -13
  76. data/lib/chef_zero/cookbook_data.rb +0 -236
  77. data/lib/chef_zero/data_normalizer.rb +0 -146
@@ -1,236 +0,0 @@
1
- require 'digest/md5'
2
- require 'hashie/mash'
3
-
4
- module ChefZero
5
- module CookbookData
6
- def self.to_hash(cookbook, name, version=nil)
7
- frozen = false
8
- if cookbook.has_key?(:frozen)
9
- frozen = cookbook[:frozen]
10
- cookbook = cookbook.dup
11
- cookbook.delete(:frozen)
12
- end
13
-
14
- result = files_from(cookbook)
15
- recipe_names = result[:recipes].map do |recipe|
16
- recipe_name = recipe[:name][0..-2]
17
- recipe_name == 'default' ? name : "#{name}::#{recipe_name}"
18
- end
19
- result[:metadata] = metadata_from(cookbook, name, version, recipe_names)
20
- result[:name] = "#{name}-#{result[:metadata][:version]}"
21
- result[:json_class] = 'Chef::CookbookVersion'
22
- result[:cookbook_name] = name
23
- result[:version] = result[:metadata][:version]
24
- result[:chef_type] = 'cookbook_version'
25
- result[:frozen?] = true if frozen
26
- result
27
- end
28
-
29
- def self.metadata_from(directory, name, version, recipe_names)
30
- metadata = PretendCookbookMetadata.new(PretendCookbook.new(name, recipe_names))
31
- # If both .rb and .json exist, read .rb
32
- # TODO if recipes has 3 recipes in it, and the Ruby/JSON has only one, should
33
- # the resulting recipe list have 1, or 3-4 recipes in it?
34
- if has_child(directory, 'metadata.rb')
35
- begin
36
- file = filename(directory, 'metadata.rb') || "(#{name}/metadata.rb)"
37
- metadata.instance_eval(read_file(directory, 'metadata.rb'), file)
38
- rescue
39
- ChefZero::Log.error("Error loading cookbook #{name}: #{$!}\n #{$!.backtrace.join("\n ")}")
40
- end
41
- elsif has_child(directory, 'metadata.json')
42
- metadata.from_json(read_file(directory, 'metadata.json'))
43
- end
44
- result = {}
45
- metadata.to_hash.each_pair do |key,value|
46
- result[key.to_sym] = value
47
- end
48
- result[:version] = version if version
49
- result
50
- end
51
-
52
- private
53
-
54
- # Just enough cookbook to make a Metadata object
55
- class PretendCookbook
56
- def initialize(name, fully_qualified_recipe_names)
57
- @name = name
58
- @fully_qualified_recipe_names = fully_qualified_recipe_names
59
- end
60
- attr_reader :name, :fully_qualified_recipe_names
61
- end
62
-
63
- # Handles loading configuration values from a Chef config file
64
- #
65
- # @author Justin Campbell <justin.campbell@riotgames.com>
66
- class PretendCookbookMetadata < Hash
67
- # @param [String] path
68
- def initialize(cookbook)
69
- self.name(cookbook.name)
70
- self.recipes(cookbook.fully_qualified_recipe_names)
71
- %w(attributes grouping dependencies supports recommendations suggestions conflicting providing replacing recipes).each do |hash_arg|
72
- self[hash_arg.to_sym] = Hashie::Mash.new
73
- end
74
- end
75
-
76
- def from_json(json)
77
- self.merge!(FFI_Yajl::Parser.parse(json))
78
- end
79
-
80
- private
81
-
82
- def depends(cookbook, *version_constraints)
83
- cookbook_arg(:dependencies, cookbook, version_constraints)
84
- end
85
-
86
- def supports(cookbook, *version_constraints)
87
- cookbook_arg(:supports, cookbook, version_constraints)
88
- end
89
-
90
- def recommends(cookbook, *version_constraints)
91
- cookbook_arg(:recommendations, cookbook, version_constraints)
92
- end
93
-
94
- def suggests(cookbook, *version_constraints)
95
- cookbook_arg(:suggestions, cookbook, version_constraints)
96
- end
97
-
98
- def conflicts(cookbook, *version_constraints)
99
- cookbook_arg(:conflicting, cookbook, version_constraints)
100
- end
101
-
102
- def provides(cookbook, *version_constraints)
103
- cookbook_arg(:providing, cookbook, version_constraints)
104
- end
105
-
106
- def replaces(cookbook, *version_constraints)
107
- cookbook_arg(:replacing, cookbook, version_constraints)
108
- end
109
-
110
- def recipe(recipe, description)
111
- self[:recipes][recipe] = description
112
- end
113
-
114
- def attribute(name, options)
115
- self[:attributes][name] = options
116
- end
117
-
118
- def grouping(name, options)
119
- self[:grouping][name] = options
120
- end
121
-
122
- def cookbook_arg(key, cookbook, version_constraints)
123
- self[key][cookbook] = version_constraints.first || ">= 0.0.0"
124
- end
125
-
126
- def method_missing(key, value = nil)
127
- if value.nil?
128
- self[key.to_sym]
129
- else
130
- store key.to_sym, value
131
- end
132
- end
133
- end
134
-
135
- def self.files_from(directory)
136
- # TODO some support .rb only
137
- result = {
138
- :attributes => load_child_files(directory, 'attributes', false),
139
- :definitions => load_child_files(directory, 'definitions', false),
140
- :recipes => load_child_files(directory, 'recipes', false),
141
- :libraries => load_child_files(directory, 'libraries', false),
142
- :templates => load_child_files(directory, 'templates', true),
143
- :files => load_child_files(directory, 'files', true),
144
- :resources => load_child_files(directory, 'resources', true),
145
- :providers => load_child_files(directory, 'providers', true),
146
- :root_files => load_files(directory, false)
147
- }
148
- set_specificity(result[:templates])
149
- set_specificity(result[:files])
150
- result
151
- end
152
-
153
- def self.has_child(directory, name)
154
- if directory.is_a?(Hash)
155
- directory.has_key?(name)
156
- else
157
- directory.child(name).exists?
158
- end
159
- end
160
-
161
- def self.read_file(directory, name)
162
- if directory.is_a?(Hash)
163
- directory[name]
164
- else
165
- directory.child(name).read
166
- end
167
- end
168
-
169
- def self.filename(directory, name)
170
- if directory.respond_to?(:file_path)
171
- File.join(directory.file_path, name)
172
- else
173
- nil
174
- end
175
- end
176
-
177
- def self.get_directory(directory, name)
178
- if directory.is_a?(Hash)
179
- directory[name].is_a?(Hash) ? directory[name] : nil
180
- else
181
- result = directory.child(name)
182
- result.dir? ? result : nil
183
- end
184
- end
185
-
186
- def self.list(directory)
187
- if directory.is_a?(Hash)
188
- directory.keys
189
- else
190
- directory.children.map { |c| c.name }
191
- end
192
- end
193
-
194
- def self.load_child_files(parent, key, recursive)
195
- result = load_files(get_directory(parent, key), recursive)
196
- result.each do |file|
197
- file[:path] = "#{key}/#{file[:path]}"
198
- end
199
- result
200
- end
201
-
202
- def self.load_files(directory, recursive)
203
- result = []
204
- if directory
205
- list(directory).each do |child_name|
206
- dir = get_directory(directory, child_name)
207
- if dir
208
- if recursive
209
- result += load_child_files(directory, child_name, recursive)
210
- end
211
- else
212
- result += load_file(read_file(directory, child_name), child_name)
213
- end
214
- end
215
- end
216
- result
217
- end
218
-
219
- def self.load_file(value, name)
220
- [{
221
- :name => name,
222
- :path => name,
223
- :checksum => Digest::MD5.hexdigest(value),
224
- :specificity => 'default'
225
- }]
226
- end
227
-
228
- def self.set_specificity(files)
229
- files.each do |file|
230
- parts = file[:path].split('/')
231
- raise "Only directories are allowed directly under templates or files: #{file[:path]}" if parts.size == 2
232
- file[:specificity] = parts[1]
233
- end
234
- end
235
- end
236
- end
@@ -1,146 +0,0 @@
1
- require 'chef_zero'
2
- require 'chef_zero/rest_base'
3
-
4
- module ChefZero
5
- class DataNormalizer
6
- def self.normalize_client(client, name)
7
- client['name'] ||= name
8
- client['admin'] ||= false
9
- client['admin'] = !!client['admin']
10
- client['public_key'] ||= PUBLIC_KEY
11
- client['validator'] ||= false
12
- client['validator'] = !!client['validator']
13
- client['json_class'] ||= "Chef::ApiClient"
14
- client['chef_type'] ||= "client"
15
- client
16
- end
17
-
18
- def self.normalize_user(user, name)
19
- user['name'] ||= name
20
- user['admin'] ||= false
21
- user['admin'] = !!user['admin']
22
- user['openid'] ||= nil
23
- user['public_key'] ||= PUBLIC_KEY
24
- user
25
- end
26
-
27
- def self.normalize_data_bag_item(data_bag_item, data_bag_name, id, method)
28
- if method == 'DELETE'
29
- # TODO SERIOUSLY, WHO DOES THIS MANY EXCEPTIONS IN THEIR INTERFACE
30
- if !(data_bag_item['json_class'] == 'Chef::DataBagItem' && data_bag_item['raw_data'])
31
- data_bag_item['id'] ||= id
32
- data_bag_item = { 'raw_data' => data_bag_item }
33
- data_bag_item['chef_type'] ||= 'data_bag_item'
34
- data_bag_item['json_class'] ||= 'Chef::DataBagItem'
35
- data_bag_item['data_bag'] ||= data_bag_name
36
- data_bag_item['name'] ||= "data_bag_item_#{data_bag_name}_#{id}"
37
- end
38
- else
39
- # If it's not already wrapped with raw_data, wrap it.
40
- if data_bag_item['json_class'] == 'Chef::DataBagItem' && data_bag_item['raw_data']
41
- data_bag_item = data_bag_item['raw_data']
42
- end
43
- # Argh. We don't do this on GET, but we do on PUT and POST????
44
- if %w(PUT POST).include?(method)
45
- data_bag_item['chef_type'] ||= 'data_bag_item'
46
- data_bag_item['data_bag'] ||= data_bag_name
47
- end
48
- data_bag_item['id'] ||= id
49
- end
50
- data_bag_item
51
- end
52
-
53
- def self.normalize_environment(environment, name)
54
- environment['name'] ||= name
55
- environment['description'] ||= ''
56
- environment['cookbook_versions'] ||= {}
57
- environment['json_class'] ||= "Chef::Environment"
58
- environment['chef_type'] ||= "environment"
59
- environment['default_attributes'] ||= {}
60
- environment['override_attributes'] ||= {}
61
- environment
62
- end
63
-
64
- def self.normalize_cookbook(endpoint, org_prefix, cookbook, name, version, base_uri, method)
65
- # TODO I feel dirty
66
- if method != 'PUT'
67
- cookbook.each_pair do |key, value|
68
- if value.is_a?(Array)
69
- value.each do |file|
70
- if file.is_a?(Hash) && file.has_key?('checksum')
71
- file['url'] ||= endpoint.build_uri(base_uri, org_prefix + ['file_store', 'checksums', file['checksum']])
72
- end
73
- end
74
- end
75
- end
76
- cookbook['name'] ||= "#{name}-#{version}"
77
- # TODO this feels wrong, but the real chef server doesn't expand this default
78
- # cookbook['version'] ||= version
79
- cookbook['cookbook_name'] ||= name
80
- cookbook['frozen?'] ||= false
81
- cookbook['metadata'] ||= {}
82
- cookbook['metadata']['version'] ||= version
83
- # Sad to not be expanding defaults just because Chef doesn't :(
84
- # cookbook['metadata']['name'] ||= name
85
- # cookbook['metadata']['description'] ||= "A fabulous new cookbook"
86
- cookbook['metadata']['long_description'] ||= ""
87
- # cookbook['metadata']['maintainer'] ||= "YOUR_COMPANY_NAME"
88
- # cookbook['metadata']['maintainer_email'] ||= "YOUR_EMAIL"
89
- # cookbook['metadata']['license'] ||= "none"
90
- cookbook['metadata']['dependencies'] ||= {}
91
- cookbook['metadata']['attributes'] ||= {}
92
- cookbook['metadata']['recipes'] ||= {}
93
- end
94
- cookbook['json_class'] ||= 'Chef::CookbookVersion'
95
- cookbook['chef_type'] ||= 'cookbook_version'
96
- if method == 'MIN'
97
- cookbook['metadata'].delete('attributes')
98
- cookbook['metadata'].delete('long_description')
99
- end
100
- cookbook
101
- end
102
-
103
- def self.normalize_node(node, name)
104
- node['name'] ||= name
105
- node['json_class'] ||= 'Chef::Node'
106
- node['chef_type'] ||= 'node'
107
- node['chef_environment'] ||= '_default'
108
- node['override'] ||= {}
109
- node['normal'] ||= {}
110
- node['default'] ||= {}
111
- node['automatic'] ||= {}
112
- node['run_list'] ||= []
113
- node['run_list'] = normalize_run_list(node['run_list'])
114
- node
115
- end
116
-
117
- def self.normalize_role(role, name)
118
- role['name'] ||= name
119
- role['description'] ||= ''
120
- role['json_class'] ||= 'Chef::Role'
121
- role['chef_type'] ||= 'role'
122
- role['default_attributes'] ||= {}
123
- role['override_attributes'] ||= {}
124
- role['run_list'] ||= []
125
- role['run_list'] = normalize_run_list(role['run_list'])
126
- role['env_run_lists'] ||= {}
127
- role['env_run_lists'].each_pair do |env, run_list|
128
- role['env_run_lists'][env] = normalize_run_list(run_list)
129
- end
130
- role
131
- end
132
-
133
- def self.normalize_run_list(run_list)
134
- run_list.map{|item|
135
- case item
136
- when /^recipe\[.*\]$/
137
- item # explicit recipe
138
- when /^role\[.*\]$/
139
- item # explicit role
140
- else
141
- "recipe[#{item}]"
142
- end
143
- }.uniq
144
- end
145
- end
146
- end