snapshot_reload 1.0.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/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rvmrc +48 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +69 -0
- data/LICENSE.txt +22 -0
- data/README.md +114 -0
- data/README.rdoc +19 -0
- data/Rakefile +66 -0
- data/bin/snapshot_reload +70 -0
- data/features/snapshot_live.feature +29 -0
- data/features/snapshot_reload.feature +171 -0
- data/features/step_definitions/snapshot_live_steps.rb +4 -0
- data/features/step_definitions/snapshot_reload_steps.rb +1 -0
- data/features/support/env.rb +17 -0
- data/lib/snapshot_reload.rb +129 -0
- data/lib/snapshot_reload/String.rb +25 -0
- data/lib/snapshot_reload/defaults.rb +18 -0
- data/lib/snapshot_reload/errors.rb +31 -0
- data/lib/snapshot_reload/fetch.rb +161 -0
- data/lib/snapshot_reload/reload.rb +69 -0
- data/lib/snapshot_reload/validate.rb +111 -0
- data/lib/snapshot_reload/version.rb +18 -0
- data/snapshot_reload.gemspec +25 -0
- data/spec/snapshot_reload_spec.rb +109 -0
- data/spec/spec_helper.rb +1 -0
- metadata +178 -0
@@ -0,0 +1,171 @@
|
|
1
|
+
#
|
2
|
+
# +Copyright+:: (c) 2012, Novu, LLC
|
3
|
+
# +License+:: All rights reserverd. For internal and private use only
|
4
|
+
# +Author+:: Tamara Temple <tamara.temple@novu.com>
|
5
|
+
#
|
6
|
+
|
7
|
+
# TODO: consolidate scenarios into outlines to make them DRYer
|
8
|
+
|
9
|
+
Feature: ensure command line options work as expected
|
10
|
+
In order to test the command line options
|
11
|
+
As a tester
|
12
|
+
I want to try out all the options
|
13
|
+
|
14
|
+
Scenario: learn how to use application
|
15
|
+
When I get help for "snapshot_reload"
|
16
|
+
Then the exit status should be 0
|
17
|
+
And the banner should be present
|
18
|
+
And the banner should document that this app takes options
|
19
|
+
And the following options should be documented:
|
20
|
+
|--version|
|
21
|
+
|--log-level LEVEL|
|
22
|
+
|--env ENVIRONMENT|
|
23
|
+
|--source S3SOURCE|
|
24
|
+
|--aws-conf AWS_CONFIG|
|
25
|
+
|--aws-key AWSKEY|
|
26
|
+
|--aws-secret AWSSECRET|
|
27
|
+
And the banner should document that this app's arguments are:
|
28
|
+
|config|which is required|
|
29
|
+
|
30
|
+
Scenario: omit a configuration file
|
31
|
+
When I run `snapshot_reload --log-level debug`
|
32
|
+
Then the output should contain "parse error: 'config' is required"
|
33
|
+
And the banner should be present
|
34
|
+
And the exit status should not be 0
|
35
|
+
|
36
|
+
Scenario: provide non-existant configuration file
|
37
|
+
When I run `snapshot_reload --log-level debug --dry-run config`
|
38
|
+
Then the exit status should be 1
|
39
|
+
And the output should contain "config file does not exist"
|
40
|
+
|
41
|
+
Scenario: provide non-yaml configuration file
|
42
|
+
Given a file named "config.txt" with:
|
43
|
+
"""
|
44
|
+
Hello There!
|
45
|
+
"""
|
46
|
+
When I run `snapshot_reload --dry-run config.txt`
|
47
|
+
Then the exit status should be 2
|
48
|
+
And the output should contain "config.txt is not YAML"
|
49
|
+
|
50
|
+
Scenario: provide existing configuration file and no credential file
|
51
|
+
Given a file named "config.yaml" with:
|
52
|
+
"""
|
53
|
+
qa:
|
54
|
+
adapter: mysql2
|
55
|
+
host: localhost
|
56
|
+
encoding: utf8
|
57
|
+
database: novu_test
|
58
|
+
pool: 5
|
59
|
+
username: novuadmin
|
60
|
+
password:
|
61
|
+
"""
|
62
|
+
When I run `snapshot_reload --log-level debug --dry-run --aws-conf aws_cred --source s3://tam-test-2/db-backups/novu-2012-12-11.sql.gz config.yaml`
|
63
|
+
Then the exit status should be 4
|
64
|
+
And the output should contain "aws_cred does not exist!"
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
Scenario: provide existing configuration file and credential file
|
69
|
+
Given a file named "config.yaml" with:
|
70
|
+
"""
|
71
|
+
qa:
|
72
|
+
adapter: mysql2
|
73
|
+
host: localhost
|
74
|
+
encoding: utf8
|
75
|
+
database: novu_test
|
76
|
+
pool: 5
|
77
|
+
username: novuadmin
|
78
|
+
password:
|
79
|
+
"""
|
80
|
+
Given a file named "aws_cred" with:
|
81
|
+
"""
|
82
|
+
access_key = A1234
|
83
|
+
secret_key = S5678
|
84
|
+
"""
|
85
|
+
When I run `snapshot_reload --log-level debug --dry-run --aws-conf aws_cred --source s3://tam-test-2/db-backups/novu-2012-12-11.sql.gz config.yaml`
|
86
|
+
Then the exit status should be 0
|
87
|
+
|
88
|
+
Scenario: provide existing configuration file with environment "other" and credential file
|
89
|
+
Given a file named "config.yaml" with:
|
90
|
+
"""
|
91
|
+
other:
|
92
|
+
adapter: mysql2
|
93
|
+
host: localhost
|
94
|
+
encoding: utf8
|
95
|
+
database: novu_test
|
96
|
+
pool: 5
|
97
|
+
username: novuadmin
|
98
|
+
password:
|
99
|
+
"""
|
100
|
+
Given a file named "aws_cred" with:
|
101
|
+
"""
|
102
|
+
access_key = A1234
|
103
|
+
secret_key = S5678
|
104
|
+
"""
|
105
|
+
When I run `snapshot_reload --log-level debug --dry-run --aws-conf aws_cred --env other --source s3://tam-test-2/db-backups/novu-2012-12-11.sql.gz config.yaml`
|
106
|
+
Then the exit status should be 0
|
107
|
+
|
108
|
+
Scenario: provide existing configuration file with environment "other" and aws-key but omit awk-secret
|
109
|
+
Given a file named "config.yaml" with:
|
110
|
+
"""
|
111
|
+
other:
|
112
|
+
adapter: mysql2
|
113
|
+
host: localhost
|
114
|
+
encoding: utf8
|
115
|
+
database: novu_test
|
116
|
+
pool: 5
|
117
|
+
username: novuadmin
|
118
|
+
password:
|
119
|
+
"""
|
120
|
+
When I run `snapshot_reload --log-level debug --dry-run --aws-key A1234 --env other --source s3://tam-test-2/db-backups/novu-2012-12-11.sql.gz config.yaml`
|
121
|
+
Then the exit status should be 9
|
122
|
+
And the output should contain "Must provide *both* aws-key and aws-secret"
|
123
|
+
|
124
|
+
Scenario: provide existing configuration file with environment "other" and aws-secret but omit awk-key
|
125
|
+
Given a file named "config.yaml" with:
|
126
|
+
"""
|
127
|
+
other:
|
128
|
+
adapter: mysql2
|
129
|
+
host: localhost
|
130
|
+
encoding: utf8
|
131
|
+
database: novu_test
|
132
|
+
pool: 5
|
133
|
+
username: novuadmin
|
134
|
+
password:
|
135
|
+
"""
|
136
|
+
When I run `snapshot_reload --log-level debug --dry-run --aws-secret S5678 --env other --source s3://tam-test-2/db-backups/novu-2012-12-11.sql.gz config.yaml`
|
137
|
+
Then the exit status should be 9
|
138
|
+
And the output should contain "Must provide *both* aws-key and aws-secret"
|
139
|
+
|
140
|
+
Scenario: provide --verbose switch
|
141
|
+
Given a file named "config.yaml" with:
|
142
|
+
"""
|
143
|
+
qa:
|
144
|
+
adapter: mysql2
|
145
|
+
host: localhost
|
146
|
+
encoding: utf8
|
147
|
+
database: novu_test
|
148
|
+
pool: 5
|
149
|
+
username: novuadmin
|
150
|
+
password:
|
151
|
+
"""
|
152
|
+
Given a file named "aws_cred" with:
|
153
|
+
"""
|
154
|
+
access_key = A1234
|
155
|
+
secret_key = S5678
|
156
|
+
"""
|
157
|
+
When I run `snapshot_reload --log-level debug --dry-run --aws-conf aws_cred --verbose --source s3://tam-test-2/db-backups/novu-2012-12-11.sql.gz config.yaml`
|
158
|
+
Then the exit status should be 0
|
159
|
+
And the output should contain "config: "
|
160
|
+
And the output should contain "env: qa"
|
161
|
+
And the output should contain "host: localhost"
|
162
|
+
And the output should contain "database: novu_test"
|
163
|
+
And the output should contain "username: novuadmin"
|
164
|
+
And the output should contain "password: "
|
165
|
+
And the output should contain "source: "
|
166
|
+
And the output should contain "aws key: A1234"
|
167
|
+
And the output should contain "aws secret: S5678"
|
168
|
+
And the output should contain "dry run: true"
|
169
|
+
And the output should contain "verbose: true"
|
170
|
+
And the output should contain "quiet: false"
|
171
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
# Put your step definitions here
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
require 'methadone/cucumber'
|
3
|
+
|
4
|
+
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
5
|
+
LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
6
|
+
|
7
|
+
Before do
|
8
|
+
# Using "announce" causes massive warnings on 1.9.2
|
9
|
+
@puts = true
|
10
|
+
@original_rubylib = ENV['RUBYLIB']
|
11
|
+
ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
12
|
+
@aruba_timeout_seconds = 3600 # need enough time to transfer the large sql file
|
13
|
+
end
|
14
|
+
|
15
|
+
After do
|
16
|
+
ENV['RUBYLIB'] = @original_rubylib
|
17
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
snapshot_reload.rb
|
4
|
+
|
5
|
+
+Copyright:+:: (c) 2012, Novu, LLC
|
6
|
+
+License:+:: All rights reserved. For internatl and private use only.
|
7
|
+
+Author:+:: Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
=end
|
10
|
+
|
11
|
+
|
12
|
+
require "snapshot_reload/version"
|
13
|
+
require "snapshot_reload/errors"
|
14
|
+
require "snapshot_reload/defaults"
|
15
|
+
require "snapshot_reload/validate"
|
16
|
+
require "snapshot_reload/fetch"
|
17
|
+
require "snapshot_reload/reload"
|
18
|
+
require "snapshot_reload/String"
|
19
|
+
require 'methadone'
|
20
|
+
|
21
|
+
module SnapshotReload
|
22
|
+
class SnapshotReload
|
23
|
+
include Methadone::CLILogging
|
24
|
+
|
25
|
+
# attr_reader :config, :env, :host, :database, :username, :password, :source, :aws_key, :aws_secret, :sql_file
|
26
|
+
|
27
|
+
def initialize(config, options=nil)
|
28
|
+
|
29
|
+
options = Hash.new if options.nil?
|
30
|
+
|
31
|
+
@config = validate_configuration(config)
|
32
|
+
@env = validate_environment(options[:env], @config)
|
33
|
+
|
34
|
+
@host = check_field(@config,@env,'host')
|
35
|
+
@database = check_field(@config,@env,'database')
|
36
|
+
@username = check_field(@config,@env,'username')
|
37
|
+
@password = check_field(@config,@env,'password',false)
|
38
|
+
|
39
|
+
@source = validate_source(options[:source])
|
40
|
+
|
41
|
+
if @source.match('^s3://')
|
42
|
+
aws = validate_aws(options['aws-conf'],
|
43
|
+
options['aws-key'], options['aws-secret'])
|
44
|
+
@aws_key = aws[0]
|
45
|
+
@aws_secret = aws[1]
|
46
|
+
end
|
47
|
+
|
48
|
+
@dry_run = options['dry-run'] ||= false
|
49
|
+
|
50
|
+
@verbose = options[:verbose] ||= false
|
51
|
+
@quiet = options[:quiet] ||= false
|
52
|
+
|
53
|
+
@verbose = false if @quiet
|
54
|
+
|
55
|
+
@sql_file = ''
|
56
|
+
|
57
|
+
if @verbose
|
58
|
+
info("config: #{@config.to_s}")
|
59
|
+
info("env: #{@env.to_s}")
|
60
|
+
info("host: #{@host.to_s}")
|
61
|
+
info("database: #{@database.to_s}")
|
62
|
+
info("username: #{@username.to_s}")
|
63
|
+
info("password: #{@password.to_s}")
|
64
|
+
info("source: #{@source.to_s}")
|
65
|
+
info("aws key: #{@aws_key}")
|
66
|
+
info("aws secret: #{@aws_secret}")
|
67
|
+
info("dry run: #{@dry_run}")
|
68
|
+
info("verbose: #{@verbose}")
|
69
|
+
info("quiet: #{@quiet}")
|
70
|
+
end
|
71
|
+
|
72
|
+
reload # and here all the magic happens!!
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
def config
|
77
|
+
@config
|
78
|
+
end
|
79
|
+
|
80
|
+
def env
|
81
|
+
@env
|
82
|
+
end
|
83
|
+
|
84
|
+
def host
|
85
|
+
@host
|
86
|
+
end
|
87
|
+
|
88
|
+
def database
|
89
|
+
@database
|
90
|
+
end
|
91
|
+
|
92
|
+
def username
|
93
|
+
@username
|
94
|
+
end
|
95
|
+
|
96
|
+
def password
|
97
|
+
@password
|
98
|
+
end
|
99
|
+
|
100
|
+
def source
|
101
|
+
@source
|
102
|
+
end
|
103
|
+
|
104
|
+
def aws_key
|
105
|
+
@aws_key
|
106
|
+
end
|
107
|
+
|
108
|
+
def aws_secret
|
109
|
+
@aws_secret
|
110
|
+
end
|
111
|
+
|
112
|
+
def sql_file
|
113
|
+
@sql_file
|
114
|
+
end
|
115
|
+
|
116
|
+
def dry_run?
|
117
|
+
@dry_run
|
118
|
+
end
|
119
|
+
|
120
|
+
def verbose?
|
121
|
+
@verbose
|
122
|
+
end
|
123
|
+
|
124
|
+
def quiet?
|
125
|
+
@quiet
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
String.rb
|
4
|
+
|
5
|
+
+Copyright:+:: (c) 2012, Novu, LLC
|
6
|
+
+License:+:: All rights reserved. For internatl and private use only.
|
7
|
+
+Author:+:: Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
Additional methods for String and NilClass, cos I want to.
|
10
|
+
Seriously, doesn't "present?" look better that "not nil?" ??
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
|
15
|
+
class String
|
16
|
+
def present?
|
17
|
+
true unless self.nil? or self.empty?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class NilClass
|
22
|
+
def present?
|
23
|
+
true unless self.nil?
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
Defaults used in the SnapshotReload module
|
4
|
+
|
5
|
+
+Copyright:+ (c) 2012 Novu, LLC
|
6
|
+
+License:+ All rights reserved. For internal and private use only
|
7
|
+
+Author:+ Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
=end
|
10
|
+
|
11
|
+
module SnapshotReload
|
12
|
+
DEFAULT_S3_SOURCE = %q{s3://novu_backups/db_backups/clean-mysqldump.sql.gz}
|
13
|
+
DEFAULT_AWS_CREDS = %q{/opt/novu/.s3cfg}
|
14
|
+
DEFAULT_ENVIRONMENT = %q{qa}
|
15
|
+
|
16
|
+
CHUNK_SIZE = 10 * 1024 * 1024 # chunk size to pull over file from S3
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
errors.rb
|
4
|
+
|
5
|
+
+Copyright:+:: (c) 2012, Novu, LLC
|
6
|
+
+License:+:: All rights reserved. For internatl and private use only.
|
7
|
+
+Author:+:: Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
Enumerate program exit errors as descriptive constants
|
10
|
+
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
module SnapshotReload
|
15
|
+
|
16
|
+
ENOCONFIG = 1
|
17
|
+
ECONFIGNOTYAML = 2
|
18
|
+
ENOENVINCONFIG = 3
|
19
|
+
ENOCRED = 4
|
20
|
+
ENOFIELD = 5
|
21
|
+
ENOSQLFILE = 6
|
22
|
+
ECMDFAILED = 7
|
23
|
+
EBADS3URI = 8
|
24
|
+
EMISSINGKEYORSECRET = 9
|
25
|
+
ENOWRITE = 10
|
26
|
+
EDROPFAILED = 11
|
27
|
+
ENOBUCKET = 12
|
28
|
+
ENOOBJECT = 13
|
29
|
+
ENOS3FILES = 14
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
fetch.rb
|
4
|
+
|
5
|
+
+Copyright:+:: (c) 2012, Novu, LLC
|
6
|
+
+License:+:: All rights reserved. For internatl and private use only.
|
7
|
+
+Author:+:: Tamara Temple <tamara.temple@novu.com>
|
8
|
+
|
9
|
+
=end
|
10
|
+
|
11
|
+
require 'methadone'
|
12
|
+
require 'fog'
|
13
|
+
|
14
|
+
module SnapshotReload
|
15
|
+
class SnapshotReload
|
16
|
+
|
17
|
+
def fetch_snapshot
|
18
|
+
|
19
|
+
if @source.match('^s3://')
|
20
|
+
@sql_file = s3_fetch
|
21
|
+
else
|
22
|
+
@sql_file = @source
|
23
|
+
end
|
24
|
+
|
25
|
+
unless File.exists?(@sql_file)
|
26
|
+
fatal("#{@sql_file} does not exist!")
|
27
|
+
exit(ENOSQLFILE)
|
28
|
+
end
|
29
|
+
|
30
|
+
info("SQL file: #{@sql_file}") if @verbose
|
31
|
+
|
32
|
+
@sql_file
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
=begin
|
38
|
+
|
39
|
+
Helper methods for fetch_snapshot
|
40
|
+
|
41
|
+
=end
|
42
|
+
|
43
|
+
|
44
|
+
def s3_fetch
|
45
|
+
|
46
|
+
matches = @source.match('^s3://([^/]+)/(.*)$')
|
47
|
+
if matches
|
48
|
+
s3_bucket_name=matches[1]
|
49
|
+
s3_object_name=matches[2]
|
50
|
+
else
|
51
|
+
fatal("#{@source} is not a valid s3 uri (must be s3://bucket/object)")
|
52
|
+
exit(EBADS3URI)
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
warn("Dry run, nothing will be fetched from S3") if @dry_run
|
57
|
+
|
58
|
+
info("Connecting to AWS S3") if @verbose
|
59
|
+
|
60
|
+
connection = Fog::Storage.new(:provider => 'AWS',
|
61
|
+
:aws_access_key_id => @aws_key,
|
62
|
+
:aws_secret_access_key => @aws_secret) unless @dry_run
|
63
|
+
|
64
|
+
|
65
|
+
unless @dry_run
|
66
|
+
|
67
|
+
buckets = connection.directories.select do |dir|
|
68
|
+
debug("Dir: #{dir.key}")
|
69
|
+
dir if dir.key == s3_bucket_name
|
70
|
+
end
|
71
|
+
|
72
|
+
if buckets.nil? or buckets.empty?
|
73
|
+
fatal("no bucket #{s3_bucket_name} found")
|
74
|
+
exit(ENOBUCKET)
|
75
|
+
end
|
76
|
+
|
77
|
+
s3_bucket = buckets.first
|
78
|
+
|
79
|
+
info("S3 Bucket #{s3_bucket.key} found") if @verbose
|
80
|
+
|
81
|
+
if s3_bucket.files.nil?
|
82
|
+
error("No files in S3 bucket #{s3_bucket_name}")
|
83
|
+
exit(ENOS3FILES)
|
84
|
+
end
|
85
|
+
|
86
|
+
files = s3_bucket.files.select do |file|
|
87
|
+
debug("File: #{file.key}")
|
88
|
+
file if file.key == s3_object_name
|
89
|
+
end
|
90
|
+
|
91
|
+
if files.nil? or files.empty?
|
92
|
+
fatal("no object #{s3_object_name} found")
|
93
|
+
exit(ENOOBJECT)
|
94
|
+
end
|
95
|
+
|
96
|
+
s3_object = files.first
|
97
|
+
|
98
|
+
info("S3 Object #{s3_object_name} found in #{s3_bucket_name}") if @verbose
|
99
|
+
|
100
|
+
s3_file = File.basename(s3_object.key)
|
101
|
+
s3_object_content_length = s3_object.content_length
|
102
|
+
|
103
|
+
else # this is just a dry run, make up stuff
|
104
|
+
|
105
|
+
s3_file = File.basename(s3_object_name)
|
106
|
+
s3_object_content_length = 0
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
if File.exists?(s3_file) and
|
111
|
+
not (File.stat(s3_file).file? and File.stat(s3_file).writable?)
|
112
|
+
fatal("#{s3_file} is not writable!")
|
113
|
+
exit(ENOWRITE)
|
114
|
+
end
|
115
|
+
|
116
|
+
info("Writing to file #{s3_file}") if @verbose
|
117
|
+
|
118
|
+
File.open(s3_file,'w') do |file|
|
119
|
+
|
120
|
+
# Calculate number of batches for extremely large files
|
121
|
+
|
122
|
+
batches = s3_object_content_length / CHUNK_SIZE
|
123
|
+
|
124
|
+
(0..batches).each do |batch|
|
125
|
+
start_byte = batch * CHUNK_SIZE
|
126
|
+
end_byte = start_byte + CHUNK_SIZE - 1
|
127
|
+
contents = get_the_object(connection, s3_bucket_name, s3_object_name, start_byte, end_byte)
|
128
|
+
info("Writing #{contents.length} bytes to #{s3_file}") if @verbose
|
129
|
+
file.write(contents)
|
130
|
+
end
|
131
|
+
|
132
|
+
# Now get the remainder
|
133
|
+
start_byte = batches * CHUNK_SIZE
|
134
|
+
end_byte = s3_object_content_length
|
135
|
+
contents = get_the_object(connection, s3_bucket_name, s3_object_name, start_byte, end_byte)
|
136
|
+
info("Writing #{contents.length} bytes to #{s3_file}") if @verbose
|
137
|
+
file.write(contents)
|
138
|
+
|
139
|
+
end # File.open
|
140
|
+
|
141
|
+
s3_file_stat = File.stat(s3_file)
|
142
|
+
info("Wrote #{s3_file_stat.size} bytes to #{s3_file}") if @verbose
|
143
|
+
|
144
|
+
s3_file # return the name of file written
|
145
|
+
|
146
|
+
end # method s3_fetch
|
147
|
+
|
148
|
+
def get_the_object(cnxn, bucket, name, range_start, range_end)
|
149
|
+
|
150
|
+
get_object_options = { 'Range' => "bytes=%d-%d" % [ range_start, range_end ] }
|
151
|
+
info("Getting #{name} from #{bucket}, range #{get_object_options['Range']}") if @verbose
|
152
|
+
return '' if @dry_run
|
153
|
+
response = cnxn.get_object(bucket,name,get_object_options)
|
154
|
+
debug("Response.class: #{response.class}")
|
155
|
+
debug("Response.status: #{response.status}")
|
156
|
+
response.body
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|