Skip to content

Commit 717244c

Browse files
committed
Add type & provider for managing plugins
1 parent 23c192d commit 717244c

File tree

7 files changed

+230
-0
lines changed

7 files changed

+230
-0
lines changed

README.md

+12
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,17 @@ mysql_grant { 'root@localhost/mysql.user':
565565
}
566566
```
567567

568+
####mysql_plugin
569+
570+
`mysql_plugin` can be used to load plugins into the MySQL Server.
571+
572+
```puppet
573+
mysql_plugin { 'auth_socket':
574+
ensure => 'present',
575+
soname => 'auth_socket.so',
576+
}
577+
```
578+
568579
##Limitations
569580

570581
This module has been tested on:
@@ -602,4 +613,5 @@ This module is based on work by David Schmitt. The following contributors have c
602613
* William Van Hevelingen
603614
* Michael Arnold
604615
* Chris Weyl
616+
* Daniël van Eeden
605617

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'mysql'))
2+
Puppet::Type.type(:mysql_plugin).provide(:mysql, :parent => Puppet::Provider::Mysql) do
3+
desc 'Manages MySQL plugins.'
4+
5+
commands :mysql => 'mysql'
6+
7+
def self.instances
8+
mysql([defaults_file, '-NBe', 'show plugins'].compact).split("\n").collect do |line|
9+
name, status, type, library, license = line.split(/\t/)
10+
new(:name => name,
11+
:ensure => :present,
12+
:soname => library
13+
)
14+
end
15+
end
16+
17+
# We iterate over each mysql_plugin entry in the catalog and compare it against
18+
# the contents of the property_hash generated by self.instances
19+
def self.prefetch(resources)
20+
plugins = instances
21+
resources.keys.each do |plugin|
22+
if provider = plugins.find { |pl| pl.name == plugin }
23+
resources[plugin].provider = provider
24+
end
25+
end
26+
end
27+
28+
def create
29+
# Use plugin_name.so as soname if it's not specified. This won't work on windows as
30+
# there it should be plugin_name.dll
31+
@resource[:soname].nil? ? (soname=@resource[:name] + '.so') : (soname=@resource[:soname])
32+
mysql([defaults_file, '-NBe', "install plugin #{@resource[:name]} soname '#{soname}'"].compact)
33+
34+
@property_hash[:ensure] = :present
35+
@property_hash[:soname] = @resource[:soname]
36+
37+
exists? ? (return true) : (return false)
38+
end
39+
40+
def destroy
41+
mysql([defaults_file, '-NBe', "uninstall plugin #{@resource[:name]}"].compact)
42+
43+
@property_hash.clear
44+
exists? ? (return false) : (return true)
45+
end
46+
47+
def exists?
48+
@property_hash[:ensure] == :present || false
49+
end
50+
51+
mk_resource_methods
52+
53+
end

lib/puppet/type/mysql_plugin.rb

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
Puppet::Type.newtype(:mysql_plugin) do
2+
@doc = 'Manage MySQL plugins.'
3+
4+
ensurable
5+
6+
autorequire(:file) { '/root/.my.cnf' }
7+
8+
newparam(:name, :namevar => true) do
9+
desc 'The name of the MySQL plugin to manage.'
10+
end
11+
12+
newproperty(:soname) do
13+
desc 'The name of the library'
14+
newvalue(/^\w+\.\w+$/)
15+
end
16+
17+
end
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
require 'spec_helper_acceptance'
2+
3+
describe 'mysql_plugin' do
4+
describe 'setup' do
5+
it 'should work with no errors' do
6+
pp = <<-EOS
7+
class { 'mysql::server': }
8+
EOS
9+
10+
apply_manifest(pp, :catch_failures => true)
11+
end
12+
end
13+
14+
describe 'load plugin' do
15+
it 'should work without errors' do
16+
pp = <<-EOS
17+
mysql_plugin { 'auth_socket':
18+
ensure => present,
19+
soname => 'auth_socket.so',
20+
}
21+
EOS
22+
23+
apply_manifest(pp, :catch_failures => true)
24+
end
25+
26+
it 'should find the plugin' do
27+
shell("mysql -NBe \"select plugin_name from information_schema.plugins where plugin_name='auth_socket'\"") do |r|
28+
expect(r.stdout).to match(/^auth_socket$/)
29+
expect(r.stderr).to be_empty
30+
end
31+
end
32+
end
33+
34+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
require 'spec_helper'
2+
3+
describe Puppet::Type.type(:mysql_plugin).provider(:mysql) do
4+
5+
let(:defaults_file) { '--defaults-extra-file=/root/.my.cnf' }
6+
7+
let(:resource) { Puppet::Type.type(:mysql_plugin).new(
8+
{ :ensure => :present,
9+
:soname => 'auth_socket.so',
10+
:name => 'auth_socket',
11+
:provider => described_class.name
12+
}
13+
)}
14+
let(:provider) { resource.provider }
15+
16+
before :each do
17+
Facter.stubs(:value).with(:root_home).returns('/root')
18+
Puppet::Util.stubs(:which).with('mysql').returns('/usr/bin/mysql')
19+
File.stubs(:file?).with('/root/.my.cnf').returns(true)
20+
provider.class.stubs(:mysql).with([defaults_file, '-NBe', 'show plugins']).returns('auth_socket ACTIVE AUTHENTICATION auth_socket.so GPL')
21+
end
22+
23+
let(:instance) { provider.class.instances.first }
24+
25+
describe 'self.prefetch' do
26+
it 'exists' do
27+
provider.class.instances
28+
provider.class.prefetch({})
29+
end
30+
end
31+
32+
describe 'create' do
33+
it 'loads a plugin' do
34+
provider.expects(:mysql).with([defaults_file, '-NBe', "install plugin #{resource[:name]} soname '#{resource[:soname]}'"])
35+
provider.expects(:exists?).returns(true)
36+
expect(provider.create).to be_truthy
37+
end
38+
end
39+
40+
describe 'destroy' do
41+
it 'unloads a plugin if present' do
42+
provider.expects(:mysql).with([defaults_file, '-NBe', "uninstall plugin #{resource[:name]}"])
43+
provider.expects(:exists?).returns(false)
44+
expect(provider.destroy).to be_truthy
45+
end
46+
end
47+
48+
describe 'exists?' do
49+
it 'checks if plugin exists' do
50+
expect(instance.exists?).to be_truthy
51+
end
52+
end
53+
54+
describe 'self.defaults_file' do
55+
it 'sets --defaults-extra-file' do
56+
File.stubs(:file?).with('/root/.my.cnf').returns(true)
57+
expect(provider.defaults_file).to eq '--defaults-extra-file=/root/.my.cnf'
58+
end
59+
it 'fails if file missing' do
60+
File.stubs(:file?).with('/root/.my.cnf').returns(false)
61+
expect(provider.defaults_file).to be_nil
62+
end
63+
end
64+
65+
describe 'soname' do
66+
it 'returns a soname' do
67+
expect(instance.soname).to eq('auth_socket.so')
68+
end
69+
end
70+
71+
end
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require 'puppet'
2+
require 'puppet/type/mysql_plugin'
3+
describe Puppet::Type.type(:mysql_plugin) do
4+
5+
before :each do
6+
@plugin = Puppet::Type.type(:mysql_plugin).new(:name => 'test', :soname => 'test.so')
7+
end
8+
9+
it 'should accept a plugin name' do
10+
expect(@plugin[:name]).to eq('test')
11+
end
12+
13+
it 'should accept a library name' do
14+
@plugin[:soname] = 'test.so'
15+
expect(@plugin[:soname]).to eq('test.so')
16+
end
17+
18+
it 'should require a name' do
19+
expect {
20+
Puppet::Type.type(:mysql_plugin).new({})
21+
}.to raise_error(Puppet::Error, 'Title or name must be provided')
22+
end
23+
24+
end

tests/mysql_plugin.pp

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class { 'mysql::server':
2+
root_password => 'password'
3+
}
4+
5+
mysql::plugin{ 'validate_password':
6+
ensure => present,
7+
soname => $::osfamily ? {
8+
windows => 'validate_password.dll',
9+
default => 'validate_password.so'
10+
}
11+
}
12+
13+
mysql::plugin{ 'auth_socket':
14+
ensure => present,
15+
soname => $::osfamily ? {
16+
windows => 'auth_socket.dll',
17+
default => 'auth_socket.so'
18+
}
19+
}

0 commit comments

Comments
 (0)