rails_health_check 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,75 @@
1
+ # Copyright (c) 2010-2013 Ian Heggie, released under the MIT license.
2
+ # See MIT-LICENSE for details.
3
+
4
+ module HealthCheck
5
+ class HealthCheckController < ActionController::Base
6
+
7
+ layout false if self.respond_to? :layout
8
+ before_action :check_origin_ip
9
+ before_action :authenticate
10
+
11
+ def index
12
+ last_modified = Time.now.utc
13
+ max_age = HealthCheck.max_age
14
+ if max_age > 1
15
+ last_modified = Time.at((last_modified.to_f / max_age).floor * max_age).utc
16
+ end
17
+ public = (max_age > 1) && ! HealthCheck.basic_auth_username
18
+ if stale?(:last_modified => last_modified, :public => public)
19
+ checks = params[:checks] ? params[:checks].split('_') : ['standard']
20
+ checks -= HealthCheck.middleware_checks if HealthCheck.installed_as_middleware
21
+ begin
22
+ errors = HealthCheck::Utils.process_checks(checks)
23
+ rescue Exception => e
24
+ errors = e.message.blank? ? e.class.to_s : e.message.to_s
25
+ end
26
+ response.headers['Cache-control'] = (public ? 'public' : 'private') + ', no-cache, must-revalidate' + (max_age > 0 ? ", max-age=#{max_age}" : '')
27
+ if errors.blank?
28
+ send_response true, nil, :ok, :ok
29
+ else
30
+ msg = HealthCheck.include_error_in_response_body ? "health_check failed: #{errors}" : nil
31
+ send_response false, msg, HealthCheck.http_status_for_error_text, HealthCheck.http_status_for_error_object
32
+ # Log a single line as some uptime checkers only record that it failed, not the text returned
33
+ if logger
34
+ logger.info msg
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def send_response(healthy, msg, text_status, obj_status)
43
+ msg ||= healthy ? HealthCheck.success : HealthCheck.failure
44
+ obj = { :healthy => healthy, :message => msg}
45
+ respond_to do |format|
46
+ format.html { render :plain => msg, :status => text_status, :content_type => 'text/plain' }
47
+ format.json { render :json => obj, :status => obj_status }
48
+ format.xml { render :xml => obj, :status => obj_status }
49
+ format.any { render :plain => msg, :status => text_status, :content_type => 'text/plain' }
50
+ end
51
+ end
52
+
53
+ def authenticate
54
+ return unless HealthCheck.basic_auth_username && HealthCheck.basic_auth_password
55
+ authenticate_or_request_with_http_basic('Health Check') do |username, password|
56
+ username == HealthCheck.basic_auth_username && password == HealthCheck.basic_auth_password
57
+ end
58
+ end
59
+
60
+ def check_origin_ip
61
+ unless HealthCheck.origin_ip_whitelist.blank? ||
62
+ HealthCheck.origin_ip_whitelist.include?(request.ip)
63
+ render :plain => 'Health check is not allowed for the requesting IP',
64
+ :status => HealthCheck.http_status_for_ip_whitelist_error,
65
+ :content_type => 'text/plain'
66
+ end
67
+ end
68
+
69
+ # turn cookies for CSRF off
70
+ def protect_against_forgery?
71
+ false
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,15 @@
1
+ module ActionDispatch::Routing
2
+ class Mapper
3
+
4
+ def health_check_routes(prefix = nil)
5
+ HealthCheck::Engine.routes_explicitly_defined = true
6
+ add_health_check_routes(prefix)
7
+ end
8
+
9
+ def add_health_check_routes(prefix = nil)
10
+ HealthCheck.uri = prefix if prefix
11
+ match "#{HealthCheck.uri}(/:checks)(.:format)", :to => 'health_check/health_check#index', via: [:get, :post], :defaults => { :format => 'txt' }
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,102 @@
1
+ module HealthCheck
2
+ class MiddlewareHealthcheck
3
+
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ (response_type, middleware_checks, full_stack_checks) = parse_env(env)
10
+ if response_type
11
+ if error_response = (ip_blocked(env) || not_authenticated(env))
12
+ return error_response
13
+ end
14
+ HealthCheck.installed_as_middleware = true
15
+ errors = ''
16
+ begin
17
+ # Process the checks to be run from middleware
18
+ errors = HealthCheck::Utils.process_checks(middleware_checks, true)
19
+ # Process remaining checks through the full stack if there are any
20
+ unless full_stack_checks.empty?
21
+ return @app.call(env)
22
+ end
23
+ rescue => e
24
+ errors = e.message.blank? ? e.class.to_s : e.message.to_s
25
+ end
26
+ healthy = errors.blank?
27
+ msg = healthy ? HealthCheck.success : "health_check failed: #{errors}"
28
+ if response_type == 'xml'
29
+ content_type = 'text/xml'
30
+ msg = { healthy: healthy, message: msg }.to_xml
31
+ error_code = HealthCheck.http_status_for_error_object
32
+ elsif response_type == 'json'
33
+ content_type = 'application/json'
34
+ msg = { healthy: healthy, message: msg }.to_json
35
+ error_code = HealthCheck.http_status_for_error_object
36
+ else
37
+ content_type = 'text/plain'
38
+ error_code = HealthCheck.http_status_for_error_text
39
+ end
40
+ [ (healthy ? 200 : error_code), { 'Content-Type' => content_type }, [msg] ]
41
+ else
42
+ @app.call(env)
43
+ end
44
+ end
45
+
46
+ protected
47
+
48
+ def parse_env(env)
49
+ uri = env['PATH_INFO']
50
+ if uri =~ /^\/#{Regexp.escape HealthCheck.uri}(\/([-_0-9a-zA-Z]*))?(\.(\w*))?$/
51
+ checks = $2.to_s == '' ? ['standard'] : $2.split('_')
52
+ response_type = $4.to_s
53
+ middleware_checks = checks & HealthCheck.middleware_checks
54
+ full_stack_checks = (checks - HealthCheck.middleware_checks) - ['and']
55
+ [response_type, middleware_checks, full_stack_checks ]
56
+ end
57
+ end
58
+
59
+ def ip_blocked(env)
60
+ return false if HealthCheck.origin_ip_whitelist.blank?
61
+ req = Rack::Request.new(env)
62
+ unless HealthCheck.origin_ip_whitelist.include?(req.ip)
63
+ [ HealthCheck.http_status_for_ip_whitelist_error,
64
+ { 'Content-Type' => 'text/plain' },
65
+ [ 'Health check is not allowed for the requesting IP' ]
66
+ ]
67
+ end
68
+ end
69
+
70
+ def not_authenticated(env)
71
+ return false unless HealthCheck.basic_auth_username && HealthCheck.basic_auth_password
72
+ auth = MiddlewareHealthcheck::Request.new(env)
73
+ if auth.provided? && auth.basic? && Rack::Utils.secure_compare(HealthCheck.basic_auth_username, auth.username) && Rack::Utils.secure_compare(HealthCheck.basic_auth_password, auth.password)
74
+ env['REMOTE_USER'] = auth.username
75
+ return false
76
+ end
77
+ [ 401,
78
+ { 'Content-Type' => 'text/plain', 'WWW-Authenticate' => 'Basic realm="Health Check"' },
79
+ [ ]
80
+ ]
81
+ end
82
+
83
+ class Request < Rack::Auth::AbstractRequest
84
+ def basic?
85
+ "basic" == scheme
86
+ end
87
+
88
+ def credentials
89
+ @credentials ||= params.unpack("m*").first.split(/:/, 2)
90
+ end
91
+
92
+ def username
93
+ credentials.first
94
+ end
95
+
96
+ def password
97
+ credentials.last
98
+ end
99
+ end
100
+
101
+ end
102
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HealthCheck
4
+ class RedisHealthCheck
5
+ extend BaseHealthCheck
6
+
7
+ class << self
8
+ def check
9
+ raise "Wrong configuration. Missing 'redis' gem" unless defined?(::Redis)
10
+
11
+ client.ping == 'PONG' ? '' : "Redis.ping returned #{res.inspect} instead of PONG"
12
+ rescue Exception => err
13
+ create_error 'redis', err.message
14
+ ensure
15
+ client.disconnect
16
+ end
17
+
18
+ def client
19
+ Redis.new(url: HealthCheck.redis_url)
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ module HealthCheck
2
+ class ResqueHealthCheck
3
+ extend BaseHealthCheck
4
+
5
+ def self.check
6
+ unless defined?(::Resque)
7
+ raise "Wrong configuration. Missing 'resque' gem"
8
+ end
9
+ res = ::Resque.redis.ping
10
+ res == 'PONG' ? '' : "Resque.redis.ping returned #{res.inspect} instead of PONG"
11
+ rescue Exception => e
12
+ create_error 'resque-redis', e.message
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,65 @@
1
+ module HealthCheck
2
+ class S3HealthCheck
3
+ extend BaseHealthCheck
4
+
5
+ class << self
6
+ def check
7
+ unless defined?(::Aws)
8
+ raise "Wrong configuration. Missing 'aws-sdk' gem"
9
+ end
10
+ return create_error 's3', 'Could not connect to aws' if aws_s3_client.nil?
11
+ HealthCheck.buckets.each do |bucket_name, permissions|
12
+ if permissions.nil? # backward compatible
13
+ permissions = [:R, :W, :D]
14
+ end
15
+ permissions.each do |permision|
16
+ begin
17
+ send(permision, bucket_name)
18
+ rescue Exception => e
19
+ raise "bucket:#{bucket_name}, permission:#{permision} - #{e.message}"
20
+ end
21
+ end
22
+ end
23
+ ''
24
+ rescue Exception => e
25
+ create_error 's3', e.message
26
+ end
27
+
28
+ private
29
+
30
+ def configure_client
31
+ return unless defined?(Rails)
32
+
33
+ aws_configuration = {
34
+ region: Rails.application.secrets.aws_default_region,
35
+ credentials: ::Aws::Credentials.new(
36
+ Rails.application.secrets.aws_access_key_id,
37
+ Rails.application.secrets.aws_secret_access_key
38
+ ),
39
+ force_path_style: true
40
+ }
41
+
42
+ ::Aws::S3::Client.new aws_configuration
43
+ end
44
+
45
+ def aws_s3_client
46
+ @aws_s3_client ||= configure_client
47
+ end
48
+
49
+ def R(bucket)
50
+ aws_s3_client.list_objects(bucket: bucket)
51
+ end
52
+
53
+ def W(bucket)
54
+ aws_s3_client.put_object(bucket: bucket,
55
+ key: "healthcheck_#{Rails.application.class.parent_name}",
56
+ body: Time.new.to_s)
57
+ end
58
+
59
+ def D(bucket)
60
+ aws_s3_client.delete_object(bucket: bucket,
61
+ key: "healthcheck_#{Rails.application.class.parent_name}")
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,17 @@
1
+ module HealthCheck
2
+ class SidekiqHealthCheck
3
+ extend BaseHealthCheck
4
+
5
+ def self.check
6
+ unless defined?(::Sidekiq)
7
+ raise "Wrong configuration. Missing 'sidekiq' gem"
8
+ end
9
+ ::Sidekiq.redis do |r|
10
+ res = r.ping
11
+ res == 'PONG' ? '' : "Sidekiq.redis.ping returned #{res.inspect} instead of PONG"
12
+ end
13
+ rescue Exception => e
14
+ create_error 'sidekiq-redis', e.message
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,171 @@
1
+ # Copyright (c) 2010-2013 Ian Heggie, released under the MIT license.
2
+ # See MIT-LICENSE for details.
3
+
4
+ module HealthCheck
5
+ class Utils
6
+
7
+ @@default_smtp_settings =
8
+ {
9
+ :address => "localhost",
10
+ :port => 25,
11
+ :domain => 'localhost.localdomain',
12
+ :user_name => nil,
13
+ :password => nil,
14
+ :authentication => nil,
15
+ :enable_starttls_auto => true,
16
+ }
17
+
18
+ cattr_accessor :default_smtp_settings
19
+
20
+ # process an array containing a list of checks
21
+ def self.process_checks(checks, called_from_middleware = false)
22
+ errors = ''
23
+ checks.each do |check|
24
+ case check
25
+ when 'and', 'site'
26
+ # do nothing
27
+ when "database"
28
+ HealthCheck::Utils.get_database_version
29
+ when "email"
30
+ errors << HealthCheck::Utils.check_email
31
+ when "emailconf"
32
+ errors << HealthCheck::Utils.check_email if HealthCheck::Utils.mailer_configured?
33
+ when "migrations", "migration"
34
+ if defined?(ActiveRecord::Migration) and ActiveRecord::Migration.respond_to?(:check_pending!)
35
+ # Rails 4+
36
+ begin
37
+ ActiveRecord::Migration.check_pending!
38
+ rescue ActiveRecord::PendingMigrationError => ex
39
+ errors << ex.message
40
+ end
41
+ else
42
+ database_version = HealthCheck::Utils.get_database_version
43
+ migration_version = HealthCheck::Utils.get_migration_version
44
+ if database_version.to_i != migration_version.to_i
45
+ errors << "Current database version (#{database_version}) does not match latest migration (#{migration_version}). "
46
+ end
47
+ end
48
+ when 'cache'
49
+ errors << HealthCheck::Utils.check_cache
50
+ when 'resque-redis-if-present'
51
+ errors << HealthCheck::ResqueHealthCheck.check if defined?(::Resque)
52
+ when 'sidekiq-redis-if-present'
53
+ errors << HealthCheck::SidekiqHealthCheck.check if defined?(::Sidekiq)
54
+ when 'redis-if-present'
55
+ errors << HealthCheck::RedisHealthCheck.check if defined?(::Redis)
56
+ when 's3-if-present'
57
+ errors << HealthCheck::S3HealthCheck.check if defined?(::Aws)
58
+ when 'resque-redis'
59
+ errors << HealthCheck::ResqueHealthCheck.check
60
+ when 'sidekiq-redis'
61
+ errors << HealthCheck::SidekiqHealthCheck.check
62
+ when 'redis'
63
+ errors << HealthCheck::RedisHealthCheck.check
64
+ when 's3'
65
+ errors << HealthCheck::S3HealthCheck.check
66
+ when "standard"
67
+ errors << HealthCheck::Utils.process_checks(HealthCheck.standard_checks, called_from_middleware)
68
+ when "middleware"
69
+ errors << "Health check not called from middleware - probably not installed as middleware." unless called_from_middleware
70
+ when "custom"
71
+ HealthCheck.custom_checks.each do |name, list|
72
+ list.each do |custom_check|
73
+ errors << custom_check.call(self)
74
+ end
75
+ end
76
+ when "all", "full"
77
+ errors << HealthCheck::Utils.process_checks(HealthCheck.full_checks, called_from_middleware)
78
+ else
79
+ if HealthCheck.custom_checks.include? check
80
+ HealthCheck.custom_checks[check].each do |custom_check|
81
+ errors << custom_check.call(self)
82
+ end
83
+ else
84
+ return "invalid argument to health_test."
85
+ end
86
+ end
87
+ end
88
+ return errors
89
+ rescue => e
90
+ return e.message
91
+ end
92
+
93
+ def self.db_migrate_path
94
+ # Lazy initialisation so Rails.root will be defined
95
+ @@db_migrate_path ||= File.join(Rails.root, 'db', 'migrate')
96
+ end
97
+
98
+ def self.db_migrate_path=(value)
99
+ @@db_migrate_path = value
100
+ end
101
+
102
+ def self.mailer_configured?
103
+ defined?(ActionMailer::Base) && (ActionMailer::Base.delivery_method != :smtp || HealthCheck::Utils.default_smtp_settings != ActionMailer::Base.smtp_settings)
104
+ end
105
+
106
+ def self.get_database_version
107
+ ActiveRecord::Migrator.current_version if defined?(ActiveRecord)
108
+ end
109
+
110
+ def self.get_migration_version(dir = self.db_migrate_path)
111
+ latest_migration = nil
112
+ Dir[File.join(dir, "[0-9]*_*.rb")].each do |f|
113
+ l = f.scan(/0*([0-9]+)_[_.a-zA-Z0-9]*.rb/).first.first rescue -1
114
+ latest_migration = l if !latest_migration || l.to_i > latest_migration.to_i
115
+ end
116
+ latest_migration
117
+ end
118
+
119
+ def self.check_email
120
+ case ActionMailer::Base.delivery_method
121
+ when :smtp
122
+ HealthCheck::Utils.check_smtp(ActionMailer::Base.smtp_settings, HealthCheck.smtp_timeout)
123
+ when :sendmail
124
+ HealthCheck::Utils.check_sendmail(ActionMailer::Base.sendmail_settings)
125
+ else
126
+ ''
127
+ end
128
+ end
129
+
130
+ def self.check_sendmail(settings)
131
+ File.executable?(settings[:location]) ? '' : 'no sendmail executable found. '
132
+ end
133
+
134
+ def self.check_smtp(settings, timeout)
135
+ status = ''
136
+ begin
137
+ if @skip_external_checks
138
+ status = '221'
139
+ else
140
+ Timeout::timeout(timeout) do |timeout_length|
141
+ t = TCPSocket.new(settings[:address], settings[:port])
142
+ begin
143
+ status = t.gets
144
+ while status != nil && status !~ /^2/
145
+ status = t.gets
146
+ end
147
+ t.puts "HELO #{settings[:domain]}\r"
148
+ while status != nil && status !~ /^250/
149
+ status = t.gets
150
+ end
151
+ t.puts "QUIT\r"
152
+ status = t.gets
153
+ ensure
154
+ t.close
155
+ end
156
+ end
157
+ end
158
+ rescue Errno::EBADF => ex
159
+ status = "Unable to connect to service"
160
+ rescue Exception => ex
161
+ status = ex.to_s
162
+ end
163
+ (status =~ /^221/) ? '' : "SMTP: #{status || 'unexpected EOF on socket'}. "
164
+ end
165
+
166
+ def self.check_cache
167
+ Rails.cache.write('__health_check_cache_test__', 'ok', :expires_in => 1.second) ? '' : 'Unable to write to cache. '
168
+ end
169
+
170
+ end
171
+ end
@@ -0,0 +1,3 @@
1
+ module HealthCheck
2
+ VERSION = "3.0.0"
3
+ end
@@ -0,0 +1,101 @@
1
+ # Copyright (c) 2010-2013 Ian Heggie, released under the MIT license.
2
+ # See MIT-LICENSE for details.
3
+
4
+ module HealthCheck
5
+
6
+ class Engine < Rails::Engine
7
+ cattr_accessor :routes_explicitly_defined
8
+ end
9
+
10
+ # Text output upon success
11
+ mattr_accessor :success
12
+ self.success = "success"
13
+
14
+ # Text output upon failure
15
+ mattr_accessor :failure
16
+ self.failure = "failure"
17
+
18
+ # Timeout in seconds used when checking smtp server
19
+ mattr_accessor :smtp_timeout
20
+ self.smtp_timeout = 30.0
21
+
22
+ # http status code used when plain text error message is output
23
+ mattr_accessor :http_status_for_error_text
24
+ self.http_status_for_error_text = 500
25
+
26
+ # http status code used when an error object is output (json or xml)
27
+ mattr_accessor :http_status_for_error_object
28
+ self.http_status_for_error_object = 500
29
+
30
+ # http status code used when the ip is not allowed for the request
31
+ mattr_accessor :http_status_for_ip_whitelist_error
32
+ self.http_status_for_ip_whitelist_error = 403
33
+
34
+ # ips allowed to perform requests
35
+ mattr_accessor :origin_ip_whitelist
36
+ self.origin_ip_whitelist = []
37
+
38
+ # max-age of response in seconds
39
+ # cache-control is public when max_age > 1 and basic authentication is used
40
+ mattr_accessor :max_age
41
+ self.max_age = 1
42
+
43
+ # s3 buckets
44
+ mattr_accessor :buckets
45
+ self.buckets = {}
46
+
47
+ # health check uri path
48
+ mattr_accessor :uri
49
+ self.uri = 'health_check'
50
+
51
+ # Basic Authentication
52
+ mattr_accessor :basic_auth_username, :basic_auth_password
53
+ self.basic_auth_username = nil
54
+ self.basic_auth_password = nil
55
+
56
+ # Array of custom check blocks
57
+ mattr_accessor :custom_checks
58
+ mattr_accessor :full_checks
59
+ mattr_accessor :standard_checks
60
+ self.custom_checks = { }
61
+ self.full_checks = ['database', 'migrations', 'custom', 'email', 'cache', 'redis-if-present', 'sidekiq-redis-if-present', 'resque-redis-if-present', 's3-if-present']
62
+ self.standard_checks = [ 'database', 'migrations', 'custom', 'emailconf' ]
63
+
64
+ # Middleware based checks
65
+ mattr_accessor :middleware_checks
66
+ self.middleware_checks = [ 'middleware' ]
67
+
68
+ mattr_accessor :installed_as_middleware
69
+
70
+ # Allow non-standard redis url
71
+ mattr_accessor :redis_url
72
+ self.redis_url = nil
73
+
74
+ # Include the error in the response body. You may want to set this to false
75
+ # if your /health_check endpoint is open to the public internet
76
+ mattr_accessor :include_error_in_response_body
77
+ self.include_error_in_response_body = true
78
+
79
+ def self.add_custom_check(name = 'custom', &block)
80
+ custom_checks[name] ||= [ ]
81
+ custom_checks[name] << block
82
+ end
83
+
84
+ def self.setup
85
+ yield self
86
+ end
87
+
88
+ end
89
+
90
+ require 'health_check/version'
91
+ require 'health_check/base_health_check'
92
+ require 'health_check/resque_health_check'
93
+ require 'health_check/s3_health_check'
94
+ require 'health_check/redis_health_check'
95
+ require 'health_check/sidekiq_health_check'
96
+ require 'health_check/utils'
97
+ require 'health_check/health_check_controller'
98
+ require 'health_check/health_check_routes'
99
+ require 'health_check/middleware_health_check'
100
+
101
+ # vi: sw=2 sm ai:
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'socket'
4
+
5
+ port = 3555
6
+
7
+
8
+ server = TCPServer.new port
9
+ puts "fake_smtp_server: Waiting for one connection to port #{port} ..."
10
+
11
+ def send(client, line)
12
+ client.puts line
13
+ puts "> #{line}"
14
+ end
15
+
16
+ def receive(client)
17
+ line = client.gets
18
+ puts "< #{line}"
19
+ line
20
+ end
21
+
22
+ client = server.accept # Wait for a client to connect
23
+ send(client, "220 dummy-smtp.example.com SMTP")
24
+ cmd = receive(client)
25
+
26
+ while cmd !~ /^QUIT\r/
27
+ if cmd =~ /^HELO(.*)\r/
28
+ send(client, "250 Welcome to a dummy smtp server")
29
+ else
30
+ send(client, "502 I am so dumb I only understand HELO and QUIT")
31
+ end
32
+ cmd = receive(client)
33
+ end
34
+ send(client, "221 Bye Bye")
35
+
36
+ client.close
37
+ puts "fake_smtp_server: Exiting now the conversation has finished."
38
+ exit 0
@@ -0,0 +1,61 @@
1
+ #!/bin/bash
2
+
3
+ # Any failure causes exit
4
+ set -e
5
+
6
+ echo Setting RAILS_ENV=test RACK_ENV=test
7
+ export RAILS_ENV=test RACK_ENV=test
8
+
9
+ base_dir=$PWD
10
+ tmp_dir=$base_dir/tmp
11
+ railsapp=$tmp_dir/railsapp
12
+ custom_file="$railsapp/tmp/custom_check.ok"
13
+ catchall_file="$railsapp/tmp/catchall_route.enabled"
14
+ success=successful
15
+
16
+ rehash=''
17
+ rbenv_which='which'
18
+
19
+ if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then
20
+ echo "Detected user installed rvm"
21
+ elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then
22
+ echo "Detected root installed rvm"
23
+ elif [[ -d "$HOME/.rbenv" ]] ; then
24
+ echo "Detected rbenv: `rbenv version`"
25
+ rehash='rbenv rehash'
26
+ rbenv_which='rbenv which'
27
+ else
28
+ printf "Note: Neither rvm nor rbenv was not found.\n"
29
+ fi
30
+
31
+ echo "Checking required commands exist:"
32
+ for cmd in bash gem egrep ls tail kill find cpio
33
+ do
34
+ echo -n " "
35
+ which $cmd || ( echo "Aborting setup_railsapp: Missing $cmd command!" && exit 2 )
36
+ done
37
+ for cmd in ruby gem
38
+ do
39
+ echo -n " "
40
+ $rbenv_which $cmd || ( echo "Aborting setup_railsapp: Missing $cmd command!" && exit 2 )
41
+ done
42
+
43
+ rails="rails"
44
+ rake="rake"
45
+
46
+ if [ -x $base_dir/test/bin/rails ]
47
+ then
48
+ rails="$base_dir/test/bin/rails"
49
+ rake="$base_dir/test/bin/rake"
50
+ export PATH="$base_dir/test/bin:$PATH"
51
+ fi
52
+
53
+ if [ -x $railsapp/bin/rails ]
54
+ then
55
+ rails="$railsapp/bin/rails"
56
+ rake="$railsapp/bin/rake"
57
+ export PATH="$railsapp/bin:$PATH"
58
+ fi
59
+
60
+ echo "Using rails=$rails, rake=$rake"
61
+