Rename and refactor database to mysql_database.

Add collate as a new managable parameter, and extend self.instances to
add in all parameters when checking existing databases.  It also adds
self.prefetch in order to speed up Puppet runs.

Provider is also switched to using mk_resource_methods to generate
all the resource readers, and exists? and other methods now use the
property_hash where appropriate.

Tests rewritten to handle changes and extend code coverage.
This commit is contained in:
Ashley Penney 2013-08-17 20:46:20 -04:00
parent 4e649d7a83
commit 7d4f9fc685
6 changed files with 254 additions and 64 deletions

View file

@ -1,52 +0,0 @@
Puppet::Type.type(:database).provide(:mysql) do
desc 'Manages MySQL database.'
defaultfor :kernel => 'Linux'
optional_commands :mysql => 'mysql'
optional_commands :mysqladmin => 'mysqladmin'
def self.defaults_file
if File.file?("#{Facter.value(:root_home)}/.my.cnf")
"--defaults-file=#{Facter.value(:root_home)}/.my.cnf"
else
nil
end
end
def defaults_file
self.class.defaults_file
end
def self.instances
mysql([defaults_file, '-NBe', 'show databases'].compact).split("\n").collect do |name|
new(:name => name)
end
end
def create
mysql([defaults_file, '-NBe', "create database `#{@resource[:name]}` character set #{resource[:charset]}"].compact)
end
def destroy
mysqladmin([defaults_file, '-f', 'drop', @resource[:name]].compact)
end
def charset
mysql([defaults_file, '-NBe', "show create database `#{resource[:name]}`"].compact).match(/.*?(\S+)\s(?:COLLATE.*)?\*\//)[1]
end
def charset=(value)
mysql([defaults_file, '-NBe', "alter database `#{resource[:name]}` CHARACTER SET #{value}"].compact)
end
def exists?
begin
mysql([defaults_file, '-NBe', 'show databases'].compact).match(/^#{@resource[:name]}$/)
rescue => e
debug(e.message)
return nil
end
end
end

View file

@ -0,0 +1,79 @@
Puppet::Type.type(:mysql_database).provide(:mysql) do
desc 'Manages MySQL databases.'
commands :mysql => 'mysql'
def self.defaults_file
if File.file?("#{Facter.value(:root_home)}/.my.cnf")
"--defaults-file=#{Facter.value(:root_home)}/.my.cnf"
else
nil
end
end
def defaults_file
self.class.defaults_file
end
def self.instances
mysql([defaults_file, '-NBe', 'show databases'].compact).split("\n").collect do |name|
attributes = {}
mysql([defaults_file, '-NBe', 'show variables like "%_database"', name].compact).split("\n").each do |line|
k,v = line.split(/\s/)
attributes[k] = v
end
new(:name => name,
:ensure => :present,
:charset => attributes['character_set_database'],
:collate => attributes['collation_database']
)
end
end
# We iterate over each mysql_database entry in the catalog and compare it against
# the contents of the property_hash generated by self.instances
def self.prefetch(resources)
databases = instances
resources.keys.each do |database|
if provider = databases.find { |db| db.name == database }
resources[database].provider = provider
end
end
end
def create
mysql([defaults_file, '-NBe', "create database `#{@resource[:name]}` character set #{@resource[:charset]}"].compact)
@property_hash[:ensure] = :present
@property_hash[:charset] = @resource[:charset]
@property_hash[:collate] = @resource[:collate]
exists? ? (return true) : (return false)
end
def destroy
mysql([defaults_file, '-NBe', "drop database `#{@resource[:name]}`"].compact)
@property_hash.clear
exists? ? (return false) : (return true)
end
def exists?
@property_hash[:ensure] == :present || false
end
mk_resource_methods
def charset=(value)
mysql([defaults_file, '-NBe', "alter database `#{resource[:name]}` CHARACTER SET #{value}"].compact)
@property_hash[:charset] = value
charset == value ? (return true) : (return false)
end
def collate=(value)
mysql([defaults_file, '-NBe', "alter database `#{resource[:name]}` COLLATE #{value}"].compact)
@property_hash[:collate] = value
collate == value ? (return true) : (return false)
end
end

View file

@ -1,17 +1,11 @@
# This has to be a separate type to enable collecting
Puppet::Type.newtype(:database) do
@doc = 'Manage databases.'
ensurable
newparam(:name, :namevar=>true) do
desc 'The name of the database.'
end
newproperty(:charset) do
desc 'The characterset to use for a database'
defaultto :utf8
newvalue(/^\S+$/)
newparam(:name, :namevar => true) do
desc 'Manage databases.'
validate do |value|
Puppet.warning("database has been deprecated in favor of mysql_database.")
true
end
end
end

View file

@ -0,0 +1,22 @@
Puppet::Type.newtype(:mysql_database) do
@doc = 'Manage MySQL databases.'
ensurable
newparam(:name, :namevar => true) do
desc 'The name of the MySQL database to manage.'
end
newproperty(:charset) do
desc 'The CHARACTER SET setting for the database'
defaultto :utf8
newvalue(/^\S+$/)
end
newproperty(:collate) do
desc 'The COLLATE setting for the database'
defaultto :utf8_general_ci
newvalue(/^\S+$/)
end
end

View file

@ -0,0 +1,118 @@
require 'spec_helper'
describe Puppet::Type.type(:mysql_database).provider(:mysql) do
let(:defaults_file) { '--defaults-file=/root/.my.cnf' }
let(:raw_databases) do
<<-SQL_OUTPUT
information_schema
mydb
mysql
performance_schema
test
SQL_OUTPUT
end
let(:parsed_databases) { %w(information_schema mydb mysql performance_schema test) }
let(:resource) { Puppet::Type.type(:mysql_database).new(
{ :ensure => :present,
:charset => 'latin1',
:collate => 'latin1_swedish_ci',
:name => 'new_database',
:provider => described_class.name
}
)}
let(:provider) { resource.provider }
before :each do
Facter.stubs(:value).with(:root_home).returns('/root')
Puppet::Util.stubs(:which).with('mysql').returns('/usr/bin/mysql')
File.stubs(:file?).with('/root/.my.cnf').returns(true)
provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show databases']).returns('new_database')
provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show variables like "%_database"', 'new_database']).returns("character_set_database latin1\ncollation_database latin1_swedish_ci\nskip_show_database OFF")
end
let(:instance) { provider.class.instances.first }
describe 'self.instances' do
it 'returns an array of databases' do
provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show databases']).returns(raw_databases)
raw_databases.each_line do |db|
provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show variables like "%_database"', db.chomp]).returns("character_set_database latin1\ncollation_database latin1_swedish_ci\nskip_show_database OFF")
end
databases = provider.class.instances.collect {|x| x.name }
parsed_databases.should match_array(databases)
end
end
describe 'self.prefetch' do
it 'exists' do
provider.class.instances
provider.class.prefetch({})
end
end
describe 'create' do
it 'makes a user' do
provider.expects(:mysql).with([defaults_file, '-NBe', "create database `#{resource[:name]}` character set #{resource[:charset]}"])
provider.expects(:exists?).returns(true)
provider.create.should be_true
end
end
describe 'destroy' do
it 'removes a user if present' do
provider.expects(:mysql).with([defaults_file, '-NBe', "drop database `#{resource[:name]}`"])
provider.expects(:exists?).returns(false)
provider.destroy.should be_true
end
end
describe 'exists?' do
it 'checks if user exists' do
instance.exists?.should be_true
end
end
describe 'self.defaults_file' do
it 'sets --defaults-file' do
File.stubs(:file?).with('/root/.my.cnf').returns(true)
provider.defaults_file.should eq '--defaults-file=/root/.my.cnf'
end
it 'fails if file missing' do
File.stubs(:file?).with('/root/.my.cnf').returns(false)
provider.defaults_file.should be_nil
end
end
describe 'charset' do
it 'returns a charset' do
instance.charset.should == 'latin1'
end
end
describe 'charset=' do
it 'changes the charset' do
provider.expects(:mysql).with([defaults_file, '-NBe', "alter database `#{resource[:name]}` CHARACTER SET blah"]).returns('0')
provider.charset=('blah')
end
end
describe 'collate' do
it 'returns a collate' do
instance.collate.should == 'latin1_swedish_ci'
end
end
describe 'collate=' do
it 'changes the collate' do
provider.expects(:mysql).with([defaults_file, '-NBe', "alter database `#{resource[:name]}` COLLATE blah"]).returns('0')
provider.collate=('blah')
end
end
end

View file

@ -0,0 +1,29 @@
require 'puppet'
require 'puppet/type/mysql_database'
describe Puppet::Type.type(:mysql_database) do
before :each do
@user = Puppet::Type.type(:mysql_database).new(:name => 'test', :charset => 'utf8', :collate => 'utf8_blah_ci')
end
it 'should accept a database name' do
@user[:name].should == 'test'
end
it 'should accept a charset' do
@user[:charset] = 'latin1'
@user[:charset].should == 'latin1'
end
it 'should accept a collate' do
@user[:collate] = 'latin1_swedish_ci'
@user[:collate].should == 'latin1_swedish_ci'
end
it 'should require a name' do
expect {
Puppet::Type.type(:mysql_database).new({})
}.to raise_error(Puppet::Error, 'Title or name must be provided')
end
end