Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tagging to doctor checks. #120

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lib/moonshot/artifact_repository/s3_bucket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def upload_to_s3(file, key)
)
end

add_doctor_check :doctor_check_bucket_exists
def doctor_check_bucket_exists
s3_client.get_bucket_location(bucket: @bucket_name)
success "Bucket '#{@bucket_name}' exists."
Expand All @@ -59,6 +60,7 @@ def doctor_check_bucket_exists
warning(str, e.message)
end

add_doctor_check :doctor_check_bucket_writable
def doctor_check_bucket_writable
s3_client.put_object(
key: 'test-object',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module Moonshot::ArtifactRepository
class S3BucketViaGithubReleases < S3Bucket
include Moonshot::BuildMechanism
include Moonshot::Shell
include Moonshot::DoctorHelper

# @override
# If release version, transfer from GitHub to S3.
Expand Down Expand Up @@ -77,6 +78,7 @@ def github_to_s3(version, s3_name)
end
end

add_doctor_check :doctor_check_hub_release_download
def doctor_check_hub_release_download
sh_out('hub release download --help')
rescue
Expand Down
19 changes: 15 additions & 4 deletions lib/moonshot/build_mechanism/github_release.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ def initialize(build_mechanism)
@build_mechanism = build_mechanism
end

def doctor_hook
def doctor_hook(options = {})
super
@build_mechanism.doctor_hook
@build_mechanism.doctor_hook(options)
end

def resources=(r)
Expand Down Expand Up @@ -174,6 +174,7 @@ def releases_url
`hub browse -u -- releases`.chomp
end

add_doctor_check :doctor_check_upstream
def doctor_check_upstream
sh_out('git remote | grep ^upstream$')
rescue => e
Expand All @@ -182,12 +183,22 @@ def doctor_check_upstream
success 'git remote `upstream` exists.'
end

add_doctor_check :doctor_check_hub_installed, is_local: true
def doctor_check_hub_installed
sh_out('hub version')
rescue => e
critical "`hub` is not installed.\n#{e.message}"
else
success '`hub` installed.'
end

add_doctor_check :doctor_check_hub_auth
def doctor_check_hub_auth
sh_out('hub ci-status 0.0.0')
rescue => e
critical "`hub` failed, install hub and authorize it.\n#{e.message}"
critical "`hub` not installed or not authorized.\n#{e.message}"
else
success '`hub` installed and authorized.'
success '`hub` authorized.'
end
end
end
1 change: 1 addition & 0 deletions lib/moonshot/build_mechanism/script.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ def run_script(step, env: {}) # rubocop:disable AbcSize
end
end

add_doctor_check :doctor_check_script_exists, is_config: true
def doctor_check_script_exists
if File.exist?(@script)
success "Script '#{@script}' exists."
Expand Down
14 changes: 12 additions & 2 deletions lib/moonshot/build_mechanism/travis_deploy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,22 @@ def check_build(version)
end
end

add_doctor_check :doctor_check_travis_installed, is_local: true
def doctor_check_travis_installed
sh_out('bundle exec travis version')
rescue => e
critical "`travis` not installed.\n#{e.message}"
else
success '`travis` installed.'
end

add_doctor_check :doctor_check_travis_auth
def doctor_check_travis_auth
sh_out("bundle exec travis raw #{@endpoint} repos/#{@slug}")
rescue => e
critical "`travis` not available or not authorized.\n#{e.message}"
critical "`travis` not installed or not authorized.\n#{e.message}"
else
success '`travis` installed and authorized.'
success '`travis` authorized.'
end
end
end
6 changes: 3 additions & 3 deletions lib/moonshot/build_mechanism/version_proxy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ def initialize(release:, dev:)
@dev = dev
end

def doctor_hook
@release.doctor_hook
@dev.doctor_hook
def doctor_hook(options = {})
@release.doctor_hook(options)
@dev.doctor_hook(options)
end

def resources=(r)
Expand Down
4 changes: 3 additions & 1 deletion lib/moonshot/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,10 @@ def delete
end

desc :doctor, 'Run configuration checks against current environment.'
option :local, aliases: 'l', type: :boolean, default: false
option :config, aliases: 'c', type: :boolean, default: false
def doctor
success = controller.doctor
success = controller.doctor(options)
raise Thor::Error, 'One or more checks failed.' unless success
end

Expand Down
10 changes: 5 additions & 5 deletions lib/moonshot/controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ def delete
run_plugins(:post_delete)
end

def doctor
def doctor(options)
# @todo use #run_hook when Stack becomes an InfrastructureProvider
success = true
success &&= stack.doctor_hook
success &&= run_hook(:build, :doctor)
success &&= run_hook(:repo, :doctor)
success &&= run_hook(:deploy, :doctor)
success &&= stack.doctor_hook(options)
success &&= run_hook(:build, :doctor, options)
success &&= run_hook(:repo, :doctor, options)
success &&= run_hook(:deploy, :doctor, options)
results = run_plugins(:doctor)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want plugins to support this, too? I am not sure how that would work though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed but this appears to be unused and how to make that happen wasn't readily obvious to me.


success = false if results.value?(false)
Expand Down
2 changes: 2 additions & 0 deletions lib/moonshot/deployment_mechanism/code_deploy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ def s3_revision_for(artifact_repo, version_name)
}
end

add_doctor_check :doctor_check_code_deploy_role
def doctor_check_code_deploy_role
iam_client.get_role(role_name: @codedeploy_role).role
success("#{@codedeploy_role} exists.")
Expand All @@ -325,6 +326,7 @@ def doctor_check_code_deploy_role
critical("Could not find #{@codedeploy_role}, ", help)
end

add_doctor_check :doctor_check_auto_scaling_resource_defined, is_config: true
def doctor_check_auto_scaling_resource_defined
@asg_logical_ids.each do |asg_logical_id|
if stack.template.resource_names.include?(asg_logical_id)
Expand Down
35 changes: 30 additions & 5 deletions lib/moonshot/doctor_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,44 @@ module Moonshot
# A series of methods for adding "doctor" checks to a mechanism.
#
module DoctorHelper
def doctor_hook
run_all_checks
def self.included(klass)
class << klass
attr_accessor :doctor_checks
end
klass.doctor_checks = {}
klass.extend ClassMethods
end

def doctor_hook(options = {})
checks = self.class.doctor_checks
checks.delete_if { |_k, v| v[:is_local] == false } if options[:local]
checks.delete_if { |_k, v| v[:is_config] == false } if options[:config]
run_checks(checks)
end

# Contains class methods
module ClassMethods
def add_doctor_check(method, flags = {})
default_flags = {
is_local: false,
is_config: false
}
doctor_checks[method] = default_flags.merge(flags)
end
end

private

def run_all_checks
def run_checks(checks)
return true if checks.empty?
success = true

puts
puts self.class.name.split('::').last
private_methods.each do |meth|

checks.each do |meth, _|
begin
send(meth) if meth =~ /^doctor_check_/
send(meth)
rescue DoctorCritical
# Stop running checks in this Mechanism.
success = false
Expand Down
2 changes: 2 additions & 0 deletions lib/moonshot/stack.rb
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ def format_event(event)
str
end

add_doctor_check :doctor_check_template_exists, is_config: true
def doctor_check_template_exists
if File.exist?(template_file)
success "CloudFormation template found at '#{template_file}'."
Expand All @@ -384,6 +385,7 @@ def doctor_check_template_exists
end
end

add_doctor_check :doctor_check_template_exists, is_config: true
def doctor_check_template_against_aws
cf_client.validate_template(template_body: template.body)
success('CloudFormation template is valid.')
Expand Down
88 changes: 54 additions & 34 deletions spec/moonshot/build_mechanism/github_release_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,51 +26,71 @@ module Moonshot # rubocop:disable ModuleLength
allow(subject).to receive(:puts)
allow(subject).to receive(:print)
expect(subject).to receive(:doctor_check_hub_auth)
expect(subject).to receive(:doctor_check_hub_installed)
expect(subject).to receive(:doctor_check_upstream)
subject.doctor_hook
end
end

describe '#doctor_check_upstream' do
around do |example|
Dir.mktmpdir do |path|
Dir.chdir(path) do
`git init`
example.run
end
describe '#doctor_check_upstream' do
around do |example|
Dir.mktmpdir do |path|
Dir.chdir(path) do
`git init`
example.run
end
end
end

it 'should fail without upstream.' do
expect(subject).to receive(:critical)
.with(/git remote `upstream` not found/)
subject.send(:doctor_check_upstream)
end
it 'should fail without upstream.' do
expect(subject).to receive(:critical)
.with(/git remote `upstream` not found/)
subject.send(:doctor_check_upstream)
end

it 'should succeed with upstream remote.' do
`git remote add upstream https://example.com/my/repo.git`
expect(subject).to receive(:success)
.with('git remote `upstream` exists.')
subject.send(:doctor_check_upstream)
end
it 'should succeed with upstream remote.' do
`git remote add upstream https://example.com/my/repo.git`
expect(subject).to receive(:success)
.with('git remote `upstream` exists.')
subject.send(:doctor_check_upstream)
end
end

describe '#doctor_check_hub_auth' do
it 'should succeed with 0 exit status.' do
expect(subject).to receive(:sh_out)
.with('hub ci-status 0.0.0')
expect(subject).to receive(:success)
.with('`hub` installed and authorized.')
subject.send(:doctor_check_hub_auth)
end
describe '#doctor_check_hub_installed' do
it 'should succeed with 0 exit status.' do
expect(subject).to receive(:sh_out)
.with('hub version')
expect(subject).to receive(:success)
.with('`hub` installed.')
subject.send(:doctor_check_hub_installed)
end

it 'should critical with non-zero exit status.' do
expect(subject).to receive(:sh_out)
.with('hub ci-status 0.0.0')
.and_raise(RuntimeError, 'oops')
expect(subject).to receive(:critical)
.with("`hub` failed, install hub and authorize it.\noops")
subject.send(:doctor_check_hub_auth)
end
it 'should critical with non-zero exit status.' do
expect(subject).to receive(:sh_out)
.with('hub version')
.and_raise(RuntimeError, 'oops')
expect(subject).to receive(:critical)
.with("`hub` is not installed.\noops")
subject.send(:doctor_check_hub_installed)
end
end

describe '#doctor_check_hub_auth' do
it 'should succeed with 0 exit status.' do
expect(subject).to receive(:sh_out)
.with('hub ci-status 0.0.0')
expect(subject).to receive(:success)
.with('`hub` authorized.')
subject.send(:doctor_check_hub_auth)
end

it 'should critical with non-zero exit status.' do
expect(subject).to receive(:sh_out)
.with('hub ci-status 0.0.0')
.and_raise(RuntimeError, 'oops')
expect(subject).to receive(:critical)
.with("`hub` not installed or not authorized.\noops")
subject.send(:doctor_check_hub_auth)
end
end

Expand Down
25 changes: 22 additions & 3 deletions spec/moonshot/build_mechanism/travis_deploy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,38 @@ module Moonshot # rubocop:disable Metrics/ModuleLength
it 'should call our hooks' do
allow(subject).to receive(:puts)
expect(subject).to receive(:puts).with('we did it')
expect(subject).to receive(:print).with(' ✓ '.green)
expect(subject).to receive(:print).with(' ✓ '.green).twice
expect(subject).to receive(:doctor_check_travis_auth) do
subject.send(:success, 'we did it')
end
subject.doctor_hook
end

describe '#doctor_check_travis_installed' do
it 'should pass if travis exits 0' do
expect(subject).to receive(:sh_out)
.with('bundle exec travis version')
expect(subject).to receive(:success)
.with('`travis` installed.')
subject.send(:doctor_check_travis_installed)
end

it 'should pass fail travis exits 1' do
expect(subject).to receive(:sh_out)
.with('bundle exec travis version')
.and_raise(RuntimeError, 'stuffs broke man')
expect(subject).to receive(:critical)
.with("`travis` not installed.\nstuffs broke man")
subject.send(:doctor_check_travis_installed)
end
end

describe '#doctor_check_travis_auth' do
it 'should pass if travis exits 0' do
expect(subject).to receive(:sh_out)
.with('bundle exec travis raw --org repos/myorg/myrepo')
expect(subject).to receive(:success)
.with('`travis` installed and authorized.')
.with('`travis` authorized.')
subject.send(:doctor_check_travis_auth)
end

Expand All @@ -40,7 +59,7 @@ module Moonshot # rubocop:disable Metrics/ModuleLength
.with('bundle exec travis raw --org repos/myorg/myrepo')
.and_raise(RuntimeError, 'stuffs broke man')
expect(subject).to receive(:critical)
.with("`travis` not available or not authorized.\nstuffs broke man")
.with("`travis` not installed or not authorized.\nstuffs broke man")
subject.send(:doctor_check_travis_auth)
end
end
Expand Down