From f88719b52fbe35c2c192c9224c82c0f823f8e289 Mon Sep 17 00:00:00 2001 From: Frederik Wagner Date: Mon, 15 Sep 2014 18:11:46 +0200 Subject: [PATCH] (MODULES-552) Add capability to specify column_privileges --- README.md | 10 ++++++++++ lib/puppet/provider/mysql_grant/mysql.rb | 17 ++++++++++++---- lib/puppet/type/mysql_grant.rb | 14 ++++++++----- spec/unit/puppet/type/mysql_grant_spec.rb | 24 +++++++++++++++++++++++ 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9f1bf5777..b52595a39 100644 --- a/README.md +++ b/README.md @@ -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: diff --git a/lib/puppet/provider/mysql_grant/mysql.rb b/lib/puppet/provider/mysql_grant/mysql.rb index 3fe691d56..539a3e63d 100644 --- a/lib/puppet/provider/mysql_grant/mysql.rb +++ b/lib/puppet/provider/mysql_grant/mysql.rb @@ -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/) diff --git a/lib/puppet/type/mysql_grant.rb b/lib/puppet/type/mysql_grant.rb index a268e4cb5..8262e1e53 100644 --- a/lib/puppet/type/mysql_grant.rb +++ b/lib/puppet/type/mysql_grant.rb @@ -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 @@ -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 diff --git a/spec/unit/puppet/type/mysql_grant_spec.rb b/spec/unit/puppet/type/mysql_grant_spec.rb index 73e0e954a..9b33058bc 100644 --- a/spec/unit/puppet/type/mysql_grant_spec.rb +++ b/spec/unit/puppet/type/mysql_grant_spec.rb @@ -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