Skip to content

Commit

Permalink
(MODULES-552) Add capability to specify column_privileges
Browse files Browse the repository at this point in the history
  • Loading branch information
fnerdwq committed Oct 6, 2014
1 parent fbef97d commit f88719b
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 9 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,16 @@ mysql_grant { 'root@localhost/*.*':
}
```

It is possible to specify privileges down to the column level:
```puppet
mysql_grant { 'root@localhost/mysql.user':
ensure => 'present',
privileges => ['SELECT (Host, User)'],
table => 'mysql.user',
user => 'root@localhost',
}
```

##Limitations

This module has been tested on:
Expand Down
17 changes: 13 additions & 4 deletions lib/puppet/provider/mysql_grant/mysql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,19 @@ def self.instances
# Matching: GRANT (SELECT, UPDATE) PRIVILEGES ON (*.*) TO ('root')@('127.0.0.1') (WITH GRANT OPTION)
if match = munged_grant.match(/^GRANT\s(.+)\sON\s(.+)\sTO\s(.*)@(.*?)(\s.*)$/)
privileges, table, user, host, rest = match.captures
# Once we split privileges up on the , we need to make sure we
# shortern ALL PRIVILEGES to just all.
stripped_privileges = privileges.split(',').map do |priv|
priv == 'ALL PRIVILEGES' ? 'ALL' : priv.lstrip.rstrip
# split on ',' if it is not a non-'('-containing string followed by a
# closing parenthesis ')'-char - e.g. only split comma separated elements not in
# parentheses
stripped_privileges = privileges.strip.split(/\s*,\s*(?![^(]*\))/).map do |priv|
# split and sort the column_privileges in the parentheses and rejoin
if priv.include?('(')
type, col=priv.strip.split(/\s+|\b/,2)
type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")"
else
# Once we split privileges up on the , we need to make sure we
# shortern ALL PRIVILEGES to just all.
priv == 'ALL PRIVILEGES' ? 'ALL' : priv.strip
end
end
# Same here, but to remove OPTION leaving just GRANT.
options = ['GRANT'] if rest.match(/WITH\sGRANT\sOPTION/)
Expand Down
14 changes: 9 additions & 5 deletions lib/puppet/type/mysql_grant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,15 @@ def initialize(*args)
# Sort the privileges array in order to ensure the comparision in the provider
# self.instances method match. Otherwise this causes it to keep resetting the
# privileges.
self[:privileges] = Array(self[:privileges]).map(&:upcase).uniq.reject{|k| k == 'GRANT' or k == 'GRANT OPTION'}.sort!
self[:privileges] = Array(self[:privileges]).map{ |priv|
# split and sort the column_privileges in the parentheses and rejoin
if priv.include?('(')
type, col=priv.strip.split(/\s+|\b/,2)
type.upcase + " (" + col.slice(1...-1).strip.split(/\s*,\s*/).sort.join(', ') + ")"
else
priv.strip.upcase
end
}.uniq.reject{|k| k == 'GRANT' or k == 'GRANT OPTION'}.sort!
end

validate do
Expand All @@ -37,10 +45,6 @@ def initialize(*args)

newproperty(:privileges, :array_matching => :all) do
desc 'Privileges for user'

munge do |value|
value.upcase
end
end

newproperty(:table) do
Expand Down
24 changes: 24 additions & 0 deletions spec/unit/puppet/type/mysql_grant_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,28 @@
}.to raise_error /name must match user and table parameters/
end

describe 'it should munge privileges' do

it 'to just ALL' do
@user = Puppet::Type.type(:mysql_grant).new(
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
:privileges => ['ALL', 'PROXY'] )
expect(@user[:privileges]).to eq(['ALL'])
end

it 'to upcase and ordered' do
@user = Puppet::Type.type(:mysql_grant).new(
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
:privileges => ['select', 'Insert'] )
expect(@user[:privileges]).to eq(['INSERT', 'SELECT'])
end

it 'ordered including column privileges' do
@user = Puppet::Type.type(:mysql_grant).new(
:name => 'foo@localhost/*.*', :table => ['*.*','@'], :user => 'foo@localhost',
:privileges => ['SELECT(Host,Address)', 'Insert'] )
expect(@user[:privileges]).to eq(['INSERT', 'SELECT (Address, Host)'])
end
end

end

0 comments on commit f88719b

Please sign in to comment.