VladTheEnterprising 0.1.8 → 0.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of VladTheEnterprising might be problematic. Click here for more details.
- data.tar.gz.sig +0 -0
- data/README.txt +6 -2
- data/Rakefile +9 -0
- data/lib/vlad/dba/mysql.rb +132 -44
- data/lib/vlad/enterprising.rb +1 -1
- metadata +2 -2
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
Binary file
|
data/README.txt
CHANGED
@@ -95,8 +95,11 @@ Currently consists of the following:
|
|
95
95
|
|
96
96
|
Migrations and Versioning
|
97
97
|
=========================
|
98
|
-
|
99
|
-
As of
|
98
|
+
|
99
|
+
As of 0.2.0, schema creations are supported. The ddl is expected to
|
100
|
+
be in: db/schemas/[SchemaName].sql
|
101
|
+
|
102
|
+
As of 0.1.8, schema migrations and versioning are supported. By
|
100
103
|
default the app will look under db/migrations/[schema name]/[version
|
101
104
|
no]-[text]/[upgrade.sql|rollback.sql]
|
102
105
|
|
@@ -139,6 +142,7 @@ Currently consists of the following:
|
|
139
142
|
being that there's ssh and the mysql client available on the
|
140
143
|
db_master.
|
141
144
|
|
145
|
+
|
142
146
|
* The Xen Master
|
143
147
|
|
144
148
|
Beginnings of a series of tasks for autmating the creation and
|
data/Rakefile
CHANGED
@@ -8,6 +8,8 @@ require './lib/nytd/dbslayer'
|
|
8
8
|
|
9
9
|
require './lib/vlad/enterprising.rb'
|
10
10
|
require './lib/nytd/builder'
|
11
|
+
require './lib/nytd/util'
|
12
|
+
require './lib/nytd/cnx_mysql'
|
11
13
|
Hoe.new('VladTheEnterprising', VLAD_ENTERPRISING_VERSION) do |p|
|
12
14
|
p.rubyforge_name = 'vlad_the_enterprising'
|
13
15
|
p.author = 'Michael L. Welles'
|
@@ -21,4 +23,11 @@ Hoe.new('VladTheEnterprising', VLAD_ENTERPRISING_VERSION) do |p|
|
|
21
23
|
end
|
22
24
|
Vlad.load()
|
23
25
|
|
26
|
+
if defined?( target_environment ) and ( target_environment == :production )
|
27
|
+
unless ENV['FORCE']
|
28
|
+
certain = ask('Are you sure you want to target production? [Y/n]')
|
29
|
+
raise "Oops, good thing we checked. Aborting." unless certain == "Y"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
24
33
|
# vim: syntax=Ruby
|
data/lib/vlad/dba/mysql.rb
CHANGED
@@ -20,7 +20,7 @@ namespace :vlad do
|
|
20
20
|
puts "#{target_host} mysql user open file ulimit: #{n}"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
|
24
24
|
desc "Bootstraps mysql slave candiates, installs mysql, syncs them to the master, and starts them."
|
25
25
|
task :bootstrap_new_slaves => [
|
26
26
|
:assert_production_target_subset,
|
@@ -41,9 +41,9 @@ namespace :vlad do
|
|
41
41
|
:check_slaves,]
|
42
42
|
|
43
43
|
|
44
|
-
|
44
|
+
task :ask_root_password do
|
45
45
|
mysql_root_password
|
46
|
-
|
46
|
+
end
|
47
47
|
|
48
48
|
task :ask_replication_password do
|
49
49
|
mysql_replication_password
|
@@ -109,10 +109,12 @@ namespace :vlad do
|
|
109
109
|
slaves = Rake::RemoteTask.hosts_for(:new_slave)
|
110
110
|
slaves.each do |slave|
|
111
111
|
name = slave.gsub(/\..*$/,"").gsub(/-/, "")
|
112
|
-
mysql_query "grant all privileges on *.* to '#{name}_dump'@'#{slave}' identified by '#{mysql_replication_password}'",
|
112
|
+
mysql_query :sql => "grant all privileges on *.* to '#{name}_dump'@'#{slave}' identified by '#{mysql_replication_password}'",
|
113
|
+
:u => "root", :p => mysql_root_password
|
113
114
|
ip = Resolv.getaddress(slave)
|
114
115
|
if ip
|
115
|
-
mysql_query "grant all privileges on *.* to '#{name}_dump'@'#{ip}' identified by '#{mysql_replication_password}'",
|
116
|
+
mysql_query :sql => "grant all privileges on *.* to '#{name}_dump'@'#{ip}' identified by '#{mysql_replication_password}'",
|
117
|
+
:u => "root", :p => mysql_root_password
|
116
118
|
end
|
117
119
|
end
|
118
120
|
end
|
@@ -121,10 +123,12 @@ namespace :vlad do
|
|
121
123
|
slaves = Rake::RemoteTask.hosts_for(:new_slave)
|
122
124
|
slaves.each do |slave|
|
123
125
|
name = slave.gsub(/\..*$/,"").gsub(/-/, "")
|
124
|
-
mysql_query "grant replication slave, super, reload on *.* to '#{name}_repl'@'#{slave}' identified by '#{mysql_replication_password}'",
|
126
|
+
mysql_query :sql => "grant replication slave, super, reload on *.* to '#{name}_repl'@'#{slave}' identified by '#{mysql_replication_password}'",
|
127
|
+
:u => "root", :p => mysql_root_password
|
125
128
|
ip = Resolv.getaddress(slave)
|
126
129
|
if ip
|
127
|
-
mysql_query "grant replication slave, super, reload on *.* to '#{name}_repl'@'#{ip}' identified by '#{mysql_replication_password}'",
|
130
|
+
mysql_query :sql => "grant replication slave, super, reload on *.* to '#{name}_repl'@'#{ip}' identified by '#{mysql_replication_password}'",
|
131
|
+
:u => "root", :p => mysql_root_password
|
128
132
|
end
|
129
133
|
end
|
130
134
|
end
|
@@ -133,8 +137,10 @@ namespace :vlad do
|
|
133
137
|
slaves = Rake::RemoteTask.hosts_for(:new_slave)
|
134
138
|
slaves.each do |slave|
|
135
139
|
name = slave.gsub(/\..*$/,"").gsub(/-/, "")
|
136
|
-
mysql_query "REVOKE replication slave, super, reload FROM #{name}_repl",
|
137
|
-
|
140
|
+
mysql_query :sql => "REVOKE replication slave, super, reload FROM #{name}_repl",
|
141
|
+
:u => "root", :p => mysql_root_password, :force => true
|
142
|
+
mysql_query :sql => "drop user #{name}_repl",
|
143
|
+
:u => "root", :p => mysql_root_password, :force => true
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
@@ -144,8 +150,10 @@ namespace :vlad do
|
|
144
150
|
slaves = Rake::RemoteTask.hosts_for(:new_slave)
|
145
151
|
slaves.each do |slave|
|
146
152
|
name = slave.gsub(/\..*$/,"").gsub(/-/, "")
|
147
|
-
mysql_query "REVOKE ALL PRIVILEGES, GRANT OPTION FROM #{name}_dump",
|
148
|
-
|
153
|
+
mysql_query :sql => "REVOKE ALL PRIVILEGES, GRANT OPTION FROM #{name}_dump",
|
154
|
+
:u => "root", :p => mysql_root_password, :force => true
|
155
|
+
mysql_query :sql => "drop user #{name}_dump",
|
156
|
+
:u => "root", :p => mysql_root_password, :force => true
|
149
157
|
end
|
150
158
|
end
|
151
159
|
|
@@ -240,9 +248,11 @@ namespace :vlad do
|
|
240
248
|
|
241
249
|
remote_task :start_new_slaves, :roles => :new_slave do
|
242
250
|
begin
|
243
|
-
mysql_query "flush privileges; slave start;",
|
251
|
+
mysql_query :sql => "flush privileges; slave start;",
|
252
|
+
:u => "root"
|
244
253
|
rescue
|
245
|
-
mysql_query "flush privileges; slave start;",
|
254
|
+
mysql_query "flush privileges; slave start;",
|
255
|
+
:u => "root", :p => mysql_root_password
|
246
256
|
end
|
247
257
|
end
|
248
258
|
|
@@ -259,12 +269,13 @@ namespace :vlad do
|
|
259
269
|
datfile = dumpfile.sub(/\.gz$/,"").sub(/-/, "-#{database}-")
|
260
270
|
dumpfile = datfile + ".gz"
|
261
271
|
run "mkdir -p `dirname #{datfile}`; exit 0"
|
262
|
-
run "#{mysqldump} --single-transaction -uroot -p'#{mysql_root_password}' #{db_arg} > #{datfile}"
|
272
|
+
run "#{mysqldump} --routines --single-transaction -uroot -p'#{mysql_root_password}' #{db_arg} > #{datfile}"
|
263
273
|
`mkdir -p \`dirname #{datfile}\``
|
264
274
|
run "nice gzip #{datfile}"
|
265
275
|
cmd="ssh #{target_host} cat #{dumpfile} > #{dumpfile}"
|
266
276
|
`#{cmd}`
|
267
|
-
|
277
|
+
run "if [ -e #{dumpfile} ]; then rm #{dumpfile}; else exit 1; fi"
|
278
|
+
FileUtils.ln_sf(File.basename(dumpfile), "dumps/#{ENV['DATABASE']}-latest.dat.gz")
|
268
279
|
puts "Done: #{dumpfile}"
|
269
280
|
end
|
270
281
|
task :dump => [:ask_root_password]
|
@@ -350,17 +361,21 @@ namespace :vlad do
|
|
350
361
|
|
351
362
|
desc "stops replication on all slaves"
|
352
363
|
remote_task :stop_slaves, :roles => [:db_slave, :new_slave] do
|
353
|
-
mysql_query "slave stop;",
|
364
|
+
mysql_query :sql => "slave stop;",
|
365
|
+
:u => "root", :p => mysql_root_password
|
354
366
|
end
|
355
367
|
|
356
368
|
desc "starts replication on all slaves"
|
357
369
|
remote_task :start_slaves, :roles => [:db_slave, :new_slave] do
|
358
|
-
mysql_query
|
370
|
+
mysql_query :sql => "slave start;",
|
371
|
+
:u => "root", :p => mysql_root_password
|
359
372
|
end
|
373
|
+
|
360
374
|
desc "shows available databases"
|
361
375
|
remote_task :show_all_databases, :roles => :db_master do
|
362
376
|
puts "#{target_host}"
|
363
|
-
mysql_query "SHOW DATABASES;",
|
377
|
+
mysql_query :sql => "SHOW DATABASES;",
|
378
|
+
:u => "root", :p => mysql_root_password
|
364
379
|
end
|
365
380
|
task :show_all_databases => [:ask_root_password]
|
366
381
|
|
@@ -383,20 +398,30 @@ namespace :vlad do
|
|
383
398
|
desc "Executes query specified in QUERY='' argument on database specified in the DATABASE='' argument on the :db_master for the target environment and prints the results"
|
384
399
|
remote_task :query, :roles => :db_master do
|
385
400
|
raise "Please specify what QUERY to run against what database, i.e. QUERY='select foo from bar' DATABASE='Movies' TARGET='staging'" unless ENV['QUERY']
|
386
|
-
puts mysql_query(ENV['QUERY'],
|
401
|
+
puts mysql_query(:sql => ENV['QUERY'],
|
402
|
+
:db => ENV['DATABASE'],
|
403
|
+
:u => 'root', :p => mysql_root_password )
|
387
404
|
end
|
388
405
|
|
389
406
|
desc "Executes query specified in QUERY='' argument on database specified in the DATABASE='' argument on all the slaves for the target environment and prints the results"
|
390
407
|
remote_task :query_slaves, :roles => :db_slave do
|
391
408
|
raise "Please specify what QUERY to run against what database, i.e. QUERY='select foo from bar' DATABASE='Movies' TARGET='staging'" unless ENV['QUERY']
|
392
|
-
puts "#{target_host}: " + mysql_query(ENV['QUERY'],ENV['DATABASE'], :u => 'root', :p => mysql_root_password ).gsub("\n", "*****")
|
409
|
+
puts "#{target_host}: " + mysql_query( :sql => ENV['QUERY'], :db => ENV['DATABASE'], :u => 'root', :p => mysql_root_password ).gsub("\n", "*****")
|
393
410
|
end
|
394
411
|
|
412
|
+
remote_task :install_slave_crontab, :roles => :db_slave do
|
413
|
+
file = "files/mysql/crontabs/db_slave.crontab"
|
414
|
+
if File.exist?(file)
|
415
|
+
scp file, ".crontab"
|
416
|
+
run "crontab .crontab"
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
395
420
|
remote_task :schema_info, :roles => :db_master do
|
396
421
|
databases.select{ |db| db == "mysql" ? false : true }.each do |database|
|
397
422
|
begin
|
398
|
-
output = mysql_query("select version from schema_info limit 1",
|
399
|
-
|
423
|
+
output = mysql_query(:sql => "select version from schema_info limit 1",
|
424
|
+
:db => database,
|
400
425
|
:u => 'root',
|
401
426
|
:p => mysql_root_password)
|
402
427
|
|
@@ -409,7 +434,38 @@ namespace :vlad do
|
|
409
434
|
end
|
410
435
|
end
|
411
436
|
task :schema_info => [:ask_root_password]
|
412
|
-
|
437
|
+
|
438
|
+
desc "Creates a database specified by DATABASE argument, using schema defined in db/schemas/[DATABASE].sql"
|
439
|
+
remote_task :create_database, :roles => :db_master do
|
440
|
+
database = ENV['DATABASE']
|
441
|
+
sql = File.read("db/schemas/#{database}.sql")
|
442
|
+
src = Tempfile.new("#{database}-create").path
|
443
|
+
create = "CREATE DATABASE IF NOT EXISTS #{database};\n"
|
444
|
+
File.open(src, "w") do |f|
|
445
|
+
f.write(sql)
|
446
|
+
if Rake.application.options.trace
|
447
|
+
puts create
|
448
|
+
puts sql
|
449
|
+
end
|
450
|
+
end
|
451
|
+
mysql_query( :sql => create, :u => 'root', :p => mysql_root_password)
|
452
|
+
scp src, src
|
453
|
+
mysql_query( :sql => "source #{src};",
|
454
|
+
:db => database,
|
455
|
+
:u => 'root',
|
456
|
+
:p => mysql_root_password)
|
457
|
+
end
|
458
|
+
task :create_database => [:assert_single_master]
|
459
|
+
|
460
|
+
remote_task :drop_database, :roles => :db_master do
|
461
|
+
database = ENV['DATABASE']
|
462
|
+
drop = "DROP DATABASE IF EXISTS #{database}"
|
463
|
+
mysql_query( :sql => drop,
|
464
|
+
:u => 'root',
|
465
|
+
:p => mysql_root_password)
|
466
|
+
end
|
467
|
+
task :drop_database => [:assert_single_master]
|
468
|
+
|
413
469
|
desc "Runs db migrations for current TARGET can be controlled with better granuarity with DATABASE and VERSION arguments"
|
414
470
|
remote_task :migrate, :roles => :db_master do
|
415
471
|
assert_database_if_version_given()
|
@@ -420,17 +476,18 @@ namespace :vlad do
|
|
420
476
|
targets.each do |database|
|
421
477
|
database_dir = File.join(migration_dir, database)
|
422
478
|
begin
|
423
|
-
output = mysql_query("select version from schema_info limit 1",
|
424
|
-
|
479
|
+
output = mysql_query(:sql => "select version from schema_info limit 1",
|
480
|
+
:db => database,
|
425
481
|
:u => 'root',
|
426
482
|
:p => mysql_root_password)
|
427
|
-
|
483
|
+
puts output if Rake.application.options.trace
|
484
|
+
current_version = output.split(/\n/)[1].to_i
|
428
485
|
rescue
|
429
486
|
current_version = 0
|
430
487
|
end
|
431
488
|
migrations = { }
|
432
489
|
dirs = Dir.new(database_dir).entries.select{|d| d.match(/^\d+/)}
|
433
|
-
dirs.each { |dir| migrations[dir.sub(/[^\d]
|
490
|
+
dirs.each { |dir| migrations[dir.sub(/[^\d].*$/, "")] = dir }
|
434
491
|
target_version = ENV['VERSION'].to_i if ENV['VERSION']
|
435
492
|
target_version ||= migrations.keys.sort{|a,b| a.to_i <=> b.to_i }.last.to_i rescue 0
|
436
493
|
case
|
@@ -450,18 +507,18 @@ namespace :vlad do
|
|
450
507
|
have_migrations = lambda{ false }
|
451
508
|
puts "#{database} already at version #{target_version} on #{target_host}"
|
452
509
|
end
|
453
|
-
|
510
|
+
sql = "CREATE TABLE IF NOT EXISTS schema_info ( version INT default 0 );\n"
|
511
|
+
mysql_query(:sql => sql,
|
512
|
+
:db => database,
|
513
|
+
:u => 'root', :p => mysql_root_password)
|
454
514
|
while have_migrations.call() do
|
455
515
|
next_version = iterator.call(current_version)
|
456
516
|
migration_file = next_file.call(current_version)
|
457
517
|
if migration_file && File.exist?(migration_file)
|
458
|
-
|
459
|
-
sql << "CREATE TABLE IF NOT EXISTS schema_info ( version INT default 0 );\n"
|
460
|
-
sql << File.read(migration_file)
|
518
|
+
sql = File.read(migration_file)
|
461
519
|
sql << "\n"
|
462
520
|
sql << "update schema_info set version = #{next_version};\n"
|
463
|
-
|
464
|
-
src = "/tmp/#{database}-version-#{File.basename(File.dirname(migration_file))}-#{File.basename(migration_file)}"
|
521
|
+
src = Tempfile.new("#{database}-version-#{File.basename(File.dirname(migration_file))}-#{File.basename(migration_file)}").path
|
465
522
|
File.open(src, "w"){ |f| f.write(sql) }
|
466
523
|
scp src, src
|
467
524
|
if Rake.application.options.trace
|
@@ -469,7 +526,10 @@ namespace :vlad do
|
|
469
526
|
puts sql
|
470
527
|
puts "============================================\n"
|
471
528
|
end
|
472
|
-
mysql_query(
|
529
|
+
mysql_query(:source => src,
|
530
|
+
:db => database,
|
531
|
+
:u => 'root',
|
532
|
+
:p => mysql_root_password)
|
473
533
|
puts "Executed: #{migration_file} on #{target_host}"
|
474
534
|
end
|
475
535
|
current_version = next_version
|
@@ -478,19 +538,31 @@ namespace :vlad do
|
|
478
538
|
end
|
479
539
|
end
|
480
540
|
task :migrate => [:ask_root_password, :assert_single_master]
|
481
|
-
|
541
|
+
|
542
|
+
desc "restores the latest dump available for given DATABASE to specified TARGET"
|
543
|
+
task :restore_latest => [:set_dumpfile, :restore]
|
544
|
+
|
545
|
+
task :set_dumpfile do
|
546
|
+
ENV["DUMPFILE"] = "dumps/#{ENV['DATABASE']}-latest.dat.gz"
|
547
|
+
end
|
548
|
+
|
482
549
|
desc "restores a dump to current db_master from file set in mysql_dumpfile or in a DUMPFILE argument"
|
483
550
|
remote_task :restore, :roles => :db_master do
|
551
|
+
dump ||= "dumps/#{ENV['DATABASE']}-latest.dat.gz"
|
484
552
|
dump = ENV["DUMPFILE"] || dump
|
485
|
-
raise "
|
553
|
+
raise "Can't find DUMPFILE '#{dump}' create specify a valid dumpfile to restore via the DUMPFILE argument!" unless File.exist?(dump)
|
486
554
|
scp dump, dump
|
487
555
|
p = ""
|
488
556
|
unless mysql_root_password.nil? or mysql_root_password == ""
|
489
557
|
p = "-p'#{mysql_root_password}' "
|
490
558
|
end
|
491
559
|
if ENV['DATABASE']
|
492
|
-
mysql_query "DROP DATABASE IF EXISTS #{ENV['DATABASE']}",
|
493
|
-
|
560
|
+
mysql_query :sql => "DROP DATABASE IF EXISTS #{ENV['DATABASE']}",
|
561
|
+
:u => 'root',
|
562
|
+
:p => mysql_root_password
|
563
|
+
mysql_query :sql => "CREATE DATABASE IF NOT EXISTS #{ENV['DATABASE']}",
|
564
|
+
:u => 'root',
|
565
|
+
:p => mysql_root_password
|
494
566
|
end
|
495
567
|
run "cat #{dump} | gunzip - | #{mysql_path_bin}/mysql -uroot #{p} #{ENV['DATABASE']}"
|
496
568
|
end
|
@@ -578,7 +650,7 @@ def mysql_replication_password
|
|
578
650
|
end
|
579
651
|
|
580
652
|
class Rake::RemoteTask
|
581
|
-
def mysql_query(
|
653
|
+
def mysql_query( options = {} )
|
582
654
|
if options[:force]
|
583
655
|
force_enabled = true
|
584
656
|
options[:force] = nil
|
@@ -586,19 +658,35 @@ class Rake::RemoteTask
|
|
586
658
|
if options[:p] == ""
|
587
659
|
options[:p] = nil
|
588
660
|
end
|
661
|
+
if options[:sql]
|
662
|
+
f=Tempfile.new("sql")
|
663
|
+
File.open(f.path, "w"){ |file| file.write(options[:sql])}
|
664
|
+
scp f.path, f.path + ".sql"
|
665
|
+
options[:source] = f.path + ".sql"
|
666
|
+
if Rake.application.options.trace
|
667
|
+
puts "#{options[:source]}: #{options[:sql]}"
|
668
|
+
end
|
669
|
+
end
|
670
|
+
database = options[:db]
|
589
671
|
args = options.keys.collect do |key|
|
590
672
|
case key
|
591
673
|
when :p :
|
592
|
-
|
593
|
-
|
594
|
-
|
674
|
+
if options[key] && options[key] != ""
|
675
|
+
"-#{key}'#{options[key]}'"
|
676
|
+
end
|
595
677
|
when :force :
|
596
|
-
|
678
|
+
""
|
679
|
+
when :db :
|
680
|
+
""
|
681
|
+
when :sql :
|
682
|
+
""
|
683
|
+
when :source :
|
684
|
+
"-e 'source #{options[:source]};'"
|
597
685
|
else
|
598
686
|
"-#{key}'#{options[key]}'"
|
599
687
|
end
|
600
688
|
end.join " "
|
601
|
-
command = "
|
689
|
+
command = "#{mysql} #{args} #{database}"
|
602
690
|
command << "; exit 0" if force_enabled
|
603
691
|
run command
|
604
692
|
end
|
data/lib/vlad/enterprising.rb
CHANGED
@@ -4,7 +4,7 @@ require 'vlad/environmentalist'
|
|
4
4
|
require 'vlad/xen_master'
|
5
5
|
require 'vlad/dba'
|
6
6
|
require 'vlad/webmaster/apache'
|
7
|
-
VLAD_ENTERPRISING_VERSION = '0.
|
7
|
+
VLAD_ENTERPRISING_VERSION = '0.2' unless defined? VLAD_ENTERPRISING_VERSION
|
8
8
|
|
9
9
|
|
10
10
|
# rsync the given files to <tt>target_host</tt>.
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: VladTheEnterprising
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date:
|
6
|
+
version: "0.2"
|
7
|
+
date: 2008-01-02 00:00:00 -05:00
|
8
8
|
summary: Adds 'enterprisey' features to Vlad The Deployer
|
9
9
|
require_paths:
|
10
10
|
- lib
|
metadata.gz.sig
CHANGED
Binary file
|