diff --git a/manifests/client.pp b/manifests/client.pp index 58cd04f..f8242df 100644 --- a/manifests/client.pp +++ b/manifests/client.pp @@ -1,47 +1,53 @@ # @summary # Installs and configures the MySQL client. # # @example Install the MySQL client # class {'::mysql::client': # package_name => 'mysql-client', # package_ensure => 'present', # bindings_enable => true, # } # # @param bindings_enable # Whether to automatically install all bindings. Valid values are `true`, `false`. Default to `false`. # @param install_options # Array of install options for managed package resources. You must pass the appropriate options for the package manager. # @param package_ensure # Whether the MySQL package should be present, absent, or a specific version. Valid values are 'present', 'absent', or 'x.y.z'. # @param package_manage # Whether to manage the MySQL client package. Defaults to `true`. +# @param service_name +# The name of the MySQL server service. Defaults are OS dependent, defined in 'params.pp'. +# @param service_provider +# The provider to use to manage the service. For Ubuntu, defaults to 'upstart'; otherwise, default is undefined. # @param package_name # The name of the MySQL client package to install. # class mysql::client ( - $bindings_enable = $mysql::params::bindings_enable, - $install_options = undef, - $package_ensure = $mysql::params::client_package_ensure, - $package_manage = $mysql::params::client_package_manage, - $package_name = $mysql::params::client_package_name, + $bindings_enable = $mysql::params::bindings_enable, + $install_options = undef, + $package_ensure = $mysql::params::client_package_ensure, + $package_manage = $mysql::params::client_package_manage, + $package_name = $mysql::params::client_package_name, + $package_provider = undef, + $package_source = undef, ) inherits mysql::params { include '::mysql::client::install' if $bindings_enable { class { 'mysql::bindings': java_enable => true, perl_enable => true, php_enable => true, python_enable => true, ruby_enable => true, } } # Anchor pattern workaround to avoid resources of mysql::client::install to # "float off" outside mysql::client anchor { 'mysql::client::start': } -> Class['mysql::client::install'] -> anchor { 'mysql::client::end': } } diff --git a/manifests/client/install.pp b/manifests/client/install.pp index 9e5f98e..91f537f 100644 --- a/manifests/client/install.pp +++ b/manifests/client/install.pp @@ -1,18 +1,20 @@ # @summary # Private class for MySQL client install. # # @api private # class mysql::client::install { if $mysql::client::package_manage { package { 'mysql_client': ensure => $mysql::client::package_ensure, install_options => $mysql::client::install_options, name => $mysql::client::package_name, + provider => $mysql::client::package_provider, + source => $mysql::client::package_source, } } } diff --git a/manifests/server.pp b/manifests/server.pp index 991e194..224cbd7 100644 --- a/manifests/server.pp +++ b/manifests/server.pp @@ -1,176 +1,182 @@ # @summary # Installs and configures the MySQL server. # # @example Install MySQL Server # class { '::mysql::server': # package_name => 'mysql-server', # package_ensure => '5.7.1+mysql~trusty', # root_password => 'strongpassword', # remove_default_accounts => true, # } # # @param config_file # The location, as a path, of the MySQL configuration file. # @param config_file_mode # The MySQL configuration file's permissions mode. # @param includedir # The location, as a path, of !includedir for custom configuration overrides. # @param install_options # Passes [install_options](https://docs.puppetlabs.com/references/latest/type.html#package-attribute-install_options) array to managed package resources. You must pass the appropriate options for the specified package manager # @param install_secret_file # Path to secret file containing temporary root password. # @param manage_config_file # Whether the MySQL configuration file should be managed. Valid values are `true`, `false`. Defaults to `true`. # @param options # A hash of options structured like the override_options, but not merged with the default options. Use this if you don't want your options merged with the default options. # @param override_options # Specifies override options to pass into MySQL. Structured like a hash in the my.cnf file: See above for usage details. # @param package_ensure # Whether the package exists or should be a specific version. Valid values are 'present', 'absent', or 'x.y.z'. Defaults to 'present'. # @param package_manage # Whether to manage the MySQL server package. Defaults to `true`. # @param package_name # The name of the MySQL server package to install. +# @param package_provider +# Define a specific provider for package install. +# @param package_source +# The location of the package source (require for some package provider) # @param purge_conf_dir # Whether the `includedir` directory should be purged. Valid values are `true`, `false`. Defaults to `false`. # @param remove_default_accounts # Specifies whether to automatically include `mysql::server::account_security`. Valid values are `true`, `false`. Defaults to `false`. # @param restart # Whether the service should be restarted when things change. Valid values are `true`, `false`. Defaults to `false`. # @param root_group # The name of the group used for root. Can be a group name or a group ID. See more about the [group](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-group). # @param mysql_group # The name of the group of the MySQL daemon user. Can be a group name or a group ID. See more about the [group](https://docs.puppetlabs.com/references/latest/type.html#file-attribute-group). # @param mycnf_owner # Name or user-id who owns the mysql-config-file. # @param mycnf_group # Name or group-id which owns the mysql-config-file. # @param root_password # The MySQL root password. Puppet attempts to set the root password and update `/root/.my.cnf` with it. This is required if `create_root_user` or `create_root_my_cnf` are true. If `root_password` is 'UNSET', then `create_root_user` and `create_root_my_cnf` are assumed to be false --- that is, the MySQL root user and `/root/.my.cnf` are not created. Password changes are supported; however, the old password must be set in `/root/.my.cnf`. Effectively, Puppet uses the old password, configured in `/root/my.cnf`, to set the new password in MySQL, and then updates `/root/.my.cnf` with the new password. # @param service_enabled # Specifies whether the service should be enabled. Valid values are `true`, `false`. Defaults to `true`. # @param service_manage # Specifies whether the service should be managed. Valid values are `true`, `false`. Defaults to `true`. # @param service_name # The name of the MySQL server service. Defaults are OS dependent, defined in 'params.pp'. # @param service_provider # The provider to use to manage the service. For Ubuntu, defaults to 'upstart'; otherwise, default is undefined. # @param create_root_user # Whether root user should be created. Valid values are `true`, `false`. Defaults to `true`. This is useful for a cluster setup with Galera. The root user has to be created only once. You can set this parameter true on one node and set it to false on the remaining nodes. # @param create_root_my_cnf # Whether to create `/root/.my.cnf`. Valid values are `true`, `false`. Defaults to `true`. `create_root_my_cnf` allows creation of `/root/.my.cnf` independently of `create_root_user`. You can use this for a cluster setup with Galera where you want `/root/.my.cnf` to exist on all nodes. # @param users # Optional hash of users to create, which are passed to [mysql_user](#mysql_user). # @param grants # Optional hash of grants, which are passed to [mysql_grant](#mysql_grant). # @param databases # Optional hash of databases to create, which are passed to [mysql_database](#mysql_database). # @param enabled # _Deprecated_ # @param manage_service # _Deprecated_ # @param old_root_password # This parameter no longer does anything. It exists only for backwards compatibility. See the `root_password` parameter above for details on changing the root password. # class mysql::server ( $config_file = $mysql::params::config_file, $config_file_mode = $mysql::params::config_file_mode, $includedir = $mysql::params::includedir, $install_options = undef, $install_secret_file = $mysql::params::install_secret_file, $manage_config_file = $mysql::params::manage_config_file, Mysql::Options $options = {}, $override_options = {}, $package_ensure = $mysql::params::server_package_ensure, $package_manage = $mysql::params::server_package_manage, $package_name = $mysql::params::server_package_name, + $package_provider = undef, + $package_source = undef, $purge_conf_dir = $mysql::params::purge_conf_dir, $remove_default_accounts = false, $restart = $mysql::params::restart, $root_group = $mysql::params::root_group, $managed_dirs = $mysql::params::managed_dirs, $mysql_group = $mysql::params::mysql_group, $mycnf_owner = $mysql::params::mycnf_owner, $mycnf_group = $mysql::params::mycnf_group, $root_password = $mysql::params::root_password, $service_enabled = $mysql::params::server_service_enabled, $service_manage = $mysql::params::server_service_manage, $service_name = $mysql::params::server_service_name, $service_provider = $mysql::params::server_service_provider, $create_root_user = $mysql::params::create_root_user, $create_root_my_cnf = $mysql::params::create_root_my_cnf, $create_root_login_file = $mysql::params::create_root_login_file, $login_file = $mysql::params::login_file, $users = {}, $grants = {}, $databases = {}, # Deprecated parameters $enabled = undef, $manage_service = undef, $old_root_password = undef ) inherits mysql::params { # Deprecated parameters. if $enabled { crit('This parameter has been renamed to service_enabled.') $real_service_enabled = $enabled } else { $real_service_enabled = $service_enabled } if $manage_service { crit('This parameter has been renamed to service_manage.') $real_service_manage = $manage_service } else { $real_service_manage = $service_manage } if $old_root_password { warning(translate('The `old_root_password` attribute is no longer used and will be removed in a future release.')) } if ! empty($options) and ! empty($override_options) { fail(translate('You can\'t specify $options and $override_options simultaneously, see the README section \'Customize server options\'!')) } # If override_options are set, create a merged together set of options. Rightmost hashes win over left. # If options are set, just use them. $_options = empty($options) ? { true => mysql::normalise_and_deepmerge($mysql::params::default_options, $override_options), false => $options, } Class['mysql::server::root_password'] -> Mysql::Db <| |> include '::mysql::server::config' include '::mysql::server::install' include '::mysql::server::managed_dirs' include '::mysql::server::installdb' include '::mysql::server::service' include '::mysql::server::root_password' include '::mysql::server::providers' if $remove_default_accounts { class { '::mysql::server::account_security': require => Anchor['mysql::server::end'], } } anchor { 'mysql::server::start': } anchor { 'mysql::server::end': } if $restart { Class['mysql::server::config'] ~> Class['mysql::server::service'] } Anchor['mysql::server::start'] -> Class['mysql::server::config'] -> Class['mysql::server::install'] -> Class['mysql::server::managed_dirs'] -> Class['mysql::server::installdb'] -> Class['mysql::server::service'] -> Class['mysql::server::root_password'] -> Class['mysql::server::providers'] -> Anchor['mysql::server::end'] } diff --git a/manifests/server/install.pp b/manifests/server/install.pp index 21c762e..9e81031 100644 --- a/manifests/server/install.pp +++ b/manifests/server/install.pp @@ -1,17 +1,19 @@ -# @summary +# @summary # Private class for managing MySQL package. # # @api private # class mysql::server::install { if $mysql::server::package_manage { package { 'mysql-server': ensure => $mysql::server::package_ensure, install_options => $mysql::server::install_options, name => $mysql::server::package_name, + provider => $mysql::server::package_provider, + source => $mysql::server::package_source, } } } diff --git a/spec/classes/mysql_client_spec.rb b/spec/classes/mysql_client_spec.rb index 6c651dc..b44b3a2 100644 --- a/spec/classes/mysql_client_spec.rb +++ b/spec/classes/mysql_client_spec.rb @@ -1,35 +1,51 @@ require 'spec_helper' describe 'mysql::client' do on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) do facts.merge(root_home: '/root') end context 'with defaults' do it { is_expected.not_to contain_class('mysql::bindings') } it { is_expected.to contain_package('mysql_client') } end context 'with bindings enabled' do let(:params) { { bindings_enable: true } } it { is_expected.to contain_class('mysql::bindings') } it { is_expected.to contain_package('mysql_client') } end context 'with package_manage set to true' do let(:params) { { package_manage: true } } it { is_expected.to contain_package('mysql_client') } end context 'with package_manage set to false' do let(:params) { { package_manage: false } } it { is_expected.not_to contain_package('mysql_client') } end + + context 'with package provider' do + let(:params) do + { + package_provider: 'dpkg', + package_source: '/somewhere', + } + end + + it do + is_expected.to contain_package('mysql_client').with( + provider: 'dpkg', + source: '/somewhere', + ) + end + end end end end diff --git a/spec/classes/mysql_server_spec.rb b/spec/classes/mysql_server_spec.rb index 771c505..066140b 100644 --- a/spec/classes/mysql_server_spec.rb +++ b/spec/classes/mysql_server_spec.rb @@ -1,281 +1,296 @@ require 'spec_helper' describe 'mysql::server' do on_supported_os.each do |os, facts| context "on #{os}" do let(:facts) do facts.merge(root_home: '/root') end context 'with defaults' do it { is_expected.to contain_class('mysql::server::install') } it { is_expected.to contain_class('mysql::server::config') } it { is_expected.to contain_class('mysql::server::service') } it { is_expected.to contain_class('mysql::server::root_password') } it { is_expected.to contain_class('mysql::server::providers') } end context 'with remove_default_accounts set' do let(:params) { { remove_default_accounts: true } } it { is_expected.to contain_class('mysql::server::account_security') } end context 'when not managing config file' do let(:params) { { manage_config_file: false } } it { is_expected.to compile.with_all_deps } end context 'when not managing the service' do let(:params) { { service_manage: false } } it { is_expected.to compile.with_all_deps } it { is_expected.not_to contain_service('mysqld') } end context 'configuration options' do context 'when specifying both $override_options and $options' do let(:params) do { override_options: { 'mysqld' => { 'datadir' => '/tmp' } }, options: { 'mysqld' => { 'max_allowed_packet' => '12M' } }, } end it { is_expected.to compile.and_raise_error(%r{You can't specify \$options and \$override_options simultaneously, see the README section 'Customize server options'!}) } end context 'when specifying $options' do let(:params) do { options: { 'mysqld' => { 'datadir' => '/tmp' } }, } end it { is_expected.to compile.with_all_deps } it { is_expected.to contain_mysql_datadir('/tmp') } it { is_expected.not_to contain_mysql_bind_addr('127.0.0.1') } end end context 'mysql::server::install' do it 'contains the package by default' do is_expected.to contain_package('mysql-server').with(ensure: :present) end context 'with package_manage set to true' do let(:params) { { package_manage: true } } it { is_expected.to contain_package('mysql-server') } end context 'with package_manage set to false' do let(:params) { { package_manage: false } } it { is_expected.not_to contain_package('mysql-server') } end context 'with datadir overridden' do let(:params) { { override_options: { 'mysqld' => { 'datadir' => '/tmp' } } } } it { is_expected.to contain_mysql_datadir('/tmp') } end + context 'with package provider' do + let(:params) do + { + package_provider: 'dpkg', + package_source: '/somewhere', + } + end + + it do + is_expected.to contain_package('mysql-server').with( + provider: 'dpkg', + source: '/somewhere', + ) + end + end end context 'mysql::server::service' do context 'with defaults' do it { is_expected.to contain_service('mysqld') } end context 'with package_manage set to true' do let(:params) { { package_manage: true } } it { is_expected.to contain_service('mysqld').that_requires('Package[mysql-server]') } end context 'with package_manage set to false' do let(:params) { { package_manage: false } } it { is_expected.to contain_service('mysqld') } it { is_expected.not_to contain_service('mysqld').that_requires('Package[mysql-server]') } end context 'service_enabled set to false' do let(:params) { { service_enabled: false } } it do is_expected.to contain_service('mysqld').with(ensure: :stopped) end context 'with package_manage set to true' do let(:params) { { package_manage: true } } it { is_expected.to contain_package('mysql-server') } end context 'with package_manage set to false' do let(:params) { { package_manage: false } } it { is_expected.not_to contain_package('mysql-server') } end context 'with datadir overridden' do let(:params) { { override_options: { 'mysqld' => { 'datadir' => '/tmp' } } } } it { is_expected.to contain_mysql_datadir('/tmp') } end end context 'with log-error overridden' do let(:params) { { override_options: { 'mysqld' => { 'log-error' => '/tmp/error.log' } } } } it { is_expected.to contain_file('/tmp/error.log') } end context 'default bind-address' do it { is_expected.to contain_file('mysql-config-file').with_content(%r{^bind-address = 127.0.0.1}) } end context 'with defined bind-address' do let(:params) { { override_options: { 'mysqld' => { 'bind-address' => '1.1.1.1' } } } } it { is_expected.to contain_file('mysql-config-file').with_content(%r{^bind-address = 1.1.1.1}) } end context 'without bind-address' do let(:params) { { override_options: { 'mysqld' => { 'bind-address' => :undef } } } } it { is_expected.to contain_file('mysql-config-file').without_content(%r{^bind-address}) } end end context 'mysql::server::root_password' do describe 'when defaults' do it { is_expected.to contain_exec('remove install pass').with( command: 'mysqladmin -u root --password=$(grep -o \'[^ ]\\+$\' /.mysql_secret) password \'\' && rm -f /.mysql_secret', onlyif: 'test -f /.mysql_secret', path: '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin', ) } it { is_expected.not_to contain_mysql_user('root@localhost') } it { is_expected.not_to contain_file('/root/.my.cnf') } end describe 'when root_password set' do let(:params) { { root_password: 'SET' } } it { is_expected.to contain_mysql_user('root@localhost') } if Puppet.version.to_f >= 3.0 it { is_expected.to contain_file('/root/.my.cnf').with(show_diff: false).that_requires('Mysql_user[root@localhost]') } else it { is_expected.to contain_file('/root/.my.cnf').that_requires('Mysql_user[root@localhost]') } end end describe 'when root_password set, create_root_user set to false' do let(:params) { { root_password: 'SET', create_root_user: false } } it { is_expected.not_to contain_mysql_user('root@localhost') } if Puppet.version.to_f >= 3.0 it { is_expected.to contain_file('/root/.my.cnf').with(show_diff: false) } else it { is_expected.to contain_file('/root/.my.cnf') } end end describe 'when root_password set, create_root_my_cnf set to false' do let(:params) { { root_password: 'SET', create_root_my_cnf: false } } it { is_expected.to contain_mysql_user('root@localhost') } it { is_expected.not_to contain_file('/root/.my.cnf') } end describe 'when root_password set, create_root_user and create_root_my_cnf set to false' do let(:params) { { root_password: 'SET', create_root_user: false, create_root_my_cnf: false } } it { is_expected.not_to contain_mysql_user('root@localhost') } it { is_expected.not_to contain_file('/root/.my.cnf') } end describe 'when install_secret_file set to /root/.mysql_secret' do let(:params) { { install_secret_file: '/root/.mysql_secret' } } it { is_expected.to contain_exec('remove install pass').with( command: 'mysqladmin -u root --password=$(grep -o \'[^ ]\\+$\' /root/.mysql_secret) password \'\' && rm -f /root/.mysql_secret', onlyif: 'test -f /root/.mysql_secret', ) } end end context 'mysql::server::providers' do describe 'with users' do let(:params) do { users: { 'foo@localhost' => { 'max_connections_per_hour' => '1', 'max_queries_per_hour' => '2', 'max_updates_per_hour' => '3', 'max_user_connections' => '4', 'password_hash' => '*F3A2A51A9B0F2BE2468926B4132313728C250DBF', }, 'foo2@localhost' => {}, } } end it { is_expected.to contain_mysql_user('foo@localhost').with( max_connections_per_hour: '1', max_queries_per_hour: '2', max_updates_per_hour: '3', max_user_connections: '4', password_hash: '*F3A2A51A9B0F2BE2468926B4132313728C250DBF' ) } it { is_expected.to contain_mysql_user('foo2@localhost').with( max_connections_per_hour: nil, max_queries_per_hour: nil, max_updates_per_hour: nil, max_user_connections: nil, password_hash: nil ) } end describe 'with grants' do let(:params) do { grants: { 'foo@localhost/somedb.*' => { 'user' => 'foo@localhost', 'table' => 'somedb.*', 'privileges' => ['SELECT', 'UPDATE'], 'options' => ['GRANT'], }, 'foo2@localhost/*.*' => { 'user' => 'foo2@localhost', 'table' => '*.*', 'privileges' => ['SELECT'], }, } } end it { is_expected.to contain_mysql_grant('foo@localhost/somedb.*').with( user: 'foo@localhost', table: 'somedb.*', privileges: ['SELECT', 'UPDATE'], options: ['GRANT'] ) } it { is_expected.to contain_mysql_grant('foo2@localhost/*.*').with( user: 'foo2@localhost', table: '*.*', privileges: ['SELECT'], options: nil ) } end describe 'with databases' do let(:params) do { databases: { 'somedb' => { 'charset' => 'latin1', 'collate' => 'latin1', }, 'somedb2' => {}, } } end it { is_expected.to contain_mysql_database('somedb').with( charset: 'latin1', collate: 'latin1', ) } it { is_expected.to contain_mysql_database('somedb2') } end end end end # rubocop:enable RSpec/NestedGroups end