chef 18.7.3 → 18.7.6
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/chef.gemspec +1 -1
- data/lib/chef/data_collector.rb +14 -0
- data/lib/chef/provider/registry_key.rb +0 -4
- data/lib/chef/resource/apt_repository.rb +2 -2
- data/lib/chef/resource/registry_key.rb +4 -16
- data/lib/chef/resource_reporter.rb +3 -0
- data/lib/chef/version.rb +1 -1
- data/spec/functional/resource/registry_spec.rb +0 -43
- data/spec/unit/data_collector_spec.rb +106 -2
- data/spec/unit/provider/registry_key_spec.rb +0 -1
- data/spec/unit/resource_reporter_spec.rb +57 -3
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7b55454579a7afa310852f734fff0049c58da87b1ac48b6a16cfb98837faa2f
|
4
|
+
data.tar.gz: 3904033b7482a4cacf06e68bd4d45540db6ed3ab8e5bf5dfdfbcd56fe99d14df
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46a1c9a9475a3cbab9d945c77ada117ad42a9499afb2fc23c162177127318931a4d724b585e796491bc4415db10fe5d06c3c46164f37d908844db9ec38e51b8a
|
7
|
+
data.tar.gz: b34573bd31fbb8dadb86b09ab9b91236fd5f66d28b10f7e12be668b052a8d10111c01fdce243c18f49f4a2e70aef87bcac964b21ed4500f3397f411b71e6f872
|
data/chef.gemspec
CHANGED
@@ -39,7 +39,7 @@ Gem::Specification.new do |s|
|
|
39
39
|
|
40
40
|
s.add_dependency "license-acceptance", ">= 1.0.5", "< 3"
|
41
41
|
s.add_dependency "mixlib-cli", ">= 2.1.1", "< 3.0"
|
42
|
-
s.add_dependency "mixlib-log", ">= 2.0.3", "
|
42
|
+
s.add_dependency "mixlib-log", ">= 2.0.3", "< 3.2"
|
43
43
|
s.add_dependency "mixlib-authentication", ">= 2.1", "< 4"
|
44
44
|
s.add_dependency "mixlib-shellout", ">= 3.1.1", "< 4.0"
|
45
45
|
s.add_dependency "mixlib-archive", ">= 0.4", "< 2.0"
|
data/lib/chef/data_collector.rb
CHANGED
@@ -270,6 +270,20 @@ class Chef
|
|
270
270
|
send_run_start unless sent_run_start?
|
271
271
|
|
272
272
|
message = Chef::DataCollector::RunEndMessage.construct_message(self, status)
|
273
|
+
|
274
|
+
begin
|
275
|
+
if ChefUtils.windows?
|
276
|
+
# Remove registry key values that are not present in the after state - CHEF-9126
|
277
|
+
message["resources"]&.each do |resource|
|
278
|
+
next unless resource["type"] == :registry_key
|
279
|
+
|
280
|
+
resource["before"][:values]&.reject! { |value| !resource["after"][:values].any? { |after_value| after_value[:name] == value[:name] } }
|
281
|
+
end
|
282
|
+
end
|
283
|
+
rescue StandardError => e
|
284
|
+
Chef::Log.warn("Error while processing registry key values: #{e.message}, #{e.backtrace[0..5]}")
|
285
|
+
end
|
286
|
+
|
273
287
|
send_to_data_collector(message)
|
274
288
|
send_to_output_locations(message)
|
275
289
|
end
|
@@ -51,10 +51,6 @@ class Chef
|
|
51
51
|
current_resource.recursive(new_resource.recursive)
|
52
52
|
if registry.key_exists?(new_resource.key)
|
53
53
|
current_registry_values = registry.get_values(new_resource.key) || []
|
54
|
-
|
55
|
-
if new_resource.only_record_changes
|
56
|
-
current_registry_values.select! { |v| new_resource.values.any? { |nv| nv[:name] == v[:name] } }
|
57
|
-
end
|
58
54
|
current_resource.values(current_registry_values)
|
59
55
|
end
|
60
56
|
values_to_hash(current_resource.unscrubbed_values)
|
@@ -308,8 +308,8 @@ class Chef
|
|
308
308
|
def install_key_from_uri(key)
|
309
309
|
key_name = key.gsub(/[^0-9A-Za-z\-]/, "_")
|
310
310
|
keyfile_path = ::File.join(Chef::Config[:file_cache_path], key_name)
|
311
|
-
tmp_dir =
|
312
|
-
at_exit {
|
311
|
+
tmp_dir = Dir.mktmpdir(".gpg")
|
312
|
+
at_exit { FileUtils.remove_entry(tmp_dir) }
|
313
313
|
|
314
314
|
if new_resource.signed_by
|
315
315
|
keyfile_path = keyring_path
|
@@ -41,19 +41,6 @@ class Chef
|
|
41
41
|
end
|
42
42
|
```
|
43
43
|
|
44
|
-
```ruby
|
45
|
-
**Suppress reporting the sibling values of the values being updated in a registry key**
|
46
|
-
registry 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\CONTROL\Session Manager' do
|
47
|
-
values [{
|
48
|
-
name: 'ProtectionMode',
|
49
|
-
type: :dword,
|
50
|
-
data: 1
|
51
|
-
}]
|
52
|
-
only_record_changes true
|
53
|
-
action :create
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
44
|
**Create a registry key with binary data: "\x01\x02\x03"**:
|
58
45
|
|
59
46
|
```ruby
|
@@ -165,9 +152,10 @@ class Chef
|
|
165
152
|
property :recursive, [TrueClass, FalseClass], default: false
|
166
153
|
property :architecture, Symbol, default: :machine, equal_to: %i{machine x86_64 i386}
|
167
154
|
property :only_record_changes, [TrueClass, FalseClass],
|
168
|
-
|
169
|
-
|
170
|
-
|
155
|
+
default: true,
|
156
|
+
introduced: "18.7.3",
|
157
|
+
description: "(no-op) disabled functionality to only record registry value changes",
|
158
|
+
deprecated: true
|
171
159
|
|
172
160
|
# Some registry key data types may not be safely reported as json.
|
173
161
|
# Example (CHEF-5323):
|
@@ -33,6 +33,9 @@ class Chef
|
|
33
33
|
as_hash["id"] = new_resource.identity.to_s
|
34
34
|
as_hash["after"] = new_resource.state_for_resource_reporter
|
35
35
|
as_hash["before"] = current_resource ? current_resource.state_for_resource_reporter : {}
|
36
|
+
# if the "before" hash is too large, we need to truncate it to avoid 413 errors
|
37
|
+
# 640K ought be enough for every Windows registry entry
|
38
|
+
as_hash["before"] = {} if as_hash["before"].to_json.length > 657920
|
36
39
|
as_hash["duration"] = ( action_record.elapsed_time * 1000 ).to_i.to_s
|
37
40
|
as_hash["delta"] = new_resource.diff if new_resource.respond_to?(:diff)
|
38
41
|
as_hash["delta"] = "" if as_hash["delta"].nil?
|
data/lib/chef/version.rb
CHANGED
@@ -294,49 +294,6 @@ describe Chef::Resource::RegistryKey do
|
|
294
294
|
expect(registry.value_exists?(registry_key, value)).to be true
|
295
295
|
end
|
296
296
|
end
|
297
|
-
|
298
|
-
context "when only_record_changes is the default (true)" do
|
299
|
-
before do
|
300
|
-
prepopulate(registry_key, prepopulated_values)
|
301
|
-
end
|
302
|
-
let(:registry_key) { "#{reg_child}\\OnlyRecordChanges" }
|
303
|
-
let(:registry_key_values) { [{ name: "ReportingVal1", type: :string, data: rand(1235..10000) }] }
|
304
|
-
|
305
|
-
it "should only report the changed value" do
|
306
|
-
subject
|
307
|
-
report = resource_reporter.prepare_run_data
|
308
|
-
|
309
|
-
expect(report["action"]).to eq("end")
|
310
|
-
expect(report["resources"][0]["type"]).to eq(:registry_key)
|
311
|
-
expect(report["resources"][0]["name"]).to eq(resource_name)
|
312
|
-
expect(report["resources"][0]["id"]).to eq(registry_key)
|
313
|
-
expect(report["resources"][0]["after"][:values]).to eq(registry_key_values)
|
314
|
-
expect(report["resources"][0]["before"][:values]).to eq(prepopulated_values.select { |ppv| ppv[:name] == "ReportingVal1" })
|
315
|
-
expect(report["resources"][0]["result"]).to eq("create")
|
316
|
-
expect(report["status"]).to eq("success")
|
317
|
-
expect(report["total_res_count"]).to eq("1")
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
context "when only_record_changes is false" do
|
322
|
-
before do
|
323
|
-
new_resource.only_record_changes(false)
|
324
|
-
prepopulate(registry_key, prepopulated_values)
|
325
|
-
end
|
326
|
-
let(:registry_key) { "#{reg_child}\\RecordItAll" }
|
327
|
-
let(:registry_key_values) { [{ name: "ReportingVal1", type: :string, data: rand(1235..10000) }] }
|
328
|
-
|
329
|
-
it "should only report the changed value" do
|
330
|
-
subject
|
331
|
-
report = resource_reporter.prepare_run_data
|
332
|
-
|
333
|
-
expect(report["resources"][0]["after"][:values]).to eq(registry_key_values)
|
334
|
-
expect(report["resources"][0]["before"][:values]).to eq(prepopulated_values)
|
335
|
-
expect(report["status"]).to eq("success")
|
336
|
-
expect(report["total_res_count"]).to eq("1")
|
337
|
-
end
|
338
|
-
|
339
|
-
end
|
340
297
|
end
|
341
298
|
end
|
342
299
|
end
|
@@ -627,7 +627,7 @@ describe Chef::DataCollector do
|
|
627
627
|
events.resource_action_start(new_resource, :create)
|
628
628
|
events.resource_current_state_loaded(new_resource, :create, current_resource)
|
629
629
|
|
630
|
-
events.resource_action_start(implementation_resource
|
630
|
+
events.resource_action_start(implementation_resource, :create)
|
631
631
|
events.resource_current_state_loaded(implementation_resource, :create, implementation_resource)
|
632
632
|
events.resource_updated(implementation_resource, :create)
|
633
633
|
events.resource_after_state_loaded(implementation_resource, :create, implementation_resource)
|
@@ -876,7 +876,6 @@ describe Chef::DataCollector do
|
|
876
876
|
send_run_failed_or_completed_event
|
877
877
|
end
|
878
878
|
end
|
879
|
-
|
880
879
|
end
|
881
880
|
end
|
882
881
|
|
@@ -968,5 +967,110 @@ describe Chef::DataCollector do
|
|
968
967
|
data_collector.send(:send_to_data_collector, message)
|
969
968
|
end
|
970
969
|
end
|
970
|
+
|
971
|
+
context "when processing Windows registry keys" do
|
972
|
+
let(:total_resource_count) { 1 }
|
973
|
+
let(:updated_resource_count) { 1 }
|
974
|
+
let(:status) { "success" }
|
975
|
+
|
976
|
+
before do
|
977
|
+
allow(ChefUtils).to receive(:windows?).and_return(true)
|
978
|
+
run_status.stop_clock
|
979
|
+
end
|
980
|
+
|
981
|
+
it "removes registry key values not present in after state" do
|
982
|
+
resource = {
|
983
|
+
"type" => :registry_key,
|
984
|
+
"before" => {
|
985
|
+
values: [
|
986
|
+
{ name: "key1", value: "val1" },
|
987
|
+
{ name: "key2", value: "val2" },
|
988
|
+
{ name: "key3", value: "val3" },
|
989
|
+
],
|
990
|
+
},
|
991
|
+
"after" => {
|
992
|
+
values: [
|
993
|
+
{ name: "key1", value: "new_val1" },
|
994
|
+
{ name: "key3", value: "new_val3" },
|
995
|
+
],
|
996
|
+
},
|
997
|
+
}
|
998
|
+
|
999
|
+
message = {
|
1000
|
+
"resources" => [resource],
|
1001
|
+
}
|
1002
|
+
|
1003
|
+
# Verify that key2 was removed from before values
|
1004
|
+
expected_before_values = [
|
1005
|
+
{ name: "key1", value: "val1" },
|
1006
|
+
{ name: "key3", value: "val3" },
|
1007
|
+
]
|
1008
|
+
|
1009
|
+
expect(http_client).to receive(:post).with(
|
1010
|
+
nil,
|
1011
|
+
hash_including("message_type" => "run_start"),
|
1012
|
+
{ "Content-Type" => "application/json" }
|
1013
|
+
)
|
1014
|
+
|
1015
|
+
expect(http_client).to receive(:post).with(
|
1016
|
+
nil,
|
1017
|
+
hash_including(
|
1018
|
+
"resources" => array_including(
|
1019
|
+
hash_including(
|
1020
|
+
"before" => hash_including(
|
1021
|
+
values: array_including(expected_before_values)
|
1022
|
+
)
|
1023
|
+
)
|
1024
|
+
)
|
1025
|
+
),
|
1026
|
+
{ "Content-Type" => "application/json" }
|
1027
|
+
)
|
1028
|
+
allow(Chef::DataCollector::RunEndMessage).to receive(:construct_message).and_return(message)
|
1029
|
+
data_collector.send(:send_run_completion, message)
|
1030
|
+
end
|
1031
|
+
|
1032
|
+
it "handles missing values gracefully" do
|
1033
|
+
resource = {
|
1034
|
+
"type" => :registry_key,
|
1035
|
+
"before" => {},
|
1036
|
+
"after" => { values: [] },
|
1037
|
+
}
|
1038
|
+
|
1039
|
+
message = {
|
1040
|
+
"resources" => [resource],
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
expect(http_client).to receive(:post).with(
|
1044
|
+
nil,
|
1045
|
+
hash_including("message_type" => "run_start"),
|
1046
|
+
{ "Content-Type" => "application/json" }
|
1047
|
+
)
|
1048
|
+
|
1049
|
+
expect(http_client).to receive(:post).with(nil, message, { "Content-Type" => "application/json" })
|
1050
|
+
|
1051
|
+
allow(Chef::DataCollector::RunEndMessage).to receive(:construct_message).and_return(message)
|
1052
|
+
expect { data_collector.send(:send_run_completion, "success") }.not_to raise_error
|
1053
|
+
end
|
1054
|
+
|
1055
|
+
it "ignores non-registry resources" do
|
1056
|
+
resource = {
|
1057
|
+
"type" => :file,
|
1058
|
+
"before" => { content: "old" },
|
1059
|
+
"after" => { content: "new" },
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
message = {
|
1063
|
+
"resources" => [resource],
|
1064
|
+
}
|
1065
|
+
expect(http_client).to receive(:post).with(nil,
|
1066
|
+
hash_including("message_type" => "run_start"),
|
1067
|
+
{ "Content-Type" => "application/json" })
|
1068
|
+
|
1069
|
+
expect(http_client).to receive(:post).with(nil, message, { "Content-Type" => "application/json" })
|
1070
|
+
|
1071
|
+
allow(Chef::DataCollector::RunEndMessage).to receive(:construct_message).and_return(message)
|
1072
|
+
expect { data_collector.send(:send_run_completion, "success") }.not_to raise_error
|
1073
|
+
end
|
1074
|
+
end
|
971
1075
|
end
|
972
1076
|
end
|
@@ -27,7 +27,6 @@ shared_examples_for "a registry key" do
|
|
27
27
|
before(:each) do
|
28
28
|
expect(@double_registry).to receive(:key_exists?).with(keyname).and_return(true)
|
29
29
|
expect(@double_registry).to receive(:get_values).with(keyname).and_return( [testval2] )
|
30
|
-
@new_resource.only_record_changes false
|
31
30
|
@provider.load_current_resource
|
32
31
|
end
|
33
32
|
|
@@ -73,7 +73,6 @@ describe Chef::ResourceReporter do
|
|
73
73
|
end
|
74
74
|
|
75
75
|
context "when first created" do
|
76
|
-
|
77
76
|
it "has no updated resources" do
|
78
77
|
expect(resource_reporter.updated_resources.count).to eq(0)
|
79
78
|
end
|
@@ -89,7 +88,6 @@ describe Chef::ResourceReporter do
|
|
89
88
|
it "should have no error_descriptions" do
|
90
89
|
expect(resource_reporter.error_descriptions).to eq({})
|
91
90
|
end
|
92
|
-
|
93
91
|
end
|
94
92
|
|
95
93
|
context "after the chef run completes" do
|
@@ -107,7 +105,6 @@ describe Chef::ResourceReporter do
|
|
107
105
|
before do
|
108
106
|
allow(rest_client).to receive(:raw_request).and_return({ "result" => "ok" })
|
109
107
|
allow(rest_client).to receive(:post).and_return({ "uri" => "https://example.com/reports/nodes/spitfire/runs/#{@run_id}" })
|
110
|
-
|
111
108
|
end
|
112
109
|
|
113
110
|
context "before converging any resources" do
|
@@ -510,6 +507,63 @@ describe Chef::ResourceReporter do
|
|
510
507
|
it_should_behave_like "a successful client run"
|
511
508
|
end
|
512
509
|
|
510
|
+
context "windows registry_key resource" do
|
511
|
+
let(:current_resource) do
|
512
|
+
resource = Chef::Resource::RegistryKey.new('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager')
|
513
|
+
resource.values([{ name: "PendingFileRenameOperations", type: :multi_string, data: 10000.times.map { |n| "C:\\Windows\\System32\\config\\systemprofile\\AppData\\Local\\Temp\\2\\Chef-20140107123456-1234-#{n}" } } ])
|
514
|
+
resource
|
515
|
+
end
|
516
|
+
|
517
|
+
let(:new_resource) do
|
518
|
+
resource = Chef::Resource::RegistryKey.new('HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager')
|
519
|
+
resource.values([ { name: "ProtectionMode", type: :dword, data: 1 } ])
|
520
|
+
allow(resource).to receive(:cookbook_name).and_return(cookbook_name)
|
521
|
+
allow(resource).to receive(:cookbook_version).and_return(cookbook_version)
|
522
|
+
resource
|
523
|
+
end
|
524
|
+
|
525
|
+
it "should raise an error when the data is too large" do
|
526
|
+
pending "Need to test truncation properly"
|
527
|
+
# Start the run
|
528
|
+
resource_reporter.run_started(run_status)
|
529
|
+
run_status.start_clock
|
530
|
+
|
531
|
+
# These 4 event callbacks are essential to populate resource state:
|
532
|
+
events.resource_action_start(new_resource, :create)
|
533
|
+
events.resource_current_state_loaded(new_resource, :create, current_resource)
|
534
|
+
events.resource_updated(new_resource, :create)
|
535
|
+
events.resource_completed(new_resource)
|
536
|
+
|
537
|
+
# Stop the run
|
538
|
+
run_status.stop_clock
|
539
|
+
|
540
|
+
# Prepare the run data - this will include the resource states
|
541
|
+
report_data = resource_reporter.prepare_run_data
|
542
|
+
|
543
|
+
# Verify the report includes our resource
|
544
|
+
expect(report_data["resources"].length).to eq(1)
|
545
|
+
expect(report_data["resources"][0]["before"]).to eq(current_resource.state_for_resource_reporter)
|
546
|
+
expect(report_data["resources"][0]["after"]).to eq(new_resource.state_for_resource_reporter)
|
547
|
+
|
548
|
+
expect(rest_client).to receive(:post) do |path, data, headers|
|
549
|
+
expect(path).to eq("reports/nodes/spitfire/runs")
|
550
|
+
raise Chef::Exceptions::ValidationFailed, "data too large" if data.length > 10000
|
551
|
+
end
|
552
|
+
|
553
|
+
# Now mock the actual post request to fail due to size
|
554
|
+
expect(rest_client).to receive(:raw_request) do |method, url, headers, data|
|
555
|
+
data_stream = Zlib::GzipReader.new(StringIO.new(data))
|
556
|
+
data = data_stream.read
|
557
|
+
expect(data).to include('"before":') # Verify current_resource state is included
|
558
|
+
expect(data).to include('"after":') # Verify new_resource state is included
|
559
|
+
raise Chef::Exceptions::ValidationFailed, "data too large"
|
560
|
+
end
|
561
|
+
|
562
|
+
# Assert that the post fails due to validation
|
563
|
+
expect { resource_reporter.run_completed(node) }.to raise_error(Chef::Exceptions::ValidationFailed)
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
513
567
|
context "for an unsuccessful run" do
|
514
568
|
|
515
569
|
before do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 18.7.
|
4
|
+
version: 18.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Jacob
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chef-config
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 18.7.
|
19
|
+
version: 18.7.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 18.7.
|
26
|
+
version: 18.7.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: chef-utils
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - '='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 18.7.
|
33
|
+
version: 18.7.6
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - '='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 18.7.
|
40
|
+
version: 18.7.6
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: train-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -133,9 +133,9 @@ dependencies:
|
|
133
133
|
- - ">="
|
134
134
|
- !ruby/object:Gem::Version
|
135
135
|
version: 2.0.3
|
136
|
-
- - "
|
136
|
+
- - "<"
|
137
137
|
- !ruby/object:Gem::Version
|
138
|
-
version: 3.
|
138
|
+
version: '3.2'
|
139
139
|
type: :runtime
|
140
140
|
prerelease: false
|
141
141
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -143,9 +143,9 @@ dependencies:
|
|
143
143
|
- - ">="
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: 2.0.3
|
146
|
-
- - "
|
146
|
+
- - "<"
|
147
147
|
- !ruby/object:Gem::Version
|
148
|
-
version: 3.
|
148
|
+
version: '3.2'
|
149
149
|
- !ruby/object:Gem::Dependency
|
150
150
|
name: mixlib-authentication
|
151
151
|
requirement: !ruby/object:Gem::Requirement
|