1
0
Fork 0
mirror of https://github.com/capistrano/capistrano synced 2023-03-27 23:21:18 -04:00

Merge pull request #1687 from irvingwashington/doctor_task_servers

[wip] doctor:servers task
This commit is contained in:
Matt Brictson 2016-05-20 10:22:29 -07:00
commit 058621c885
7 changed files with 206 additions and 5 deletions

View file

@ -6,6 +6,7 @@ Reverse Chronological Order:
https://github.com/capistrano/capistrano/compare/v3.5.0...HEAD https://github.com/capistrano/capistrano/compare/v3.5.0...HEAD
* Added a `doctor:servers` subtask that outputs a summary of servers, roles & properties (@irvingwashington)
* Raise a better error when an after hook isnt found (@jdelStrother) * Raise a better error when an after hook isnt found (@jdelStrother)
* Restrict the uploaded git wrapper script permissions to 700 (@irvingwashington) * Restrict the uploaded git wrapper script permissions to 700 (@irvingwashington)
* Make path to git wrapper script configurable (@thickpaddy) * Make path to git wrapper script configurable (@thickpaddy)

View file

@ -133,16 +133,16 @@ module Capistrano
installer.install(plugin, load_hooks: load_hooks) installer.install(plugin, load_hooks: load_hooks)
end end
def servers
@servers ||= Servers.new
end
private private
def cmdline_filters def cmdline_filters
@cmdline_filters ||= [] @cmdline_filters ||= []
end end
def servers
@servers ||= Servers.new
end
def installer def installer
@installer ||= PluginInstaller.new @installer ||= PluginInstaller.new
end end

View file

@ -119,6 +119,10 @@ module Capistrano
end end
end end
def to_h
@properties
end
private private
def lvalue(key) def lvalue(key)

View file

@ -1,5 +1,6 @@
require "capistrano/doctor/environment_doctor" require "capistrano/doctor/environment_doctor"
require "capistrano/doctor/gems_doctor" require "capistrano/doctor/gems_doctor"
require "capistrano/doctor/variables_doctor" require "capistrano/doctor/variables_doctor"
require "capistrano/doctor/servers_doctor"
load File.expand_path("../tasks/doctor.rake", __FILE__) load File.expand_path("../tasks/doctor.rake", __FILE__)

View file

@ -0,0 +1,105 @@
require "capistrano/doctor/output_helpers"
module Capistrano
module Doctor
class ServersDoctor
include Capistrano::Doctor::OutputHelpers
def initialize(env=Capistrano::Configuration.env)
@servers = env.servers.to_a
end
def call
title("Servers (#{servers.size})")
rwc = RoleWhitespaceChecker.new(servers)
table(servers) do |server, row|
sd = ServerDecorator.new(server)
row << sd.uri_form
row << sd.roles
row << sd.properties
row.yellow if rwc.any_has_whitespace?(server.roles)
end
if rwc.whitespace_roles.any?
warning "\nWhitespace detected in role(s) #{rwc.whitespace_roles_decorated}. " \
"This might be a result of a mistyped \"%w()\" array literal."
end
puts
end
private
attr_reader :servers
class RoleWhitespaceChecker
attr_reader :whitespace_roles, :servers
def initialize(servers)
@servers = servers
@whitespace_roles = find_whitespace_roles
end
def any_has_whitespace?(roles)
roles.any? { |role| include_whitespace?(role) }
end
def include_whitespace?(role)
role =~ /\s/
end
def whitespace_roles_decorated
whitespace_roles.map(&:inspect).join(", ")
end
private
def find_whitespace_roles
servers.map(&:roles).map(&:to_a).flatten.uniq
.select { |role| include_whitespace?(role) }
end
end
class ServerDecorator
def initialize(server)
@server = server
end
def uri_form
[
server.user,
server.user && "@",
server.hostname,
server.port && ":",
server.port
].compact.join
end
def roles
server.roles.to_a.inspect
end
def properties
return "" unless server.properties.keys.any?
pretty_inspect(server.properties.to_h)
end
private
attr_reader :server
# Hashes with proper padding
def pretty_inspect(element)
return element.inspect unless element.is_a?(Hash)
pairs_string = element.keys.map do |key|
[pretty_inspect(key), pretty_inspect(element.fetch(key))].join(" => ")
end.join(", ")
"{ #{pairs_string} }"
end
end
end
end
end

View file

@ -1,5 +1,5 @@
desc "Display a Capistrano troubleshooting report (all doctor: tasks)" desc "Display a Capistrano troubleshooting report (all doctor: tasks)"
task doctor: ["doctor:environment", "doctor:gems", "doctor:variables"] task doctor: ["doctor:environment", "doctor:gems", "doctor:variables", "doctor:servers"]
namespace :doctor do namespace :doctor do
desc "Display Ruby environment details" desc "Display Ruby environment details"
@ -16,4 +16,9 @@ namespace :doctor do
task :variables do task :variables do
Capistrano::Doctor::VariablesDoctor.new.call Capistrano::Doctor::VariablesDoctor.new.call
end end
desc "Display the effective servers configuration"
task :servers do
Capistrano::Doctor::ServersDoctor.new.call
end
end end

View file

@ -0,0 +1,85 @@
require "spec_helper"
require "capistrano/doctor/servers_doctor"
module Capistrano
module Doctor
describe ServersDoctor do
include Capistrano::DSL
let(:doc) { ServersDoctor.new }
after { Capistrano::Configuration.reset! }
it "prints using 4-space indentation" do
expect { doc.call }.to output(/^ {4}/).to_stdout
end
it "prints the number of defined servers" do
role :app, %w(example.com)
server "www@example.com:22"
expect { doc.call }.to output(/Servers \(2\)/).to_stdout
end
describe "prints the server's details" do
it "including username" do
server "www@example.com"
expect { doc.call }.to output(/www@example.com/).to_stdout
end
it "including port" do
server "www@example.com:22"
expect { doc.call }.to output(/www@example.com:22/).to_stdout
end
it "including roles" do
role :app, %w(example.com)
expect { doc.call }.to output(/example.com\s+\[:app\]/).to_stdout
end
it "including empty roles" do
server "example.com"
expect { doc.call }.to output(/example.com\s+\[\]/).to_stdout
end
it "including properties" do
server "example.com", roles: %w(app db), primary: true
expect { doc.call }.to \
output(/example.com\s+\[:app, :db\]\s+\{ :primary => true \}/).to_stdout
end
it "including misleading role name alert" do
server "example.com", roles: ["web app db"]
warning_msg = 'Whitespace detected in role(s) :"web app db". ' \
'This might be a result of a mistyped "%w()" array literal'
expect { doc.call }.to output(/#{Regexp.escape(warning_msg)}/).to_stdout
end
end
it "doesn't fail for no servers" do
expect { doc.call }.to output("\nServers (0)\n \n").to_stdout
end
describe "Rake" do
before do
load File.expand_path("../../../../../lib/capistrano/doctor.rb",
__FILE__)
end
after do
Rake::Task.clear
end
it "has an doctor:servers task that calls ServersDoctor" do
ServersDoctor.any_instance.expects(:call)
Rake::Task["doctor:servers"].invoke
end
it "has a doctor task that depends on doctor:servers" do
expect(Rake::Task["doctor"].prerequisites).to \
include("doctor:servers")
end
end
end
end
end