Skip to content

Commit

Permalink
Refactor maintenance commands
Browse files Browse the repository at this point in the history
  • Loading branch information
zzaakiirr committed Jul 19, 2024
1 parent c595899 commit c45737f
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 206 deletions.
24 changes: 6 additions & 18 deletions lib/command/maintenance.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,14 @@ class Maintenance < Base
DESC
WITH_INFO_HEADER = false

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

domain_data = if config.domain
cp.fetch_domain(config.domain)
else
cp.find_domain_for([one_off_workload, maintenance_workload])
end
unless domain_data
raise "Can't find domain. " \
"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."
end
private

if cp.domain_workload_matches?(domain_data, maintenance_workload)
puts "on"
else
puts "off"
end
def maintenance_mode
@maintenance_mode ||= MaintenanceMode.new(self)
end
end
end
46 changes: 6 additions & 40 deletions lib/command/maintenance_off.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,14 @@ class MaintenanceOff < Base
- 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
DESC

def call # rubocop:disable Metrics/MethodLength
one_off_workload = config[:one_off_workload]
maintenance_workload = config.current[:maintenance_workload] || "maintenance"

domain_data = if config.domain
cp.fetch_domain(config.domain)
else
cp.find_domain_for([one_off_workload, maintenance_workload])
end
unless domain_data
raise "Can't find domain. " \
"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."
end

domain = domain_data["name"]
if cp.domain_workload_matches?(domain_data, one_off_workload)
progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
return
end

cp.fetch_workload!(maintenance_workload)

# Start all other workloads
run_cpflow_command("ps:start", "-a", config.app, "--wait")

progress.puts

# Switch domain workload
step("Switching workload for domain '#{domain}' to '#{one_off_workload}'") do
cp.set_domain_workload(domain_data, one_off_workload)

# Give it a bit of time for the domain to update
Kernel.sleep(30)
end

progress.puts
def call
maintenance_mode.disable!
end

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

progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
def maintenance_mode
@maintenance_mode ||= ::MaintenanceMode.new(self)
end
end
end
46 changes: 6 additions & 40 deletions lib/command/maintenance_on.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,48 +15,14 @@ class MaintenanceOn < Base
- 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
DESC

def call # rubocop:disable Metrics/MethodLength
one_off_workload = config[:one_off_workload]
maintenance_workload = config.current[:maintenance_workload] || "maintenance"

domain_data = if config.domain
cp.fetch_domain(config.domain)
else
cp.find_domain_for([one_off_workload, maintenance_workload])
end
unless domain_data
raise "Can't find domain. " \
"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."
end

domain = domain_data["name"]
if cp.domain_workload_matches?(domain_data, maintenance_workload)
progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
return
end

cp.fetch_workload!(maintenance_workload)

# Start maintenance workload
run_cpflow_command("ps:start", "-a", config.app, "-w", maintenance_workload, "--wait")

progress.puts

# Switch domain workload
step("Switching workload for domain '#{domain}' to '#{maintenance_workload}'") do
cp.set_domain_workload(domain_data, maintenance_workload)

# Give it a bit of time for the domain to update
Kernel.sleep(30)
end

progress.puts
def call
maintenance_mode.enable!
end

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

progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
def maintenance_mode
@maintenance_mode ||= ::MaintenanceMode.new(self)
end
end
end
106 changes: 106 additions & 0 deletions lib/core/maintenance_mode.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# frozen_string_literal: true

require "forwardable"

class MaintenanceMode
extend Forwardable

def_delegators :@command, :config, :progress, :cp, :step, :run_cpflow_command

def initialize(command)
@command = command
end

def enabled?
validate_domain_exists!
cp.domain_workload_matches?(domain_data, maintenance_workload)
end

def disabled?
!enabled?
end

def enable!
if enabled?
progress.puts("Maintenance mode is already enabled for app '#{config.app}'.")
return
end

validate_maintenance_workload_exists!

run_maintenance_workload(:start)
switch_domain_workload(to: maintenance_workload)
run_all_workloads(:stop)

progress.puts("\nMaintenance mode enabled for app '#{config.app}'.")
end

def disable!
if disabled?
progress.puts("Maintenance mode is already disabled for app '#{config.app}'.")
return
end

validate_maintenance_workload_exists!

run_all_workloads(:start)
switch_domain_workload(to: one_off_workload)
run_maintenance_workload(:stop)

progress.puts("\nMaintenance mode disabled for app '#{config.app}'.")
end

private

def validate_domain_exists!
return if domain_data

raise "Can't find domain. " \
"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."
end

def validate_maintenance_workload_exists!
cp.fetch_workload!(maintenance_workload)
end

def run_all_workloads(start_or_stop)
run_cpflow_command("ps:#{start_or_stop}", "-a", config.app, "--wait")

progress.puts
end

def run_maintenance_workload(start_or_stop)
run_cpflow_command("ps:#{start_or_stop}", "-a", config.app, "-w", maintenance_workload, "--wait")

progress.puts
end

def switch_domain_workload(to:)
step("Switching workload for domain '#{domain_data['name']}' to '#{to}'") do
cp.set_domain_workload(domain_data, to)

# Give it a bit of time for the domain to update
Kernel.sleep(30)
end

progress.puts
end

def domain_data
@domain_data ||=
if config.domain
cp.fetch_domain(config.domain)
else
cp.find_domain_for([one_off_workload, maintenance_workload])
end
end

def one_off_workload
@one_off_workload ||= config[:one_off_workload]
end

def maintenance_workload
@maintenance_workload ||= config.current[:maintenance_workload] || "maintenance"
end
end
48 changes: 1 addition & 47 deletions spec/command/maintenance_off_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,5 @@
require "spec_helper"

describe Command::MaintenanceOff do
context "when app has no domain" do
let!(:app) { dummy_test_app("nothing") }

it "raises error" do
result = run_cpflow_command("maintenance:off", "-a", app)

expect(result[:status]).not_to eq(0)
expect(result[:stderr]).to include("Can't find domain")
end
end

context "when maintenance workload does not exist" do
let!(:app) { dummy_test_app("default", create_if_not_exists: true) }

it "raises error" do
result = run_cpflow_command("maintenance:off", "-a", app)

expect(result[:status]).not_to eq(0)
expect(result[:stderr]).to include("Can't find workload 'maintenance'")
end
end

context "when maintenance workload exists" do
let!(:app) { dummy_test_app("full", create_if_not_exists: true) }

before do
allow(Kernel).to receive(:sleep)

run_cpflow_command!("ps:start", "-a", app, "--wait")
end

it "does nothing if maintenance mode is already disabled", :slow do
run_cpflow_command!("maintenance:off", "-a", app)
result = run_cpflow_command("maintenance:off", "-a", app)

expect(result[:status]).to eq(0)
expect(result[:stderr]).to include("Maintenance mode is already disabled for app '#{app}'")
end

it "disables maintenance mode", :slow do
run_cpflow_command!("maintenance:on", "-a", app)
result = run_cpflow_command("maintenance:off", "-a", app)

expect(result[:status]).to eq(0)
expect(result[:stderr]).to include("Maintenance mode disabled for app '#{app}'")
end
end
it_behaves_like "switch maintenance mode command", action: :off
end
48 changes: 1 addition & 47 deletions spec/command/maintenance_on_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,5 @@
require "spec_helper"

describe Command::MaintenanceOn do
context "when app has no domain" do
let!(:app) { dummy_test_app("nothing") }

it "raises error" do
result = run_cpflow_command("maintenance:on", "-a", app)

expect(result[:status]).not_to eq(0)
expect(result[:stderr]).to include("Can't find domain")
end
end

context "when maintenance workload does not exist" do
let!(:app) { dummy_test_app("default", create_if_not_exists: true) }

it "raises error" do
result = run_cpflow_command("maintenance:on", "-a", app)

expect(result[:status]).not_to eq(0)
expect(result[:stderr]).to include("Can't find workload 'maintenance'")
end
end

context "when maintenance workload exists" do
let!(:app) { dummy_test_app("full", create_if_not_exists: true) }

before do
allow(Kernel).to receive(:sleep)

run_cpflow_command!("ps:start", "-a", app, "--wait")
end

it "does nothing if maintenance mode is already enabled", :slow do
run_cpflow_command!("maintenance:on", "-a", app)
result = run_cpflow_command("maintenance:on", "-a", app)

expect(result[:status]).to eq(0)
expect(result[:stderr]).to include("Maintenance mode is already enabled for app '#{app}'")
end

it "enables maintenance mode", :slow do
run_cpflow_command!("maintenance:off", "-a", app)
result = run_cpflow_command("maintenance:on", "-a", app)

expect(result[:status]).to eq(0)
expect(result[:stderr]).to include("Maintenance mode enabled for app '#{app}'")
end
end
it_behaves_like "switch maintenance mode command", action: :on
end
11 changes: 1 addition & 10 deletions spec/command/maintenance_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,7 @@
require "spec_helper"

describe Command::Maintenance do
context "when app has no domain" do
let!(:app) { dummy_test_app("nothing") }

it "raises error" do
result = run_cpflow_command("maintenance", "-a", app)

expect(result[:status]).not_to eq(0)
expect(result[:stderr]).to include("Can't find domain")
end
end
include_examples "validates domain existence", command: "maintenance"

context "when app has domain" do
let!(:app) { dummy_test_app("full", create_if_not_exists: true) }
Expand Down
6 changes: 2 additions & 4 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@
end

require_relative "../lib/cpflow"
require_relative "support/dummy_app_setup"
require_relative "support/command_helpers"
require_relative "support/date_time_helpers"
require_relative "support/stub_env"

Dir["./spec/support/**/*.rb"].sort.each { |f| require f }

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

0 comments on commit c45737f

Please sign in to comment.