chef-zero 15.0.17 → 15.0.21
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.
- checksums.yaml +4 -4
- data/Gemfile +36 -31
- data/LICENSE +201 -201
- data/Rakefile +73 -68
- data/bin/chef-zero +111 -111
- data/chef-zero.gemspec +34 -33
- data/lib/chef_zero/chef_data/acl_path.rb +140 -140
- data/lib/chef_zero/chef_data/cookbook_data.rb +237 -237
- data/lib/chef_zero/chef_data/data_normalizer.rb +276 -276
- data/lib/chef_zero/chef_data/default_creator.rb +476 -476
- data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
- data/lib/chef_zero/data_store/data_error.rb +32 -32
- data/lib/chef_zero/data_store/data_not_found_error.rb +29 -29
- data/lib/chef_zero/data_store/default_facade.rb +143 -147
- data/lib/chef_zero/data_store/interface_v1.rb +67 -67
- data/lib/chef_zero/data_store/interface_v2.rb +18 -18
- data/lib/chef_zero/data_store/memory_store.rb +33 -33
- data/lib/chef_zero/data_store/memory_store_v2.rb +159 -159
- data/lib/chef_zero/data_store/raw_file_store.rb +143 -143
- data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +150 -150
- data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +105 -105
- data/lib/chef_zero/dist.rb +9 -9
- data/lib/chef_zero/endpoints/acl_endpoint.rb +39 -39
- data/lib/chef_zero/endpoints/acls_endpoint.rb +41 -41
- data/lib/chef_zero/endpoints/actor_default_key_endpoint.rb +78 -78
- data/lib/chef_zero/endpoints/actor_endpoint.rb +184 -184
- data/lib/chef_zero/endpoints/actor_key_endpoint.rb +62 -62
- data/lib/chef_zero/endpoints/actor_keys_endpoint.rb +129 -129
- data/lib/chef_zero/endpoints/actors_endpoint.rb +104 -104
- data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +32 -32
- data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/containers_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/controls_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/cookbook_artifact_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/cookbook_artifact_identifier_endpoint.rb +68 -68
- data/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
- data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +136 -136
- data/lib/chef_zero/endpoints/cookbooks_base.rb +80 -80
- data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
- data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
- data/lib/chef_zero/endpoints/dummy_endpoint.rb +29 -29
- data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +126 -126
- data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
- data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
- data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
- data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
- data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
- data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
- data/lib/chef_zero/endpoints/node_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/nodes_endpoint.rb +34 -34
- data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
- data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -30
- data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/organization_endpoint.rb +47 -47
- data/lib/chef_zero/endpoints/organization_user_base.rb +15 -15
- data/lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/organization_user_key_endpoint.rb +17 -17
- data/lib/chef_zero/endpoints/organization_user_keys_endpoint.rb +17 -17
- data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -43
- data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
- data/lib/chef_zero/endpoints/organizations_endpoint.rb +61 -61
- data/lib/chef_zero/endpoints/policies_endpoint.rb +26 -26
- data/lib/chef_zero/endpoints/policy_endpoint.rb +24 -24
- data/lib/chef_zero/endpoints/policy_group_endpoint.rb +46 -46
- data/lib/chef_zero/endpoints/policy_group_policy_endpoint.rb +83 -83
- data/lib/chef_zero/endpoints/policy_groups_endpoint.rb +38 -38
- data/lib/chef_zero/endpoints/policy_revision_endpoint.rb +66 -66
- data/lib/chef_zero/endpoints/policy_revisions_endpoint.rb +15 -15
- data/lib/chef_zero/endpoints/principal_endpoint.rb +55 -55
- data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
- data/lib/chef_zero/endpoints/rest_object_endpoint.rb +78 -78
- data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
- data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
- data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
- data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +51 -51
- data/lib/chef_zero/endpoints/search_endpoint.rb +208 -208
- data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
- data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -14
- data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
- data/lib/chef_zero/endpoints/universe_endpoint.rb +15 -15
- data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +41 -41
- data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
- data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
- data/lib/chef_zero/endpoints/version_endpoint.rb +13 -13
- data/lib/chef_zero/log.rb +7 -7
- data/lib/chef_zero/rest_base.rb +332 -332
- data/lib/chef_zero/rest_error_response.rb +11 -11
- data/lib/chef_zero/rest_request.rb +84 -88
- data/lib/chef_zero/rest_router.rb +72 -72
- data/lib/chef_zero/rspec.rb +355 -355
- data/lib/chef_zero/server.rb +730 -730
- data/lib/chef_zero/socketless_server_map.rb +92 -93
- data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
- data/lib/chef_zero/solr/query/phrase.rb +23 -23
- data/lib/chef_zero/solr/query/range_query.rb +46 -46
- data/lib/chef_zero/solr/query/regexpable_query.rb +30 -30
- data/lib/chef_zero/solr/query/subquery.rb +37 -37
- data/lib/chef_zero/solr/query/term.rb +45 -45
- data/lib/chef_zero/solr/query/unary_operator.rb +41 -41
- data/lib/chef_zero/solr/solr_doc.rb +53 -53
- data/lib/chef_zero/solr/solr_parser.rb +208 -208
- data/lib/chef_zero/version.rb +3 -3
- data/lib/chef_zero.rb +10 -10
- data/spec/run_oc_pedant.rb +226 -226
- data/spec/search_spec.rb +36 -36
- data/spec/server_spec.rb +96 -96
- data/spec/socketless_server_map_spec.rb +74 -74
- data/spec/support/oc_pedant.rb +149 -149
- data/spec/support/secrets.json +6 -6
- data/spec/support/stickywicket.pem +27 -27
- metadata +35 -18
@@ -1,276 +1,276 @@
|
|
1
|
-
require_relative "../../chef_zero"
|
2
|
-
require_relative "../rest_base"
|
3
|
-
require_relative "default_creator"
|
4
|
-
|
5
|
-
module ChefZero
|
6
|
-
module ChefData
|
7
|
-
class DataNormalizer
|
8
|
-
|
9
|
-
COOKBOOK_SEGMENTS = %w{ resources providers recipes definitions libraries attributes files templates root_files }.freeze
|
10
|
-
|
11
|
-
def self.normalize_acls(acls)
|
12
|
-
ChefData::DefaultCreator::PERMISSIONS.each do |perm|
|
13
|
-
acls[perm] ||= {}
|
14
|
-
acls[perm]["groups"] ||= []
|
15
|
-
if acls[perm].key? "users"
|
16
|
-
# When clients and users are split, their combined list
|
17
|
-
# is the final list of actors that a subsequent GET will
|
18
|
-
# provide. Each list is guaranteed to be unique, but the
|
19
|
-
# combined list is not.
|
20
|
-
acls[perm]["actors"] = acls[perm]["clients"].uniq +
|
21
|
-
acls[perm]["users"].uniq
|
22
|
-
else
|
23
|
-
# this gets doubled sometimes, for reasons.
|
24
|
-
(acls[perm]["actors"] ||= []).uniq!
|
25
|
-
end
|
26
|
-
end
|
27
|
-
acls
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.normalize_client(client, name, orgname = nil)
|
31
|
-
client["name"] ||= name
|
32
|
-
client["clientname"] ||= name
|
33
|
-
client["admin"] = !!client["admin"] if client.key?("admin")
|
34
|
-
client["public_key"] = PUBLIC_KEY unless client.key?("public_key")
|
35
|
-
client["orgname"] ||= orgname
|
36
|
-
client["validator"] ||= false
|
37
|
-
client["validator"] = !!client["validator"]
|
38
|
-
client["json_class"] ||= "Chef::ApiClient"
|
39
|
-
client["chef_type"] ||= "client"
|
40
|
-
client
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.normalize_container(container, name)
|
44
|
-
container.delete("id")
|
45
|
-
container["containername"] = name
|
46
|
-
container["containerpath"] = name
|
47
|
-
container
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.normalize_user(user, name, identity_keys, osc_compat, method = nil)
|
51
|
-
user[identity_keys.first] ||= name
|
52
|
-
user["public_key"] = PUBLIC_KEY unless user.key?("public_key")
|
53
|
-
user["admin"] ||= false
|
54
|
-
user["admin"] = !!user["admin"]
|
55
|
-
user["openid"] ||= nil
|
56
|
-
unless osc_compat
|
57
|
-
if method == "GET"
|
58
|
-
user.delete("admin")
|
59
|
-
user.delete("password")
|
60
|
-
user.delete("openid")
|
61
|
-
end
|
62
|
-
user["email"] ||= nil
|
63
|
-
user["first_name"] ||= nil
|
64
|
-
user["last_name"] ||= nil
|
65
|
-
user["display_name"] ||= nil
|
66
|
-
end
|
67
|
-
user
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.normalize_data_bag_item(data_bag_item, data_bag_name, id, method)
|
71
|
-
if method == "DELETE"
|
72
|
-
# TODO SERIOUSLY, WHO DOES THIS MANY EXCEPTIONS IN THEIR INTERFACE
|
73
|
-
unless data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
|
74
|
-
data_bag_item["id"] ||= id
|
75
|
-
data_bag_item = { "raw_data" => data_bag_item }
|
76
|
-
data_bag_item["chef_type"] ||= "data_bag_item"
|
77
|
-
data_bag_item["json_class"] ||= "Chef::DataBagItem"
|
78
|
-
data_bag_item["data_bag"] ||= data_bag_name
|
79
|
-
data_bag_item["name"] ||= "data_bag_item_#{data_bag_name}_#{id}"
|
80
|
-
end
|
81
|
-
else
|
82
|
-
# If it's not already wrapped with raw_data, wrap it.
|
83
|
-
if data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
|
84
|
-
data_bag_item = data_bag_item["raw_data"]
|
85
|
-
end
|
86
|
-
# Argh. We don't do this on GET, but we do on PUT and POST????
|
87
|
-
if %w{PUT POST}.include?(method)
|
88
|
-
data_bag_item["chef_type"] ||= "data_bag_item"
|
89
|
-
data_bag_item["data_bag"] ||= data_bag_name
|
90
|
-
end
|
91
|
-
data_bag_item["id"] ||= id
|
92
|
-
end
|
93
|
-
data_bag_item
|
94
|
-
end
|
95
|
-
|
96
|
-
def self.normalize_cookbook(endpoint, org_prefix, cookbook, name, version, base_uri, method,
|
97
|
-
is_cookbook_artifact = false, api_version: 2)
|
98
|
-
# TODO I feel dirty
|
99
|
-
if method == "PUT" && api_version < 2
|
100
|
-
cookbook["all_files"] = cookbook.delete(["root_files"]) { [] }
|
101
|
-
COOKBOOK_SEGMENTS.each do |segment|
|
102
|
-
next unless cookbook.key? segment
|
103
|
-
|
104
|
-
cookbook[segment].each do |file|
|
105
|
-
file["name"] = "#{segment}/#{file["name"]}"
|
106
|
-
cookbook["all_files"] << file
|
107
|
-
end
|
108
|
-
cookbook.delete(segment)
|
109
|
-
end
|
110
|
-
elsif method != "PUT"
|
111
|
-
if cookbook.key? "all_files"
|
112
|
-
cookbook["all_files"].each do |file|
|
113
|
-
if file.is_a?(Hash) && file.key?("checksum")
|
114
|
-
file["url"] ||= endpoint.build_uri(base_uri, org_prefix + ["file_store", "checksums", file["checksum"]])
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
# down convert to old style manifest, ensuring we don't send all_files on the wire and that we correctly divine segments
|
119
|
-
# any file that's not in an old segment is just dropped on the floor.
|
120
|
-
if api_version < 2
|
121
|
-
|
122
|
-
# the spec appears to think we should send empty arrays for each segment, so let's do that
|
123
|
-
COOKBOOK_SEGMENTS.each { |seg| cookbook[seg] ||= [] }
|
124
|
-
|
125
|
-
cookbook["all_files"].each do |file|
|
126
|
-
segment, name = file["name"].split("/")
|
127
|
-
|
128
|
-
# root_files have no segment prepended
|
129
|
-
if name.nil?
|
130
|
-
name = segment
|
131
|
-
segment = "root_files"
|
132
|
-
end
|
133
|
-
|
134
|
-
file.delete("full_path")
|
135
|
-
next unless COOKBOOK_SEGMENTS.include? segment
|
136
|
-
|
137
|
-
file["name"] = name
|
138
|
-
cookbook[segment] << file
|
139
|
-
end
|
140
|
-
cookbook.delete("all_files")
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
cookbook["name"] ||= "#{name}-#{version}"
|
145
|
-
# TODO it feels wrong, but the real chef server doesn't expand 'version', so we don't either.
|
146
|
-
|
147
|
-
cookbook["frozen?"] ||= false
|
148
|
-
cookbook["metadata"] ||= {}
|
149
|
-
cookbook["metadata"]["version"] ||= version
|
150
|
-
|
151
|
-
# defaults set by the client and not the Server:
|
152
|
-
# metadata[name, description, maintainer, maintainer_email, license]
|
153
|
-
|
154
|
-
cookbook["metadata"]["long_description"] ||= ""
|
155
|
-
cookbook["metadata"]["dependencies"] ||= {}
|
156
|
-
cookbook["metadata"]["attributes"] ||= {}
|
157
|
-
cookbook["metadata"]["recipes"] ||= {}
|
158
|
-
end
|
159
|
-
|
160
|
-
if is_cookbook_artifact
|
161
|
-
cookbook.delete("json_class")
|
162
|
-
else
|
163
|
-
cookbook["cookbook_name"] ||= name
|
164
|
-
cookbook["json_class"] ||= "Chef::CookbookVersion"
|
165
|
-
end
|
166
|
-
|
167
|
-
cookbook["chef_type"] ||= "cookbook_version"
|
168
|
-
if method == "MIN"
|
169
|
-
cookbook["metadata"].delete("attributes")
|
170
|
-
cookbook["metadata"].delete("long_description")
|
171
|
-
end
|
172
|
-
cookbook
|
173
|
-
end
|
174
|
-
|
175
|
-
def self.normalize_environment(environment, name)
|
176
|
-
environment["name"] ||= name
|
177
|
-
environment["description"] ||= ""
|
178
|
-
environment["cookbook_versions"] ||= {}
|
179
|
-
environment["json_class"] ||= "Chef::Environment"
|
180
|
-
environment["chef_type"] ||= "environment"
|
181
|
-
environment["default_attributes"] ||= {}
|
182
|
-
environment["override_attributes"] ||= {}
|
183
|
-
environment
|
184
|
-
end
|
185
|
-
|
186
|
-
def self.normalize_group(group, name, orgname)
|
187
|
-
group.delete("id")
|
188
|
-
if group["actors"].is_a?(Hash)
|
189
|
-
group["users"] ||= group["actors"]["users"]
|
190
|
-
group["clients"] ||= group["actors"]["clients"]
|
191
|
-
group["groups"] ||= group["actors"]["groups"]
|
192
|
-
group["actors"] = nil
|
193
|
-
end
|
194
|
-
group["users"] ||= []
|
195
|
-
group["clients"] ||= []
|
196
|
-
group["actors"] ||= (group["clients"] + group["users"])
|
197
|
-
group["groups"] ||= []
|
198
|
-
group["orgname"] ||= orgname if orgname
|
199
|
-
group["name"] ||= name
|
200
|
-
group["groupname"] ||= name
|
201
|
-
|
202
|
-
group["users"].uniq!
|
203
|
-
group["clients"].uniq!
|
204
|
-
group["actors"].uniq!
|
205
|
-
group["groups"].uniq!
|
206
|
-
group
|
207
|
-
end
|
208
|
-
|
209
|
-
def self.normalize_node(node, name)
|
210
|
-
node["name"] ||= name
|
211
|
-
node["json_class"] ||= "Chef::Node"
|
212
|
-
node["chef_type"] ||= "node"
|
213
|
-
node["chef_environment"] ||= "_default"
|
214
|
-
node["override"] ||= {}
|
215
|
-
node["normal"] ||= { "tags" => [] }
|
216
|
-
node["default"] ||= {}
|
217
|
-
node["automatic"] ||= {}
|
218
|
-
node["run_list"] ||= []
|
219
|
-
node["run_list"] = normalize_run_list(node["run_list"])
|
220
|
-
node
|
221
|
-
end
|
222
|
-
|
223
|
-
def self.normalize_policy(policy, name, revision)
|
224
|
-
policy["name"] ||= name
|
225
|
-
policy["revision_id"] ||= revision
|
226
|
-
policy["run_list"] ||= []
|
227
|
-
policy["cookbook_locks"] ||= {}
|
228
|
-
policy
|
229
|
-
end
|
230
|
-
|
231
|
-
def self.normalize_policy_group(policy_group, name)
|
232
|
-
policy_group[name] ||= "name"
|
233
|
-
policy_group["policies"] ||= {}
|
234
|
-
policy_group
|
235
|
-
end
|
236
|
-
|
237
|
-
def self.normalize_organization(org, name)
|
238
|
-
org["name"] ||= name
|
239
|
-
org["full_name"] ||= name
|
240
|
-
org["org_type"] ||= "Business"
|
241
|
-
org["clientname"] ||= "#{name}-validator"
|
242
|
-
org["billing_plan"] ||= "platform-free"
|
243
|
-
org
|
244
|
-
end
|
245
|
-
|
246
|
-
def self.normalize_role(role, name)
|
247
|
-
role["name"] ||= name
|
248
|
-
role["description"] ||= ""
|
249
|
-
role["json_class"] ||= "Chef::Role"
|
250
|
-
role["chef_type"] ||= "role"
|
251
|
-
role["default_attributes"] ||= {}
|
252
|
-
role["override_attributes"] ||= {}
|
253
|
-
role["run_list"] ||= []
|
254
|
-
role["run_list"] = normalize_run_list(role["run_list"])
|
255
|
-
role["env_run_lists"] ||= {}
|
256
|
-
role["env_run_lists"].each_pair do |env, run_list|
|
257
|
-
role["env_run_lists"][env] = normalize_run_list(run_list)
|
258
|
-
end
|
259
|
-
role
|
260
|
-
end
|
261
|
-
|
262
|
-
def self.normalize_run_list(run_list)
|
263
|
-
run_list.map do |item|
|
264
|
-
case item
|
265
|
-
when /^recipe\[.*\]$/
|
266
|
-
item # explicit recipe
|
267
|
-
when /^role\[.*\]$/
|
268
|
-
item # explicit role
|
269
|
-
else
|
270
|
-
"recipe[#{item}]"
|
271
|
-
end
|
272
|
-
end.uniq
|
273
|
-
end
|
274
|
-
end
|
275
|
-
end
|
276
|
-
end
|
1
|
+
require_relative "../../chef_zero"
|
2
|
+
require_relative "../rest_base"
|
3
|
+
require_relative "default_creator"
|
4
|
+
|
5
|
+
module ChefZero
|
6
|
+
module ChefData
|
7
|
+
class DataNormalizer
|
8
|
+
|
9
|
+
COOKBOOK_SEGMENTS = %w{ resources providers recipes definitions libraries attributes files templates root_files }.freeze
|
10
|
+
|
11
|
+
def self.normalize_acls(acls)
|
12
|
+
ChefData::DefaultCreator::PERMISSIONS.each do |perm|
|
13
|
+
acls[perm] ||= {}
|
14
|
+
acls[perm]["groups"] ||= []
|
15
|
+
if acls[perm].key? "users"
|
16
|
+
# When clients and users are split, their combined list
|
17
|
+
# is the final list of actors that a subsequent GET will
|
18
|
+
# provide. Each list is guaranteed to be unique, but the
|
19
|
+
# combined list is not.
|
20
|
+
acls[perm]["actors"] = acls[perm]["clients"].uniq +
|
21
|
+
acls[perm]["users"].uniq
|
22
|
+
else
|
23
|
+
# this gets doubled sometimes, for reasons.
|
24
|
+
(acls[perm]["actors"] ||= []).uniq!
|
25
|
+
end
|
26
|
+
end
|
27
|
+
acls
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.normalize_client(client, name, orgname = nil)
|
31
|
+
client["name"] ||= name
|
32
|
+
client["clientname"] ||= name
|
33
|
+
client["admin"] = !!client["admin"] if client.key?("admin")
|
34
|
+
client["public_key"] = PUBLIC_KEY unless client.key?("public_key")
|
35
|
+
client["orgname"] ||= orgname
|
36
|
+
client["validator"] ||= false
|
37
|
+
client["validator"] = !!client["validator"]
|
38
|
+
client["json_class"] ||= "Chef::ApiClient"
|
39
|
+
client["chef_type"] ||= "client"
|
40
|
+
client
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.normalize_container(container, name)
|
44
|
+
container.delete("id")
|
45
|
+
container["containername"] = name
|
46
|
+
container["containerpath"] = name
|
47
|
+
container
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.normalize_user(user, name, identity_keys, osc_compat, method = nil)
|
51
|
+
user[identity_keys.first] ||= name
|
52
|
+
user["public_key"] = PUBLIC_KEY unless user.key?("public_key")
|
53
|
+
user["admin"] ||= false
|
54
|
+
user["admin"] = !!user["admin"]
|
55
|
+
user["openid"] ||= nil
|
56
|
+
unless osc_compat
|
57
|
+
if method == "GET"
|
58
|
+
user.delete("admin")
|
59
|
+
user.delete("password")
|
60
|
+
user.delete("openid")
|
61
|
+
end
|
62
|
+
user["email"] ||= nil
|
63
|
+
user["first_name"] ||= nil
|
64
|
+
user["last_name"] ||= nil
|
65
|
+
user["display_name"] ||= nil
|
66
|
+
end
|
67
|
+
user
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.normalize_data_bag_item(data_bag_item, data_bag_name, id, method)
|
71
|
+
if method == "DELETE"
|
72
|
+
# TODO SERIOUSLY, WHO DOES THIS MANY EXCEPTIONS IN THEIR INTERFACE
|
73
|
+
unless data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
|
74
|
+
data_bag_item["id"] ||= id
|
75
|
+
data_bag_item = { "raw_data" => data_bag_item }
|
76
|
+
data_bag_item["chef_type"] ||= "data_bag_item"
|
77
|
+
data_bag_item["json_class"] ||= "Chef::DataBagItem"
|
78
|
+
data_bag_item["data_bag"] ||= data_bag_name
|
79
|
+
data_bag_item["name"] ||= "data_bag_item_#{data_bag_name}_#{id}"
|
80
|
+
end
|
81
|
+
else
|
82
|
+
# If it's not already wrapped with raw_data, wrap it.
|
83
|
+
if data_bag_item["json_class"] == "Chef::DataBagItem" && data_bag_item["raw_data"]
|
84
|
+
data_bag_item = data_bag_item["raw_data"]
|
85
|
+
end
|
86
|
+
# Argh. We don't do this on GET, but we do on PUT and POST????
|
87
|
+
if %w{PUT POST}.include?(method)
|
88
|
+
data_bag_item["chef_type"] ||= "data_bag_item"
|
89
|
+
data_bag_item["data_bag"] ||= data_bag_name
|
90
|
+
end
|
91
|
+
data_bag_item["id"] ||= id
|
92
|
+
end
|
93
|
+
data_bag_item
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.normalize_cookbook(endpoint, org_prefix, cookbook, name, version, base_uri, method,
|
97
|
+
is_cookbook_artifact = false, api_version: 2)
|
98
|
+
# TODO I feel dirty
|
99
|
+
if method == "PUT" && api_version < 2
|
100
|
+
cookbook["all_files"] = cookbook.delete(["root_files"]) { [] }
|
101
|
+
COOKBOOK_SEGMENTS.each do |segment|
|
102
|
+
next unless cookbook.key? segment
|
103
|
+
|
104
|
+
cookbook[segment].each do |file|
|
105
|
+
file["name"] = "#{segment}/#{file["name"]}"
|
106
|
+
cookbook["all_files"] << file
|
107
|
+
end
|
108
|
+
cookbook.delete(segment)
|
109
|
+
end
|
110
|
+
elsif method != "PUT"
|
111
|
+
if cookbook.key? "all_files"
|
112
|
+
cookbook["all_files"].each do |file|
|
113
|
+
if file.is_a?(Hash) && file.key?("checksum")
|
114
|
+
file["url"] ||= endpoint.build_uri(base_uri, org_prefix + ["file_store", "checksums", file["checksum"]])
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# down convert to old style manifest, ensuring we don't send all_files on the wire and that we correctly divine segments
|
119
|
+
# any file that's not in an old segment is just dropped on the floor.
|
120
|
+
if api_version < 2
|
121
|
+
|
122
|
+
# the spec appears to think we should send empty arrays for each segment, so let's do that
|
123
|
+
COOKBOOK_SEGMENTS.each { |seg| cookbook[seg] ||= [] }
|
124
|
+
|
125
|
+
cookbook["all_files"].each do |file|
|
126
|
+
segment, name = file["name"].split("/")
|
127
|
+
|
128
|
+
# root_files have no segment prepended
|
129
|
+
if name.nil?
|
130
|
+
name = segment
|
131
|
+
segment = "root_files"
|
132
|
+
end
|
133
|
+
|
134
|
+
file.delete("full_path")
|
135
|
+
next unless COOKBOOK_SEGMENTS.include? segment
|
136
|
+
|
137
|
+
file["name"] = name
|
138
|
+
cookbook[segment] << file
|
139
|
+
end
|
140
|
+
cookbook.delete("all_files")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
cookbook["name"] ||= "#{name}-#{version}"
|
145
|
+
# TODO it feels wrong, but the real chef server doesn't expand 'version', so we don't either.
|
146
|
+
|
147
|
+
cookbook["frozen?"] ||= false
|
148
|
+
cookbook["metadata"] ||= {}
|
149
|
+
cookbook["metadata"]["version"] ||= version
|
150
|
+
|
151
|
+
# defaults set by the client and not the Server:
|
152
|
+
# metadata[name, description, maintainer, maintainer_email, license]
|
153
|
+
|
154
|
+
cookbook["metadata"]["long_description"] ||= ""
|
155
|
+
cookbook["metadata"]["dependencies"] ||= {}
|
156
|
+
cookbook["metadata"]["attributes"] ||= {}
|
157
|
+
cookbook["metadata"]["recipes"] ||= {}
|
158
|
+
end
|
159
|
+
|
160
|
+
if is_cookbook_artifact
|
161
|
+
cookbook.delete("json_class")
|
162
|
+
else
|
163
|
+
cookbook["cookbook_name"] ||= name
|
164
|
+
cookbook["json_class"] ||= "Chef::CookbookVersion"
|
165
|
+
end
|
166
|
+
|
167
|
+
cookbook["chef_type"] ||= "cookbook_version"
|
168
|
+
if method == "MIN"
|
169
|
+
cookbook["metadata"].delete("attributes")
|
170
|
+
cookbook["metadata"].delete("long_description")
|
171
|
+
end
|
172
|
+
cookbook
|
173
|
+
end
|
174
|
+
|
175
|
+
def self.normalize_environment(environment, name)
|
176
|
+
environment["name"] ||= name
|
177
|
+
environment["description"] ||= ""
|
178
|
+
environment["cookbook_versions"] ||= {}
|
179
|
+
environment["json_class"] ||= "Chef::Environment"
|
180
|
+
environment["chef_type"] ||= "environment"
|
181
|
+
environment["default_attributes"] ||= {}
|
182
|
+
environment["override_attributes"] ||= {}
|
183
|
+
environment
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.normalize_group(group, name, orgname)
|
187
|
+
group.delete("id")
|
188
|
+
if group["actors"].is_a?(Hash)
|
189
|
+
group["users"] ||= group["actors"]["users"]
|
190
|
+
group["clients"] ||= group["actors"]["clients"]
|
191
|
+
group["groups"] ||= group["actors"]["groups"]
|
192
|
+
group["actors"] = nil
|
193
|
+
end
|
194
|
+
group["users"] ||= []
|
195
|
+
group["clients"] ||= []
|
196
|
+
group["actors"] ||= (group["clients"] + group["users"])
|
197
|
+
group["groups"] ||= []
|
198
|
+
group["orgname"] ||= orgname if orgname
|
199
|
+
group["name"] ||= name
|
200
|
+
group["groupname"] ||= name
|
201
|
+
|
202
|
+
group["users"].uniq!
|
203
|
+
group["clients"].uniq!
|
204
|
+
group["actors"].uniq!
|
205
|
+
group["groups"].uniq!
|
206
|
+
group
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.normalize_node(node, name)
|
210
|
+
node["name"] ||= name
|
211
|
+
node["json_class"] ||= "Chef::Node"
|
212
|
+
node["chef_type"] ||= "node"
|
213
|
+
node["chef_environment"] ||= "_default"
|
214
|
+
node["override"] ||= {}
|
215
|
+
node["normal"] ||= { "tags" => [] }
|
216
|
+
node["default"] ||= {}
|
217
|
+
node["automatic"] ||= {}
|
218
|
+
node["run_list"] ||= []
|
219
|
+
node["run_list"] = normalize_run_list(node["run_list"])
|
220
|
+
node
|
221
|
+
end
|
222
|
+
|
223
|
+
def self.normalize_policy(policy, name, revision)
|
224
|
+
policy["name"] ||= name
|
225
|
+
policy["revision_id"] ||= revision
|
226
|
+
policy["run_list"] ||= []
|
227
|
+
policy["cookbook_locks"] ||= {}
|
228
|
+
policy
|
229
|
+
end
|
230
|
+
|
231
|
+
def self.normalize_policy_group(policy_group, name)
|
232
|
+
policy_group[name] ||= "name"
|
233
|
+
policy_group["policies"] ||= {}
|
234
|
+
policy_group
|
235
|
+
end
|
236
|
+
|
237
|
+
def self.normalize_organization(org, name)
|
238
|
+
org["name"] ||= name
|
239
|
+
org["full_name"] ||= name
|
240
|
+
org["org_type"] ||= "Business"
|
241
|
+
org["clientname"] ||= "#{name}-validator"
|
242
|
+
org["billing_plan"] ||= "platform-free"
|
243
|
+
org
|
244
|
+
end
|
245
|
+
|
246
|
+
def self.normalize_role(role, name)
|
247
|
+
role["name"] ||= name
|
248
|
+
role["description"] ||= ""
|
249
|
+
role["json_class"] ||= "Chef::Role"
|
250
|
+
role["chef_type"] ||= "role"
|
251
|
+
role["default_attributes"] ||= {}
|
252
|
+
role["override_attributes"] ||= {}
|
253
|
+
role["run_list"] ||= []
|
254
|
+
role["run_list"] = normalize_run_list(role["run_list"])
|
255
|
+
role["env_run_lists"] ||= {}
|
256
|
+
role["env_run_lists"].each_pair do |env, run_list|
|
257
|
+
role["env_run_lists"][env] = normalize_run_list(run_list)
|
258
|
+
end
|
259
|
+
role
|
260
|
+
end
|
261
|
+
|
262
|
+
def self.normalize_run_list(run_list)
|
263
|
+
run_list.map do |item|
|
264
|
+
case item
|
265
|
+
when /^recipe\[.*\]$/
|
266
|
+
item # explicit recipe
|
267
|
+
when /^role\[.*\]$/
|
268
|
+
item # explicit role
|
269
|
+
else
|
270
|
+
"recipe[#{item}]"
|
271
|
+
end
|
272
|
+
end.uniq
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|