summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Smith <tsmith84@gmail.com>2020-03-23 19:27:31 -0700
committerTim Smith <tsmith84@gmail.com>2020-03-23 19:27:31 -0700
commit9745b76aaa950d035fe6c0c6bbc1f13b99ec79ae (patch)
treeb46ae6c4341fd581df646d7a08a1b15a147eacb6
parentbd327ef2e98573c4f2e98c97306121b8e1045d18 (diff)
downloadchef-9745b76aaa950d035fe6c0c6bbc1f13b99ec79ae.tar.gz
Use random to ensure we have a splay sleep time in range
The previous method was resulting in wildly out of range times. Signed-off-by: Tim Smith <tsmith@chef.io>
-rw-r--r--lib/chef/resource/chef_client_cron.rb14
-rw-r--r--spec/unit/resource/chef_client_cron_spec.rb18
2 files changed, 16 insertions, 16 deletions
diff --git a/lib/chef/resource/chef_client_cron.rb b/lib/chef/resource/chef_client_cron.rb
index 4266ffdcc8..e4ed4bca8f 100644
--- a/lib/chef/resource/chef_client_cron.rb
+++ b/lib/chef/resource/chef_client_cron.rb
@@ -17,6 +17,7 @@
require_relative "../resource"
require_relative "../dist"
require_relative "helpers/cron_validations"
+require "digest/md5"
class Chef
class Resource
@@ -54,19 +55,19 @@ class Chef
default: "root"
property :minute, [Integer, String],
- description: "The minute at which #{Chef::Dist::PRODUCT} is to run (0 - 59).",
+ description: "The minute at which #{Chef::Dist::PRODUCT} is to run (0 - 59) or a cron pattern such as '0,30'.",
default: "0,30", callbacks: {
"should be a valid minute spec" => ->(spec) { Chef::ResourceHelpers::CronValidations.validate_numeric(spec, 0, 59) },
}
property :hour, [Integer, String],
- description: "The hour at which #{Chef::Dist::PRODUCT} is to run (0 - 23).",
+ description: "The hour at which #{Chef::Dist::PRODUCT} is to run (0 - 23) or a cron pattern such as '0,12'.",
default: "*", callbacks: {
"should be a valid hour spec" => ->(spec) { Chef::ResourceHelpers::CronValidations.validate_numeric(spec, 0, 23) },
}
property :day, [Integer, String],
- description: "The day of month at which #{Chef::Dist::PRODUCT} is to run (1 - 31).",
+ description: "The day of month at which #{Chef::Dist::PRODUCT} is to run (1 - 31) or a cron pattern such as '1,7,14,21,28'.",
default: "*", callbacks: {
"should be a valid day spec" => ->(spec) { Chef::ResourceHelpers::CronValidations.validate_numeric(spec, 1, 31) },
}
@@ -158,10 +159,9 @@ class Chef
action_class do
# Generate a uniformly distributed unique number to sleep.
def splay_sleep_time(splay)
- if splay.to_i > 0
- seed = node["shard_seed"] || Digest::MD5.hexdigest(node.name).to_s.hex
- seed % splay.to_i
- end
+ seed = node["shard_seed"] || Digest::MD5.hexdigest(node.name).to_s.hex
+ random = Random.new(seed.to_i)
+ random.rand(splay)
end
def cron_command
diff --git a/spec/unit/resource/chef_client_cron_spec.rb b/spec/unit/resource/chef_client_cron_spec.rb
index fec9461eeb..2d67efdb31 100644
--- a/spec/unit/resource/chef_client_cron_spec.rb
+++ b/spec/unit/resource/chef_client_cron_spec.rb
@@ -52,49 +52,49 @@ describe Chef::Resource::ChefClientCron do
describe "#splay_sleep_time" do
it "uses shard_seed attribute if present" do
node.automatic_attrs[:shard_seed] = "73399073"
- expect(provider.splay_sleep_time(300)).to eql("73399073")
+ expect(provider.splay_sleep_time(300)).to satisfy { |v| v >= 0 && v <= 300 }
end
it "uses a hex conversion of a md5 hash of the splay if present" do
node.automatic_attrs[:shard_seed] = nil
allow(node).to receive(:name).and_return("test_node")
- expect(provider.splay_sleep_time(300)).to eql(114)
+ expect(provider.splay_sleep_time(300)).to satisfy { |v| v >= 0 && v <= 300 }
end
end
describe "#cron_command" do
before do
- node.automatic_attrs[:shard_seed] = "73399073"
+ allow(provider).to receive(:splay_sleep_time).and_return("123")
end
it "creates a valid command if using all default properties" do
- expect(provider.cron_command).to eql("/bin/sleep 73399073; /opt/chef/bin/chef-client > /var/log/chef/client.log 2>&1")
+ expect(provider.cron_command).to eql("/bin/sleep 123; /opt/chef/bin/chef-client > /var/log/chef/client.log 2>&1")
end
it "uses daemon_options if set" do
resource.daemon_options ["--foo 1", "--bar 2"]
- expect(provider.cron_command).to eql("/bin/sleep 73399073; /opt/chef/bin/chef-client --foo 1 --bar 2 > /var/log/chef/client.log 2>&1")
+ expect(provider.cron_command).to eql("/bin/sleep 123; /opt/chef/bin/chef-client --foo 1 --bar 2 > /var/log/chef/client.log 2>&1")
end
it "uses custom log files / paths if set" do
resource.log_file_name "my-client.log"
resource.log_directory "/var/log/my-chef/"
- expect(provider.cron_command).to eql("/bin/sleep 73399073; /opt/chef/bin/chef-client > /var/log/my-chef/my-client.log 2>&1")
+ expect(provider.cron_command).to eql("/bin/sleep 123; /opt/chef/bin/chef-client > /var/log/my-chef/my-client.log 2>&1")
end
it "uses mailto if set" do
resource.mailto "bob@example.com"
- expect(provider.cron_command).to eql("/bin/sleep 73399073; /opt/chef/bin/chef-client > /var/log/chef/client.log 2>&1 || echo \"Chef Infra Client execution failed\"")
+ expect(provider.cron_command).to eql("/bin/sleep 123; /opt/chef/bin/chef-client > /var/log/chef/client.log 2>&1 || echo \"Chef Infra Client execution failed\"")
end
it "uses custom chef-client binary if set" do
resource.chef_binary_path "/usr/local/bin/chef-client"
- expect(provider.cron_command).to eql("/bin/sleep 73399073; /usr/local/bin/chef-client > /var/log/chef/client.log 2>&1")
+ expect(provider.cron_command).to eql("/bin/sleep 123; /usr/local/bin/chef-client > /var/log/chef/client.log 2>&1")
end
it "appends to the log file appending if set" do
resource.append_log_file true
- expect(provider.cron_command).to eql("/bin/sleep 73399073; /opt/chef/bin/chef-client >> /var/log/chef/client.log 2>&1")
+ expect(provider.cron_command).to eql("/bin/sleep 123; /opt/chef/bin/chef-client >> /var/log/chef/client.log 2>&1")
end
end
end