chef-zero 2.2.1 → 3.0.0.rc.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/Rakefile +5 -1
- data/bin/chef-zero +17 -0
- data/lib/chef_zero/chef_data/acl_path.rb +139 -0
- data/lib/chef_zero/chef_data/cookbook_data.rb +240 -0
- data/lib/chef_zero/chef_data/data_normalizer.rb +207 -0
- data/lib/chef_zero/chef_data/default_creator.rb +446 -0
- data/lib/chef_zero/data_store/default_facade.rb +149 -0
- data/lib/chef_zero/data_store/interface_v1.rb +18 -0
- data/lib/chef_zero/data_store/memory_store.rb +2 -1
- data/lib/chef_zero/data_store/memory_store_v2.rb +3 -36
- data/lib/chef_zero/data_store/raw_file_store.rb +147 -0
- data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +39 -103
- data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +1 -1
- data/lib/chef_zero/endpoints/acl_endpoint.rb +38 -0
- data/lib/chef_zero/endpoints/acls_endpoint.rb +29 -0
- data/lib/chef_zero/endpoints/actor_endpoint.rb +36 -10
- data/lib/chef_zero/endpoints/actors_endpoint.rb +38 -6
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +15 -9
- data/lib/chef_zero/endpoints/container_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/containers_endpoint.rb +13 -0
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +15 -14
- data/lib/chef_zero/endpoints/cookbooks_base.rb +2 -2
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +4 -4
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +5 -4
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +6 -6
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +3 -3
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +1 -1
- data/lib/chef_zero/endpoints/group_endpoint.rb +20 -0
- data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -0
- data/lib/chef_zero/endpoints/license_endpoint.rb +25 -0
- data/lib/chef_zero/endpoints/node_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/not_found_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -0
- data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +29 -0
- data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -0
- data/lib/chef_zero/endpoints/organization_endpoint.rb +41 -0
- data/lib/chef_zero/endpoints/organization_user_endpoint.rb +48 -0
- data/lib/chef_zero/endpoints/organization_users_endpoint.rb +14 -0
- data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -0
- data/lib/chef_zero/endpoints/organizations_endpoint.rb +55 -0
- data/lib/chef_zero/endpoints/principal_endpoint.rb +15 -3
- data/lib/chef_zero/endpoints/rest_list_endpoint.rb +8 -6
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +12 -10
- data/lib/chef_zero/endpoints/role_endpoint.rb +5 -5
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +2 -2
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +4 -4
- data/lib/chef_zero/endpoints/search_endpoint.rb +10 -10
- data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -0
- data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +40 -0
- data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -0
- data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -0
- data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -0
- data/lib/chef_zero/rest_base.rb +79 -13
- data/lib/chef_zero/rest_error_response.rb +1 -1
- data/lib/chef_zero/rest_request.rb +4 -0
- data/lib/chef_zero/rest_router.rb +1 -0
- data/lib/chef_zero/rspec.rb +55 -8
- data/lib/chef_zero/server.rb +87 -21
- data/lib/chef_zero/version.rb +1 -1
- data/spec/run_oc_pedant.rb +53 -0
- data/spec/{run.rb → run_pedant.rb} +13 -4
- data/spec/server_spec.rb +54 -0
- data/spec/support/oc_pedant.rb +134 -0
- data/spec/support/pedant.rb +1 -1
- metadata +54 -13
- data/lib/chef_zero/cookbook_data.rb +0 -236
- 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
|