Skip to content

Commit 594b706

Browse files
authored
Refactor maintenance commands (#212)
* Refactor maintenance commands
1 parent ed1bcad commit 594b706

File tree

9 files changed

+202
-206
lines changed

9 files changed

+202
-206
lines changed

lib/command/maintenance.rb

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,14 @@ class Maintenance < Base
1717
DESC
1818
WITH_INFO_HEADER = false
1919

20-
def call # rubocop:disable Metrics/MethodLength
21-
one_off_workload = config[:one_off_workload]
22-
maintenance_workload = config.current[:maintenance_workload] || "maintenance"
20+
def call
21+
puts maintenance_mode.enabled? ? "on" : "off"
22+
end
2323

24-
domain_data = if config.domain
25-
cp.fetch_domain(config.domain)
26-
else
27-
cp.find_domain_for([one_off_workload, maintenance_workload])
28-
end
29-
unless domain_data
30-
raise "Can't find domain. " \
31-
"Maintenance mode is only supported for domains that use path based routing mode " \
32-
"and have a route configured for the prefix '/' on either port 80 or 443."
33-
end
24+
private
3425

35-
if cp.domain_workload_matches?(domain_data, maintenance_workload)
36-
puts "on"
37-
else
38-
puts "off"
39-
end
26+
def maintenance_mode
27+
@maintenance_mode ||= MaintenanceMode.new(self)
4028
end
4129
end
4230
end

lib/command/maintenance_off.rb

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,48 +15,14 @@ class MaintenanceOff < Base
1515
- Maintenance mode is only supported for domains that use path based routing mode and have a route configured for the prefix '/' on either port 80 or 443
1616
DESC
1717

18-
def call # rubocop:disable Metrics/MethodLength
19-
one_off_workload = config[:one_off_workload]
20-
maintenance_workload = config.current[:maintenance_workload] || "maintenance"
21-
22-
domain_data = if config.domain
23-
cp.fetch_domain(config.domain)
24-
else
25-
cp.find_domain_for([one_off_workload, maintenance_workload])
26-
end
27-
unless domain_data
28-
raise "Can't find domain. " \
29-
"Maintenance mode is only supported for domains that use path based routing mode " \
30-
"and have a route configured for the prefix '/' on either port 80 or 443."
31-
end
32-
33-
domain = domain_data["name"]
34-
if cp.domain_workload_matches?(domain_data, one_off_workload)
35-
progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
36-
return
37-
end
38-
39-
cp.fetch_workload!(maintenance_workload)
40-
41-
# Start all other workloads
42-
run_cpflow_command("ps:start", "-a", config.app, "--wait")
43-
44-
progress.puts
45-
46-
# Switch domain workload
47-
step("Switching workload for domain '#{domain}' to '#{one_off_workload}'") do
48-
cp.set_domain_workload(domain_data, one_off_workload)
49-
50-
# Give it a bit of time for the domain to update
51-
Kernel.sleep(30)
52-
end
53-
54-
progress.puts
18+
def call
19+
maintenance_mode.disable!
20+
end
5521

56-
# Stop maintenance workload
57-
run_cpflow_command("ps:stop", "-a", config.app, "-w", maintenance_workload, "--wait")
22+
private
5823

59-
progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
24+
def maintenance_mode
25+
@maintenance_mode ||= MaintenanceMode.new(self)
6026
end
6127
end
6228
end

lib/command/maintenance_on.rb

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -15,48 +15,14 @@ class MaintenanceOn < Base
1515
- Maintenance mode is only supported for domains that use path based routing mode and have a route configured for the prefix '/' on either port 80 or 443
1616
DESC
1717

18-
def call # rubocop:disable Metrics/MethodLength
19-
one_off_workload = config[:one_off_workload]
20-
maintenance_workload = config.current[:maintenance_workload] || "maintenance"
21-
22-
domain_data = if config.domain
23-
cp.fetch_domain(config.domain)
24-
else
25-
cp.find_domain_for([one_off_workload, maintenance_workload])
26-
end
27-
unless domain_data
28-
raise "Can't find domain. " \
29-
"Maintenance mode is only supported for domains that use path based routing mode " \
30-
"and have a route configured for the prefix '/' on either port 80 or 443."
31-
end
32-
33-
domain = domain_data["name"]
34-
if cp.domain_workload_matches?(domain_data, maintenance_workload)
35-
progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
36-
return
37-
end
38-
39-
cp.fetch_workload!(maintenance_workload)
40-
41-
# Start maintenance workload
42-
run_cpflow_command("ps:start", "-a", config.app, "-w", maintenance_workload, "--wait")
43-
44-
progress.puts
45-
46-
# Switch domain workload
47-
step("Switching workload for domain '#{domain}' to '#{maintenance_workload}'") do
48-
cp.set_domain_workload(domain_data, maintenance_workload)
49-
50-
# Give it a bit of time for the domain to update
51-
Kernel.sleep(30)
52-
end
53-
54-
progress.puts
18+
def call
19+
maintenance_mode.enable!
20+
end
5521

56-
# Stop all other workloads
57-
run_cpflow_command("ps:stop", "-a", config.app, "--wait")
22+
private
5823

59-
progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
24+
def maintenance_mode
25+
@maintenance_mode ||= MaintenanceMode.new(self)
6026
end
6127
end
6228
end

lib/core/maintenance_mode.rb

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# frozen_string_literal: true
2+
3+
require "forwardable"
4+
5+
class MaintenanceMode
6+
extend Forwardable
7+
8+
def_delegators :@command, :config, :progress, :cp, :step, :run_cpflow_command
9+
10+
def initialize(command)
11+
@command = command
12+
end
13+
14+
def enabled?
15+
validate_domain_exists!
16+
cp.domain_workload_matches?(domain_data, maintenance_workload)
17+
end
18+
19+
def disabled?
20+
validate_domain_exists!
21+
cp.domain_workload_matches?(domain_data, one_off_workload)
22+
end
23+
24+
def enable!
25+
if enabled?
26+
progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
27+
else
28+
enable_maintenance_mode
29+
end
30+
end
31+
32+
def disable!
33+
if disabled?
34+
progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
35+
else
36+
disable_maintenance_mode
37+
end
38+
end
39+
40+
private
41+
42+
def enable_maintenance_mode
43+
validate_maintenance_workload_exists!
44+
45+
start_or_stop_maintenance_workload(:start)
46+
switch_domain_workload(to: maintenance_workload)
47+
start_or_stop_all_workloads(:stop)
48+
49+
progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
50+
end
51+
52+
def disable_maintenance_mode
53+
validate_maintenance_workload_exists!
54+
55+
start_or_stop_maintenance_workload(:start)
56+
switch_domain_workload(to: one_off_workload)
57+
start_or_stop_all_workloads(:stop)
58+
59+
progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
60+
end
61+
62+
def validate_domain_exists!
63+
return if domain_data
64+
65+
raise "Can't find domain. " \
66+
"Maintenance mode is only supported for domains that use path based routing mode " \
67+
"and have a route configured for the prefix '/' on either port 80 or 443."
68+
end
69+
70+
def validate_maintenance_workload_exists!
71+
cp.fetch_workload!(maintenance_workload)
72+
end
73+
74+
def start_or_stop_all_workloads(action)
75+
run_cpflow_command("ps:#{action}", "-a", config.app, "--wait")
76+
77+
progress.puts
78+
end
79+
80+
def start_or_stop_maintenance_workload(action)
81+
run_cpflow_command("ps:#{action}", "-a", config.app, "-w", maintenance_workload, "--wait")
82+
83+
progress.puts
84+
end
85+
86+
def switch_domain_workload(to:)
87+
step("Switching workload for domain '#{domain_data['name']}' to '#{to}'") do
88+
cp.set_domain_workload(domain_data, to)
89+
90+
# Give it a bit of time for the domain to update
91+
Kernel.sleep(30)
92+
end
93+
94+
progress.puts
95+
end
96+
97+
def domain_data
98+
@domain_data ||=
99+
if config.domain
100+
cp.fetch_domain(config.domain)
101+
else
102+
cp.find_domain_for([one_off_workload, maintenance_workload])
103+
end
104+
end
105+
106+
def one_off_workload
107+
@one_off_workload ||= config[:one_off_workload]
108+
end
109+
110+
def maintenance_workload
111+
@maintenance_workload ||= config.current[:maintenance_workload] || "maintenance"
112+
end
113+
end

spec/command/maintenance_off_spec.rb

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,5 @@
33
require "spec_helper"
44

55
describe Command::MaintenanceOff do
6-
context "when app has no domain" do
7-
let!(:app) { dummy_test_app("nothing") }
8-
9-
it "raises error" do
10-
result = run_cpflow_command("maintenance:off", "-a", app)
11-
12-
expect(result[:status]).not_to eq(0)
13-
expect(result[:stderr]).to include("Can't find domain")
14-
end
15-
end
16-
17-
context "when maintenance workload does not exist" do
18-
let!(:app) { dummy_test_app("default", create_if_not_exists: true) }
19-
20-
it "raises error" do
21-
result = run_cpflow_command("maintenance:off", "-a", app)
22-
23-
expect(result[:status]).not_to eq(0)
24-
expect(result[:stderr]).to include("Can't find workload 'maintenance'")
25-
end
26-
end
27-
28-
context "when maintenance workload exists" do
29-
let!(:app) { dummy_test_app("full", create_if_not_exists: true) }
30-
31-
before do
32-
allow(Kernel).to receive(:sleep)
33-
34-
run_cpflow_command!("ps:start", "-a", app, "--wait")
35-
end
36-
37-
it "does nothing if maintenance mode is already disabled", :slow do
38-
run_cpflow_command!("maintenance:off", "-a", app)
39-
result = run_cpflow_command("maintenance:off", "-a", app)
40-
41-
expect(result[:status]).to eq(0)
42-
expect(result[:stderr]).to include("Maintenance mode is already disabled for app '#{app}'")
43-
end
44-
45-
it "disables maintenance mode", :slow do
46-
run_cpflow_command!("maintenance:on", "-a", app)
47-
result = run_cpflow_command("maintenance:off", "-a", app)
48-
49-
expect(result[:status]).to eq(0)
50-
expect(result[:stderr]).to include("Maintenance mode disabled for app '#{app}'")
51-
end
52-
end
6+
it_behaves_like "switches maintenance mode command", action: :off
537
end

spec/command/maintenance_on_spec.rb

Lines changed: 1 addition & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,5 @@
33
require "spec_helper"
44

55
describe Command::MaintenanceOn do
6-
context "when app has no domain" do
7-
let!(:app) { dummy_test_app("nothing") }
8-
9-
it "raises error" do
10-
result = run_cpflow_command("maintenance:on", "-a", app)
11-
12-
expect(result[:status]).not_to eq(0)
13-
expect(result[:stderr]).to include("Can't find domain")
14-
end
15-
end
16-
17-
context "when maintenance workload does not exist" do
18-
let!(:app) { dummy_test_app("default", create_if_not_exists: true) }
19-
20-
it "raises error" do
21-
result = run_cpflow_command("maintenance:on", "-a", app)
22-
23-
expect(result[:status]).not_to eq(0)
24-
expect(result[:stderr]).to include("Can't find workload 'maintenance'")
25-
end
26-
end
27-
28-
context "when maintenance workload exists" do
29-
let!(:app) { dummy_test_app("full", create_if_not_exists: true) }
30-
31-
before do
32-
allow(Kernel).to receive(:sleep)
33-
34-
run_cpflow_command!("ps:start", "-a", app, "--wait")
35-
end
36-
37-
it "does nothing if maintenance mode is already enabled", :slow do
38-
run_cpflow_command!("maintenance:on", "-a", app)
39-
result = run_cpflow_command("maintenance:on", "-a", app)
40-
41-
expect(result[:status]).to eq(0)
42-
expect(result[:stderr]).to include("Maintenance mode is already enabled for app '#{app}'")
43-
end
44-
45-
it "enables maintenance mode", :slow do
46-
run_cpflow_command!("maintenance:off", "-a", app)
47-
result = run_cpflow_command("maintenance:on", "-a", app)
48-
49-
expect(result[:status]).to eq(0)
50-
expect(result[:stderr]).to include("Maintenance mode enabled for app '#{app}'")
51-
end
52-
end
6+
it_behaves_like "switches maintenance mode command", action: :on
537
end

spec/command/maintenance_spec.rb

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,7 @@
33
require "spec_helper"
44

55
describe Command::Maintenance do
6-
context "when app has no domain" do
7-
let!(:app) { dummy_test_app("nothing") }
8-
9-
it "raises error" do
10-
result = run_cpflow_command("maintenance", "-a", app)
11-
12-
expect(result[:status]).not_to eq(0)
13-
expect(result[:stderr]).to include("Can't find domain")
14-
end
15-
end
6+
include_examples "validates domain existence", command: "maintenance"
167

178
context "when app has domain" do
189
let!(:app) { dummy_test_app("full", create_if_not_exists: true) }

spec/spec_helper.rb

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,8 @@
2828
end
2929

3030
require_relative "../lib/cpflow"
31-
require_relative "support/dummy_app_setup"
32-
require_relative "support/command_helpers"
33-
require_relative "support/date_time_helpers"
34-
require_relative "support/stub_env"
31+
32+
Dir["#{__dir__}/support/**/*.rb"].sort.each { |f| require f }
3533

3634
# This file was generated by the `rspec --init` command. Conventionally, all
3735
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.

0 commit comments

Comments
 (0)