Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Major refactor of mysql module.

This is a major change to the module and would be released as a new
version.

* Add self.instances to database and database_user for puppet resource.
* Update database provider to use flush method.
* Update module to conform to puppet-lint recommendations.
* Cleanup some unecessary logic in mysql::db define type.
* Move mysql_restart to config class.
* Use class to class dependency instead of resource dependency.
* Change appropriate rspec-puppet tests.
* Add fixtures directory to simplify testing.
* Update raketask and spec_helper to reflect fixture changes.
* Update mysql_password function to support validation.
* Move client installation to a separate class.
* Update documentation and readme.
  • Loading branch information...
commit b1f90fd1d2581186c6fb07c10a4a76f5c5a073b1 1 parent 1e926b4
@nanliu nanliu authored
Showing with 553 additions and 438 deletions.
  1. +1 −1  Modulefile
  2. +59 −44 README.md
  3. +15 −11 Rakefile
  4. +10 −4 lib/puppet/parser/functions/mysql_password.rb
  5. +5 −4 lib/puppet/provider/database/default.rb
  6. +18 −13 lib/puppet/provider/database/mysql.rb
  7. +10 −4 lib/puppet/provider/database_grant/default.rb
  8. +142 −143 lib/puppet/provider/database_grant/mysql.rb
  9. +8 −4 lib/puppet/provider/database_user/default.rb
  10. +20 −16 lib/puppet/provider/database_user/mysql.rb
  11. +3 −5 lib/puppet/type/database.rb
  12. +3 −3 lib/puppet/type/database_grant.rb
  13. +7 −9 lib/puppet/type/database_user.rb
  14. +75 −33 manifests/config.pp
  15. +27 −29 manifests/db.pp
  16. +10 −6 manifests/init.pp
  17. +22 −13 manifests/params.pp
  18. +5 −4 manifests/python.pp
  19. +8 −14 manifests/ruby.pp
  20. +18 −33 manifests/server.pp
  21. +9 −8 manifests/server/monitor.pp
  22. +9 −8 manifests/server/mysqltuner.pp
  23. +3 −0  spec/classes/mysql_init_spec.rb
  24. +4 −4 spec/defines/mysql_db_spec.rb
  25. 0  spec/fixtures/manifests/site.pp
  26. +1 −0  spec/fixtures/modules/mysql
  27. +11 −2 spec/spec_helper.rb
  28. +30 −0 spec/unit/mysql_password_spec.rb
  29. +3 −3 templates/my.cnf.erb
  30. +6 −6 tests/mysql_database.pp
  31. +10 −10 tests/mysql_user.pp
  32. +1 −4 tests/server.pp
View
2  Modulefile
@@ -1,5 +1,5 @@
name 'puppetlabs-mysql'
-version '0.0.1'
+version '0.1.0'
source 'git://github.com/puppetlabs/puppetlabs-mysql.git'
author 'Puppet Labs'
license 'Apache'
View
103 README.md
@@ -1,68 +1,83 @@
# Mysql module for Puppet
+This module manages mysql on Linux (RedHat/Debian) distros. A native mysql provider implements database resource type to handle database, database user, and database permission.
## Description
-This module has evolved and is originally based on work by David Schmitt.
-If anyone else was involved in the development of this module
-and wants credit, let Puppetlabs know.
+
+This module is based on work by David Schmitt. The following contributor have contributed patches to this module (beyond Puppet Labs):
+
+* Christian G. Warden
+* Daniel Black
+* Justin Ellison
+* Lowe Schmidt
+* Matthias Pigulla
+* William Van Hevelingen
## Usage
### mysql
Installs the mysql-client package.
-<pre>
-class { 'mysql': }
-</pre>
+
+ class { 'mysql': }
### mysql::python
Installs mysql bindings for python.
-<pre>
-class { 'mysql::python': }
-</pre>
+
+ class { 'mysql::python': }
### mysql::ruby
Installs mysql bindings for ruby.
-<pre>
-class { 'mysql::ruby': }
-</pre>
+
+ class { 'mysql::ruby': }
### mysql::server
-Installs mysql-server, starts service, sets `root_pw`, and sets root.
-<pre>
-class { 'mysql::server':
- config_hash => { 'root_password' => 'foo' }
-}
-</pre>
+Installs mysql-server packages, configures my.cnf and starts mysqld service:
+
+ class { 'mysql::server':
+ config_hash => { 'root_password' => 'foo' }
+ }
-Login information in `/etc/.my.cnf` and `/root/.my.cnf`.
+Database login information stored in `/root/.my.cnf`.
### mysql::db
Creates a database with a user and assign some privileges.
-<pre>
-mysql::db { 'mydb':
- user => 'myuser',
- password => 'mypass',
- host => 'localhost',
- grant => ['all'],
-}
-</pre>
+ mysql::db { 'mydb':
+ user => 'myuser',
+ password => 'mypass',
+ host => 'localhost',
+ grant => ['all'],
+ }
### Providers for database types:
-<pre>
-database { 'mydb':
- charset => 'latin1',
-}
-</pre>
-
-<pre>
-database_user { 'bob@localhost':
- password_hash => mysql_password('foo')
-}
-</pre>
-
-<pre>
-database_grant { 'user@localhost/database':
- privileges => ['all'] ,
-}
-</pre>
+MySQL provider supports puppet resources command:
+
+ $ puppet resource database
+ database { 'information_schema':
+ ensure => 'present',
+ charset => 'utf8',
+ }
+ database { 'mysql':
+ ensure => 'present',
+ charset => 'latin1',
+ }
+
+The custom resources can be used in any other manifests:
+
+ database { 'mydb':
+ charset => 'latin1',
+ }
+
+ database_user { 'bob@localhost':
+ password_hash => mysql_password('foo')
+ }
+
+ database_grant { 'user@localhost/database':
+ privileges => ['all'] ,
+ }
+
+A resource default can be specified to handle dependency:
+
+ Database {
+ require => Class['mysql::server'],
+ }
View
26 Rakefile
@@ -1,14 +1,18 @@
+require 'rubygems'
require 'rake'
+require 'rspec/core/rake_task'
require 'fileutils'
-begin
- require 'rspec/core/rake_task'
- HAVE_RSPEC = true
-rescue LoadError
- HAVE_RSPEC = false
+task :default do
+ system("rake -T")
end
-task :default => [:build]
+desc "Run all rspec-puppet tests"
+RSpec::Core::RakeTask.new(:spec) do |t|
+ t.rspec_opts = ['--color']
+ # ignores fixtures directory.
+ t.pattern = 'spec/{classes,defines,unit}/**/*_spec.rb'
+end
def update_module_version
gitdesc = %x{git describe}.chomp
@@ -39,9 +43,9 @@ task :clean do
FileUtils.rm_rf("pkg/")
end
-if HAVE_RSPEC then
- desc 'Run all module spec tests (Requires rspec-puppet gem)'
- task :spec do
- system 'rspec --format d spec/'
- end
+desc "Check puppet manifests with puppet-lint"
+task :lint do
+ # This requires pull request: https://github.com/rodjek/puppet-lint/pull/81
+ system("puppet-lint manifests")
+ system("puppet-lint tests")
end
View
14 lib/puppet/parser/functions/mysql_password.rb
@@ -2,8 +2,14 @@
require 'digest/sha1'
module Puppet::Parser::Functions
- newfunction(:mysql_password, :type => :rvalue) do |args|
- '*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(args[0])).upcase
- end
-end
+ newfunction(:mysql_password, :type => :rvalue, :doc => <<-EOS
+ Returns the mysql password hash from the clear text password.
+ EOS
+ ) do |args|
+
+ raise(Puppet::ParseError, "mysql_password(): Wrong number of arguments " +
+ "given (#{args.size} for 1)") if args.size != 1
+ '*' + Digest::SHA1.hexdigest(Digest::SHA1.digest(args[0])).upcase
+ end
+end
View
9 lib/puppet/provider/database/default.rb
@@ -1,7 +1,11 @@
Puppet::Type.type(:database).provide(:default) do
desc "This is a default provider that does nothing. This allows us to install mysql on the same puppet run where we want to use it."
-
+
+ def self.instances
+ []
+ end
+
def create
return false
end
@@ -14,7 +18,6 @@ def exists?
fail('This is just the default provider for database, all it does is fail')
end
-
def charset
return false
end
@@ -22,6 +25,4 @@ def charset
def charset=(value)
return false
end
- # retrieve the current set of mysql databases
end
-
View
31 lib/puppet/provider/database/mysql.rb
@@ -1,21 +1,34 @@
Puppet::Type.type(:database).provide(:mysql) do
- desc "Create mysql database."
+ desc "Manages MySQL database."
defaultfor :kernel => 'Linux'
- optional_commands :mysqladmin => 'mysqladmin'
optional_commands :mysql => 'mysql'
- optional_commands :mysqlshow => 'mysqlshow'
-
+ optional_commands :mysqladmin => 'mysqladmin'
+
+ def self.instances
+ mysql('-NBe', "show databases").split("\n").collect do |name|
+ new(:name => name)
+ end
+ end
+
def create
- mysql('-NBe', "CREATE DATABASE #{@resource[:name]} CHARACTER SET #{resource[:charset]}")
+ mysql('-NBe', "create database #{@resource[:name]} character set #{resource[:charset]}")
end
def destroy
mysqladmin('-f', 'drop', @resource[:name])
end
+ def charset
+ mysql('-NBe', "show create database #{resource[:name]}").match(/.*?(\S+)\s\*\//)[1]
+ end
+
+ def charset=(value)
+ mysql('-NBe', "alter database #{resource[:name]} CHARACTER SET #{value}")
+ end
+
def exists?
begin
mysql('-NBe', "show databases").match(/^#{@resource[:name]}$/)
@@ -24,14 +37,6 @@ def exists?
return nil
end
end
-
- def charset
- mysql('-NBe', "show create database #{resource[:name]}").match(/.*?(\S+)\s\*\//)[1]
- end
- def charset=(value)
- mysql('-NBe', "alter database #{resource[:name]} CHARACTER SET #{value}")
- end
- # retrieve the current set of mysql databases
end
View
14 lib/puppet/provider/database_grant/default.rb
@@ -1,21 +1,27 @@
# A grant is either global or per-db. This can be distinguished by the syntax
# of the name:
-# user@host => global
-# user@host/db => per-db
+# user@host => global
+# user@host/db => per-db
Puppet::Type.type(:database_grant).provide(:default) do
desc "Uses mysql as database."
+ def self.instances
+ []
+ end
+
def destroy
return false
end
+
def create
return false
end
- def exists?
+
+ def exists?
fail('Default provider for database_grant should never be used')
end
-
+
end
View
285 lib/puppet/provider/database_grant/mysql.rb
@@ -1,155 +1,154 @@
# A grant is either global or per-db. This can be distinguished by the syntax
# of the name:
-# user@host => global
-# user@host/db => per-db
+# user@host => global
+# user@host/db => per-db
MYSQL_USER_PRIVS = [ :select_priv, :insert_priv, :update_priv, :delete_priv,
- :create_priv, :drop_priv, :reload_priv, :shutdown_priv, :process_priv,
- :file_priv, :grant_priv, :references_priv, :index_priv, :alter_priv,
- :show_db_priv, :super_priv, :create_tmp_table_priv, :lock_tables_priv,
- :execute_priv, :repl_slave_priv, :repl_client_priv, :create_view_priv,
- :show_view_priv, :create_routine_priv, :alter_routine_priv,
- :create_user_priv, :event_priv, :trigger_priv
+ :create_priv, :drop_priv, :reload_priv, :shutdown_priv, :process_priv,
+ :file_priv, :grant_priv, :references_priv, :index_priv, :alter_priv,
+ :show_db_priv, :super_priv, :create_tmp_table_priv, :lock_tables_priv,
+ :execute_priv, :repl_slave_priv, :repl_client_priv, :create_view_priv,
+ :show_view_priv, :create_routine_priv, :alter_routine_priv,
+ :create_user_priv, :event_priv, :trigger_priv
]
MYSQL_DB_PRIVS = [ :select_priv, :insert_priv, :update_priv, :delete_priv,
- :create_priv, :drop_priv, :grant_priv, :references_priv, :index_priv,
- :alter_priv, :create_tmp_table_priv, :lock_tables_priv, :create_view_priv,
- :show_view_priv, :create_routine_priv, :alter_routine_priv, :execute_priv
+ :create_priv, :drop_priv, :grant_priv, :references_priv, :index_priv,
+ :alter_priv, :create_tmp_table_priv, :lock_tables_priv, :create_view_priv,
+ :show_view_priv, :create_routine_priv, :alter_routine_priv, :execute_priv
]
Puppet::Type.type(:database_grant).provide(:mysql) do
- desc "Uses mysql as database."
-
- defaultfor :kernel => 'Linux'
-
- optional_commands :mysql => 'mysql'
- optional_commands :mysqladmin => 'mysqladmin'
-
- def mysql_flush
- mysqladmin "flush-privileges"
- end
-
- # this parses the
- def split_name(string)
- matches = /^([^@]*)@([^\/]*)(\/(.*))?$/.match(string).captures.compact
- case matches.length
- when 2
- {
- :type => :user,
- :user => matches[0],
- :host => matches[1]
- }
- when 4
- {
- :type => :db,
- :user => matches[0],
- :host => matches[1],
- :db => matches[3]
- }
- end
- end
-
- def create_row
- unless @resource.should(:privileges).empty?
- name = split_name(@resource[:name])
- case name[:type]
- when :user
- mysql "mysql", "-e", "INSERT INTO user (host, user) VALUES ('%s', '%s')" % [
- name[:host], name[:user],
- ]
- when :db
- mysql "mysql", "-e", "INSERT INTO db (host, user, db) VALUES ('%s', '%s', '%s')" % [
- name[:host], name[:user], name[:db],
- ]
- end
- mysql_flush
- end
- end
-
- def destroy
- mysql "mysql", "-e", "REVOKE ALL ON '%s'.* FROM '%s@%s'" % [ @resource[:privileges], @resource[:database], @resource[:name], @resource[:host] ]
- end
-
- def row_exists?
- name = split_name(@resource[:name])
- fields = [:user, :host]
- if name[:type] == :db
- fields << :db
- end
- not mysql( "mysql", "-NBe", 'SELECT "1" FROM %s WHERE %s' % [ name[:type], fields.map do |f| "%s = '%s'" % [f, name[f]] end.join(' AND ')]).empty?
- end
-
- def all_privs_set?
- all_privs = case split_name(@resource[:name])[:type]
- when :user
- MYSQL_USER_PRIVS
- when :db
- MYSQL_DB_PRIVS
- end
- all_privs = all_privs.collect do |p| p.to_s end.sort.join("|")
- privs = privileges.collect do |p| p.to_s end.sort.join("|")
-
- all_privs == privs
- end
-
- def privileges
- name = split_name(@resource[:name])
- privs = ""
-
- case name[:type]
- when :user
- privs = mysql "mysql", "-Be", 'select * from user where user="%s" and host="%s"' % [ name[:user], name[:host] ]
- when :db
- privs = mysql "mysql", "-Be", 'select * from db where user="%s" and host="%s" and db="%s"' % [ name[:user], name[:host], name[:db] ]
- end
-
- if privs.match(/^$/)
- privs = [] # no result, no privs
- else
- # returns a line with field names and a line with values, each tab-separated
- privs = privs.split(/\n/).map! do |l| l.chomp.split(/\t/) end
- # transpose the lines, so we have key/value pairs
- privs = privs[0].zip(privs[1])
- privs = privs.select do |p| p[0].match(/_priv$/) and p[1] == 'Y' end
- end
-
- privs.collect do |p| symbolize(p[0].downcase) end
- end
-
- def privileges=(privs)
- unless row_exists?
- create_row
- end
-
- # puts "Setting privs: ", privs.join(", ")
- name = split_name(@resource[:name])
- stmt = ''
- where = ''
- all_privs = []
- case name[:type]
- when :user
- stmt = 'update user set '
- where = ' where user="%s" and host="%s"' % [ name[:user], name[:host] ]
- all_privs = MYSQL_USER_PRIVS
- when :db
- stmt = 'update db set '
- where = ' where user="%s" and host="%s"' % [ name[:user], name[:host] ]
- all_privs = MYSQL_DB_PRIVS
- end
-
- if privs[0] == :all
- privs = all_privs
- end
-
- # puts "stmt:", stmt
- set = all_privs.collect do |p| "%s = '%s'" % [p, privs.include?(p) ? 'Y' : 'N'] end.join(', ')
- # puts "set:", set
- stmt = stmt << set << where
-
- mysql "mysql", "-Be", stmt
- mysql_flush
- end
+ desc "Uses mysql as database."
+
+ defaultfor :kernel => 'Linux'
+
+ optional_commands :mysql => 'mysql'
+ optional_commands :mysqladmin => 'mysqladmin'
+
+ def mysql_flush
+ mysqladmin "flush-privileges"
+ end
+
+ # this parses the
+ def split_name(string)
+ matches = /^([^@]*)@([^\/]*)(\/(.*))?$/.match(string).captures.compact
+ case matches.length
+ when 2
+ {
+ :type => :user,
+ :user => matches[0],
+ :host => matches[1]
+ }
+ when 4
+ {
+ :type => :db,
+ :user => matches[0],
+ :host => matches[1],
+ :db => matches[3]
+ }
+ end
+ end
+
+ def create_row
+ unless @resource.should(:privileges).empty?
+ name = split_name(@resource[:name])
+ case name[:type]
+ when :user
+ mysql "mysql", "-e", "INSERT INTO user (host, user) VALUES ('%s', '%s')" % [
+ name[:host], name[:user],
+ ]
+ when :db
+ mysql "mysql", "-e", "INSERT INTO db (host, user, db) VALUES ('%s', '%s', '%s')" % [
+ name[:host], name[:user], name[:db],
+ ]
+ end
+ mysql_flush
+ end
+ end
+
+ def destroy
+ mysql "mysql", "-e", "REVOKE ALL ON '%s'.* FROM '%s@%s'" % [ @resource[:privileges], @resource[:database], @resource[:name], @resource[:host] ]
+ end
+
+ def row_exists?
+ name = split_name(@resource[:name])
+ fields = [:user, :host]
+ if name[:type] == :db
+ fields << :db
+ end
+ not mysql( "mysql", "-NBe", 'SELECT "1" FROM %s WHERE %s' % [ name[:type], fields.map do |f| "%s = '%s'" % [f, name[f]] end.join(' AND ')]).empty?
+ end
+
+ def all_privs_set?
+ all_privs = case split_name(@resource[:name])[:type]
+ when :user
+ MYSQL_USER_PRIVS
+ when :db
+ MYSQL_DB_PRIVS
+ end
+ all_privs = all_privs.collect do |p| p.to_s end.sort.join("|")
+ privs = privileges.collect do |p| p.to_s end.sort.join("|")
+
+ all_privs == privs
+ end
+
+ def privileges
+ name = split_name(@resource[:name])
+ privs = ""
+
+ case name[:type]
+ when :user
+ privs = mysql "mysql", "-Be", 'select * from user where user="%s" and host="%s"' % [ name[:user], name[:host] ]
+ when :db
+ privs = mysql "mysql", "-Be", 'select * from db where user="%s" and host="%s" and db="%s"' % [ name[:user], name[:host], name[:db] ]
+ end
+
+ if privs.match(/^$/)
+ privs = [] # no result, no privs
+ else
+ # returns a line with field names and a line with values, each tab-separated
+ privs = privs.split(/\n/).map! do |l| l.chomp.split(/\t/) end
+ # transpose the lines, so we have key/value pairs
+ privs = privs[0].zip(privs[1])
+ privs = privs.select do |p| p[0].match(/_priv$/) and p[1] == 'Y' end
+ end
+
+ privs.collect do |p| symbolize(p[0].downcase) end
+ end
+
+ def privileges=(privs)
+ unless row_exists?
+ create_row
+ end
+
+ # puts "Setting privs: ", privs.join(", ")
+ name = split_name(@resource[:name])
+ stmt = ''
+ where = ''
+ all_privs = []
+ case name[:type]
+ when :user
+ stmt = 'update user set '
+ where = ' where user="%s" and host="%s"' % [ name[:user], name[:host] ]
+ all_privs = MYSQL_USER_PRIVS
+ when :db
+ stmt = 'update db set '
+ where = ' where user="%s" and host="%s"' % [ name[:user], name[:host] ]
+ all_privs = MYSQL_DB_PRIVS
+ end
+
+ if privs[0] == :all
+ privs = all_privs
+ end
+
+ # puts "stmt:", stmt
+ set = all_privs.collect do |p| "%s = '%s'" % [p, privs.include?(p) ? 'Y' : 'N'] end.join(', ')
+ # puts "set:", set
+ stmt = stmt << set << where
+
+ mysql "mysql", "-Be", stmt
+ mysql_flush
+ end
end
-
View
12 lib/puppet/provider/database_user/default.rb
@@ -2,22 +2,26 @@
desc "manage users for a mysql database."
+ def self.instances
+ []
+ end
+
def create
return false
end
-
+
def destroy
return false
end
-
+
def exists?
fail("this is just a default, it should not actually be used")
end
-
+
def password_hash
return false
end
-
+
def password_hash=(string)
return false
end
View
36 lib/puppet/provider/database_user/mysql.rb
@@ -4,35 +4,39 @@
defaultfor :kernel => 'Linux'
- optional_commands :mysql => 'mysql'
+ optional_commands :mysql => 'mysql'
optional_commands :mysqladmin => 'mysqladmin'
+ def self.instances
+ users = mysql("mysql", '-BNe' "select concat(User, '@',Host) as User from mysql.user").split("\n")
+ users.select{ |user| user =~ /\.+@/ }.collect do |name|
+ new(:name => name)
+ end
+ end
+
def create
- mysql "mysql", "-e", "create user '%s' identified by PASSWORD '%s'" % [ @resource[:name].sub("@", "'@'"), @resource.value(:password_hash) ]
- mysql_flush
+ mysql("mysql", "-e", "create user '%s' identified by PASSWORD '%s'" % [ @resource[:name].sub("@", "'@'"), @resource.value(:password_hash) ])
end
-
+
def destroy
- mysql "mysql", "-e", "drop user '%s'" % @resource.value(:name).sub("@", "'@'")
- mysql_flush
- end
-
- def exists?
- not mysql("mysql", "-NBe", "select '1' from user where CONCAT(user, '@', host) = '%s'" % @resource.value(:name)).empty?
+ mysql("mysql", "-e", "drop user '%s'" % @resource.value(:name).sub("@", "'@'") )
end
-
+
def password_hash
mysql("mysql", "-NBe", "select password from user where CONCAT(user, '@', host) = '%s'" % @resource.value(:name)).chomp
end
-
+
def password_hash=(string)
- mysql "mysql", "-e", "SET PASSWORD FOR '%s' = '%s'" % [ @resource[:name].sub("@", "'@'"), string ]
- mysql_flush
+ mysql("mysql", "-e", "SET PASSWORD FOR '%s' = '%s'" % [ @resource[:name].sub("@", "'@'"), string ] )
end
- private
+ def exists?
+ not mysql("mysql", "-NBe", "select '1' from user where CONCAT(user, '@', host) = '%s'" % @resource.value(:name)).empty?
+ end
- def mysql_flush
+ def flush
+ @property_hash.clear
mysqladmin "flush-privileges"
end
+
end
View
8 lib/puppet/type/database.rb
@@ -1,14 +1,13 @@
# This has to be a separate type to enable collecting
Puppet::Type.newtype(:database) do
- @doc = "Manage creation/deletion of a database."
+ @doc = "Manage databases."
ensurable
- newparam(:name) do
+ newparam(:name, :namevar=>true) do
desc "The name of the database."
- isnamevar
end
-
+
newproperty(:charset) do
desc "The characterset to use for a database"
defaultto :utf8
@@ -16,4 +15,3 @@
end
end
-
View
6 lib/puppet/type/database_grant.rb
@@ -25,7 +25,7 @@
reqs
end
- newparam(:name) do
+ newparam(:name, :namevar=>true) do
desc "The primary key: either user@host for global privilges or user@host/database for database specific privileges"
end
@@ -60,7 +60,7 @@ def is_to_s(currentvalue = @is)
# use the sorted outputs for comparison
def insync?(is)
if defined? @should and @should
- case self.should_to_s
+ case self.should_to_s
when "all"
self.provider.all_privs_set?
when self.is_to_s(is)
@@ -72,7 +72,7 @@ def insync?(is)
true
end
end
-
end
+
end
View
16 lib/puppet/type/database_user.rb
@@ -4,16 +4,13 @@
ensurable
- newparam(:name) do
- desc "The name of the user. This uses the 'username@hostname' or username@hosname."
+ newparam(:name, :namevar=>true) do
+ desc "The name of the user. This uses the 'username@hostname' or username@hostname."
validate do |value|
- unless value =~ /\w+@[\w%]+/
- raise ArgumentError, "Invalid database user #{value}"
- end
- list = value.split('@')
- if list[0].size > 16
- raise ArgumentError,
- "MySQL usernames are limited to a maximum of 16 characters"
+ raise(ArgumentError, "Invalid database user #{value}") unless value =~ /\w+@[\w%]+/
+ username = value.split('@')[0]
+ if username.size > 16
+ raise ArgumentError, "MySQL usernames are limited to a maximum of 16 characters"
end
end
end
@@ -22,4 +19,5 @@
desc "The password hash of the user. Use mysql_password() for creating such a hash."
newvalue(/\w+/)
end
+
end
View
108 manifests/config.pp
@@ -1,56 +1,98 @@
+# Class: mysql::config
+#
+# Parameters:
+#
+# [*root_password*] - root user password.
+# [*old_root_password*] - previous root user password,
+# [*bind_address*] - address to bind service.
+# [*port*] - port to bind service.
+# [*etc_root_password*] - whether to save /etc/.my.cnf.
+# [*service_name*] - mysql service name.
+# [*config_file*] - my.cnf configuration file path.
+# [*socket*] - mysql socket.
+#
+# Actions:
+#
+# Requires:
+#
+# class mysql::server
+#
+# Usage:
+#
+# class { 'mysql::config':
+# root_password => 'changeme',
+# bind_address => $::ipaddress,
+# }
+#
class mysql::config(
- $root_password = 'UNSET',
+ $root_password = 'UNSET',
$old_root_password = '',
- $bind_address = '127.0.0.1',
- $port = 3306,
- # rather or not to store the rootpw in /etc/my.cnf
- $etc_root_password = false
-) {
- include mysql::params
+ $bind_address = $mysql::params::bind_address,
+ $port = $mysql::params::port,
+ $etc_root_password = $mysql::params::etc_root_password,
+ $service_name = $mysql::params::service_name,
+ $config_file = $mysql::params::config_file,
+ $socket = $mysql::params::socket,
+) inherits mysql::params {
+
+ Class['mysql::server'] -> Class['mysql::config']
+
+ File {
+ owner => 'root',
+ group => 'root',
+ mode => '0400',
+ notify => Exec['mysqld-restart'],
+ }
+
+ # This kind of sucks, that I have to specify a difference resource for
+ # restart. the reason is that I need the service to be started before mods
+ # to the config file which can cause a refresh
+ exec { 'mysqld-restart':
+ command => "service ${service_name} restart",
+ refreshonly => true,
+ path => '/sbin/:/usr/sbin/',
+ subscribe => Exec['set_mysql_rootpw']
+ }
# manage root password if it is set
- if !($root_password == 'UNSET') {
+ if $root_password != 'UNSET' {
case $old_root_password {
- '': {$old_pw=''}
- default: {$old_pw="-p${old_root_password}"}
+ '': { $old_pw='' }
+ default: { $old_pw="-p${old_root_password}" }
}
- exec{ 'set_mysql_rootpw':
+
+ exec { 'set_mysql_rootpw':
command => "mysqladmin -u root ${old_pw} password ${root_password}",
- #logoutput => on_failure,
logoutput => true,
- unless => "mysqladmin -u root -p${root_password} status > /dev/null",
+ unless => "mysqladmin -u root -p${root_password} status > /dev/null",
path => '/usr/local/sbin:/usr/bin',
- require => [Package['mysql-server'], Service['mysqld']],
- before => File['/root/.my.cnf'],
- notify => Exec['mysqld-restart'],
}
- file{'/root/.my.cnf':
+
+ file { '/root/.my.cnf':
content => template('mysql/my.cnf.pass.erb'),
+ require => Exec['set_mysql_rootpw'],
}
+
if $etc_root_password {
- file{'/etc/my.cnf':
- content => template('mysql/my.cnf.pass.erb'),
- require => Exec['set_mysql_rootpw'],
- }
+ file{ '/etc/my.cnf':
+ content => template('mysql/my.cnf.pass.erb'),
+ require => Exec['set_mysql_rootpw'],
+ }
}
}
- File {
- owner => 'root',
- group => 'root',
- mode => '0400',
- notify => Exec['mysqld-restart'],
- require => Package['mysql-server']
- }
+
+
file { '/etc/mysql':
ensure => directory,
- mode => '755',
+ mode => '0755',
}
file { '/etc/mysql/conf.d':
- ensure => directory,
- mode => '755',
+ ensure => directory,
+ mode => '0755',
}
-
- file { $mysql::params::config_file:
+ file { $config_file:
content => template('mysql/my.cnf.erb'),
+ mode => '0644',
}
+
}
View
56 manifests/db.pp
@@ -1,23 +1,26 @@
# Define: mysql::db
#
-# This module creates database instances, a user,
-# and grants that user privileges to the DB.
+# This module creates database instances, a user, and grants that user
+# privileges to the database.
#
# Parameters:
-# [*title*] - database name
-# [*user*] - user to create
-# [*password*] - user's password
-# [*charset*] - charset for db
-# [*host*] - host for assigning privileges to user
-# [*grant*] - array of privileges to grant to user
-# [*sql*] - sql to inject in db (always runs)
+# [*title*] - mysql database name.
+# [*user*] - username to create and grant access.
+# [*password*] - user's password.
+# [*charset*] - database charset.
+# [*host*] - host for assigning privileges to user.
+# [*grant*] - array of privileges to grant user.
+# [*enforce_sql*] - whether to enforce or conditionally run sql on creation.
+# [*sql*] - sql statement to run.
#
# Actions:
#
# Requires:
#
+# class mysql::server
+#
# Sample Usage:
-#
+#
# mysql::db { 'mydb':
# user => 'my_user',
# password => 'password',
@@ -28,15 +31,15 @@
define mysql::db (
$user,
$password,
- $charset = 'utf8',
- $host = 'localhost',
- $grant='all',
- $enforce_sql = false,
- $sql=''
+ $charset = 'utf8',
+ $host = 'localhost',
+ $grant = 'all',
+ $sql = '',
+ $enforce_sql = false
) {
if $grant == 'all' {
- $safe_grant = [ 'alter_priv','alter_routine_priv','create_priv','create_routine_priv','create_tmp_table_priv','create_view_priv','delete_priv','drop_priv','event_priv','execute_priv','grant_priv','index_priv','insert_priv','lock_tables_priv','references_priv','select_priv','show_view_priv','trigger_priv','update_priv']
+ $safe_grant = [ 'alter_priv', 'alter_routine_priv', 'create_priv', 'create_routine_priv', 'create_tmp_table_priv', 'create_view_priv', 'delete_priv', 'drop_priv', 'event_priv', 'execute_priv', 'grant_priv', 'index_priv', 'insert_priv', 'lock_tables_priv', 'references_priv', 'select_priv', 'show_view_priv', 'trigger_priv', 'update_priv']
} else {
$safe_grant = $grant
}
@@ -46,34 +49,29 @@
charset => $charset,
provider => 'mysql',
require => Class['mysql::server'],
- notify => $sql ? {
- '' => undef,
- default => Exec["${name}-import-import"],
- }
}
- database_user{"${user}@${host}":
+ database_user { "${user}@${host}":
ensure => present,
password_hash => mysql_password($password),
provider => 'mysql',
require => Database[$name],
}
- database_grant{"${user}@${host}/${name}":
- # privileges => [ 'alter_priv', 'insert_priv', 'select_priv', 'update_priv' ],
+ database_grant { "${user}@${host}/${name}":
privileges => $safe_grant,
provider => 'mysql',
require => Database_user["${user}@${host}"],
}
- if($sql) {
- exec{"${name}-import-import":
+ if $sql {
+ exec{ "${name}-import":
command => "/usr/bin/mysql -u ${user} -p${password} -h ${host} ${name} < ${sql}",
logoutput => true,
- refreshonly => $enforce_sql ? {
- true => false,
- false => true,
- },
+ refreshonly => ! $enforce_sql,
+ require => Database_grant["${user}@${host}/${name}"],
+ subscribe => Database[$name],
}
}
+
}
View
16 manifests/init.pp
@@ -1,20 +1,24 @@
# Class: mysql
#
-# this module installs mysql client software.
+# This class installs mysql client software.
#
# Parameters:
# [*client_package_name*] - The name of the mysql client package.
+#
# Actions:
#
# Requires:
#
# Sample Usage:
#
-class mysql(
- $client_package_name = $mysql::params::client_package_name
+class mysql (
+ $package_name = $mysql::params::client_package_name,
+ $package_ensure = 'present'
) inherits mysql::params {
- package {"mysql-client":
- name => $client_package_name,
- ensure => installed,
+
+ package { 'mysql_client':
+ name => $package_name,
+ ensure => $package_ensure,
}
+
}
View
35 manifests/params.pp
@@ -1,7 +1,6 @@
# Class: mysql::params
#
-# This class holds parameters that need to be
-# accessed by other classes.
+# The mysql configuration settings.
#
# Parameters:
#
@@ -11,17 +10,25 @@
#
# Sample Usage:
#
-class mysql::params{
- case $::operatingsystem {
- 'centos', 'redhat', 'fedora': {
- $service_name = 'mysqld'
- $client_package_name = 'mysql'
- $socket = '/var/lib/mysql/mysql.sock'
- $config_file = '/etc/my.cnf'
- $ruby_package_name = 'ruby-mysql'
- $python_package_name = 'MySQL-python'
+class mysql::params {
+
+ $bind_address = '127.0.0.1'
+ $port = 3306
+ $server_package_name = 'mysql-server'
+ $etc_root_password = false
+
+ case $::osfamily {
+ 'RedHat': {
+ $service_name = 'mysqld'
+ $client_package_name = 'mysql'
+ $socket = '/var/lib/mysql/mysql.sock'
+ $config_file = '/etc/my.cnf'
+ $ruby_package_name = 'ruby-mysql'
+ $ruby_package_provider = 'gem'
+ $python_package_name = 'MySQL-python'
}
- 'ubuntu', 'debian': {
+
+ 'Debian': {
$service_name = 'mysql'
$client_package_name = 'mysql-client'
$socket = '/var/run/mysqld/mysqld.sock'
@@ -29,8 +36,10 @@
$ruby_package_name = 'libmysql-ruby'
$python_package_name = 'python-mysqldb'
}
+
default: {
- fail("Unsupported operating system: ${::operatingsystem}. ${module_name} supports debian, ubuntu, redhat, centos, and fedora.")
+ fail("Unsupported operatingsystem: ${::operatingsystem}, module ${module_name} only support osfamily RedHat and Debian")
}
}
+
}
View
9 manifests/python.pp
@@ -14,12 +14,13 @@
# Sample Usage:
#
class mysql::python(
- $ensure = installed,
- $package_name = $mysql::params::python_package_name
+ $package_name = $mysql::params::python_package_name,
+ $package_ensure = 'present'
) inherits mysql::params {
package { 'python-mysqldb':
- name => $package_name,
- ensure => $ensure,
+ name => $package_name,
+ ensure => $package_ensure,
}
+
}
View
22 manifests/ruby.pp
@@ -13,22 +13,16 @@
#
# Sample Usage:
#
-class mysql::ruby(
- $ensure = installed,
- $package_name = $mysql::params::ruby_package_name,
- $package_provider = 'gem'
+class mysql::ruby (
+ $package_name = $mysql::params::ruby_package_name,
+ $package_provider = $mysql::params::ruby_package_provider,
+ $package_ensure = 'present'
) inherits mysql::params {
- # I am not making the mysql package a dep for this
- # the only dep is the package which yum will resolve for me.
- #case $operatingsystem {
- # 'debian', 'ubuntu' : {$ruby_mysql_name = 'libmysql-ruby'}
- # default: {$ruby_mysql_name = 'ruby-mysql'}
- #}
- package{'ruby-mysql':
- # name => $ruby_mysql_name,
- name => $package_name,
+ package{ 'ruby_mysql':
+ name => $package_name,
+ ensure => $package_ensure,
provider => $package_provider,
- ensure => $ensure,
}
+
}
View
51 manifests/server.pp
@@ -1,12 +1,12 @@
# Class: mysql::server
#
-# manages the installation of the mysql server.
-# manages the package, service, my.cnf
+# manages the installation of the mysql server. manages the package, service,
+# my.cnf
#
# Parameters:
-# [*config_hash*] - hash of config parameters that need to be set.
-# [*service_name*] - name of service
-# [*package_name*] - name of package
+# [*package_name*] - name of package
+# [*service_name*] - name of service
+# [*config_hash*] - hash of config parameters that need to be set.
#
# Actions:
#
@@ -14,40 +14,25 @@
#
# Sample Usage:
#
-class mysql::server(
- $service_name = $mysql::params::service_name,
- $config_hash = {},
- $package_name = 'mysql-server'
+class mysql::server (
+ $package_name = $mysql::params::server_package_name,
+ $package_ensure = 'present',
+ $service_name = $mysql::params::service_name,
+ $config_hash = {}
) inherits mysql::params {
- # automatically create a class to deal with
- # configuration
- $hash = {
- "mysql::config" => $config_hash
- }
- create_resources("class", $hash)
+ create_resources( 'class', {'mysql::config' => $config_hash} )
- package{'mysql-server':
+ package { 'mysql-server':
name => $package_name,
- ensure => present,
- notify => Service['mysqld'],
+ ensure => $package_ensure,
}
+
service { 'mysqld':
- name => $service_name,
- ensure => running,
- enable => true,
- }
- # this kind of sucks, that I have to specify a difference resource for restart.
- # the reason is that I need the service to be started before mods to the config
- # file which can cause a refresh
- exec{ 'mysqld-restart':
- command => "service ${service_name} restart",
- refreshonly => true,
- path => '/sbin/:/usr/sbin/',
- }
- File{
- owner => 'mysql',
- group => 'mysql',
+ name => $service_name,
+ ensure => running,
+ enable => true,
require => Package['mysql-server'],
}
+
}
View
17 manifests/server/monitor.pp
@@ -1,18 +1,19 @@
-
class mysql::server::monitor (
$mysql_monitor_username,
$mysql_monitor_password,
$mysql_monitor_hostname
) {
- database_user{
- "${mysql_monitor_username}@${mysql_monitor_hostname}":
- password_hash => mysql_password($mysql_monitor_password),
- ensure => present,
- require => Service['mysqld'],
+ class ['mysql::server'] -> class['mysql::monitor']
+
+ database_user{ "${mysql_monitor_username}@${mysql_monitor_hostname}":
+ password_hash => mysql_password($mysql_monitor_password),
+ ensure => present,
}
+
database_grant { "${mysql_monitor_username}@${mysql_monitor_hostname}":
- privileges => [ 'process_priv', 'super_priv' ],
- require => [ Mysql_user["${mysql_monitor_username}@${mysql_monitor_hostname}"], Service['mysqld']],
+ privileges => [ 'process_priv', 'super_priv' ],
+ require => Mysql_user["${mysql_monitor_username}@${mysql_monitor_hostname}"],
}
+
}
View
17 manifests/server/mysqltuner.pp
@@ -1,15 +1,16 @@
# Copyright 2009 Larry Ludwig (larrylud@gmail.com)
#
-# Licensed under the Apache License, Version 2.0 (the "License"); you
-# may not use this file except in compliance with the License. You
-# may obtain a copy of the License at
+# Licensed under the Apache License, Version 2.0 (the "License"); you may not
+# use this file except in compliance with the License. You may obtain a copy of
+# the License at:
#
# http://www.apache.org/licenses/LICENSE-2.0
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an "AS IS"
-# BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-# or implied. See the License for the specific language governing
-# permissions and limitations under the License.
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations under
+# the License.
#
class mysql::server::mysqltuner {
# mysql performance tester
View
3  spec/classes/mysql_init_spec.rb
@@ -1,6 +1,9 @@
require 'spec_helper'
describe 'mysql' do
+ let :facts do
+ { :osfamily => 'Debian'}
+ end
it { should contain_class 'mysql' }
end
View
8 spec/defines/mysql_db_spec.rb
@@ -13,18 +13,18 @@
should contain_database('test_db').without_notify
end
- it 'should notify exec to import sql if sql script is given' do
+ it 'should subscribe to database if sql script is given' do
params.merge!({'sql' => 'test_sql'})
- should contain_database('test_db').with_notify('Exec[test_db-import-import]')
+ should contain_exec('test_db-import').with_subscribe('Database[test_db]')
end
it 'should only import sql script on creation if not enforcing' do
params.merge!({'sql' => 'test_sql', 'enforce_sql' => false})
- should contain_exec('test_db-import-import').with_refreshonly(true)
+ should contain_exec('test_db-import').with_refreshonly(true)
end
it 'should import sql script on creation if enforcing' do
params.merge!({'sql' => 'test_sql', 'enforce_sql' => true})
- should contain_exec('test_db-import-import').with_refreshonly(false)
+ should contain_exec('test_db-import').with_refreshonly(false)
end
end
View
0  spec/fixtures/manifests/site.pp
No changes.
View
1  spec/fixtures/modules/mysql
View
13 spec/spec_helper.rb
@@ -1,7 +1,16 @@
require 'puppet'
-require 'rubygems'
+require 'rspec'
require 'rspec-puppet'
+def param_value(subject, type, title, param)
+ subject.resource(type, title).send(:parameters)[param.to_sym]
+end
+
RSpec.configure do |c|
- c.module_path = File.join(File.dirname(__FILE__), '../../')
+ c.module_path = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures/modules'))
+ # Using an empty site.pp file to avoid: https://github.com/rodjek/rspec-puppet/issues/15
+ c.manifest_dir = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures/manifests'))
+ # Use fixtures for config file mainly to support using our own hiera.yaml settings.
+ # Pending: https://github.com/rodjek/rspec-puppet/pull/21
+ # c.config = File.expand_path(File.join(File.dirname(__FILE__), 'fixtures/puppet.conf'))
end
View
30 spec/unit/mysql_password_spec.rb
@@ -0,0 +1,30 @@
+#!/usr/bin/env rspec
+require 'spec_helper'
+
+describe "the mysql_password function" do
+ before :all do
+ Puppet::Parser::Functions.autoloader.loadall
+ end
+
+ before :each do
+ @scope = Puppet::Parser::Scope.new
+ end
+
+ it "should exist" do
+ Puppet::Parser::Functions.function("mysql_password").should == "function_mysql_password"
+ end
+
+ it "should raise a ParseError if there is less than 1 arguments" do
+ lambda { @scope.function_mysql_password([]) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should raise a ParseError if there is more than 1 arguments" do
+ lambda { @scope.function_mysql_password(['foo', 'bar']) }.should( raise_error(Puppet::ParseError))
+ end
+
+ it "should convert password into a hash" do
+ result = @scope.function_mysql_password(["password"])
+ result.should(eq('*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'))
+ end
+
+end
View
6 templates/my.cnf.erb
@@ -1,12 +1,12 @@
[client]
port = <%= port %>
-socket = <%= scope.lookupvar('mysql::params::socket') %>
+socket = <%= socket %>
[mysqld_safe]
-socket = <%= scope.lookupvar('mysql::params::socket') %>
+socket = <%= socket %>
nice = 0
[mysqld]
user = mysql
-socket = <%= scope.lookupvar('mysql::params::socket') %>
+socket = <%= socket %>
port = <%= port %>
basedir = /usr
datadir = /var/lib/mysql
View
12 tests/mysql_database.pp
@@ -1,12 +1,12 @@
class { 'mysql::server':
config_hash => {'root_password' => 'password'}
}
-database{['test1', 'test2', 'test3']:
- ensure => present,
- charset => 'utf8',
+database{ ['test1', 'test2', 'test3']:
+ ensure => present,
+ charset => 'utf8',
require => Class['mysql::server'],
}
-database{'test4':
- ensure => present,
- charset => 'latin1',
+database{ 'test4':
+ ensure => present,
+ charset => 'latin1',
}
View
20 tests/mysql_user.pp
@@ -1,23 +1,23 @@
-$mysql_root_pw='password'
+$mysql_root_pw = 'password'
+
class { 'mysql::server':
config_hash => {
root_password => 'password',
}
}
-#database_user{['test1@localhost', 'test2@localhost', 'test3@localhost']:
-database_user{'redmine@localhost':
-# ensure => absent,
- ensure => present,
+
+database_user{ 'redmine@localhost':
+ ensure => present,
password_hash => mysql_password('redmine'),
- require => Class['mysql::server'],
+ require => Class['mysql::server'],
}
-database_user{'dan@localhost':
- ensure => present,
+database_user{ 'dan@localhost':
+ ensure => present,
password_hash => mysql_password('blah')
}
-database_user{'dan@%':
- ensure => present,
+database_user{ 'dan@%':
+ ensure => present,
password_hash => mysql_password('blah'),
}
View
5 tests/server.pp
@@ -1,6 +1,3 @@
class { 'mysql::server':
- config_hash => {
- 'root_password' => 'password',
- #'old_root_password' => 'puppet'
- }
+ config_hash => { 'root_password' => 'password', },
}
Please sign in to comment.
Something went wrong with that request. Please try again.