Skip to content

Commit c778add

Browse files
committed
Refactor finalize out of scale action
* also start separating total instance count from current scale target
1 parent 1dbe7f7 commit c778add

File tree

5 files changed

+189
-45
lines changed

5 files changed

+189
-45
lines changed

lib/cloud_controller/deployment_updater/actions/finalize.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def call
1515

1616
update_non_web_processes
1717
restart_non_web_processes
18+
1819
deployment.update(
1920
state: DeploymentModel::DEPLOYED_STATE,
2021
status_value: DeploymentModel::FINALIZED_STATUS_VALUE,

lib/cloud_controller/deployment_updater/actions/scale.rb

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
require 'cloud_controller/deployment_updater/actions/scale_down_canceled_processes'
22
require 'cloud_controller/deployment_updater/actions/scale_down_old_process'
33
require 'cloud_controller/deployment_updater/actions/finalize'
4+
require 'cloud_controller/diego/constants'
45

56
module VCAP::CloudController
67
module DeploymentUpdater
78
module Actions
89
class Scale
910
HEALTHY_STATES = [VCAP::CloudController::Diego::LRP_RUNNING, VCAP::CloudController::Diego::LRP_STARTING].freeze
10-
attr_reader :deployment, :logger, :app
11+
attr_reader :deployment, :logger, :app, :target_total_instance_count, :interim_desired_instance_count
1112

12-
def initialize(deployment, logger)
13+
def initialize(deployment, logger, target_total_instance_count, interim_desired_instance_count = nil)
1314
@deployment = deployment
1415
@logger = logger
1516
@app = deployment.app
17+
@target_total_instance_count = target_total_instance_count
18+
@interim_desired_instance_count = interim_desired_instance_count || target_total_instance_count
1619
end
1720

1821
def call
@@ -31,21 +34,19 @@ def call
3134
status_value: DeploymentModel::ACTIVE_STATUS_VALUE,
3235
status_reason: DeploymentModel::DEPLOYING_STATUS_REASON
3336
)
34-
35-
if deploying_web_process.instances >= deployment.original_web_process_instance_count
36-
Finalize.new(deployment).call
37-
return
38-
end
39-
37+
4038
ScaleDownCanceledProcesses.new(deployment).call
4139

4240
scale_down_old_processes if can_downscale?
4341

42+
return true if deploying_web_process.instances >= interim_desired_instance_count
43+
4444
if can_scale?
4545
deploying_web_process.update(instances: desired_new_instances)
4646
deployment.update(last_healthy_at: Time.now)
4747
end
4848
end
49+
false
4950
end
5051

5152
private
@@ -83,11 +84,11 @@ def can_downscale?
8384
end
8485

8586
def desired_non_deploying_instances
86-
[deployment.original_web_process_instance_count - routable_instances.count, 0].max
87+
[target_total_instance_count - routable_instances.count, 0].max
8788
end
8889

8990
def desired_new_instances
90-
[routable_instances.count + deployment.max_in_flight, deployment.original_web_process_instance_count].min
91+
[routable_instances.count + deployment.max_in_flight, interim_desired_instance_count].min
9192
end
9293

9394
def oldest_web_process_with_instances

lib/cloud_controller/deployment_updater/updater.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require 'cloud_controller/deployment_updater/actions/scale'
22
require 'cloud_controller/deployment_updater/actions/cancel'
33
require 'cloud_controller/deployment_updater/actions/canary'
4+
require 'cloud_controller/deployment_updater/actions/finalize'
45
module VCAP::CloudController
56
module DeploymentUpdater
67
class Updater
@@ -13,7 +14,8 @@ def initialize(deployment, logger)
1314

1415
def scale
1516
with_error_logging('error-scaling-deployment') do
16-
Actions::Scale.new(deployment, logger).call
17+
finished = Actions::Scale.new(deployment, logger, deployment.original_web_process_instance_count).call
18+
Actions::Finalize.new(deployment).call if finished
1719
logger.info("ran-deployment-update-for-#{deployment.guid}")
1820
end
1921
end

spec/unit/lib/cloud_controller/deployment_updater/actions/scale_spec.rb

Lines changed: 105 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
module VCAP::CloudController
55
RSpec.describe DeploymentUpdater::Actions::Scale do
6-
subject(:scale_action) { DeploymentUpdater::Actions::Scale.new(deployment, logger) }
6+
subject(:scale_action) { DeploymentUpdater::Actions::Scale.new(deployment, logger, target_total_instance_count) }
7+
let(:target_total_instance_count) { 6 }
78
let(:a_day_ago) { Time.now - 1.day }
89
let(:an_hour_ago) { Time.now - 1.hour }
910
let(:app) { AppModel.make(droplet: droplet, revisions_enabled: true) }
@@ -30,7 +31,6 @@ module VCAP::CloudController
3031
let(:revision) { RevisionModel.make(app: app, droplet: droplet, version: 300) }
3132
let!(:deploying_route_mapping) { RouteMappingModel.make(app: web_process.app, process_type: deploying_web_process.type) }
3233
let(:space) { web_process.space }
33-
let(:original_web_process_instance_count) { 6 }
3434
let(:current_web_instances) { 6 }
3535
let(:current_deploying_instances) { 0 }
3636

@@ -41,7 +41,6 @@ module VCAP::CloudController
4141
app: web_process.app,
4242
deploying_web_process: deploying_web_process,
4343
state: state,
44-
original_web_process_instance_count: original_web_process_instance_count,
4544
max_in_flight: max_in_flight
4645
)
4746
end
@@ -74,7 +73,7 @@ module VCAP::CloudController
7473
let(:current_deploying_instances) { 1 }
7574

7675
it 'scales the old web process down by one' do
77-
expect(original_web_process_instance_count).to be > current_deploying_instances
76+
expect(target_total_instance_count).to be > current_deploying_instances
7877
expect do
7978
subject.call
8079
end.to change {
@@ -97,7 +96,6 @@ module VCAP::CloudController
9796
app: web_process.app,
9897
deploying_web_process: deploying_web_process,
9998
state: 'DEPLOYING',
100-
original_web_process_instance_count: original_web_process_instance_count,
10199
max_in_flight: 2
102100
)
103101
end
@@ -126,7 +124,6 @@ module VCAP::CloudController
126124
app: web_process.app,
127125
deploying_web_process: deploying_web_process,
128126
state: 'DEPLOYING',
129-
original_web_process_instance_count: 6,
130127
max_in_flight: 5
131128
)
132129
end
@@ -156,7 +153,6 @@ module VCAP::CloudController
156153
app: web_process.app,
157154
deploying_web_process: deploying_web_process,
158155
state: 'DEPLOYING',
159-
original_web_process_instance_count: original_web_process_instance_count,
160156
max_in_flight: 100
161157
)
162158
end
@@ -166,7 +162,7 @@ module VCAP::CloudController
166162
subject.call
167163
end.to change {
168164
deploying_web_process.reload.instances
169-
}.by(original_web_process_instance_count)
165+
}.by(target_total_instance_count)
170166
end
171167

172168
it 'doesnt scale down the old web process (there is no new routable instance yet)' do
@@ -178,7 +174,10 @@ module VCAP::CloudController
178174
end
179175
end
180176

181-
context 'when the deployment process has reached original_web_process_instance_count' do
177+
context 'when the deployment process has reached interim_desired_instance_count' do
178+
let(:interim_desired_instance_count) { 3 }
179+
let(:target_total_instance_count) { 6 }
180+
182181
let(:droplet) do
183182
DropletModel.make(
184183
process_types: {
@@ -188,7 +187,9 @@ module VCAP::CloudController
188187
)
189188
end
190189

191-
let(:current_deploying_instances) { original_web_process_instance_count }
190+
subject(:scale_action) { DeploymentUpdater::Actions::Scale.new(deployment, logger, target_total_instance_count, interim_desired_instance_count) }
191+
192+
let(:current_deploying_instances) { interim_desired_instance_count }
192193

193194
let!(:interim_deploying_web_process) do
194195
ProcessModel.make(
@@ -200,31 +201,24 @@ module VCAP::CloudController
200201
)
201202
end
202203

203-
before do
204-
allow(ProcessRestart).to receive(:restart)
205-
RevisionProcessCommandModel.where(
206-
process_type: 'worker',
207-
revision_guid: revision.guid
208-
).update(process_command: 'revision-non-web-1-command')
209-
end
210-
211-
it 'finalizes the deployment' do
212-
subject.call
204+
it 'returns true and leaves the deployment in a deploying state' do
205+
expect(subject.call).to be true
213206
deployment.reload
214-
expect(deployment.state).to eq(DeploymentModel::DEPLOYED_STATE)
215-
expect(deployment.status_value).to eq(DeploymentModel::FINALIZED_STATUS_VALUE)
216-
expect(deployment.status_reason).to eq(DeploymentModel::DEPLOYED_STATUS_REASON)
207+
expect(deployment.state).to eq(DeploymentModel::DEPLOYING_STATE)
208+
209+
earliest_web_process = deployment.app.web_processes.first
210+
expect(earliest_web_process.guid).to eq(web_process.guid)
211+
expect(earliest_web_process.instances).to eq(2)
212+
expect(interim_deploying_web_process.instances).to eq(1)
217213

218-
after_web_process = deployment.app.web_processes.first
219-
expect(after_web_process.guid).to eq(deploying_web_process.guid)
220-
expect(after_web_process.instances).to eq(6)
214+
expect(deploying_web_process.instances).to eq(3)
221215
end
222216
end
223217

224218
context 'when the (oldest) web process will be at zero instances and is type web' do
225219
let(:current_web_instances) { 1 }
226220
let(:current_deploying_instances) { 3 }
227-
let(:original_web_process_instance_count) { 6 }
221+
let(:target_total_instance_count) { 6 }
228222

229223
let!(:interim_deploying_web_process) do
230224
ProcessModel.make(
@@ -253,7 +247,6 @@ module VCAP::CloudController
253247
app: web_process.app,
254248
deploying_web_process: deploying_web_process,
255249
state: 'DEPLOYING',
256-
original_web_process_instance_count: original_web_process_instance_count,
257250
max_in_flight: 10
258251
)
259252
end
@@ -304,7 +297,7 @@ module VCAP::CloudController
304297

305298
context 'when there are more instances in interim processes than there should be' do
306299
let(:current_deploying_instances) { 10 }
307-
let(:original_web_process_instance_count) { 20 }
300+
let(:target_total_instance_count) { 20 }
308301
let(:max_in_flight) { 4 }
309302

310303
let!(:web_process) do
@@ -385,7 +378,7 @@ module VCAP::CloudController
385378

386379
context 'when there are fewer instances in interim processes than there should be' do
387380
let(:current_deploying_instances) { 10 }
388-
let(:original_web_process_instance_count) { 20 }
381+
let(:target_total_instance_count) { 20 }
389382
let(:max_in_flight) { 4 }
390383

391384
let!(:web_process) do
@@ -430,7 +423,7 @@ module VCAP::CloudController
430423

431424
context 'when some instances are missing' do
432425
let(:current_web_instances) { 10 }
433-
let(:original_web_process_instance_count) { 10 }
426+
let(:target_total_instance_count) { 10 }
434427

435428
let(:current_deploying_instances) { 9 }
436429
let(:max_in_flight) { 5 }
@@ -454,7 +447,7 @@ module VCAP::CloudController
454447

455448
context 'when some, but not all, instances have finished' do
456449
let(:current_web_instances) { 10 }
457-
let(:original_web_process_instance_count) { 10 }
450+
let(:target_total_instance_count) { 10 }
458451

459452
let(:current_deploying_instances) { 5 }
460453
let(:max_in_flight) { 5 }
@@ -677,7 +670,6 @@ module VCAP::CloudController
677670
app: web_process.app,
678671
deploying_web_process: deploying_web_process,
679672
state: 'DEPLOYING',
680-
original_web_process_instance_count: original_web_process_instance_count,
681673
max_in_flight: 10
682674
)
683675
end
@@ -687,7 +679,7 @@ module VCAP::CloudController
687679
subject.call
688680
end.to change {
689681
deploying_web_process.reload.instances
690-
}.by(original_web_process_instance_count)
682+
}.by(target_total_instance_count)
691683
end
692684
end
693685
end
@@ -728,5 +720,84 @@ module VCAP::CloudController
728720
expect(deployment).not_to have_received(:update)
729721
end
730722
end
723+
724+
describe 'interim_desired_instance_count' do
725+
let(:deployment) do
726+
DeploymentModel.make(
727+
app: web_process.app,
728+
deploying_web_process: deploying_web_process,
729+
state: 'DEPLOYING',
730+
max_in_flight: 100
731+
)
732+
end
733+
734+
context 'when not passed in' do
735+
subject(:scale_action) { DeploymentUpdater::Actions::Scale.new(deployment, logger, target_total_instance_count) }
736+
let(:target_total_instance_count) { 6 }
737+
738+
it 'scales up the new web process to the target_total_instance_count' do
739+
expect do
740+
subject.call
741+
end.to change {
742+
deploying_web_process.reload.instances
743+
}.by(target_total_instance_count)
744+
end
745+
746+
it 'doesnt scale down the old web process (there is no new routable instance yet)' do
747+
expect do
748+
subject.call
749+
end.not_to(change do
750+
web_process.reload.instances
751+
end)
752+
end
753+
754+
context 'when there are routable instances' do
755+
let(:current_deploying_instances) { 6 }
756+
757+
it 'does scale down the old web process' do
758+
expect do
759+
subject.call
760+
end.to(change do
761+
web_process.reload.instances
762+
end.from(6).to(0))
763+
end
764+
765+
end
766+
end
767+
768+
context 'when passed in' do
769+
let(:interim_desired_instance_count) { 3 }
770+
let(:target_total_instance_count) { 6 }
771+
subject(:scale_action) { DeploymentUpdater::Actions::Scale.new(deployment, logger, target_total_instance_count, interim_desired_instance_count) }
772+
773+
it 'scales up the new web process to the interim_desired_instance_count' do
774+
expect do
775+
subject.call
776+
end.to change {
777+
deploying_web_process.reload.instances
778+
}.by(interim_desired_instance_count)
779+
end
780+
781+
it 'doesnt scale down the old web process (there is no new routable instance yet)' do
782+
expect do
783+
subject.call
784+
end.not_to(change do
785+
web_process.reload.instances
786+
end)
787+
end
788+
789+
context 'when there are routable instances' do
790+
let(:current_deploying_instances) { 3 }
791+
792+
it 'does scale down the old web process' do
793+
expect do
794+
subject.call
795+
end.to(change do
796+
web_process.reload.instances
797+
end.from(6).to(3))
798+
end
799+
end
800+
end
801+
end
731802
end
732803
end

0 commit comments

Comments
 (0)