chef-zero 5.3.2 → 13.0.0

Sign up to get free protection for your applications and to get access to all the features.
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