chef-zero 5.3.2 → 13.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c112587ef733b5fcb5a38cfe65d5008e797f7df8
4
- data.tar.gz: 4e19d9af2a6fc423de906afccef0e878da603736
3
+ metadata.gz: 396ae8f8740ff30a19cf21a04cf020be332b9f9e
4
+ data.tar.gz: e9d0bab91a60b421e3e17b69488ff377777bdeb3
5
5
  SHA512:
6
- metadata.gz: b576d2cd5cad7f0504bcf4818e2ce144d356a0f68f98f3d29134043bc67b4d632b70306613eb742a3dce907de7ed205d9780756ef87f62f32152b71e5c3c550a
7
- data.tar.gz: 747890ec9ca51713a8ff529b123686348d2db1294e2a7f9712fd127411cd556b866c6ab179df9e43be7e0222549e3ddb1dd393a28d608f8f7a4cb2840025cf06
6
+ metadata.gz: a059d4ae5e327a1e9b1d6c1bfb1ba5a0585483935b3499c83167c580daf1fc7300ad378e236276a05555e4f9feb0629b40899f5ccfcc86aff09f7a4acefdf82d
7
+ data.tar.gz: 5a160f7e546ab7242335f0416ed2443d0d64c0d19547c26f1796cac9c4078c865b092e7172c221c8c180ac882b938c7af7d354f4af6b17bf473d3b323a899536
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
  s.homepage = "http://www.chef.io"
13
13
  s.license = "Apache 2.0"
14
14
 
15
- s.required_ruby_version = ">= 2.2.2"
15
+ s.required_ruby_version = ">= 2.3.1"
16
16
 
17
17
  s.add_dependency "mixlib-log", "~> 1.3"
18
18
  s.add_dependency "hashie", ">= 2.0", "< 4.0"
@@ -2,7 +2,7 @@ module ChefZero
2
2
  require "chef_zero/log"
3
3
 
4
4
  MIN_API_VERSION = 0
5
- MAX_API_VERSION = 1
5
+ MAX_API_VERSION = 2
6
6
 
7
7
  CERTIFICATE = "-----BEGIN CERTIFICATE-----\nMIIDMzCCApygAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnjELMAkGA1UEBhMCVVMx\nEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxFjAUBgNVBAoM\nDU9wc2NvZGUsIEluYy4xHDAaBgNVBAsME0NlcnRpZmljYXRlIFNlcnZpY2UxMjAw\nBgNVBAMMKW9wc2NvZGUuY29tL2VtYWlsQWRkcmVzcz1hdXRoQG9wc2NvZGUuY29t\nMB4XDTEyMTEyMTAwMzQyMVoXDTIyMTExOTAwMzQyMVowgZsxEDAOBgNVBAcTB1Nl\nYXR0bGUxEzARBgNVBAgTCldhc2hpbmd0b24xCzAJBgNVBAYTAlVTMRwwGgYDVQQL\nExNDZXJ0aWZpY2F0ZSBTZXJ2aWNlMRYwFAYDVQQKEw1PcHNjb2RlLCBJbmMuMS8w\nLQYDVQQDFCZVUkk6aHR0cDovL29wc2NvZGUuY29tL0dVSURTL3VzZXJfZ3VpZDCC\nASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANLDmPbR71bS2esZlZh/HfC6\n0azXFjl2677wq2ovk9xrUb0Ui4ZLC66TqQ9C/RBzOjXU4TRf3hgPTqvlCgHusl0d\nIcLCrsSl6kPEhJpYWWfRoroIAwf82A9yLQekhqXZEXu5EKkwoUMqyF6m0ZCasaE1\ny8niQxdLAsk3ady/CGQlFqHTPKFfU5UASR2LRtYC1MCIvJHDFRKAp9kPJbQo9P37\nZ8IU7cDudkZFgNLmDixlWsh7C0ghX8fgAlj1P6FgsFufygam973k79GhIP54dELB\nc0S6E8ekkRSOXU9jX/IoiXuFglBvFihAdhvED58bMXzj2AwXUyeAlxItnvs+NVUC\nAwEAATANBgkqhkiG9w0BAQUFAAOBgQBkFZRbMoywK3hb0/X7MXmPYa7nlfnd5UXq\nr2n32ettzZNmEPaI2d1j+//nL5qqhOlrWPS88eKEPnBOX/jZpUWOuAAddnrvFzgw\nrp/C2H7oMT+29F+5ezeViLKbzoFYb4yECHBoi66IFXNae13yj7taMboBeUmE664G\nTB/MZpRr8g==\n-----END CERTIFICATE-----\n"
8
8
  PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0sOY9tHvVtLZ6xmVmH8d\n8LrRrNcWOXbrvvCrai+T3GtRvRSLhksLrpOpD0L9EHM6NdThNF/eGA9Oq+UKAe6y\nXR0hwsKuxKXqQ8SEmlhZZ9GiuggDB/zYD3ItB6SGpdkRe7kQqTChQyrIXqbRkJqx\noTXLyeJDF0sCyTdp3L8IZCUWodM8oV9TlQBJHYtG1gLUwIi8kcMVEoCn2Q8ltCj0\n/ftnwhTtwO52RkWA0uYOLGVayHsLSCFfx+ACWPU/oWCwW5/KBqb3veTv0aEg/nh0\nQsFzRLoTx6SRFI5dT2Nf8iiJe4WCUG8WKEB2G8QPnxsxfOPYDBdTJ4CXEi2e+z41\nVQIDAQAB\n-----END PUBLIC KEY-----\n"
@@ -13,7 +13,9 @@ module ChefZero
13
13
  end
14
14
 
15
15
  result = files_from(cookbook)
16
- recipe_names = result[:recipes].map do |recipe|
16
+ recipe_names = result[:all_files].select do |file|
17
+ file[:name].start_with?("recipes/")
18
+ end.map do |recipe|
17
19
  recipe_name = recipe[:name][0..-2]
18
20
  recipe_name == "default" ? name : "#{name}::#{recipe_name}"
19
21
  end
@@ -86,26 +88,10 @@ module ChefZero
86
88
  cookbook_arg(:supports, cookbook, version_constraints)
87
89
  end
88
90
 
89
- def recommends(cookbook, *version_constraints)
90
- cookbook_arg(:recommendations, cookbook, version_constraints)
91
- end
92
-
93
- def suggests(cookbook, *version_constraints)
94
- cookbook_arg(:suggestions, cookbook, version_constraints)
95
- end
96
-
97
- def conflicts(cookbook, *version_constraints)
98
- cookbook_arg(:conflicting, cookbook, version_constraints)
99
- end
100
-
101
91
  def provides(cookbook, *version_constraints)
102
92
  cookbook_arg(:providing, cookbook, version_constraints)
103
93
  end
104
94
 
105
- def replaces(cookbook, *version_constraints)
106
- cookbook_arg(:replacing, cookbook, version_constraints)
107
- end
108
-
109
95
  def gem(*opts)
110
96
  self[:gems] ||= []
111
97
  self[:gems] << opts
@@ -119,10 +105,6 @@ module ChefZero
119
105
  self[:attributes][name] = options
120
106
  end
121
107
 
122
- def grouping(name, options)
123
- self[:grouping][name] = options
124
- end
125
-
126
108
  def cookbook_arg(key, cookbook, version_constraints)
127
109
  self[key][cookbook] = version_constraints.first || ">= 0.0.0"
128
110
  end
@@ -142,19 +124,14 @@ module ChefZero
142
124
 
143
125
  def self.files_from(directory)
144
126
  # TODO some support .rb only
127
+ result = load_files(directory)
128
+
129
+ set_specificity(result, :templates)
130
+ set_specificity(result, :files)
131
+
145
132
  result = {
146
- :attributes => load_child_files(directory, "attributes", false),
147
- :definitions => load_child_files(directory, "definitions", false),
148
- :recipes => load_child_files(directory, "recipes", false),
149
- :libraries => load_child_files(directory, "libraries", true),
150
- :templates => load_child_files(directory, "templates", true),
151
- :files => load_child_files(directory, "files", true),
152
- :resources => load_child_files(directory, "resources", true),
153
- :providers => load_child_files(directory, "providers", true),
154
- :root_files => load_files(directory, false),
133
+ all_files: result,
155
134
  }
156
- set_specificity(result[:templates])
157
- set_specificity(result[:files])
158
135
  result
159
136
  end
160
137
 
@@ -199,45 +176,52 @@ module ChefZero
199
176
  end
200
177
  end
201
178
 
202
- def self.load_child_files(parent, key, recursive)
203
- result = load_files(get_directory(parent, key), recursive)
179
+ def self.load_child_files(parent, key, recursive, part)
180
+ result = load_files(get_directory(parent, key), recursive, part)
204
181
  result.each do |file|
205
182
  file[:path] = "#{key}/#{file[:path]}"
206
183
  end
207
184
  result
208
185
  end
209
186
 
210
- def self.load_files(directory, recursive)
187
+ def self.load_files(directory, recursive = true, part = nil)
211
188
  result = []
212
189
  if directory
213
190
  list(directory).each do |child_name|
214
191
  dir = get_directory(directory, child_name)
215
192
  if dir
193
+ child_part = child_name if part.nil?
216
194
  if recursive
217
- result += load_child_files(directory, child_name, recursive)
195
+ result += load_child_files(directory, child_name, recursive, child_part)
218
196
  end
219
197
  else
220
- result += load_file(read_file(directory, child_name), child_name)
198
+ result += load_file(read_file(directory, child_name), child_name, part)
221
199
  end
222
200
  end
223
201
  end
224
202
  result
225
203
  end
226
204
 
227
- def self.load_file(value, name)
205
+ def self.load_file(value, name, part = nil)
206
+ specific_name = part ? "#{part}/#{name}" : name
228
207
  [{
229
- :name => name,
208
+ :name => specific_name,
230
209
  :path => name,
231
210
  :checksum => Digest::MD5.hexdigest(value),
232
211
  :specificity => "default",
233
212
  }]
234
213
  end
235
214
 
236
- def self.set_specificity(files)
215
+ def self.set_specificity(files, type)
237
216
  files.each do |file|
217
+ next unless file[:name].split("/")[0] == type.to_s
218
+
238
219
  parts = file[:path].split("/")
239
- raise "Only directories are allowed directly under templates or files: #{file[:path]}" if parts.size == 2
240
- file[:specificity] = parts[1]
220
+ file[:specificity] = if parts.size == 2
221
+ "default"
222
+ else
223
+ parts[1]
224
+ end
241
225
  end
242
226
  end
243
227
  end
@@ -5,6 +5,9 @@ require "chef_zero/chef_data/default_creator"
5
5
  module ChefZero
6
6
  module ChefData
7
7
  class DataNormalizer
8
+
9
+ COOKBOOK_SEGMENTS = %w{ resources providers recipes definitions libraries attributes files templates root_files }
10
+
8
11
  def self.normalize_acls(acls)
9
12
  ChefData::DefaultCreator::PERMISSIONS.each do |perm|
10
13
  acls[perm] ||= {}
@@ -90,18 +93,51 @@ module ChefZero
90
93
  end
91
94
 
92
95
  def self.normalize_cookbook(endpoint, org_prefix, cookbook, name, version, base_uri, method,
93
- is_cookbook_artifact = false)
96
+ is_cookbook_artifact = false, api_version: 2)
94
97
  # TODO I feel dirty
95
- if method != "PUT"
96
- cookbook.each_pair do |key, value|
97
- if value.is_a?(Array)
98
- value.each do |file|
99
- if file.is_a?(Hash) && file.has_key?("checksum")
100
- file["url"] ||= endpoint.build_uri(base_uri, org_prefix + ["file_store", "checksums", file["checksum"]])
98
+ if method == "PUT" && api_version < 2
99
+ cookbook["all_files"] = cookbook.delete(["root_files"]) { [] }
100
+ COOKBOOK_SEGMENTS.each do |segment|
101
+ next unless cookbook.has_key? segment
102
+ cookbook[segment].each do |file|
103
+ file["name"] = "#{segment}/#{file['name']}"
104
+ cookbook["all_files"] << file
105
+ end
106
+ cookbook.delete(segment)
107
+ end
108
+ elsif method != "PUT"
109
+ if cookbook.key? "all_files"
110
+ cookbook["all_files"].each do |file|
111
+ if file.is_a?(Hash) && file.has_key?("checksum")
112
+ file["url"] ||= endpoint.build_uri(base_uri, org_prefix + ["file_store", "checksums", file["checksum"]])
113
+ end
114
+ end
115
+
116
+ # down convert to old style manifest, ensuring we don't send all_files on the wire and that we correctly divine segments
117
+ # any file that's not in an old segment is just dropped on the floor.
118
+ if api_version < 2
119
+
120
+ # the spec appears to think we should send empty arrays for each segment, so let's do that
121
+ COOKBOOK_SEGMENTS.each { |seg| cookbook[seg] ||= [] }
122
+
123
+ cookbook["all_files"].each do |file|
124
+ segment, name = file["name"].split("/")
125
+
126
+ # root_files have no segment prepended
127
+ if name.nil?
128
+ name = segment
129
+ segment = "root_files"
101
130
  end
131
+
132
+ file.delete("full_path")
133
+ next unless COOKBOOK_SEGMENTS.include? segment
134
+ file["name"] = name
135
+ cookbook[segment] << file
102
136
  end
137
+ cookbook.delete("all_files")
103
138
  end
104
139
  end
140
+
105
141
  cookbook["name"] ||= "#{name}-#{version}"
106
142
  # TODO it feels wrong, but the real chef server doesn't expand 'version', so we don't either.
107
143
 
@@ -9,7 +9,7 @@ module ChefZero
9
9
 
10
10
  # GET /organizations/ORG/cookbook_artifacts/NAME/IDENTIFIER
11
11
  def get(request)
12
- cookbook_data = normalize(request, parse_json(get_data(request)))
12
+ cookbook_data = normalize(request, get_data(request))
13
13
  return json_response(200, cookbook_data)
14
14
  end
15
15
 
@@ -19,7 +19,8 @@ module ChefZero
19
19
  return error(409, "Cookbooks cannot be modified, and a cookbook with this identifier already exists.")
20
20
  end
21
21
 
22
- set_data(request, nil, request.body, :create_dir)
22
+ cb_data = normalize(request, request.body)
23
+ set_data(request, nil, to_json(cb_data), :create_dir)
23
24
 
24
25
  return already_json_response(201, request.body)
25
26
  end
@@ -28,7 +29,7 @@ module ChefZero
28
29
  def delete(request)
29
30
  begin
30
31
  doomed_cookbook_json = get_data(request)
31
- identified_cookbook_data = normalize(request, parse_json(doomed_cookbook_json))
32
+ identified_cookbook_data = normalize(request, doomed_cookbook_json)
32
33
  delete_data(request)
33
34
 
34
35
  # go through the recipes and delete stuff in the file store.
@@ -59,9 +60,10 @@ module ChefZero
59
60
  end
60
61
 
61
62
  def normalize(request, cookbook_artifact_data)
63
+ cookbook = parse_json(cookbook_artifact_data)
62
64
  ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1],
63
- cookbook_artifact_data, request.rest_path[3], request.rest_path[4],
64
- request.base_uri, request.method, true)
65
+ cookbook, request.rest_path[3], request.rest_path[4],
66
+ request.base_uri, request.method, true, api_version: request.api_version)
65
67
  end
66
68
  end
67
69
  end
@@ -37,7 +37,7 @@ module ChefZero
37
37
  end
38
38
 
39
39
  # Set the cookbook
40
- set_data(request, request.rest_path, request.body, :create_dir, :create)
40
+ set_data(request, request.rest_path, populate_defaults(request, request.body), :create_dir, :create)
41
41
 
42
42
  # If the cookbook was updated, check for deleted files and clean them up
43
43
  if existing_cookbook
@@ -47,7 +47,7 @@ module ChefZero
47
47
  end
48
48
  end
49
49
 
50
- already_json_response(existing_cookbook ? 200 : 201, populate_defaults(request, request.body))
50
+ already_json_response(existing_cookbook ? 200 : 201, populate_defaults(request, request.body, normalize: false))
51
51
  end
52
52
 
53
53
  def delete(request)
@@ -116,10 +116,12 @@ module ChefZero
116
116
  end
117
117
  end
118
118
 
119
- def populate_defaults(request, response_json)
119
+ def populate_defaults(request, response_json, normalize: true)
120
120
  # Inject URIs into each cookbook file
121
121
  cookbook = FFI_Yajl::Parser.parse(response_json)
122
- cookbook = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, request.rest_path[3], request.rest_path[4], request.base_uri, request.method)
122
+ cookbook["chef_type"] ||= "cookbook_version"
123
+ cookbook["json_class"] ||= "Chef::CookbookVersion"
124
+ cookbook = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, request.rest_path[3], request.rest_path[4], request.base_uri, request.method, false, api_version: request.api_version) if normalize
123
125
  FFI_Yajl::Encoder.encode(cookbook, :pretty => true)
124
126
  end
125
127
 
@@ -47,18 +47,15 @@ module ChefZero
47
47
  end
48
48
 
49
49
  def recipe_names(cookbook_name, cookbook)
50
- result = []
51
- if cookbook["recipes"]
52
- cookbook["recipes"].each do |recipe|
53
- if recipe["path"] == "recipes/#{recipe['name']}" && recipe["name"][-3..-1] == ".rb"
54
- if recipe["name"] == "default.rb"
55
- result << cookbook_name
56
- end
57
- result << "#{cookbook_name}::#{recipe['name'][0..-4]}"
58
- end
50
+ cookbook["all_files"].inject([]) do |acc, file|
51
+ part, name = file["name"].split("/")
52
+ next unless part == "recipes" || File.extname(name) != ".rb"
53
+ if name == "default.rb"
54
+ acc << cookbook_name
55
+ else
56
+ acc << "#{cookbook_name}::#{File.basename(name, ".rb")}"
59
57
  end
60
58
  end
61
- result
62
59
  end
63
60
  end
64
61
  end
@@ -49,7 +49,7 @@ module ChefZero
49
49
  result = {}
50
50
  solved.each_pair do |name, versions|
51
51
  cookbook = FFI_Yajl::Parser.parse(get_data(request, request.rest_path[0..1] + ["cookbooks", name, versions[0]]))
52
- result[name] = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, name, versions[0], request.base_uri, "MIN")
52
+ result[name] = ChefData::DataNormalizer.normalize_cookbook(self, request.rest_path[0..1], cookbook, name, versions[0], request.base_uri, "MIN", false, api_version: request.api_version)
53
53
  end
54
54
  json_response(200, result)
55
55
  end
@@ -4,7 +4,7 @@ module ChefZero
4
4
  module Endpoints
5
5
  # /server_api_version
6
6
  class ServerAPIVersionEndpoint < RestBase
7
- API_VERSION = 1
7
+ API_VERSION = 2
8
8
  def get(request)
9
9
  json_response(200, { "min_api_version" => MIN_API_VERSION, "max_api_version" => MAX_API_VERSION },
10
10
  request_version: request.api_version, response_version: API_VERSION)
@@ -19,15 +19,7 @@ module ChefZero
19
19
  end
20
20
 
21
21
  def check_api_version(request)
22
- return if request.api_version.nil? # Not present in headers
23
- version = request.api_version.to_i
24
-
25
- unless version.to_s == request.api_version.to_s # Version is not an Integer
26
- return json_response(406,
27
- { "username" => request.requestor },
28
- request_version: -1, response_version: -1
29
- )
30
- end
22
+ version = request.api_version
31
23
 
32
24
  if version > MAX_API_VERSION || version < MIN_API_VERSION
33
25
  response = {
@@ -38,10 +30,15 @@ module ChefZero
38
30
  }
39
31
 
40
32
  return json_response(406,
41
- response,
42
- request_version: version, response_version: -1
43
- )
33
+ response,
34
+ request_version: version, response_version: -1
35
+ )
44
36
  end
37
+ rescue ArgumentError
38
+ return json_response(406,
39
+ { "username" => request.requestor },
40
+ request_version: -1, response_version: -1
41
+ )
45
42
  end
46
43
 
47
44
  def call(request)
@@ -3,8 +3,6 @@ require "rack/request"
3
3
  module ChefZero
4
4
  class RestRequest
5
5
 
6
- ZERO = "0".freeze
7
-
8
6
  def initialize(env, rest_base_prefix = [])
9
7
  @env = env
10
8
  @rest_base_prefix = rest_base_prefix
@@ -28,11 +26,11 @@ module ChefZero
28
26
  end
29
27
 
30
28
  def api_version
31
- @env["HTTP_X_OPS_SERVER_API_VERSION"] || ZERO
29
+ Integer(@env["HTTP_X_OPS_SERVER_API_VERSION"] || 0)
32
30
  end
33
31
 
34
32
  def api_v0?
35
- api_version == ZERO
33
+ api_version == 0
36
34
  end
37
35
 
38
36
  def requestor
@@ -1,3 +1,3 @@
1
1
  module ChefZero
2
- VERSION = "5.3.2"
2
+ VERSION = "13.0.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-zero
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.2
4
+ version: 13.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Keiser
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-28 00:00:00.000000000 Z
11
+ date: 2017-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mixlib-log
@@ -295,7 +295,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
295
295
  requirements:
296
296
  - - ">="
297
297
  - !ruby/object:Gem::Version
298
- version: 2.2.2
298
+ version: 2.3.1
299
299
  required_rubygems_version: !ruby/object:Gem::Requirement
300
300
  requirements:
301
301
  - - ">="
@@ -303,7 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
303
303
  version: '0'
304
304
  requirements: []
305
305
  rubyforge_project:
306
- rubygems_version: 2.6.10
306
+ rubygems_version: 2.6.11
307
307
  signing_key:
308
308
  specification_version: 4
309
309
  summary: Self-contained, easy-setup, fast-start in-memory Chef server for testing