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.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +36 -31
  3. data/LICENSE +201 -201
  4. data/Rakefile +73 -68
  5. data/bin/chef-zero +111 -111
  6. data/chef-zero.gemspec +34 -33
  7. data/lib/chef_zero/chef_data/acl_path.rb +140 -140
  8. data/lib/chef_zero/chef_data/cookbook_data.rb +237 -237
  9. data/lib/chef_zero/chef_data/data_normalizer.rb +276 -276
  10. data/lib/chef_zero/chef_data/default_creator.rb +476 -476
  11. data/lib/chef_zero/data_store/data_already_exists_error.rb +29 -29
  12. data/lib/chef_zero/data_store/data_error.rb +32 -32
  13. data/lib/chef_zero/data_store/data_not_found_error.rb +29 -29
  14. data/lib/chef_zero/data_store/default_facade.rb +143 -147
  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 +159 -159
  19. data/lib/chef_zero/data_store/raw_file_store.rb +143 -143
  20. data/lib/chef_zero/data_store/v1_to_v2_adapter.rb +150 -150
  21. data/lib/chef_zero/data_store/v2_to_v1_adapter.rb +105 -105
  22. data/lib/chef_zero/dist.rb +9 -9
  23. data/lib/chef_zero/endpoints/acl_endpoint.rb +39 -39
  24. data/lib/chef_zero/endpoints/acls_endpoint.rb +41 -41
  25. data/lib/chef_zero/endpoints/actor_default_key_endpoint.rb +78 -78
  26. data/lib/chef_zero/endpoints/actor_endpoint.rb +184 -184
  27. data/lib/chef_zero/endpoints/actor_key_endpoint.rb +62 -62
  28. data/lib/chef_zero/endpoints/actor_keys_endpoint.rb +129 -129
  29. data/lib/chef_zero/endpoints/actors_endpoint.rb +104 -104
  30. data/lib/chef_zero/endpoints/authenticate_user_endpoint.rb +32 -32
  31. data/lib/chef_zero/endpoints/container_endpoint.rb +22 -22
  32. data/lib/chef_zero/endpoints/containers_endpoint.rb +25 -25
  33. data/lib/chef_zero/endpoints/controls_endpoint.rb +16 -16
  34. data/lib/chef_zero/endpoints/cookbook_artifact_endpoint.rb +24 -24
  35. data/lib/chef_zero/endpoints/cookbook_artifact_identifier_endpoint.rb +68 -68
  36. data/lib/chef_zero/endpoints/cookbook_artifacts_endpoint.rb +34 -34
  37. data/lib/chef_zero/endpoints/cookbook_endpoint.rb +39 -39
  38. data/lib/chef_zero/endpoints/cookbook_version_endpoint.rb +136 -136
  39. data/lib/chef_zero/endpoints/cookbooks_base.rb +80 -80
  40. data/lib/chef_zero/endpoints/cookbooks_endpoint.rb +19 -19
  41. data/lib/chef_zero/endpoints/data_bag_endpoint.rb +45 -45
  42. data/lib/chef_zero/endpoints/data_bag_item_endpoint.rb +25 -25
  43. data/lib/chef_zero/endpoints/data_bags_endpoint.rb +23 -23
  44. data/lib/chef_zero/endpoints/dummy_endpoint.rb +29 -29
  45. data/lib/chef_zero/endpoints/environment_cookbook_endpoint.rb +24 -24
  46. data/lib/chef_zero/endpoints/environment_cookbook_versions_endpoint.rb +126 -126
  47. data/lib/chef_zero/endpoints/environment_cookbooks_endpoint.rb +22 -22
  48. data/lib/chef_zero/endpoints/environment_endpoint.rb +33 -33
  49. data/lib/chef_zero/endpoints/environment_nodes_endpoint.rb +23 -23
  50. data/lib/chef_zero/endpoints/environment_recipes_endpoint.rb +22 -22
  51. data/lib/chef_zero/endpoints/environment_role_endpoint.rb +36 -36
  52. data/lib/chef_zero/endpoints/file_store_file_endpoint.rb +22 -22
  53. data/lib/chef_zero/endpoints/group_endpoint.rb +20 -20
  54. data/lib/chef_zero/endpoints/groups_endpoint.rb +13 -13
  55. data/lib/chef_zero/endpoints/license_endpoint.rb +25 -25
  56. data/lib/chef_zero/endpoints/node_endpoint.rb +34 -34
  57. data/lib/chef_zero/endpoints/node_identifiers_endpoint.rb +22 -22
  58. data/lib/chef_zero/endpoints/nodes_endpoint.rb +34 -34
  59. data/lib/chef_zero/endpoints/not_found_endpoint.rb +11 -11
  60. data/lib/chef_zero/endpoints/organization_association_request_endpoint.rb +22 -22
  61. data/lib/chef_zero/endpoints/organization_association_requests_endpoint.rb +30 -30
  62. data/lib/chef_zero/endpoints/organization_authenticate_user_endpoint.rb +26 -26
  63. data/lib/chef_zero/endpoints/organization_endpoint.rb +47 -47
  64. data/lib/chef_zero/endpoints/organization_user_base.rb +15 -15
  65. data/lib/chef_zero/endpoints/organization_user_default_key_endpoint.rb +16 -16
  66. data/lib/chef_zero/endpoints/organization_user_endpoint.rb +26 -26
  67. data/lib/chef_zero/endpoints/organization_user_key_endpoint.rb +17 -17
  68. data/lib/chef_zero/endpoints/organization_user_keys_endpoint.rb +17 -17
  69. data/lib/chef_zero/endpoints/organization_users_endpoint.rb +43 -43
  70. data/lib/chef_zero/endpoints/organization_validator_key_endpoint.rb +20 -20
  71. data/lib/chef_zero/endpoints/organizations_endpoint.rb +61 -61
  72. data/lib/chef_zero/endpoints/policies_endpoint.rb +26 -26
  73. data/lib/chef_zero/endpoints/policy_endpoint.rb +24 -24
  74. data/lib/chef_zero/endpoints/policy_group_endpoint.rb +46 -46
  75. data/lib/chef_zero/endpoints/policy_group_policy_endpoint.rb +83 -83
  76. data/lib/chef_zero/endpoints/policy_groups_endpoint.rb +38 -38
  77. data/lib/chef_zero/endpoints/policy_revision_endpoint.rb +66 -66
  78. data/lib/chef_zero/endpoints/policy_revisions_endpoint.rb +15 -15
  79. data/lib/chef_zero/endpoints/principal_endpoint.rb +55 -55
  80. data/lib/chef_zero/endpoints/rest_list_endpoint.rb +42 -42
  81. data/lib/chef_zero/endpoints/rest_object_endpoint.rb +78 -78
  82. data/lib/chef_zero/endpoints/role_endpoint.rb +16 -16
  83. data/lib/chef_zero/endpoints/role_environments_endpoint.rb +14 -14
  84. data/lib/chef_zero/endpoints/sandbox_endpoint.rb +27 -27
  85. data/lib/chef_zero/endpoints/sandboxes_endpoint.rb +51 -51
  86. data/lib/chef_zero/endpoints/search_endpoint.rb +208 -208
  87. data/lib/chef_zero/endpoints/searches_endpoint.rb +18 -18
  88. data/lib/chef_zero/endpoints/server_api_version_endpoint.rb +14 -14
  89. data/lib/chef_zero/endpoints/system_recovery_endpoint.rb +30 -30
  90. data/lib/chef_zero/endpoints/universe_endpoint.rb +15 -15
  91. data/lib/chef_zero/endpoints/user_association_request_endpoint.rb +41 -41
  92. data/lib/chef_zero/endpoints/user_association_requests_count_endpoint.rb +19 -19
  93. data/lib/chef_zero/endpoints/user_association_requests_endpoint.rb +19 -19
  94. data/lib/chef_zero/endpoints/user_organizations_endpoint.rb +22 -22
  95. data/lib/chef_zero/endpoints/version_endpoint.rb +13 -13
  96. data/lib/chef_zero/log.rb +7 -7
  97. data/lib/chef_zero/rest_base.rb +332 -332
  98. data/lib/chef_zero/rest_error_response.rb +11 -11
  99. data/lib/chef_zero/rest_request.rb +84 -88
  100. data/lib/chef_zero/rest_router.rb +72 -72
  101. data/lib/chef_zero/rspec.rb +355 -355
  102. data/lib/chef_zero/server.rb +730 -730
  103. data/lib/chef_zero/socketless_server_map.rb +92 -93
  104. data/lib/chef_zero/solr/query/binary_operator.rb +52 -52
  105. data/lib/chef_zero/solr/query/phrase.rb +23 -23
  106. data/lib/chef_zero/solr/query/range_query.rb +46 -46
  107. data/lib/chef_zero/solr/query/regexpable_query.rb +30 -30
  108. data/lib/chef_zero/solr/query/subquery.rb +37 -37
  109. data/lib/chef_zero/solr/query/term.rb +45 -45
  110. data/lib/chef_zero/solr/query/unary_operator.rb +41 -41
  111. data/lib/chef_zero/solr/solr_doc.rb +53 -53
  112. data/lib/chef_zero/solr/solr_parser.rb +208 -208
  113. data/lib/chef_zero/version.rb +3 -3
  114. data/lib/chef_zero.rb +10 -10
  115. data/spec/run_oc_pedant.rb +226 -226
  116. data/spec/search_spec.rb +36 -36
  117. data/spec/server_spec.rb +96 -96
  118. data/spec/socketless_server_map_spec.rb +74 -74
  119. data/spec/support/oc_pedant.rb +149 -149
  120. data/spec/support/secrets.json +6 -6
  121. data/spec/support/stickywicket.pem +27 -27
  122. 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