sdbport 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.4.0:
2
+
3
+ * Added sequential export
4
+ * Added specs for CLI
5
+ * Updated README
6
+
1
7
  ## 0.3.0:
2
8
 
3
9
  * Added support for reading multiple env configs
data/README.md CHANGED
@@ -6,7 +6,9 @@ Sdbport exports & imports data from AWS SimpleDB domains. It can be used as a cl
6
6
 
7
7
  ## Installation
8
8
 
9
+ ```
9
10
  gem install sdbport
11
+ ```
10
12
 
11
13
  ## Getting Started
12
14
 
@@ -20,13 +22,20 @@ export AWS_SECRET_ACCESS_KEY=your_aws_secret
20
22
  Export SimpleDB domain from us-west-1:
21
23
 
22
24
  ```
23
- sdbport export -a $AWS_ACCESS_KEY_ID -s $AWS_SECRET_ACCESS_KEY -r us-west-1 -n data -o /tmp/test-domain-dump
25
+ sdbport export -k $AWS_ACCESS_KEY_ID -s $AWS_SECRET_ACCESS_KEY -r us-west-1 -n data -o /tmp/test-domain-dump
26
+ ```
27
+
28
+ To export larger SimpleDB domains, add -w. This writes each chunk to file as it is received rather than storing in memory:
29
+
30
+ ```
31
+ sdbport export -k $AWS_ACCESS_KEY_ID -s $AWS_SECRET_ACCESS_KEY -r us-west-1 -n data -o /tmp/test-domain-dump -w
24
32
  ```
25
33
 
26
34
  Import into domain in us-east-1
27
35
 
28
36
  ```
29
- sdbport import -a $AWS_ACCESS_KEY_ID -s $AWS_SECRET_ACCESS_KEY -r us-west-1 -n data -i /tmp/test-domain-dump
37
+ sdbport import -k $AWS_ACCESS_KEY_ID -s $AWS_SECRET_ACCESS_KEY -r us-west-1 -n data -i /tmp/test-domain-dump
38
+ ```
30
39
 
31
40
  ## Exporting and importing from multiple accounts.
32
41
 
@@ -35,6 +35,17 @@ module Sdbport
35
35
  end
36
36
  end
37
37
 
38
+ def select_and_store_chunk_of_tokens(query, options = {})
39
+ options.merge! 'NextToken' => @token_for_next_chunk
40
+ chunk = sdb.select(query, options).body
41
+ @token_for_next_chunk = chunk['NextToken']
42
+ return chunk['Items']
43
+ end
44
+
45
+ def more_chunks?
46
+ @token_for_next_chunk != nil
47
+ end
48
+
38
49
  def count(domain)
39
50
  body = sdb.select("SELECT count(*) FROM `#{domain}`").body
40
51
  body['Items']['Domain']['Count'].first.to_i
@@ -19,7 +19,12 @@ module Sdbport
19
19
  :access_key => access_key,
20
20
  :secret_key => secret_key,
21
21
  :logger => logger
22
- exit 1 unless domain.export opts[:output]
22
+
23
+ if opts[:write_as_you_go]
24
+ exit 1 unless domain.export_sequential_write opts[:output]
25
+ else
26
+ exit 1 unless domain.export opts[:output]
27
+ end
23
28
  end
24
29
 
25
30
  def read_options
@@ -44,6 +49,7 @@ EOS
44
49
  opt :access_key, "AWS Access Key ID", :type => :string,
45
50
  :short => 'k'
46
51
  opt :secret_key, "AWS Secret Access Key", :type => :string
52
+ opt :write_as_you_go, "Write chunks to disk as they are received from Simple DB"
47
53
  end
48
54
  end
49
55
  end
@@ -18,6 +18,10 @@ module Sdbport
18
18
  domain_export.export output
19
19
  end
20
20
 
21
+ def export_sequential_write(output)
22
+ domain_export.export_sequential_write output
23
+ end
24
+
21
25
  def purge
22
26
  domain_purge.purge
23
27
  end
@@ -13,8 +13,7 @@ module Sdbport
13
13
  end
14
14
 
15
15
  def export(output)
16
- @logger.info "Export #{@name} in #{@region} to #{output}"
17
- file = File.open(output, 'w')
16
+ file = setup_file output
18
17
  export_domain.each do |item|
19
18
  file.write convert_to_string item
20
19
  file.write "\n"
@@ -22,8 +21,27 @@ module Sdbport
22
21
  return true if file.close.nil?
23
22
  end
24
23
 
24
+ def export_sequential_write(output)
25
+ file = setup_file output
26
+ @logger.info "Writing to disk as records received."
27
+
28
+ while true
29
+ export_domain_with_sequential_write.each do |item|
30
+ file.write convert_to_string item
31
+ file.write "\n"
32
+ end
33
+ break unless sdb.more_chunks?
34
+ end
35
+ return true if file.close.nil?
36
+ end
37
+
25
38
  private
26
39
 
40
+ def setup_file(output)
41
+ @logger.info "Export #{@name} in #{@region} to #{output}"
42
+ File.open(output, 'w')
43
+ end
44
+
27
45
  def sdb
28
46
  @sdb ||= AWS::SimpleDB.new :access_key => @access_key,
29
47
  :secret_key => @secret_key,
@@ -34,6 +52,10 @@ module Sdbport
34
52
  sdb.select_and_follow_tokens "select * from `#{@name}`"
35
53
  end
36
54
 
55
+ def export_domain_with_sequential_write
56
+ sdb.select_and_store_chunk_of_tokens "select * from `#{@name}`"
57
+ end
58
+
37
59
  def convert_to_string(item)
38
60
  item.to_json
39
61
  end
@@ -1,3 +1,3 @@
1
1
  module Sdbport
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -49,6 +49,29 @@ describe Sdbport do
49
49
  'id3' => 'val3' }
50
50
  end
51
51
 
52
+ it "should perform select query given and store next token" do
53
+ body_stub0 = stub 'body0', :body => { 'Items' =>
54
+ { 'id1' => 'val1' },
55
+ 'NextToken' => '1'
56
+ }
57
+ body_stub1 = stub 'body1', :body => { 'Items' =>
58
+ { 'id2' => 'val2' },
59
+ 'NextToken' => nil
60
+ }
61
+ @fog_mock.should_receive(:select).
62
+ with('select * from name', 'NextToken' => nil).
63
+ and_return body_stub0
64
+ @sdb.select_and_store_chunk_of_tokens('select * from name').
65
+ should == { 'id1' => 'val1' }
66
+ @sdb.more_chunks?.should be_true
67
+ @fog_mock.should_receive(:select).
68
+ with('select * from name', 'NextToken' => '1').
69
+ and_return body_stub1
70
+ @sdb.select_and_store_chunk_of_tokens('select * from name').
71
+ should == { 'id2' => 'val2' }
72
+ @sdb.more_chunks?.should be_false
73
+ end
74
+
52
75
  it "should create a new domain when it does not exist" do
53
76
  @fog_mock.stub :list_domains => @body_stub
54
77
  @body_stub.stub :body => { 'Domains' => [] }
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sdbport::CLI::Destroy do
4
+ before do
5
+ @domain_mock = mock "domain"
6
+ @logger_stub = stub "logger"
7
+ @options = { :name => 'daname',
8
+ :region => 'us-west-1',
9
+ :secret_key => 'private',
10
+ :access_key => 'abc',
11
+ :level => 'debug' }
12
+
13
+ Sdbport::SdbportLogger.should_receive(:new).
14
+ with(:log_level => 'debug').
15
+ and_return @logger_stub
16
+ @destroy = Sdbport::CLI::Destroy.new
17
+ end
18
+
19
+ it "should perform destroy the domain" do
20
+ Trollop.stub :options => @options
21
+ Sdbport::Domain.should_receive(:new).
22
+ with(:name => 'daname',
23
+ :region => 'us-west-1',
24
+ :secret_key => 'private',
25
+ :access_key => 'abc',
26
+ :logger => @logger_stub).
27
+ and_return @domain_mock
28
+ @domain_mock.should_receive(:destroy).and_return true
29
+ @destroy.destroy
30
+ end
31
+
32
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sdbport::CLI::Export do
4
+ before do
5
+ @domain_mock = mock "domain"
6
+ @logger_stub = stub "logger"
7
+ @options = { :name => 'daname',
8
+ :region => 'us-west-1',
9
+ :secret_key => 'private',
10
+ :access_key => 'abc',
11
+ :level => 'debug',
12
+ :output => '/test/file' }
13
+
14
+ Sdbport::SdbportLogger.should_receive(:new).
15
+ with(:log_level => 'debug').
16
+ and_return @logger_stub
17
+ @export = Sdbport::CLI::Export.new
18
+ end
19
+
20
+ it "should perform a in memeory write" do
21
+ Trollop.stub :options => @options
22
+ Sdbport::Domain.should_receive(:new).
23
+ with(:name => 'daname',
24
+ :region => 'us-west-1',
25
+ :secret_key => 'private',
26
+ :access_key => 'abc',
27
+ :logger => @logger_stub).
28
+ and_return @domain_mock
29
+ @domain_mock.should_receive(:export).with('/test/file').
30
+ and_return true
31
+ @export.export
32
+ end
33
+
34
+ it "should perform a sequential write" do
35
+ @options.merge! :write_as_you_go => true
36
+ Trollop.stub :options => @options
37
+ Sdbport::Domain.should_receive(:new).
38
+ with(:name => 'daname',
39
+ :region => 'us-west-1',
40
+ :secret_key => 'private',
41
+ :access_key => 'abc',
42
+ :logger => @logger_stub).
43
+ and_return @domain_mock
44
+ @domain_mock.should_receive(:export_sequential_write).
45
+ with('/test/file').
46
+ and_return true
47
+ @export.export
48
+ end
49
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sdbport::CLI::Import do
4
+ before do
5
+ @domain_mock = mock "domain"
6
+ @logger_stub = stub "logger"
7
+ @options = { :name => 'daname',
8
+ :region => 'us-west-1',
9
+ :secret_key => 'private',
10
+ :access_key => 'abc',
11
+ :level => 'debug',
12
+ :input => '/test/file' }
13
+
14
+ Sdbport::SdbportLogger.should_receive(:new).
15
+ with(:log_level => 'debug').
16
+ and_return @logger_stub
17
+ @import = Sdbport::CLI::Import.new
18
+ end
19
+
20
+ it "should perform an import from file" do
21
+ Trollop.stub :options => @options
22
+ Sdbport::Domain.should_receive(:new).
23
+ with(:name => 'daname',
24
+ :region => 'us-west-1',
25
+ :secret_key => 'private',
26
+ :access_key => 'abc',
27
+ :logger => @logger_stub).
28
+ and_return @domain_mock
29
+ @domain_mock.should_receive(:import).with('/test/file').
30
+ and_return true
31
+ @import.import
32
+ end
33
+
34
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sdbport::CLI::Purge do
4
+ before do
5
+ @domain_mock = mock "domain"
6
+ @logger_stub = stub "logger"
7
+ @options = { :name => 'daname',
8
+ :region => 'us-west-1',
9
+ :secret_key => 'private',
10
+ :access_key => 'abc',
11
+ :level => 'debug' }
12
+
13
+ Sdbport::SdbportLogger.should_receive(:new).
14
+ with(:log_level => 'debug').
15
+ and_return @logger_stub
16
+ @purge = Sdbport::CLI::Purge.new
17
+ end
18
+
19
+ it "should perform a purge on the domain" do
20
+ Trollop.stub :options => @options
21
+ Sdbport::Domain.should_receive(:new).
22
+ with(:name => 'daname',
23
+ :region => 'us-west-1',
24
+ :secret_key => 'private',
25
+ :access_key => 'abc',
26
+ :logger => @logger_stub).
27
+ and_return @domain_mock
28
+ @domain_mock.should_receive(:purge).and_return true
29
+ @purge.purge
30
+ end
31
+
32
+ end
@@ -30,4 +30,22 @@ describe Sdbport do
30
30
  @export.export('/tmp/file').should be_true
31
31
  end
32
32
 
33
+ it "should export the given domain sequentially to disk" do
34
+ File.should_receive(:open).with('/tmp/file', 'w').
35
+ and_return @file_mock
36
+ data = { 'item1' =>
37
+ { 'attribute' => [ 'value' ] },
38
+ 'item2' =>
39
+ { 'attribute' => [ 'different' ] }
40
+ }
41
+ @sdb_mock.should_receive(:select_and_store_chunk_of_tokens).
42
+ with('select * from `name`').
43
+ and_return data
44
+ @file_mock.should_receive(:write).with("[\"item1\",{\"attribute\":[\"value\"]}]")
45
+ @file_mock.should_receive(:write).with("[\"item2\",{\"attribute\":[\"different\"]}]")
46
+ @sdb_mock.should_receive(:more_chunks?).and_return false
47
+ @file_mock.should_receive(:write).with("\n").exactly(2).times
48
+ @file_mock.should_receive(:close).and_return nil
49
+ @export.export_sequential_write('/tmp/file').should be_true
50
+ end
33
51
  end
@@ -15,7 +15,7 @@ describe Sdbport do
15
15
  @domain.import('/tmp/file').should be_true
16
16
  end
17
17
 
18
- it "should call domain_export from the given output" do
18
+ it "should call export from the given output" do
19
19
  Sdbport::Domain::Export.should_receive(:new).
20
20
  with(:args1 => 'val1').
21
21
  and_return @mock
@@ -24,6 +24,15 @@ describe Sdbport do
24
24
  @domain.export('/tmp/file').should be_true
25
25
  end
26
26
 
27
+ it "should call export_sequential_write with the given output" do
28
+ Sdbport::Domain::Export.should_receive(:new).
29
+ with(:args1 => 'val1').
30
+ and_return @mock
31
+ @mock.should_receive(:export_sequential_write).with('/tmp/file').
32
+ and_return true
33
+ @domain.export_sequential_write('/tmp/file').should be_true
34
+ end
35
+
27
36
  it "should call domain_purge" do
28
37
  Sdbport::Domain::Purge.stub :new => @mock
29
38
  @mock.should_receive(:purge).and_return true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sdbport
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-02 00:00:00.000000000 Z
12
+ date: 2012-10-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70269257047280 !ruby/object:Gem::Requirement
16
+ requirement: &70336407307380 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70269257047280
24
+ version_requirements: *70336407307380
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: fog
27
- requirement: &70269257046800 !ruby/object:Gem::Requirement
27
+ requirement: &70336407306100 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70269257046800
35
+ version_requirements: *70336407306100
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: trollop
38
- requirement: &70269257046300 !ruby/object:Gem::Requirement
38
+ requirement: &70336407304460 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70269257046300
46
+ version_requirements: *70336407304460
47
47
  description: Import and export AWS SimpleDB domains.
48
48
  email:
49
49
  - brett@weav.net
@@ -79,6 +79,10 @@ files:
79
79
  - lib/sdbport/version.rb
80
80
  - sdbport.gemspec
81
81
  - spec/aws/simpledb_spec.rb
82
+ - spec/cli/destroy_spec.rb
83
+ - spec/cli/export_spec.rb
84
+ - spec/cli/import_spec.rb
85
+ - spec/cli/purge_spec.rb
82
86
  - spec/cli_spec.rb
83
87
  - spec/config_spec.rb
84
88
  - spec/domain/destroy_spec.rb
@@ -102,7 +106,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
102
106
  version: '0'
103
107
  segments:
104
108
  - 0
105
- hash: 3777096327641096662
109
+ hash: 3976557266021725498
106
110
  required_rubygems_version: !ruby/object:Gem::Requirement
107
111
  none: false
108
112
  requirements:
@@ -111,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
111
115
  version: '0'
112
116
  segments:
113
117
  - 0
114
- hash: 3777096327641096662
118
+ hash: 3976557266021725498
115
119
  requirements: []
116
120
  rubyforge_project:
117
121
  rubygems_version: 1.8.16
@@ -120,6 +124,10 @@ specification_version: 3
120
124
  summary: Import and export AWS SimpleDB domains.
121
125
  test_files:
122
126
  - spec/aws/simpledb_spec.rb
127
+ - spec/cli/destroy_spec.rb
128
+ - spec/cli/export_spec.rb
129
+ - spec/cli/import_spec.rb
130
+ - spec/cli/purge_spec.rb
123
131
  - spec/cli_spec.rb
124
132
  - spec/config_spec.rb
125
133
  - spec/domain/destroy_spec.rb