Skip to content
This repository has been archived by the owner on May 31, 2024. It is now read-only.

Add ability to ignore unlisted users #11

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 28 additions & 26 deletions bin/gratan
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,38 @@ mysql_options = {
}

options = {
:dry_run => false,
:color => true,
:debug => false,
:dry_run => false,
:color => true,
:debug => false,
:ignore_unlisted_users => false,
}

ARGV.options do |opt|
begin
opt.on('' , '--host HOST') {|v| mysql_options[:host] = v }
opt.on('' , '--port PORT', Integer) {|v| mysql_options[:port] = v }
opt.on('' , '--socket SOCKET') {|v| mysql_options[:socket] = v }
opt.on('' , '--username USERNAME') {|v| mysql_options[:username] = v }
opt.on('' , '--password PASSWORD') {|v| mysql_options[:password] = v }
opt.on('' , '--database DATABASE') {|v| mysql_options[:database] = v }
opt.on('-a', '--apply') { mode = :apply }
opt.on('-f', '--file FILE') {|v| file = v }
opt.on('' , '--dry-run') { options[:dry_run] = true }
opt.on('-e', '--export') { mode = :export }
opt.on('' , '--with-identifier') { options[:with_identifier] = true }
opt.on('' , '--split') { split = true }
opt.on('' , '--chunk-by-user') { options[:chunk_by_user] = true }
opt.on('-o', '--output FILE') {|v| output_file = v }
opt.on('' , '--ignore-user REGEXP') {|v| options[:ignore_user] = Regexp.new(v) }
opt.on('' , '--target-user REGEXP') {|v| options[:target_user] = Regexp.new(v) }
opt.on('' , '--ignore-object REGEXP') {|v| options[:ignore_object] = Regexp.new(v) }
opt.on('' , '--enable-expired') { options[:enable_expired] = true }
opt.on('' , '--ignore-not-exist') {|v| options[:ignore_not_exist] = true }
opt.on('' , '--no-color') { options[:color] = false }
opt.on('' , '--debug') { options[:debug] = true }
opt.on('' , '--auto-identify OUTPUT') {|v| options[:identifier] = Gratan::Identifier::Auto.new(v, options) }
opt.on('' , '--csv-identify CSV') {|v| options[:identifier] = Gratan::Identifier::CSV.new(v, options) }
opt.on('' , '--host HOST') {|v| mysql_options[:host] = v }
opt.on('' , '--port PORT', Integer) {|v| mysql_options[:port] = v }
opt.on('' , '--socket SOCKET') {|v| mysql_options[:socket] = v }
opt.on('' , '--username USERNAME') {|v| mysql_options[:username] = v }
opt.on('' , '--password PASSWORD') {|v| mysql_options[:password] = v }
opt.on('' , '--database DATABASE') {|v| mysql_options[:database] = v }
opt.on('-a', '--apply') { mode = :apply }
opt.on('-f', '--file FILE') {|v| file = v }
opt.on('' , '--dry-run') { options[:dry_run] = true }
opt.on('-e', '--export') { mode = :export }
opt.on('' , '--with-identifier') { options[:with_identifier] = true }
opt.on('' , '--split') { split = true }
opt.on('' , '--chunk-by-user') { options[:chunk_by_user] = true }
opt.on('-o', '--output FILE') {|v| output_file = v }
opt.on('' , '--ignore-user REGEXP') {|v| options[:ignore_user] = Regexp.new(v) }
opt.on('' , '--target-user REGEXP') {|v| options[:target_user] = Regexp.new(v) }
opt.on('' , '--ignore-object REGEXP') {|v| options[:ignore_object] = Regexp.new(v) }
opt.on('' , '--enable-expired') { options[:enable_expired] = true }
opt.on('' , '--ignore-not-exist') { options[:ignore_not_exist] = true }
opt.on('' , '--ignore-unlisted-users') { options[:ignore_unlisted_users] = true }
opt.on('' , '--no-color') { options[:color] = false }
opt.on('' , '--debug') { options[:debug] = true }
opt.on('' , '--auto-identify OUTPUT') {|v| options[:identifier] = Gratan::Identifier::Auto.new(v, options) }
opt.on('' , '--csv-identify CSV') {|v| options[:identifier] = Gratan::Identifier::CSV.new(v, options) }

opt.on('-h', '--help') do
puts opt.help
Expand Down
18 changes: 11 additions & 7 deletions lib/gratan/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,25 @@ def walk(file, options)

actual_attrs = actual.delete(user_host)

if actual_attrs
if expected_attrs == :dropped
drop_user(*user_host) if actual_attrs
elsif actual_attrs
walk_user(*user_host, expected_attrs, actual_attrs)
else
create_user(*user_host, expected_attrs)
end
end

actual.each do |user_host, attrs|
next if user_host[0] =~ options[:ignore_user]
unless options[:ignore_unlisted_users]
actual.each do |user_host, attrs|
next if user_host[0] =~ options[:ignore_user]

if options[:target_user]
next unless user_host[0] =~ options[:target_user]
end
if options[:target_user]
next unless user_host[0] =~ options[:target_user]
end

drop_user(*user_host)
drop_user(*user_host)
end
end
end

Expand Down
17 changes: 13 additions & 4 deletions lib/gratan/dsl/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,22 +35,31 @@ def user(name, host_or_array, options = {}, &block)
name = name.to_s
hosts = [host_or_array].flatten.map {|i| i.to_s }

expired = options.delete(:expired)
expired = Time.parse(expired) if expired

dropped = options.delete(:dropped)

hosts.each do |host|
options ||= {}

__validate("User `#{name}@#{host}` is already defined") do
not @result.has_key?([name, host])
end

if @options[:enable_expired] and (expired = options.delete(:expired))
expired = Time.parse(expired)

if @options[:enable_expired] and expired
if Time.new >= expired
log(:warn, "User `#{name}@#{host}` has expired", :color => :yellow)
return
@result[[name, host]] = :dropped
next
end
end

if dropped
@result[[name, host]] = :dropped
next
end

@result[[name, host]] = {
:objects => Gratan::DSL::Context::User.new(name, host, @options, &block).result,
:options => options,
Expand Down
8 changes: 8 additions & 0 deletions spec/drop/drop_user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
grant 'ALL PRIVILEGES'
end
end

user 'jimbob', ['localhost', 'bomb.com'] do
on '*.*' do
grant 'USAGE'
end
end
RUBY
}
end
Expand All @@ -46,6 +52,8 @@
grant 'ALL PRIVILEGES'
end
end

user 'jimbob', ['localhost', 'bomb.com'], dropped: true
RUBY
}

Expand Down
48 changes: 48 additions & 0 deletions spec/drop/ignore_unlisted_users_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
describe 'Gratan::Client#apply' do
before(:each) do
apply {
<<-RUBY
user 'scott', 'localhost', identified: 'tiger' do
on '*.*' do
grant 'SELECT'
end
end

user 'bob', 'localhost' do
on '*.*' do
grant 'USAGE'
end
end

user 'jimbob', 'localhost' do
on '*.*' do
grant 'USAGE'
end
end
RUBY
}
end

context 'when grant privs with ignore_unlisted_users' do
subject { client(ignore_unlisted_users: true) }

it do
apply(subject) {
<<-RUBY
user 'scott', 'localhost', identified: 'tiger' do
on '*.*' do
grant 'SELECT'
end
end

user 'jimbob', 'localhost', dropped: true
RUBY
}

expect(show_grants).to match_array [
"GRANT SELECT ON *.* TO 'scott'@'localhost' IDENTIFIED BY PASSWORD '*F2F68D0BB27A773C1D944270E5FAFED515A3FA40'",
"GRANT USAGE ON *.* TO 'bob'@'localhost'",
]
end
end
end