sdbport 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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