# Copyright (C) 2011 RightScale, Inc, All Rights Reserved Worldwide. # # THIS PROGRAM IS CONFIDENTIAL AND PROPRIETARY TO RIGHTSCALE # AND CONSTITUTES A VALUABLE TRADE SECRET. Any unauthorized use, # reproduction, modification, or disclosure of this program is # strictly prohibited. Any use of this program by an authorized # licensee is strictly subject to the terms and conditions, # including confidentiality obligations, set forth in the applicable # License Agreement between RightScale.com, Inc. and # the licensee module RightConf class RubyConfigurator # RVM version used to install rubies RVM_VERSION = '1.2.6' include Configurator register :ruby description "Installs ruby interpreter and rubygems.\n" + 'Installs and uses rvm on supported (i.e. non-Windows) platforms' settings :version => 'Ruby version using rvm notation (see "rvm list known")', :rubygems => 'Rubygems version, e.g. "1.3.7"', :gemset => 'Gemset to be used for platforms supporting rvm' validate_has_settings :version, :rubygems # Switch to ruby version defined in settings # Use rvm and install it if needed # # === Return # true:: Always return true def run_linux check_rvm(RVM_VERSION) report_check("Checking whether #{version} is the active ruby") out = Command.execute('rvm', 'list').output if out =~ /^=> #{version.gsub('.', '\\.')}/ report_success else report_failure report_check("Switching to #{version}") out = Command.execute('rvm', 'use', version).output case out when /is not installed\./ report_failure report_fatal "Failed to install #{ruby}: #{@out}" if @out @out = install_ruby(version) run return true when /^Using / report_success check_rvmrc aborting(true) else report_fatal("Failed to use #{version}:\n#{out}") end end if gemset report_check("Checking whether gemset #{gemset} exists") res = Command.execute('rvm', version, 'gemset', 'list') if res.output =~ /^#{gemset}$/ report_success else report_failure report_check("Creating gemset #{gemset} for #{version}") Command.execute('rvm', version, 'gemset', 'create', gemset, :abort_on_failure => "Failed to create gemset '#{gemset}'") Command.execute('rvm', "#{version}@#{gemset}", 'gem', 'install', 'rconf') report_success end report_check("Switching to gemset #{gemset}") Command.execute('rvm', version, 'gemset', 'use', gemset, :abort_on_failure => "Failed to switch to gemset '#{gemset}'") report_success end true end alias :run_darwin :run_linux # Switch to ruby version defined in settings # TBD # # === Return # true:: Always return true def run_windows end # Set command prefix when already configured # Re-create .rvmrc if needed # # === Return # true:: Always return true def post_process Command.set_prefix("rvm #{version}@#{gemset} exec --") check_rvmrc true end protected # Check whether the right version of RVM is installed and install it if not # # === Parameters # version(String):: Version of RVM to be checked, e.g. '1.2.6' # # === Return # true:: Always return true def check_rvm(version) report_check("Checking that rvm #{version} is installed") out = Command.execute('rvm', '--version').output if out =~ /rvm #{RVM_VERSION.gsub('.', '\\.')}/ report_success else report_failure report_check("Installing rvm #{version}") rvm_src = File.join(ENV['HOME'] || '/root', '.rvm/src') FileUtils.mkdir_p(rvm_src) Dir.chdir(rvm_src) do Command.execute('curl', '-O', '-f', "http://rvm.beginrescueend.com/releases/rvm-#{version}.tar.gz", :abort_on_failure => "Failed to download rvm #{version}") Command.execute('tar', 'zxf', "rvm-#{version}.tar.gz", :abort_on_failure => "Failed to extract rvm tgz from #{File.join(Dir.getwd, 'rvm-' + version + '.tar.gz')}") end Dir.chdir(File.join(rvm_src, "rvm-#{version}")) do Command.execute('./install', :abort_on_failure => "Failed to install rvm #{version}") end report_success aborting(true) end setup_bashrc true end # Install given ruby version using rvm # # === Parameters # ruby(String):: Ruby version compatible with rvm # # === Return # out(String):: Installation output def install_ruby(ruby) Platform.dispatch(ruby) { :install_ruby_prerequesites } report_check("Installing #{ruby} (this will take a while, please be patient)") Command.execute('rvm', 'install', ruby, :abort_on_failure => 'Failed to install ruby') res = Command.execute('rvm', ruby, 'gem', 'install', 'rconf') report_success res.output end # Make sure to install all required linux packages first # # === Return # true:: Always return true def install_ruby_prerequesites_linux_ubuntu(ruby) report_check("Installing required packages, this could take a while") packages = [] if ruby =~ /^ree-|^ruby-/ packages = %w(build-essential bison openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev) end # TBD Define packages needed for other rubies Command.sudo('apt-get', 'install', '-y', *packages) report_success end # Make sure to install all required CentOS / RedHhat packages first # NOTE: For centos 5.4 final iconv-devel might not be available :( # # === Return # true:: Always return true def install_ruby_prerequesites_linux_centos(ruby) report_check("Installing required packages, this could take a while") packages = [] if ruby =~ /^ree-|^ruby-/ packages = %w(gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel iconv-devel) end # TBD Define packages needed for other rubies Command.sudo('yum', 'install', '-y', *packages) report_success end alias :install_ruby_prerequesites_linux_redhat :install_ruby_prerequesites_linux_centos # No pre-requesites to install ree or Matz ruby on Mac (TBD others) # # === Return # true:: Always return true def install_ruby_prerequesites_darwin(ruby) true end # Check .rvmrc and its content # # === Return # true:: Always return true def check_rvmrc return true if File.exist?('.rvmrc') report_check('Setting up .rvmrc') begin File.open('.rvmrc', 'w') do |f| f.puts "rvm #{version}@#{gemset}" f.puts "type -P rconf &>/dev/null && { rconf; }" f.puts "type -P rconf &>/dev/null || { echo 'rconf not installed, skipping (see .rvmrc)'; }" end report_success post_note "Configuration required switching the active ruby\nPlease run " + 'cd ..;cd -'.blue + ' to activate it and finish configuration'.green rescue Exception => e report_failure report_error(e.message) end true end # Setup .bashrc for rvm support # # === Return # true:: Always return true def setup_bashrc candidates = ['.bashrc', '.bash_profile'] candidates.map! { |c| File.join(ENV['HOME'], c) } bashrc_path = candidates.detect { |c| File.exist?(c) } if bashrc_path content = IO.read(bashrc_path) unless content.include?(rvm_bash_activation) i = content.index(/^\s*PATH=[^$PATH]/) if i next_line = content.index("\n", i + 1) if next_line content.insert(next_line + 1, rvm_bash_activation + "\n") else content += "\n" + rvm_bash_activation end else content = rvm_bash_activation + "\n" + content end FileUtils.mv(bashrc_path, bashrc_path + '.old') File.open(bashrc_path, 'w') { |f| f.puts content } post_note 'rvm was installed, please reload your shell to activate it and re-run rconf' aborting(true) end else report_error("Failed to update bashrc to activate rvm, no bashrc found") end end # rvm bash activation code # # === Return # code(String):: Code that needs to be added to bashrc to activate rvm def rvm_bash_activation code = <