diff --git a/lib/puppet/rails.rb b/lib/puppet/rails.rb index 90330c2f2..2ad25a003 100644 --- a/lib/puppet/rails.rb +++ b/lib/puppet/rails.rb @@ -1,150 +1,150 @@ # Load the appropriate libraries, or set a class indicating they aren't available require 'facter' require 'puppet' module Puppet::Rails Puppet.config.setdefaults(:puppetmaster, :dblocation => { :default => "$statedir/clientconfigs.sqlite3", :mode => 0600, :owner => "$user", :group => "$group", :desc => "The database cache for client configurations. Used for querying within the language." }, - :dbadapter => [ "mysql", "The type of database to use." ], + :dbadapter => [ "sqlite3", "The type of database to use." ], + :dbmigrate => [ false, "Whether to automatically migrate the database." ], :dbname => [ "puppet", "The name of the database to use." ], :dbserver => [ "localhost", "The database server for Client caching. Only used when networked databases are used."], :dbuser => [ "puppet", "The database user for Client caching. Only used when networked databases are used."], :dbpassword => [ "puppet", "The database password for Client caching. Only used when networked databases are used."], :railslog => {:default => "/tmp/puppetpuppetrails.log", :mode => 0600, :owner => "$user", :group => "$group", :desc => "Where Rails-specific logs are sent" } ) def self.clear end def self.teardown unless defined? ActiveRecord::Base raise Puppet::DevError, "No activerecord, cannot init Puppet::Rails" end Puppet.config.use(:puppetmaster) args = {:adapter => Puppet[:dbadapter]} case Puppet[:dbadapter] when "sqlite3": args[:database] = Puppet[:dblocation] when "mysql": args[:host] = Puppet[:dbserver] args[:username] = Puppet[:dbuser] args[:password] = Puppet[:dbpassword] args[:database] = Puppet[:dbname] end begin ActiveRecord::Base.establish_connection(args) rescue => detail if Puppet[:trace] puts detail.backtrace end raise Puppet::Error, "Could not connect to database: %s" % detail end ActiveRecord::Base.connection.tables.each do |t| ActiveRecord::Base.connection.drop_table t end @inited = false end # Set up our database connection. It'd be nice to have a "use" system # that could make callbacks. def self.init unless Puppet.features.rails? raise Puppet::DevError, "No activerecord, cannot init Puppet::Rails" end # This global init does not work for testing, because we remove # the state dir on every test. #unless (defined? @inited and @inited) or defined? Test::Unit::TestCase unless (defined? @inited and @inited) Puppet.config.use(:puppet) ActiveRecord::Base.logger = Logger.new(Puppet[:railslog]) args = {:adapter => Puppet[:dbadapter]} case Puppet[:dbadapter] when "sqlite3": args[:database] = Puppet[:dblocation] #unless FileTest.exists?(Puppet[:dblocation]) # Puppet.config.use(:puppet) # Puppet.config.write(:dblocation) do |f| # f.print "" # end #end when "mysql": args[:host] = Puppet[:dbserver] args[:username] = Puppet[:dbuser] args[:password] = Puppet[:dbpassword] args[:database] = Puppet[:dbname] end begin ActiveRecord::Base.establish_connection(args) rescue => detail if Puppet[:trace] puts detail.backtrace end raise Puppet::Error, "Could not connect to database: %s" % detail end unless ActiveRecord::Base.connection.tables.include?("resources") require 'puppet/rails/database/schema' - Puppet::Rails::Schema.init - #puts "Database initialized: #{@inited.inspect} " + Puppet::Rails::Schema.init end @inited = true end ActiveRecord::Base.logger = Logger.new(Puppet[:railslog]) - if Puppet[:dbadapter] == "sqlite3" and ! FileTest.exists?(Puppet[:dblocation]) - + if Puppet[:dbmigrate] dbdir = nil $:.each { |d| tmp = File.join(d, "puppet/rails/database") if FileTest.directory?(tmp) dbdir = tmp + break end } unless dbdir raise Puppet::Error, "Could not find Puppet::Rails database dir" end begin ActiveRecord::Migrator.migrate(dbdir) rescue => detail if Puppet[:trace] puts detail.backtrace end raise Puppet::Error, "Could not initialize database: %s" % detail end end Puppet.config.use(:puppetmaster) ActiveRecord::Base.logger = Logger.new(Puppet[:railslog]) end end if Puppet.features.rails? require 'puppet/rails/host' end # $Id$ diff --git a/lib/puppet/rails/database/01_puppet_initialize.rb b/lib/puppet/rails/database/01_puppet_initialize.rb deleted file mode 100644 index 485634004..000000000 --- a/lib/puppet/rails/database/01_puppet_initialize.rb +++ /dev/null @@ -1,45 +0,0 @@ -class PuppetInitialize < ActiveRecord::Migration - require 'sqlite3' - - def self.up - if ActiveRecord::Migration.respond_to?(:verbose) - ActiveRecord::Migration.verbose = false - end - - # 'type' cannot be a column name, apparently - create_table :rails_resources do |table| - table.column :title, :string, :null => false - table.column :restype, :string, :null => false - table.column :tags, :string - table.column :file, :string - table.column :line, :integer - table.column :host_id, :integer - table.column :exported, :boolean - end - - create_table :rails_parameters do |table| - table.column :name, :string, :null => false - table.column :value, :string, :null => false - table.column :file, :string - table.column :line, :integer - table.column :rails_resource_id, :integer - end - - create_table :hosts do |table| - table.column :name, :string, :null => false - table.column :ip, :string - table.column :facts, :string - table.column :connect, :date - table.column :success, :date - table.column :classes, :string - end - end - - def self.down - drop_table :rails_resources - drop_table :rails_parameters - drop_table :hosts - end -end - -# $Id$ diff --git a/lib/puppet/rails/host.rb b/lib/puppet/rails/host.rb index dd6ffce0e..441b9ee54 100644 --- a/lib/puppet/rails/host.rb +++ b/lib/puppet/rails/host.rb @@ -1,105 +1,110 @@ require 'puppet/rails/resource' require 'pp' class Puppet::Rails::Host < ActiveRecord::Base has_many :fact_values, :through => :fact_names has_many :fact_names belongs_to :puppet_classes has_many :source_files has_many :resources, :include => [ :param_names, :param_values ] acts_as_taggable def facts(name) fv = self.fact_values.find(:first, :conditions => "fact_names.name = '#{name}'") return fv.value end # If the host already exists, get rid of its objects def self.clean(host) if obj = self.find_by_name(host) obj.rails_objects.clear return obj else return nil end end # Store our host in the database. def self.store(hash) unless hash[:name] raise ArgumentError, "You must specify the hostname for storage" end args = {} if hash[:facts].include?("ipaddress") args[:ip] = hash[:facts]["ipaddress"] end - host = self.find_or_create_by_name(hash[:facts]["hostname"], args) + host = nil + Puppet::Util.benchmark(:info, "Found/created host") do + host = self.find_or_create_by_name(hash[:facts]["hostname"], args) + end hash[:facts].each do |name, value| fn = host.fact_names.find_or_create_by_name(name) fv = fn.fact_values.find_or_create_by_value(value) host.fact_names << fn end unless hash[:resources] raise ArgumentError, "You must pass resources" end - typenames = [] + typenames = [] Puppet::Type.loadall Puppet::Type.eachtype do |type| typenames << type.name.to_s end - hash[:resources].each do |resource| - resargs = resource.to_hash.stringify_keys + Puppet::Util.benchmark(:info, "Converted resources") do + hash[:resources].each do |resource| + resargs = resource.to_hash.stringify_keys - if typenames.include?(resource.type) - rtype = "Puppet#{resource.type.to_s.capitalize}" - end + if typenames.include?(resource.type) + rtype = "Puppet#{resource.type.to_s.capitalize}" + end - res = host.resources.find_or_create_by_title(resource[:title]) - res.type = rtype - res.save - resargs.each do |param, value| - pn = res.param_names.find_or_create_by_name(param) - pv = pn.param_values.find_or_create_by_value(value) - res.param_names << pn + res = host.resources.find_or_create_by_title(resource[:title]) + res.type = rtype + res.save + resargs.each do |param, value| + pn = res.param_names.find_or_create_by_name(param) + pv = pn.param_values.find_or_create_by_value(value) + res.param_names << pn + end end end Puppet::Util.benchmark(:info, "Saved host to database") do host.save end return host end # Add all of our RailsObjects def addobjects(objects) objects.each do |tobj| params = {} tobj.each do |p,v| params[p] = v end args = {:ptype => tobj.type, :name => tobj.name} [:tags, :file, :line].each do |param| if val = tobj.send(param) args[param] = val end end robj = rails_objects.build(args) robj.addparams(params) if tobj.collectable robj.toggle(:collectable) end end end end # $Id$ diff --git a/test/lib/puppettest/railstesting.rb b/test/lib/puppettest/railstesting.rb index 3b65f5b34..baac6e03a 100644 --- a/test/lib/puppettest/railstesting.rb +++ b/test/lib/puppettest/railstesting.rb @@ -1,44 +1,46 @@ module PuppetTest::RailsTesting Parser = Puppet::Parser AST = Puppet::Parser::AST include PuppetTest::ParserTesting def railsinit Puppet::Rails.init end def railsteardown - Puppet::Rails.teardown + if Puppet[:dbadapter] != "sqlite3" + Puppet::Rails.teardown + end end def railsresource(type = "file", title = "/tmp/testing", params = {}) railsteardown railsinit # We need a host for resources #host = Puppet::Rails::Host.new(:name => Facter.value("hostname")) # Now build a resource resources = [] resources << mkresource(:type => type, :title => title, :exported => true, :params => params) # Now collect our facts facts = Facter.to_hash # Now try storing our crap host = nil assert_nothing_raised { host = Puppet::Rails::Host.store( :resources => resources, :facts => facts, :name => facts["hostname"] ) } # Now save the whole thing host.save end end # $Id$ diff --git a/test/rails/rails.rb b/test/rails/rails.rb index 381150be3..05fad4c87 100755 --- a/test/rails/rails.rb +++ b/test/rails/rails.rb @@ -1,89 +1,94 @@ #!/usr/bin/env ruby $:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/ require 'puppet' require 'puppet/rails' require 'puppet/parser/interpreter' require 'puppet/parser/parser' require 'puppet/client' require 'puppettest' require 'puppettest/parsertesting' require 'puppettest/resourcetesting' require 'puppettest/railstesting' class TestRails < Test::Unit::TestCase include PuppetTest::ParserTesting include PuppetTest::ResourceTesting include PuppetTest::RailsTesting def test_includerails assert_nothing_raised { require 'puppet/rails' } end # Don't do any tests w/out this class - if defined? ActiveRecord::Base + if Puppet.features.rails? + def setup + super + railsinit + end + + def teardown + super + railsteardown + end + def test_hostcache railsinit @interp, @scope, @source = mkclassframing # First make some objects resources = [] 20.times { |i| resources << mkresource(:type => "file", :title => "/tmp/file#{i.to_s}", :params => {:owner => "user#{i}"}) } # Now collect our facts facts = Facter.to_hash - assert_nothing_raised { - Puppet::Rails.teardown - Puppet::Rails.init - } - # Now try storing our crap host = nil assert_nothing_raised { host = Puppet::Rails::Host.store( :resources => resources, :facts => facts, :name => facts["hostname"], :classes => ["one", "two::three", "four"] ) } assert(host, "Did not create host") host = nil assert_nothing_raised { host = Puppet::Rails::Host.find_by_name(facts["hostname"]) } assert(host, "Could not find host object") assert(host.resources, "No objects on host") assert_equal(facts["hostname"], host.facts("hostname"), "Did not retrieve facts") count = 0 host.resources.each do |resource| count += 1 i = nil if resource[:title] =~ /file([0-9]+)/ i = $1 else raise "Got weird resource %s" % resource.inspect end assert_equal("user#{i}", resource.parameters["owner"]) end assert_equal(20, count, "Did not get enough resources") end else $stderr.puts "Install Rails for Rails and Caching tests" end end # $Id$