cassandra_backup 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = 'cassandra_backup'
5
- s.version = '0.1.1'
5
+ s.version = '0.2.0'
6
6
  s.description = 'Cassandra Backup'
7
7
  s.summary = 'Cassandra Backup'
8
8
  s.authors = ['Infogroup']
@@ -27,6 +27,12 @@ module CassandraBackup
27
27
  opts.on('-w', '--where=\'where_conditions\'') do |v|
28
28
  options[:where] = v
29
29
  end
30
+ opts.on('--[no-]create-info', "Write out CREATE statements. Defaults to true.") do |v|
31
+ options[:create_info] = v
32
+ end
33
+ opts.on('--[no-]data', "Write out table data. Defaults to true.") do |v|
34
+ options[:data] = v
35
+ end
30
36
  opts.on('-h', 'Show this help message.') do
31
37
  $stdout.puts opts; exit
32
38
  end
@@ -44,4 +50,4 @@ module CassandraBackup
44
50
  (options[name] ||= []).concat value.split(/\s|,/)
45
51
  end
46
52
  end
47
- end
53
+ end
@@ -1,46 +1,31 @@
1
1
  module CassandraBackup
2
2
  class Config
3
+ DEFAULT_OPTIONS = {
4
+ input: STDIN,
5
+ output: STDOUT,
6
+ data: true,
7
+ create_info: true,
8
+ servers: ['127.0.0.1:9160']
9
+ }
10
+
3
11
  attr_reader :options
4
12
  def initialize(options = {})
5
- @options = options
6
-
13
+ @options = DEFAULT_OPTIONS.dup.update(options)
7
14
  require_version!
8
15
  end
9
16
 
10
- def servers
11
- if options[:servers]
12
- options[:servers]
13
- else
14
- ['127.0.0.1:9160']
17
+ [:servers, :input, :output, :create_info, :data, :keyspace, :tables, :where].each do |option|
18
+ define_method option do
19
+ options[option]
15
20
  end
16
21
  end
17
22
 
18
- def input
19
- options[:input] || STDIN
20
- end
21
-
22
- def output
23
- options[:output] || STDOUT
24
- end
25
-
26
23
  def require_version!
27
24
  if options[:version]
28
25
  require "cassandra-cql/#{options[:version]}"
29
26
  end
30
27
  end
31
28
 
32
- def keyspace
33
- options[:keyspace]
34
- end
35
-
36
- def tables
37
- options[:tables]
38
- end
39
-
40
- def where
41
- options[:where]
42
- end
43
-
44
29
  def connection
45
30
  if keyspace
46
31
  options = {keyspace: keyspace}
@@ -50,4 +35,4 @@ module CassandraBackup
50
35
  @connection ||= CassandraCQL::Database.new(servers, options)
51
36
  end
52
37
  end
53
- end
38
+ end
@@ -4,9 +4,7 @@ module CassandraBackup
4
4
  new(command.config).run
5
5
  end
6
6
 
7
- attr_reader :config
8
- attr_reader :cqlsh
9
- attr_reader :primary_keys
7
+ attr_reader :config, :cqlsh, :primary_keys
10
8
  def initialize(config)
11
9
  @config = config
12
10
  @cqlsh = CassandraBackup::Cqlsh.new(config)
@@ -15,24 +13,29 @@ module CassandraBackup
15
13
 
16
14
  def run
17
15
  table_names.each { |table_name| dump_table_schema(table_name) }
18
- table_names.each { |table_name| dump_table_rows(table_name) }
16
+ table_names.each { |table_name| dump_table_rows(table_name) } if config.data
19
17
  end
20
18
 
21
19
  def dump_table_schema(table_name)
22
20
  table_description = cqlsh.exec("DESCRIBE COLUMNFAMILY #{table_name}")
23
21
  capture_primary_key(table_name, table_description)
24
- config.output.puts(table_description)
25
- config.output.puts
22
+
23
+ if config.create_info
24
+ config.output.puts(table_description)
25
+ config.output.puts
26
+ end
26
27
  end
27
28
 
28
29
  def dump_table_rows(table_name)
30
+ return unless config.data
31
+
29
32
  primary_key = primary_key_for(table_name)
30
33
  each_row(table_name) do |row|
31
34
  next if row.keys.size == 1 && row.keys.first == primary_key
32
35
 
33
36
  colummns = CassandraCQL::Statement.quote(row.keys)
34
37
  values = CassandraCQL::Statement.quote(row.values.map { |v| CassandraCQL::Statement.escape(v) })
35
-
38
+
36
39
  config.output.puts "INSERT INTO #{table_name} (#{colummns}) VALUES (#{values});"
37
40
  end
38
41
  end
@@ -53,7 +56,7 @@ module CassandraBackup
53
56
  def primary_key_for(table_name)
54
57
  primary_keys[table_name] || 'id'
55
58
  end
56
-
59
+
57
60
  def capture_primary_key(table_name, table_description)
58
61
  if table_description =~ /^\s*(\w+).*PRIMARY KEY/
59
62
  primary_keys[table_name] = $1
@@ -62,7 +65,9 @@ module CassandraBackup
62
65
 
63
66
  def each_row(table_name)
64
67
  primary_key = primary_key_for(table_name)
65
- cassandra_result = execute "SELECT * FROM #{table_name}"
68
+ select_cql = "SELECT * FROM #{table_name}"
69
+
70
+ cassandra_result = execute_with_where(select_cql, [config.where])
66
71
 
67
72
  while cassandra_result.rows > 0
68
73
  last_fetch = nil
@@ -72,7 +77,17 @@ module CassandraBackup
72
77
  end
73
78
 
74
79
  where_cql = "'#{primary_key}' > '#{last_fetch[primary_key]}'"
75
- cassandra_result = execute "SELECT * FROM #{table_name} WHERE #{where_cql}"
80
+ cassandra_result = execute_with_where(select_cql, [where_cql, config.where])
81
+ end
82
+ end
83
+
84
+ def execute_with_where(select_cql, wheres)
85
+ wheres = wheres.compact
86
+
87
+ if wheres.any?
88
+ execute "#{select_cql} WHERE #{wheres.join(' AND ')}"
89
+ else
90
+ execute select_cql
76
91
  end
77
92
  end
78
93
  end
@@ -13,6 +13,11 @@ class CassandraBackup::CommandTest < MiniTest::Spec
13
13
  end
14
14
  end
15
15
 
16
+ def test_boolean_options
17
+ assert_equal false, command('zombies --no-data').options[:data]
18
+ assert_equal false, command('zombies --no-create-info').options[:create_info]
19
+ end
20
+
16
21
  def test_array_options
17
22
  [:servers, :tables].each do |option|
18
23
  assert_nil command('zombies').options[option]
@@ -22,6 +27,14 @@ class CassandraBackup::CommandTest < MiniTest::Spec
22
27
  end
23
28
  end
24
29
 
30
+ def test_boolean_options
31
+ [ { "create-info" => :create_info }, { "data" => :data }].each do |option|
32
+ assert_nil command('zombies').options[option.values.first]
33
+ assert command("zombies --#{option.keys.first}").options[option.values.first], "--#{option} should enable command"
34
+ refute command("zombies --no-#{option.keys.first}").options[option.values.first], "--no-#{option} should disable command"
35
+ end
36
+ end
37
+
25
38
  def test_config
26
39
  assert_kind_of CassandraBackup::Config, command('zombies').config
27
40
  end
@@ -30,4 +43,4 @@ class CassandraBackup::CommandTest < MiniTest::Spec
30
43
  def command(line)
31
44
  CassandraBackup::Command.new Shellwords.shellsplit(line)
32
45
  end
33
- end
46
+ end
@@ -1,19 +1,12 @@
1
1
  require 'helper'
2
2
 
3
3
  class CassandraBackup::ConfigTest < MiniTest::Spec
4
- def test_servers
4
+ def test_defaults
5
5
  assert_equal ['127.0.0.1:9160'], config.servers
6
- assert_equal ['foo'], config(servers: ['foo']).servers
7
- end
8
-
9
- def test_input
10
6
  assert_equal STDIN, config.input
11
- refute_equal STDIN, config(input: StringIO.new).input
12
- end
13
-
14
- def test_output
15
7
  assert_equal STDOUT, config.output
16
- refute_equal STDOUT, config(output: StringIO.new).output
8
+ assert_equal true, config.data
9
+ assert_equal true, config.create_info
17
10
  end
18
11
 
19
12
  def test_require_version
@@ -6,38 +6,73 @@ class CassandraBackup::DumperTest < MiniTest::Spec
6
6
  assert_equal ['presidents'], create_dumper(tables: ['presidents']).table_names
7
7
  end
8
8
 
9
- def test_dump_table_schema
10
- output = StringIO.new
11
- dumper = create_dumper output: output
9
+ def test_dump_create_info
10
+ dumper = create_dumper tables: ['senators']
12
11
 
13
- dumper.dump_table_schema('senators')
12
+ output = run_dumper(dumper)
14
13
 
15
- output.rewind
16
- lines = output.readlines
17
- assert_match /CREATE TABLE senators/, lines.first
18
- assert_equal "\n", lines.last
14
+ assert_match /CREATE TABLE senators/, output
19
15
  assert_equal({"senators" => "id"}, dumper.primary_keys)
20
16
  end
21
17
 
22
- def test_dump_table_rows
23
- output = StringIO.new
24
- dumper = create_dumper output: output
18
+ def test_bypass_create_info
19
+ dumper = create_dumper create_info: false, tables: ['senators']
20
+
21
+ output = run_dumper(dumper)
22
+
23
+ refute_match /CREATE TABLE/, output
24
+ assert_equal({"senators" => "id"}, dumper.primary_keys)
25
+ end
26
+
27
+ def test_dump_data
28
+ dumper = create_dumper
25
29
  dumper.execute "TRUNCATE senators"
26
30
  dumper.execute "INSERT INTO senators ('id', 'name', 'state') VALUES ('abc', 'K''la', 'WA')"
27
31
  dumper.execute "INSERT INTO senators ('id', 'name', 'state') VALUES ('xyz', 'Bob', 'NY')"
28
32
 
29
- dumper.dump_table_rows('senators')
33
+ output = run_dumper(dumper)
30
34
 
31
- output.rewind
32
- lines = output.readlines
35
+ assert output.include?("INSERT INTO senators ('id','name','state') VALUES ('xyz','Bob','NY');")
36
+ end
37
+
38
+ def test_dump_data_with_where
39
+ dumper = create_dumper where: "'state' = 'WA'", tables: ['senators']
40
+ dumper.execute "TRUNCATE senators"
41
+ dumper.execute "INSERT INTO senators ('id', 'name', 'state') VALUES ('abc', 'Patty Murray', 'WA')"
42
+ dumper.execute "INSERT INTO senators ('id', 'name', 'state') VALUES ('xyz', 'John McCain', 'AZ')"
43
+
44
+ output = run_dumper(dumper)
45
+
46
+ assert_match /Patty Murray/, output
47
+ refute_match /John McCain/, output
48
+ end
33
49
 
34
- assert_equal 2, lines.size
35
- assert lines.include?("INSERT INTO senators ('id','name','state') VALUES ('abc','K''la','WA');\n")
36
- assert lines.include?("INSERT INTO senators ('id','name','state') VALUES ('xyz','Bob','NY');\n")
37
- end
50
+ def test_bypass_data
51
+ dumper = create_dumper data: false, tables: ['senators']
52
+
53
+ dumper.execute "TRUNCATE senators"
54
+ dumper.execute "INSERT INTO senators ('id', 'name', 'state') VALUES ('abc', 'K''la', 'WA')"
55
+
56
+ output = run_dumper(dumper)
57
+
58
+ assert_match /CREATE TABLE senators/, output
59
+ refute_match /INSERT INTO senators/, output
60
+ end
38
61
 
39
62
  private
63
+ def config(options = {})
64
+ CassandraBackup::Config.new(options.merge(keyspace: 'cassandra_dump_test'))
65
+ end
66
+
40
67
  def create_dumper(options = {})
41
- CassandraBackup::Dumper.new CassandraBackup::Config.new(options.merge(keyspace: 'cassandra_dump_test'))
68
+ CassandraBackup::Dumper.new config(options)
69
+ end
70
+
71
+ def run_dumper(dumper)
72
+ output = StringIO.new
73
+ dumper.config.options[:output] = output
74
+ dumper.run
75
+ output.rewind
76
+ output.readlines.to_s
42
77
  end
43
78
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassandra_backup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-03 00:00:00.000000000 Z
12
+ date: 2012-11-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cassandra-cql