Skip to content

Commit c58db7a

Browse files
authored
Merge pull request #9484 from joshcooper/splaylimit_daemon
(PUP-12061) Allow splay and splaylimit to be modified in puppet.conf
2 parents d0ec909 + 15bc22b commit c58db7a

File tree

4 files changed

+126
-5
lines changed

4 files changed

+126
-5
lines changed

Diff for: lib/puppet/daemon.rb

+13-1
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,25 @@ def remove_pidfile
157157

158158
# Loop forever running events - or, at least, until we exit.
159159
def run_event_loop
160-
agent_run = Puppet::Scheduler.create_job(Puppet[:runinterval], Puppet[:splay], Puppet[:splaylimit]) do
160+
splaylimit = Puppet[:splay] ? Puppet[:splaylimit] : 0
161+
162+
agent_run = Puppet::Scheduler.create_job(Puppet[:runinterval], true, splaylimit) do |job|
163+
if job.splay != 0
164+
Puppet.info "Running agent every #{job.run_interval} seconds with splay #{job.splay} of #{job.splay_limit} seconds"
165+
else
166+
Puppet.info "Running agent every #{job.run_interval} seconds"
167+
end
168+
161169
# Splay for the daemon is handled in the scheduler
162170
agent.run(:splay => false)
163171
end
164172

165173
reparse_run = Puppet::Scheduler.create_job(Puppet[:filetimeout]) do
166174
Puppet.settings.reparse_config_files
167175
agent_run.run_interval = Puppet[:runinterval]
176+
# Puppet[:splaylimit] defaults to Puppet[:runinterval] so if runinterval
177+
# changes, but splaylimit doesn't, we'll still recalculate splay
178+
agent_run.splay_limit = Puppet[:splay] ? Puppet[:splaylimit] : 0
168179
if Puppet[:filetimeout] == 0
169180
reparse_run.disable
170181
else
@@ -181,6 +192,7 @@ def run_event_loop
181192

182193
reparse_run.disable if Puppet[:filetimeout] == 0
183194

195+
# these are added in a different order than they are defined
184196
@scheduler.run_loop([reparse_run, agent_run, signal_loop])
185197
end
186198
end

Diff for: lib/puppet/scheduler/splay_job.rb

+14-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
module Puppet::Scheduler
44
class SplayJob < Job
5-
attr_reader :splay
5+
attr_reader :splay, :splay_limit
66

77
def initialize(run_interval, splay_limit, &block)
8-
@splay = calculate_splay(splay_limit)
8+
@splay, @splay_limit = calculate_splay(splay_limit)
99
super(run_interval, &block)
1010
end
1111

@@ -25,10 +25,21 @@ def ready?(time)
2525
end
2626
end
2727

28+
# Recalculates splay.
29+
#
30+
# @param splay_limit [Integer] the maximum time (in seconds) to delay before an agent's first run.
31+
# @return @splay [Integer] a random integer less than or equal to the splay limit that represents the seconds to
32+
# delay before next agent run.
33+
def splay_limit=(splay_limit)
34+
if @splay_limit != splay_limit
35+
@splay, @splay_limit = calculate_splay(splay_limit)
36+
end
37+
end
38+
2839
private
2940

3041
def calculate_splay(limit)
31-
rand(limit + 1)
42+
[rand(limit + 1), limit]
3243
end
3344
end
3445
end

Diff for: spec/unit/daemon_spec.rb

+82-1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ def run_loop(jobs)
6060
end
6161

6262
describe "when starting" do
63+
let(:reparse_run) { scheduler.jobs[0] }
64+
let(:agent_run) { scheduler.jobs[1] }
65+
6366
before do
6467
allow(daemon).to receive(:set_signal_traps)
6568
end
@@ -77,7 +80,85 @@ def run_loop(jobs)
7780
it "disables the reparse of configs if the filetimeout is 0" do
7881
Puppet[:filetimeout] = 0
7982
daemon.start
80-
expect(scheduler.jobs[0]).not_to be_enabled
83+
expect(reparse_run).not_to be_enabled
84+
end
85+
86+
it "does not splay the agent run by default" do
87+
daemon.start
88+
expect(agent_run.splay).to eq(0)
89+
end
90+
91+
describe "and calculating splay" do
92+
before do
93+
# Set file timeout so the daemon reparses
94+
Puppet[:filetimeout] = 1
95+
Puppet[:splay] = true
96+
end
97+
98+
it "recalculates when splaylimit changes" do
99+
daemon.start
100+
101+
Puppet[:splaylimit] = 60
102+
init_splay = agent_run.splay
103+
next_splay = init_splay + 1
104+
allow(agent_run).to receive(:rand).and_return(next_splay)
105+
reparse_run.run(Time.now)
106+
107+
expect(agent_run.splay).to eq(next_splay)
108+
end
109+
110+
it "does not change splay if splaylimit is unmodified" do
111+
daemon.start
112+
113+
init_splay = agent_run.splay
114+
reparse_run.run(Time.now)
115+
116+
expect(agent_run.splay).to eq(init_splay)
117+
end
118+
119+
it "recalculates when splay is enabled later" do
120+
Puppet[:splay] = false
121+
daemon.start
122+
123+
Puppet[:splay] = true
124+
allow(agent_run).to receive(:rand).and_return(999)
125+
reparse_run.run(Time.now)
126+
127+
expect(agent_run.splay).to eq(999)
128+
end
129+
130+
it "sets splay to 0 when splay is disabled" do
131+
daemon.start
132+
133+
Puppet[:splay] = false
134+
reparse_run.run(Time.now)
135+
136+
expect(agent_run.splay).to eq(0)
137+
end
138+
139+
it "recalculates splay when runinterval is decreased" do
140+
Puppet[:runinterval] = 60
141+
daemon.start
142+
143+
Puppet[:runinterval] = Puppet[:runinterval] - 30
144+
new_splay = agent_run.splay + 1
145+
allow(agent_run).to receive(:rand).and_return(new_splay)
146+
reparse_run.run(Time.now)
147+
148+
expect(agent_run.splay).to eq(new_splay)
149+
end
150+
151+
it "recalculates splay when runinterval is increased" do
152+
Puppet[:runinterval] = 60
153+
daemon.start
154+
155+
Puppet[:runinterval] = Puppet[:runinterval] + 30
156+
new_splay = agent_run.splay - 1
157+
allow(agent_run).to receive(:rand).and_return(new_splay)
158+
reparse_run.run(Time.now)
159+
160+
expect(agent_run.splay).to eq(new_splay)
161+
end
81162
end
82163
end
83164

Diff for: spec/unit/scheduler/splay_job_spec.rb

+17
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,21 @@
3131
expect(job).to receive(:splay).and_return(6)
3232
expect(job.ready?(start_time)).not_to be
3333
end
34+
35+
it "does not apply a splay if the splaylimit is unchanged" do
36+
old_splay = job.splay
37+
job.splay_limit = splay_limit
38+
expect(job.splay).to eq(old_splay)
39+
end
40+
41+
it "applies a splay if the splaylimit is changed" do
42+
new_splay = 999
43+
allow(job).to receive(:rand).and_return(new_splay)
44+
job.splay_limit = splay_limit + 1
45+
expect(job.splay).to eq(new_splay)
46+
end
47+
48+
it "returns the splay_limit" do
49+
expect(job.splay_limit).to eq(splay_limit)
50+
end
3451
end

0 commit comments

Comments
 (0)