Skip to content

Commit

Permalink
magical gem -> apt dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
jnewland committed Mar 13, 2009
1 parent 1b07f60 commit 68ce73f
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 33 deletions.
2 changes: 2 additions & 0 deletions lib/moonshine/manifest/rails.rb
Expand Up @@ -15,6 +15,8 @@ def validate_platform
end
recipe :validate_platform

configure(:apt_gems => YAML.load_file(File.join(File.dirname(__FILE__), 'rails', 'apt_gems.yml')))

require File.join(File.dirname(__FILE__), 'rails', 'passenger.rb')
include Moonshine::Manifest::Rails::Passenger
require File.join(File.dirname(__FILE__), 'rails', 'mysql.rb')
Expand Down
20 changes: 20 additions & 0 deletions lib/moonshine/manifest/rails/apt_gems.yml
@@ -0,0 +1,20 @@
mysql:
- libmysqlclient15-dev
sqlite3-ruby:
- sqlite3
- libsqlite3-dev
nokogiri:
- libxml2-dev
- libxslt1-dev
rmagick:
- imagemagick
- libmagick9-dev
paperclip:
- imagemagick
- libmagick9-dev
thoughtbot-paperclip:
- imagemagick
- libmagick9-dev
mini_magick:
- imagemagick
- libmagick9-dev
3 changes: 1 addition & 2 deletions lib/moonshine/manifest/rails/mysql.rb
Expand Up @@ -26,8 +26,7 @@ def mysql_server

# Install the <tt>mysql</tt> rubygem and dependencies
def mysql_gem
package "libmysqlclient15-dev", :ensure => :installed
package "mysql", :ensure => :installed, :provider => :gem, :require => package("libmysqlclient15-dev")
gem('mysql')
end

# GRANT the database user specified in the current <tt>database_environment</tt>
Expand Down
103 changes: 82 additions & 21 deletions lib/moonshine/manifest/rails/rails.rb
Expand Up @@ -76,26 +76,10 @@ def rails_gems
exec 'rails_gems', :command => 'true'
return unless configuration[:gems]
configuration[:gems].each do |gem|
hash = {
:provider => :gem,
:before => exec('rails_gems')
}
hash.merge!(:source => gem[:source]) if gem[:source]
exact_dep = gem[:version] ? Gem::Dependency.new(gem[:name], gem[:version]) : Gem::Dependency.new(gem[:name], '>0')
matches = Gem.source_index.search(exact_dep)
installed_spec = matches.first
if installed_spec
#it's already loaded, let's just specify that we want it installed
hash.merge!(:ensure => :installed)
elsif gem[:version]
#if it's not installed and version specified, we require that version
hash.merge!(:ensure => gem[:version])
else
#otherwise we don't care
hash.merge!(:ensure => :installed)
end
#finally create the dependency
package(gem[:name], hash)
gem(gem[:name], {
:version => gem[:version],
:source => gem[:source]
})
end
end

Expand Down Expand Up @@ -131,8 +115,85 @@ def rails_directories
end

private
# Creates package("#{name}") with <tt>:provider</tt> set to <tt>:gem</tt>.
# The given <tt>options[:version]</tt> requirement is tweaked to ensure
# gems aren't reinstalled on each run. <tt>options[:source]</tt> does what
# you'd expect, as well.
#
# === Gem Package Dependencies
#
# System dependencies are loaded if any exist for the gem or any of it's
# gem dependencies in <tt>apt_gems.yml</tt>. For example, calling
# <tt>gem('webrat')</tt> knows to install <tt>libxml2-dev</tt> and
# <tt>libxslt1-dev</tt> because those are defined as dependencies for
# <tt>nokogiri</tt>.
#
# To define system dependencies not include in moonshine:
#
# class UrManifest < ShadowPuppet::Manifest
# configure(:apt_gems => {
# :fakegem => [
# 'package1',
# 'package2
# ]
# })
# end
#
# If you were then to require the installation of <tt>fakegem</tt> <strong>
# or any gem that depends on <tt>fakegem</tt></strong>, <tt>package1</tt>
# and <tt>package2</tt> would be installed first via apt.
def gem(name, options = {})
hash = {
:provider => :gem,
:before => exec('rails_gems'),
}
hash.merge!(:source => options[:source]) if options[:source]
#fixup the version required
exact_dep = Gem::Dependency.new(name, options[:version] || '>0')
matches = Gem.source_index.search(exact_dep)
installed_spec = matches.first
if installed_spec
#it's already loaded, let's just specify that we want it installed
hash.merge!(:ensure => :installed)
else
if options[:version]
#if it's not installed and version specified, we require that version
hash.merge!(:ensure => options[:version])
else
#otherwise we don't care
hash.merge!(:ensure => :installed)
end
hash = append_system_dependecies(exact_dep, hash)
end
hash.delete(:version)
package(name, hash)
end

def append_system_dependecies(exact_dep, hash) #:nodoc:
#fixup the requires key to be an array
if hash[:require] && !hash[:require].is_a?(Array)
hash[:require] = [hash[:require]]
end
hash[:require] = [] unless hash[:require]
# load this gems' dependencies. we don't create packages for em, we just
# check them against the system dependency map
specs = Gem::SpecFetcher.fetcher.fetch exact_dep
spec = specs.first.first
deps = spec.dependencies
deps << exact_dep
deps.each do |dep|
(configuration[:apt_gems][dep.name.to_sym] || []).each do |apt|
package apt, :ensure => :installed
hash[:require] << package(apt)
end
end
hash.delete(:require) if hash[:require] == []
hash
rescue
hash
end

# Creates exec('rake #name') that runs in <tt>rails root</tt> of the rails
# Creates exec("rake #name") that runs in <tt>rails root</tt> of the rails
# app, with RAILS_ENV properly set
def rake(name, options = {})
exec("rake #{name}", {
Expand Down
11 changes: 1 addition & 10 deletions lib/moonshine/manifest/rails/sqlite3.rb
Expand Up @@ -2,16 +2,7 @@ module Moonshine::Manifest::Rails::Sqlite3

# Install the sqlite3 gem and it's dependencies
def sqlite3
package 'sqlite3', :ensure => :installed
package 'libsqlite3-dev', :ensure => :installed
package 'sqlite3-ruby',
:ensure => :installed,
:provider => :gem,
:require => [
package('sqlite3'),
package('libsqlite3-dev')
],
:before => exec('rails_gems')
gem 'sqlite3-ruby', :before => exec('rails_gems')
end

end
27 changes: 27 additions & 0 deletions test/moonshine/manifest/rails_test.rb
@@ -1,5 +1,20 @@
require File.dirname(__FILE__) + '/../../test_helper.rb'

#mock out the gem source index to fake like passenger is installed, but
#nothing else
module Gem #:nodoc:
class SourceIndex #:nodoc:
alias_method :orig_search, :search
def search(gem_pattern, platform_only = false)
if gem_pattern.name.to_s =~ /passenger/
orig_search(gem_pattern, platform_only)
else
[]
end
end
end
end

class Moonshine::Manifest::RailsTest < Test::Unit::TestCase

def setup
Expand All @@ -21,6 +36,18 @@ def test_loads_gems_from_config_hash
end
end

def test_magically_loads_gem_dependencies
@manifest.configure(:gems => [
{ :name => 'webrat' },
{ :name => 'thoughtbot-paperclip', :source => 'http://gems.github.com/' }
])
@manifest.rails_gems
assert_not_nil @manifest.puppet_resources[Puppet::Type::Package]['webrat']
assert_not_nil @manifest.puppet_resources[Puppet::Type::Package]['thoughtbot-paperclip']
assert_not_nil @manifest.puppet_resources[Puppet::Type::Package]['libxml2-dev']
assert_not_nil @manifest.puppet_resources[Puppet::Type::Package]['imagemagick']
end

def test_creates_directories
config = {
:application => 'foo',
Expand Down

0 comments on commit 68ce73f

Please sign in to comment.