chef-utils 16.18.0 → 17.0.242
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-utils.gemspec +5 -1
- data/lib/chef-utils/dist.rb +0 -6
- data/lib/chef-utils/dsl/cloud.rb +21 -10
- data/lib/chef-utils/dsl/introspection.rb +11 -0
- data/lib/chef-utils/dsl/platform.rb +1 -1
- data/lib/chef-utils/dsl/windows.rb +1 -1
- data/lib/chef-utils/mash.rb +13 -6
- data/lib/chef-utils/parallel_map.rb +131 -0
- data/lib/chef-utils/version.rb +1 -1
- data/spec/unit/dsl/cloud_spec.rb +4 -0
- data/spec/unit/dsl/introspection_spec.rb +12 -0
- data/spec/unit/parallel_map_spec.rb +156 -0
- metadata +21 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b28b0dd9a34f1242fdeca73f39924515befdec0a2990e4bd56d4d94f071c2aa
|
4
|
+
data.tar.gz: 49cb4691092f6b0db0567a8975e72c3905682208ff0c089fe3149ef8ee8da4d0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16f7f528de5d5fb631552951cef5f0e763bffce0c52bb2fb563f8d1cebd16269027dc3a2daf1f151bc58d5901adfb2309d93ecc3b6868e29f75be14b5538511b
|
7
|
+
data.tar.gz: 705ddfa785ecb1a7448a95f342a3718e5f90996131fe2678c6cd15875f3eee5d5cc7d5b7d38fabfa1500c07df26eac804261360cd13b205a7a24435a8a4ee922
|
data/chef-utils.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/chef/chef/tree/master/chef-utils"
|
14
14
|
spec.license = "Apache-2.0"
|
15
15
|
|
16
|
-
spec.required_ruby_version = ">= 2.6
|
16
|
+
spec.required_ruby_version = ">= 2.6"
|
17
17
|
|
18
18
|
spec.metadata = {
|
19
19
|
"bug_tracker_uri" => "https://github.com/chef/chef/issues",
|
@@ -41,6 +41,10 @@ Gem::Specification.new do |spec|
|
|
41
41
|
# ABSOLUTELY NO EXCEPTIONS
|
42
42
|
#
|
43
43
|
|
44
|
+
# concurrent-ruby is: 1. lightweight, 2. has zero deps, 3. is external to chef
|
45
|
+
# this is used for the parallel_map enumerable extension for lightweight threading
|
46
|
+
spec.add_dependency "concurrent-ruby"
|
47
|
+
|
44
48
|
spec.files = %w{Rakefile LICENSE} + Dir.glob("*.gemspec") +
|
45
49
|
Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
|
46
50
|
end
|
data/lib/chef-utils/dist.rb
CHANGED
data/lib/chef-utils/dsl/cloud.rb
CHANGED
@@ -23,7 +23,7 @@ module ChefUtils
|
|
23
23
|
module Cloud
|
24
24
|
include Internal
|
25
25
|
|
26
|
-
# Determine if the current node is
|
26
|
+
# Determine if the current node is running in a known cloud.
|
27
27
|
#
|
28
28
|
# @param [Chef::Node] node the node to check
|
29
29
|
# @since 15.8
|
@@ -35,7 +35,18 @@ module ChefUtils
|
|
35
35
|
!node["cloud"].nil?
|
36
36
|
end
|
37
37
|
|
38
|
-
#
|
38
|
+
# Determine if the current node is running in Alibaba Cloud
|
39
|
+
#
|
40
|
+
# @param [Chef::Node] node the node to check
|
41
|
+
# @since 17.0
|
42
|
+
#
|
43
|
+
# @return [Boolean]
|
44
|
+
#
|
45
|
+
def alibaba?(node = __getnode)
|
46
|
+
node.key?("alibaba")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Determine if the current node is running in AWS EC2.
|
39
50
|
#
|
40
51
|
# @param [Chef::Node] node the node to check
|
41
52
|
# @since 15.8
|
@@ -46,7 +57,7 @@ module ChefUtils
|
|
46
57
|
node.key?("ec2")
|
47
58
|
end
|
48
59
|
|
49
|
-
#
|
60
|
+
# Determine if the current node running in Google Compute Engine (GCE).
|
50
61
|
#
|
51
62
|
# @param [Chef::Node] node the node to check
|
52
63
|
# @since 15.8
|
@@ -57,7 +68,7 @@ module ChefUtils
|
|
57
68
|
node.key?("gce")
|
58
69
|
end
|
59
70
|
|
60
|
-
#
|
71
|
+
# Determine if the current node is running in Rackspace.
|
61
72
|
#
|
62
73
|
# @param [Chef::Node] node the node to check
|
63
74
|
# @since 15.8
|
@@ -68,7 +79,7 @@ module ChefUtils
|
|
68
79
|
node.key?("rackspace")
|
69
80
|
end
|
70
81
|
|
71
|
-
#
|
82
|
+
# Determine if the current node is running in Eucalyptus.
|
72
83
|
#
|
73
84
|
# @param [Chef::Node] node the node to check
|
74
85
|
# @since 15.8
|
@@ -81,7 +92,7 @@ module ChefUtils
|
|
81
92
|
# chef-sugar backcompat method
|
82
93
|
alias_method :euca?, :eucalyptus?
|
83
94
|
|
84
|
-
#
|
95
|
+
# Determine if the current node is running in Linode.
|
85
96
|
#
|
86
97
|
# @param [Chef::Node] node the node to check
|
87
98
|
# @since 15.8
|
@@ -92,7 +103,7 @@ module ChefUtils
|
|
92
103
|
node.key?("linode")
|
93
104
|
end
|
94
105
|
|
95
|
-
#
|
106
|
+
# Determine if the current node is running in OpenStack.
|
96
107
|
#
|
97
108
|
# @param [Chef::Node] node the node to check
|
98
109
|
# @since 15.8
|
@@ -103,7 +114,7 @@ module ChefUtils
|
|
103
114
|
node.key?("openstack")
|
104
115
|
end
|
105
116
|
|
106
|
-
#
|
117
|
+
# Determine if the current node is running in Microsoft Azure.
|
107
118
|
#
|
108
119
|
# @param [Chef::Node] node the node to check
|
109
120
|
# @since 15.8
|
@@ -114,7 +125,7 @@ module ChefUtils
|
|
114
125
|
node.key?("azure")
|
115
126
|
end
|
116
127
|
|
117
|
-
#
|
128
|
+
# Determine if the current node is running in DigitalOcean.
|
118
129
|
#
|
119
130
|
# @param [Chef::Node] node the node to check
|
120
131
|
# @since 15.8
|
@@ -127,7 +138,7 @@ module ChefUtils
|
|
127
138
|
# chef-sugar backcompat method
|
128
139
|
alias_method :digitalocean?, :digital_ocean?
|
129
140
|
|
130
|
-
#
|
141
|
+
# Determine if the current node is running in SoftLayer (IBM Cloud).
|
131
142
|
#
|
132
143
|
# @param [Chef::Node] node the node to check
|
133
144
|
# @since 15.8
|
@@ -29,6 +29,17 @@ module ChefUtils
|
|
29
29
|
module Introspection
|
30
30
|
include TrainHelpers
|
31
31
|
|
32
|
+
# Determine if the node is using the Chef Effortless pattern in which the Chef Infra Client is packaged using Chef Habitat
|
33
|
+
#
|
34
|
+
# @param [Chef::Node] node the node to check
|
35
|
+
# @since 17.0
|
36
|
+
#
|
37
|
+
# @return [Boolean]
|
38
|
+
#
|
39
|
+
def effortless?(node = __getnode)
|
40
|
+
!!(node && node.read("chef_packages", "chef", "chef_effortless"))
|
41
|
+
end
|
42
|
+
|
32
43
|
# Determine if the node is a docker container.
|
33
44
|
#
|
34
45
|
# @param [Chef::Node] node the node to check
|
@@ -58,7 +58,7 @@ module ChefUtils
|
|
58
58
|
node["kernel"]["product_type"] == "Server"
|
59
59
|
end
|
60
60
|
|
61
|
-
# Determine the current Windows NT version. The NT version often differs from the marketing version, but offers a good way to find desktop and server releases that are based on the same codebase.
|
61
|
+
# Determine the current Windows NT version. The NT version often differs from the marketing version, but offers a good way to find desktop and server releases that are based on the same codebase. For example NT 6.3 corresponds to Windows 8.1 and Windows 2012 R2.
|
62
62
|
#
|
63
63
|
# @param [Chef::Node] node the node to check
|
64
64
|
# @since 15.8
|
data/lib/chef-utils/mash.rb
CHANGED
@@ -94,6 +94,10 @@ module ChefUtils
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
+
unless method_defined?(:regular_reader)
|
98
|
+
alias_method :regular_reader, :[]
|
99
|
+
end
|
100
|
+
|
97
101
|
unless method_defined?(:regular_writer)
|
98
102
|
alias_method :regular_writer, :[]=
|
99
103
|
end
|
@@ -102,12 +106,9 @@ module ChefUtils
|
|
102
106
|
alias_method :regular_update, :update
|
103
107
|
end
|
104
108
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
unless method_defined?(:regular_delete)
|
110
|
-
alias_method :regular_delete, :delete
|
109
|
+
# @param key<Object> The key to get.
|
110
|
+
def [](key)
|
111
|
+
regular_reader(key)
|
111
112
|
end
|
112
113
|
|
113
114
|
# @param key<Object> The key to set.
|
@@ -120,6 +121,12 @@ module ChefUtils
|
|
120
121
|
regular_writer(convert_key(key), convert_value(value))
|
121
122
|
end
|
122
123
|
|
124
|
+
# internal API for use by Chef's deep merge cache
|
125
|
+
# @api private
|
126
|
+
def internal_get(key)
|
127
|
+
regular_reader(key)
|
128
|
+
end
|
129
|
+
|
123
130
|
# internal API for use by Chef's deep merge cache
|
124
131
|
# @api private
|
125
132
|
def internal_set(key, value)
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "concurrent/executors"
|
20
|
+
require "concurrent/future"
|
21
|
+
require "singleton" unless defined?(Singleton)
|
22
|
+
|
23
|
+
module ChefUtils
|
24
|
+
#
|
25
|
+
# This module contains ruby refinements that adds several methods to the Enumerable
|
26
|
+
# class which are useful for parallel processing.
|
27
|
+
#
|
28
|
+
module ParallelMap
|
29
|
+
refine Enumerable do
|
30
|
+
|
31
|
+
# Enumerates through the collection in parallel using the thread pool provided
|
32
|
+
# or the default thread pool. By using the default thread pool this supports
|
33
|
+
# recursively calling the method without deadlocking while using a globally
|
34
|
+
# fixed number of workers. This method supports lazy collections. It returns
|
35
|
+
# synchronously, waiting until all the work is done. Failures are only reported
|
36
|
+
# after the collection has executed and only the first exception is raised.
|
37
|
+
#
|
38
|
+
# (0..).lazy.parallel_map { |i| i*i }.first(5)
|
39
|
+
#
|
40
|
+
# @return [Array] output results
|
41
|
+
#
|
42
|
+
def parallel_map(pool: nil)
|
43
|
+
return self unless block_given?
|
44
|
+
|
45
|
+
pool ||= ChefUtils::DefaultThreadPool.instance.pool
|
46
|
+
|
47
|
+
futures = map do |item|
|
48
|
+
future = Concurrent::Future.execute(executor: pool) do
|
49
|
+
yield item
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
futures.map(&:value!)
|
54
|
+
end
|
55
|
+
|
56
|
+
# This has the same behavior as parallel_map but returns the enumerator instead of
|
57
|
+
# the return values.
|
58
|
+
#
|
59
|
+
# @return [Enumerable] the enumerable for method chaining
|
60
|
+
#
|
61
|
+
def parallel_each(pool: nil, &block)
|
62
|
+
return self unless block_given?
|
63
|
+
|
64
|
+
parallel_map(pool: pool, &block)
|
65
|
+
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
# The flat_each method is tightly coupled to the usage of parallel_map within the
|
70
|
+
# ChefFS implementation. It is not itself a parallel method, but it is used to
|
71
|
+
# iterate through the 2nd level of nested structure, which is tied to the nested
|
72
|
+
# structures that ChefFS returns.
|
73
|
+
#
|
74
|
+
# This is different from Enumerable#flat_map because that behaves like map.flatten(1) while
|
75
|
+
# this behaves more like flatten(1).each. We need this on an Enumerable, so we have no
|
76
|
+
# Enumerable#flatten method to call.
|
77
|
+
#
|
78
|
+
# [ [ 1, 2 ], [ 3, 4 ] ].flat_each(&block) calls block four times with 1, 2, 3, 4
|
79
|
+
#
|
80
|
+
# [ [ 1, 2 ], [ 3, 4 ] ].flat_map(&block) calls block twice with [1, 2] and [3,4]
|
81
|
+
#
|
82
|
+
def flat_each(&block)
|
83
|
+
map do |value|
|
84
|
+
if value.is_a?(Enumerable)
|
85
|
+
value.each(&block)
|
86
|
+
else
|
87
|
+
yield value
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# The DefaultThreadPool has a fixed thread size and has no
|
95
|
+
# queue of work and the behavior on failure to find a thread is for the
|
96
|
+
# caller to run the work. This contract means that the thread pool can
|
97
|
+
# be called recursively without deadlocking and while keeping the fixed
|
98
|
+
# number of threads (and not exponentially growing the thread pool with
|
99
|
+
# the depth of recursion).
|
100
|
+
#
|
101
|
+
class DefaultThreadPool
|
102
|
+
include Singleton
|
103
|
+
|
104
|
+
DEFAULT_THREAD_SIZE = 10
|
105
|
+
|
106
|
+
# Size of the thread pool, must be set before getting the thread pool or
|
107
|
+
# calling parallel_map/parallel_each. Does not (but could be modified to)
|
108
|
+
# support dynamic resizing. To get fully synchronous behavior set this equal to
|
109
|
+
# zero rather than one since the caller will get work if the threads are
|
110
|
+
# busy.
|
111
|
+
#
|
112
|
+
# @return [Integer] number of threads
|
113
|
+
attr_accessor :threads
|
114
|
+
|
115
|
+
# Memoizing accessor for the thread pool
|
116
|
+
#
|
117
|
+
# @return [Concurrent::ThreadPoolExecutor] the thread pool
|
118
|
+
def pool
|
119
|
+
@pool ||= Concurrent::ThreadPoolExecutor.new(
|
120
|
+
min_threads: threads || DEFAULT_THREAD_SIZE,
|
121
|
+
max_threads: threads || DEFAULT_THREAD_SIZE,
|
122
|
+
max_queue: 0,
|
123
|
+
# "synchronous" redefines the 0 in max_queue to mean 'no queue' instead of 'infinite queue'
|
124
|
+
# it does not mean synchronous execution (no threads) but synchronous offload to the threads.
|
125
|
+
synchronous: true,
|
126
|
+
# this prevents deadlocks on recursive parallel usage
|
127
|
+
fallback_policy: :caller_runs
|
128
|
+
)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/chef-utils/version.rb
CHANGED
data/spec/unit/dsl/cloud_spec.rb
CHANGED
@@ -45,6 +45,10 @@ RSpec.describe ChefUtils::DSL::Cloud do
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
context "on alibaba" do
|
49
|
+
cloud_reports_true_for(:cloud?, :alibaba?, node: { "alibaba" => {}, "cloud" => {} })
|
50
|
+
end
|
51
|
+
|
48
52
|
context "on ec2" do
|
49
53
|
cloud_reports_true_for(:cloud?, :ec2?, node: { "ec2" => {}, "cloud" => {} })
|
50
54
|
end
|
@@ -32,6 +32,18 @@ RSpec.describe ChefUtils::DSL::Introspection do
|
|
32
32
|
|
33
33
|
let(:test_instance) { IntrospectionTestClass.new(node) }
|
34
34
|
|
35
|
+
context "#effortless?" do
|
36
|
+
# FIXME: use a real VividMash for these tests instead of stubbing
|
37
|
+
it "is false by default" do
|
38
|
+
expect(node).to receive(:read).with("chef_packages", "chef", "chef_effortless").and_return(nil)
|
39
|
+
expect(ChefUtils.effortless?(node)).to be false
|
40
|
+
end
|
41
|
+
it "is true when ohai reports a effortless" do
|
42
|
+
expect(node).to receive(:read).with("chef_packages", "chef", "chef_effortless").and_return(true)
|
43
|
+
expect(ChefUtils.effortless?(node)).to be true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
35
47
|
context "#docker?" do
|
36
48
|
# FIXME: use a real VividMash for these tests instead of stubbing
|
37
49
|
it "is false by default" do
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#
|
3
|
+
# Copyright:: Copyright (c) Chef Software Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require "chef-utils/parallel_map"
|
20
|
+
|
21
|
+
using ChefUtils::ParallelMap
|
22
|
+
|
23
|
+
RSpec.describe ChefUtils::ParallelMap do
|
24
|
+
|
25
|
+
shared_examples_for "common parallel API tests" do
|
26
|
+
|
27
|
+
before(:each) do
|
28
|
+
ChefUtils::DefaultThreadPool.instance.instance_variable_set(:@pool, nil)
|
29
|
+
ChefUtils::DefaultThreadPool.instance.threads = threads
|
30
|
+
end
|
31
|
+
|
32
|
+
after(:each) do
|
33
|
+
ChefUtils::DefaultThreadPool.instance.instance_variable_set(:@pool, nil)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "parallel_map runs in parallel" do
|
37
|
+
# this is implicitly also testing that we run in the caller when we exhaust threads by running threads+1
|
38
|
+
val = threads + 1
|
39
|
+
ret = []
|
40
|
+
start = Time.now
|
41
|
+
(1..val).parallel_map do |i|
|
42
|
+
loop do
|
43
|
+
if val == i
|
44
|
+
ret << i
|
45
|
+
val -= 1
|
46
|
+
break
|
47
|
+
end
|
48
|
+
# we spin for quite awhile to wait for very slow testers if we have to
|
49
|
+
if Time.now - start > 30
|
50
|
+
raise "timed out; deadlocked due to lack of parallelization?"
|
51
|
+
end
|
52
|
+
|
53
|
+
# need to sleep a tiny bit to let other threads schedule
|
54
|
+
sleep 0.000001
|
55
|
+
end
|
56
|
+
end
|
57
|
+
expected = (1..threads + 1).to_a.reverse
|
58
|
+
expect(ret).to eql(expected)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "parallel_each runs in parallel" do
|
62
|
+
# this is implicitly also testing that we run in the caller when we exhaust threads by running threads+1
|
63
|
+
val = threads + 1
|
64
|
+
ret = []
|
65
|
+
start = Time.now
|
66
|
+
(1..val).parallel_each do |i|
|
67
|
+
loop do
|
68
|
+
if val == i
|
69
|
+
ret << i
|
70
|
+
val -= 1
|
71
|
+
break
|
72
|
+
end
|
73
|
+
# we spin for quite awhile to wait for very slow testers if we have to
|
74
|
+
if Time.now - start > 30
|
75
|
+
raise "timed out; deadlocked due to lack of parallelization?"
|
76
|
+
end
|
77
|
+
|
78
|
+
# need to sleep a tiny bit to let other threads schedule
|
79
|
+
sleep 0.000001
|
80
|
+
end
|
81
|
+
end
|
82
|
+
expected = (1..threads + 1).to_a.reverse
|
83
|
+
expect(ret).to eql(expected)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "parallel_map throws exceptions" do
|
87
|
+
expect { (0..10).parallel_map { |i| raise "boom" } }.to raise_error(RuntimeError)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "parallel_each throws exceptions" do
|
91
|
+
expect { (0..10).parallel_each { |i| raise "boom" } }.to raise_error(RuntimeError)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "parallel_map runs" do
|
95
|
+
ans = Timeout.timeout(30) do
|
96
|
+
(1..10).parallel_map { |i| i }
|
97
|
+
end
|
98
|
+
expect(ans).to eql((1..10).to_a)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "parallel_each runs" do
|
102
|
+
Timeout.timeout(30) do
|
103
|
+
(1..10).parallel_each { |i| i }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
it "recursive parallel_map will not deadlock" do
|
108
|
+
ans = Timeout.timeout(30) do
|
109
|
+
(1..2).parallel_map { |i| (1..2).parallel_map { |i| i } }
|
110
|
+
end
|
111
|
+
expect(ans).to eql([[1, 2], [1, 2]])
|
112
|
+
end
|
113
|
+
|
114
|
+
it "recursive parallel_each will not deadlock" do
|
115
|
+
ans = Timeout.timeout(30) do
|
116
|
+
(1..2).parallel_each { |i| (1..2).parallel_each { |i| i } }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
it "parallel_map is lazy" do
|
121
|
+
ans = Timeout.timeout(30) do
|
122
|
+
(1..).lazy.parallel_map { |i| i }.first(5)
|
123
|
+
end
|
124
|
+
expect(ans).to eql((1..5).to_a)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "parallel_each is lazy" do
|
128
|
+
ans = Timeout.timeout(30) do
|
129
|
+
(1..).lazy.parallel_each { |i| i }.first(5)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
context "with 10 threads" do
|
135
|
+
let(:threads) { 10 }
|
136
|
+
it_behaves_like "common parallel API tests"
|
137
|
+
end
|
138
|
+
|
139
|
+
context "with 0 threads" do
|
140
|
+
let(:threads) { 0 }
|
141
|
+
it_behaves_like "common parallel API tests"
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with 1 threads" do
|
145
|
+
let(:threads) { 1 }
|
146
|
+
it_behaves_like "common parallel API tests"
|
147
|
+
end
|
148
|
+
|
149
|
+
context "flat_each" do
|
150
|
+
it "runs each over items which are nested one level" do
|
151
|
+
sum = 0
|
152
|
+
[ [ 1, 2 ], [3, 4]].flat_each { |i| sum += i }
|
153
|
+
expect(sum).to eql(10)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chef-utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 17.0.242
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chef Software, Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
12
|
-
dependencies:
|
11
|
+
date: 2021-04-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: concurrent-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description:
|
14
28
|
email:
|
15
29
|
- oss@chef.io
|
@@ -38,6 +52,7 @@ files:
|
|
38
52
|
- lib/chef-utils/dsl/windows.rb
|
39
53
|
- lib/chef-utils/internal.rb
|
40
54
|
- lib/chef-utils/mash.rb
|
55
|
+
- lib/chef-utils/parallel_map.rb
|
41
56
|
- lib/chef-utils/version.rb
|
42
57
|
- lib/chef-utils/version_string.rb
|
43
58
|
- spec/spec_helper.rb
|
@@ -54,6 +69,7 @@ files:
|
|
54
69
|
- spec/unit/dsl/which_spec.rb
|
55
70
|
- spec/unit/dsl/windows_spec.rb
|
56
71
|
- spec/unit/mash_spec.rb
|
72
|
+
- spec/unit/parallel_map_spec.rb
|
57
73
|
homepage: https://github.com/chef/chef/tree/master/chef-utils
|
58
74
|
licenses:
|
59
75
|
- Apache-2.0
|
@@ -71,14 +87,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
71
87
|
requirements:
|
72
88
|
- - ">="
|
73
89
|
- !ruby/object:Gem::Version
|
74
|
-
version: 2.6
|
90
|
+
version: '2.6'
|
75
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
92
|
requirements:
|
77
93
|
- - ">="
|
78
94
|
- !ruby/object:Gem::Version
|
79
95
|
version: '0'
|
80
96
|
requirements: []
|
81
|
-
rubygems_version: 3.
|
97
|
+
rubygems_version: 3.2.15
|
82
98
|
signing_key:
|
83
99
|
specification_version: 4
|
84
100
|
summary: Basic utility functions for Core Chef Infra development
|