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

Commit

Permalink
Merge 26ab2d4 into 16f3a3a
Browse files Browse the repository at this point in the history
  • Loading branch information
schleyfox committed Nov 25, 2014
2 parents 16f3a3a + 26ab2d4 commit 0f50861
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 42 deletions.
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
31 changes: 21 additions & 10 deletions lib/gratan/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,22 @@ def chunk_by_user(exported)
def apply(file, options = {})
options = @options.merge(options)

apply_context(
load_file(file, options),
options)
end

def apply_context(expected, options = {})
options = @options.merge(options)

in_progress do
walk(file, options)
walk(expected, options)
end
end

private

def walk(file, options)
expected = load_file(file, options)
def walk(expected, options)
actual = Gratan::Exporter.export(@driver, options.merge(:with_identifier => true))

expected.each do |user_host, expected_attrs|
Expand All @@ -76,21 +83,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
19 changes: 13 additions & 6 deletions lib/gratan/dsl/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ def initialize(path, options = {}, &block)
instance_eval(&block)
end

private

def require(file)
grantfile = (file =~ %r|\A/|) ? file : File.expand_path(File.join(File.dirname(@path), file))

Expand All @@ -35,22 +33,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

0 comments on commit 0f50861

Please sign in to comment.