buckler 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.
- checksums.yaml +7 -0
- data/.gitignore +66 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -0
- data/.yardopts +4 -0
- data/CONTRIBUTING.md +29 -0
- data/Gemfile +2 -0
- data/LICENSE.md +9 -0
- data/README.md +96 -0
- data/Rakefile +16 -0
- data/bin/bucket +18 -0
- data/buckler.gemspec +31 -0
- data/lib/buckler.rb +29 -0
- data/lib/buckler/actions.rb +90 -0
- data/lib/buckler/actions/create_bucket.rb +53 -0
- data/lib/buckler/actions/destroy_bucket.rb +22 -0
- data/lib/buckler/actions/empty_bucket.rb +16 -0
- data/lib/buckler/actions/get_bucket.rb +0 -0
- data/lib/buckler/actions/list_buckets.rb +21 -0
- data/lib/buckler/actions/list_regions.rb +23 -0
- data/lib/buckler/actions/sync_buckets.rb +106 -0
- data/lib/buckler/aws.rb +81 -0
- data/lib/buckler/commands.rb +271 -0
- data/lib/buckler/heroku.rb +41 -0
- data/lib/buckler/logging.rb +19 -0
- data/lib/buckler/monkey_patches.rb +19 -0
- data/lib/buckler/regions.rb +23 -0
- data/lib/buckler/strings.rb +24 -0
- data/lib/buckler/thread_dispatch.rb +48 -0
- data/lib/buckler/version.rb +14 -0
- data/test/buckler_test.rb +80 -0
- data/test/integration/bad_options_test.rb +25 -0
- data/test/integration/create_bucket_test.rb +27 -0
- data/test/integration/destroy_bucket_test.rb +21 -0
- data/test/integration/empty_bucket_test.rb +25 -0
- data/test/integration/list_buckets_test.rb +20 -0
- data/test/integration/list_regions_test.rb +15 -0
- data/test/integration/sync_buckets_test.rb +30 -0
- data/test/run.rb +23 -0
- metadata +192 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module Buckler
|
2
|
+
|
3
|
+
def self.destroy_bucket!(name:, confirmation:nil)
|
4
|
+
|
5
|
+
connect_to_s3!
|
6
|
+
@bucket = get_bucket!(name)
|
7
|
+
require_confirmation!(name_required:name, confirmation:confirmation)
|
8
|
+
|
9
|
+
if @bucket.versioning.status == "Enabled"
|
10
|
+
log "The bucket #{name.bucketize} has versioning enabled, it cannot be deleted."
|
11
|
+
log "You must disable versioning in the AWS Mangement Console."
|
12
|
+
exit false
|
13
|
+
end
|
14
|
+
|
15
|
+
log "Destroying bucket #{name.bucketize}…"
|
16
|
+
@bucket.delete!(max_attempts:3)
|
17
|
+
log "Bucket #{name.bucketize} was destroyed ✔"
|
18
|
+
exit true
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Buckler
|
2
|
+
|
3
|
+
def self.empty_bucket!(name:, confirmation:nil)
|
4
|
+
|
5
|
+
connect_to_s3!
|
6
|
+
@bucket = get_bucket!(name)
|
7
|
+
require_confirmation!(name_required:name, confirmation:confirmation)
|
8
|
+
|
9
|
+
log "Deleting all objects in bucket #{name.bucketize}…"
|
10
|
+
@bucket.clear!
|
11
|
+
log "Bucket #{name.bucketize} is now empty ✔"
|
12
|
+
exit true
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Buckler
|
2
|
+
|
3
|
+
def self.list_buckets!
|
4
|
+
|
5
|
+
connect_to_s3!
|
6
|
+
|
7
|
+
verbose "Fetching buckets visible to #{@aws_access_key_id}…"
|
8
|
+
table = [["NAME", "REGION", "VERSIONING"]]
|
9
|
+
|
10
|
+
@s3.list_buckets.buckets.each do |bucket|
|
11
|
+
region = @s3.get_bucket_location(bucket:bucket.name).location_constraint.presence || "us-east-1"
|
12
|
+
versioning = @s3.get_bucket_versioning(bucket:bucket.name).status.presence || "Not Configured"
|
13
|
+
table << [bucket.name, region, versioning]
|
14
|
+
end
|
15
|
+
|
16
|
+
puts_table!(table)
|
17
|
+
exit true
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Buckler
|
2
|
+
|
3
|
+
def self.list_regions!
|
4
|
+
|
5
|
+
table = [["REGION", "NAME", nil]]
|
6
|
+
|
7
|
+
S3_BUCKET_REGIONS.each do |name, human_name|
|
8
|
+
case name
|
9
|
+
when "us-east-1"
|
10
|
+
table << [name, human_name, "Default region"]
|
11
|
+
when "cn-north-1"
|
12
|
+
table << [name, human_name, "Requires chinese account"]
|
13
|
+
else
|
14
|
+
table << [name, human_name, nil]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
puts_table!(table)
|
19
|
+
exit true
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module Buckler
|
2
|
+
|
3
|
+
def self.sync_buckets!(source_name:, target_name:, confirmation:nil)
|
4
|
+
|
5
|
+
unless source_name.present? && target_name.present?
|
6
|
+
alert "You must provide both a source bucket and a target bucket"
|
7
|
+
alert "Usage: bucket sync <source-bucket> <target-bucket>"
|
8
|
+
exit false
|
9
|
+
end
|
10
|
+
|
11
|
+
unless source_name != target_name
|
12
|
+
alert "The source bucket name and target bucket name must be different"
|
13
|
+
exit false
|
14
|
+
end
|
15
|
+
|
16
|
+
connect_to_s3!
|
17
|
+
@source_bucket = get_bucket!(source_name)
|
18
|
+
@target_bucket = get_bucket!(target_name)
|
19
|
+
|
20
|
+
source_name = @source_bucket.name.bucketize(:pink).freeze
|
21
|
+
target_name = @target_bucket.name.bucketize.freeze
|
22
|
+
|
23
|
+
require_confirmation!(name_required:@target_bucket.name, confirmation:confirmation, additional_lines:[
|
24
|
+
"The contents of #{source_name} will be synced into #{target_name}.",
|
25
|
+
"Objects in #{target_name} that aren’t in the source bucket will be removed.",
|
26
|
+
])
|
27
|
+
|
28
|
+
log "Syncing #{source_name} into #{target_name}…"
|
29
|
+
log "Fetching bucket file lists…"
|
30
|
+
|
31
|
+
@source_bucket_keys = @source_bucket.objects.collect(&:key)
|
32
|
+
@target_bucket_keys = @target_bucket.objects.collect(&:key)
|
33
|
+
|
34
|
+
# -------------------------------------------------------------------------
|
35
|
+
# Delete bucket differences
|
36
|
+
# -------------------------------------------------------------------------
|
37
|
+
|
38
|
+
@keys_to_delete = @target_bucket_keys - @source_bucket_keys
|
39
|
+
|
40
|
+
@dispatch = Buckler::ThreadDispatch.new
|
41
|
+
|
42
|
+
log "Deleting unshared objects from target bucket…"
|
43
|
+
|
44
|
+
@keys_to_delete.lazy.each do |key|
|
45
|
+
@dispatch.queue(lambda {
|
46
|
+
log "Deleting #{target_name}/#{key}"
|
47
|
+
@target_bucket.object(key).delete
|
48
|
+
})
|
49
|
+
end
|
50
|
+
|
51
|
+
time_elapsed = @dispatch.perform_and_wait
|
52
|
+
log "Unshared objects deleted from target bucket (#{time_elapsed} seconds) ✔"
|
53
|
+
|
54
|
+
# -------------------------------------------------------------------------
|
55
|
+
# Sync files
|
56
|
+
# -------------------------------------------------------------------------
|
57
|
+
|
58
|
+
@dispatch = Buckler::ThreadDispatch.new
|
59
|
+
|
60
|
+
@source_bucket_keys.lazy.each do |object_key|
|
61
|
+
|
62
|
+
@dispatch.queue(lambda {
|
63
|
+
|
64
|
+
source_object = Aws::S3::Object.new(@source_bucket.name, object_key, client:@s3)
|
65
|
+
target_object = Aws::S3::Object.new(@target_bucket.name, object_key, client:@s3)
|
66
|
+
|
67
|
+
options = {
|
68
|
+
storage_class: source_object.storage_class,
|
69
|
+
metadata: source_object.metadata,
|
70
|
+
content_encoding: source_object.content_encoding,
|
71
|
+
content_language: source_object.content_language,
|
72
|
+
content_type: source_object.content_type,
|
73
|
+
cache_control: source_object.cache_control,
|
74
|
+
expires: source_object.expires,
|
75
|
+
}
|
76
|
+
|
77
|
+
if source_object.content_disposition.present?
|
78
|
+
options[:content_disposition] = ActiveSupport::Inflector.transliterate(source_object.content_disposition, "")
|
79
|
+
end
|
80
|
+
|
81
|
+
if source_object.content_length > 5242882 # 5 megabytes + 2 bytes
|
82
|
+
options[:multipart_copy] = true
|
83
|
+
options[:content_length] = source_object.content_length
|
84
|
+
end
|
85
|
+
|
86
|
+
target_object.copy_from(source_object, options)
|
87
|
+
target_object.acl.put({
|
88
|
+
access_control_policy: {
|
89
|
+
grants: source_object.acl.grants,
|
90
|
+
owner: source_object.acl.owner,
|
91
|
+
}
|
92
|
+
})
|
93
|
+
|
94
|
+
log "Copied #{source_name} → #{target_name}/#{object_key}"
|
95
|
+
|
96
|
+
})
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
time_elapsed = @dispatch.perform_and_wait
|
101
|
+
log "#{@source_bucket_keys.count} objects synced in #{target_name} (#{time_elapsed} seconds) ✔"
|
102
|
+
exit true
|
103
|
+
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
data/lib/buckler/aws.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
module Buckler
|
2
|
+
|
3
|
+
# Returns the discovered AWS Access Key ID
|
4
|
+
# Prerequisite: `Buckler.discover_aws_credentials!`
|
5
|
+
def self.aws_access_key_id
|
6
|
+
@aws_access_key_id
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns an Aws::S3::Client in the given `region`
|
10
|
+
# Prerequisite: `Buckler.discover_aws_credentials!`
|
11
|
+
def self.connect_to_s3!(region:"us-east-1")
|
12
|
+
return @s3 if @s3.present?
|
13
|
+
@s3 = Aws::S3::Client.new(
|
14
|
+
region: region,
|
15
|
+
access_key_id: @aws_access_key_id,
|
16
|
+
secret_access_key: @aws_secret_access_key,
|
17
|
+
)
|
18
|
+
return @s3
|
19
|
+
end
|
20
|
+
|
21
|
+
# Attempts to find the AWS Access Key ID and Secret Access Key
|
22
|
+
# by searching the command line paramters, the environment, the .env, and Heroku in that order.
|
23
|
+
# The parameters are the values of --id and --secret on the command line.
|
24
|
+
# The program ends if credentials cannot be discovered.
|
25
|
+
def self.discover_aws_credentials!(key_id:nil, key:nil)
|
26
|
+
|
27
|
+
verbose "Attempting to find AWS credentials…"
|
28
|
+
|
29
|
+
# Try to find keys as command line parameters, if the invoker has set them directly
|
30
|
+
if key_id.present? && key.present?
|
31
|
+
verbose "The Access Key ID and Secret Access Key were set as command line options ✔"
|
32
|
+
@aws_access_key_id = key_id
|
33
|
+
@aws_secret_access_key = key
|
34
|
+
return true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Try to find keys in the current environment, if the invoker has set them directly
|
38
|
+
key_id = ENV["AWS_ACCESS_KEY_ID"]
|
39
|
+
key = ENV["AWS_SECRET_ACCESS_KEY"]
|
40
|
+
if key_id.present? && key.present?
|
41
|
+
verbose "AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY found as environment variables ✔"
|
42
|
+
@aws_access_key_id = key_id
|
43
|
+
@aws_secret_access_key = key
|
44
|
+
return true
|
45
|
+
end
|
46
|
+
|
47
|
+
# Try to find keys in a .env file in this directory
|
48
|
+
Dotenv.load
|
49
|
+
key_id = ENV["AWS_ACCESS_KEY_ID"]
|
50
|
+
key = ENV["AWS_SECRET_ACCESS_KEY"]
|
51
|
+
if key_id.present? && key.present?
|
52
|
+
verbose "AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY found in the .env file ✔"
|
53
|
+
@aws_access_key_id = key_id
|
54
|
+
@aws_secret_access_key = key
|
55
|
+
return true
|
56
|
+
end
|
57
|
+
|
58
|
+
# Try to find keys by asking Heroku about the project in this directory
|
59
|
+
if heroku_available?
|
60
|
+
key_id = heroku_config_get("AWS_ACCESS_KEY_ID")
|
61
|
+
key = heroku_config_get("AWS_SECRET_ACCESS_KEY")
|
62
|
+
if key_id.present? && key.present?
|
63
|
+
verbose "AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY found on your Heroku application ✔"
|
64
|
+
@aws_access_key_id = key_id
|
65
|
+
@aws_secret_access_key = key
|
66
|
+
return true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
alert "Could not discover any AWS credentials."
|
71
|
+
alert "Set command line options --id and --secret"
|
72
|
+
alert "Or, set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY as environment variables."
|
73
|
+
alert "Or, set them in a .env file in this directory."
|
74
|
+
if heroku_available?
|
75
|
+
alert "Or, set them on a Heroku application in this directory with `heroku config:set`."
|
76
|
+
end
|
77
|
+
exit false
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
module Buckler::Commands; end
|
2
|
+
|
3
|
+
Buckler::Commands::Root = Cri::Command.define do
|
4
|
+
|
5
|
+
name "bucket"
|
6
|
+
usage "bucket <command> [options]"
|
7
|
+
summary "peform common actions on Amazon S3 buckets"
|
8
|
+
description %{
|
9
|
+
Buckler allows you perform common actions on your Amazon S3 buckets.
|
10
|
+
|
11
|
+
Run #{"bucket help <command>".bold} for more information about the commands below.
|
12
|
+
|
13
|
+
You will need a AWS Access Key ID and AWS Secret Access Key pair with
|
14
|
+
permission to mange your S3 buckets. Do not use your root keys.
|
15
|
+
Generate a new set of keys with S3 permissions only.
|
16
|
+
https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#lock-away-credentials
|
17
|
+
|
18
|
+
When you run the bucket command, Buckler tries to automatically
|
19
|
+
discover AWS credentials around your working directory.
|
20
|
+
|
21
|
+
#{"Dotenv:".bold} If the current folder has a file named .env, Buckler will look
|
22
|
+
for variables called AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY in the file.
|
23
|
+
See Heroku’s documentation on this environment file format.
|
24
|
+
https://devcenter.heroku.com/articles/heroku-local#set-up-your-local-environment-variables
|
25
|
+
|
26
|
+
#{"Heroku:".bold} If the current folder has a Git repository with a Heroku remote,
|
27
|
+
Buckler will ask your Heroku application for variables
|
28
|
+
named AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY using heroku config:get
|
29
|
+
|
30
|
+
#{"Command Line:".bold} You can set the pair directly by providing the
|
31
|
+
command line options --id and --secret:
|
32
|
+
|
33
|
+
bucket list --id YOUR_AWS_ID --secret YOUR_AWS_SECRET
|
34
|
+
|
35
|
+
#{"Environment:".bold} You can set the pair directly as environment variables.
|
36
|
+
|
37
|
+
AWS_ACCESS_KEY_ID=your-id AWS_SECRET_ACCESS_KEY=your-secret bucket list
|
38
|
+
}
|
39
|
+
|
40
|
+
flag :v, :verbose, "Output additional information for all commands"
|
41
|
+
option nil, :id, "Your AWS Access Key ID", argument: :required
|
42
|
+
option nil, :secret, "Your AWS Secret Access Key", argument: :required
|
43
|
+
|
44
|
+
run do |opts, args, cmd|
|
45
|
+
puts Buckler::Commands::Root.help
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
Buckler::Commands::Version = Cri::Command.define do
|
51
|
+
|
52
|
+
name "version"
|
53
|
+
usage "version"
|
54
|
+
summary "Print Buckler’s version"
|
55
|
+
description %{
|
56
|
+
Prints Buckler’s version number.
|
57
|
+
}
|
58
|
+
|
59
|
+
run do |opts, args, cmd|
|
60
|
+
log Buckler::VERSION::STRING
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
Buckler::Commands::Regions = Cri::Command.define do
|
66
|
+
|
67
|
+
name "regions"
|
68
|
+
usage "regions"
|
69
|
+
summary "list all Amazon S3 regions"
|
70
|
+
description %{
|
71
|
+
Prints a list of all Amazon S3 bucket region names and where they are on Earth.
|
72
|
+
|
73
|
+
When creating buckets, you should select the region that is
|
74
|
+
closest to the users or computers that will be using the bucket.
|
75
|
+
|
76
|
+
Heroku applications in Heroku’s America region should use Amazon region us-east-1.
|
77
|
+
|
78
|
+
Heroku applications in Heroku’s Europe region should use Amazon region eu-west-1.
|
79
|
+
}
|
80
|
+
|
81
|
+
run do |opts, args, cmd|
|
82
|
+
Buckler.list_regions!
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
Buckler::Commands::List = Cri::Command.define do
|
88
|
+
|
89
|
+
name "list"
|
90
|
+
usage "list"
|
91
|
+
summary "List all buckets on your account"
|
92
|
+
description %{
|
93
|
+
Prints a list of all Amazon S3 buckets on your account.
|
94
|
+
|
95
|
+
“All” may be releative, AWS access keys can be generated without
|
96
|
+
the power to see every bucket available to the master keys.
|
97
|
+
}
|
98
|
+
|
99
|
+
run do |opts, args, cmd|
|
100
|
+
$buckler_verbose_mode = true if opts[:verbose].present?
|
101
|
+
Buckler.discover_aws_credentials!(key_id:opts[:id], key:opts[:secret])
|
102
|
+
Buckler.list_buckets!
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
Buckler::Commands::Create = Cri::Command.define do
|
108
|
+
|
109
|
+
name "create"
|
110
|
+
usage "create <bucket-name>"
|
111
|
+
summary "Create a new bucket"
|
112
|
+
description %{
|
113
|
+
Creates a new bucket on your Amazon S3 account with the given name.
|
114
|
+
The bucket will be empty. The bucket is created in AWS region us-east-1 unless
|
115
|
+
you specify a different region with the --region option.
|
116
|
+
Get a list of all valid regions with `Buckler regions`.
|
117
|
+
|
118
|
+
For maximum compatability, Amazon always recomends that you use
|
119
|
+
DNS and TLS-safe bucket names,
|
120
|
+
which contain only the ASCII characters a-z, 0-9, or the hypen (-)
|
121
|
+
|
122
|
+
Bucket names with dots or uppercase letters may be unable
|
123
|
+
to use certain Amazon Web Service features.
|
124
|
+
|
125
|
+
Some example good bucket names:
|
126
|
+
your-project-name,
|
127
|
+
your-project-name-staging,
|
128
|
+
and your-project-name-dev1
|
129
|
+
|
130
|
+
For more information:
|
131
|
+
http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
|
132
|
+
}
|
133
|
+
|
134
|
+
option :r, :region, "The AWS region where the bucket should be created (default: us-east-1)", argument: :required
|
135
|
+
|
136
|
+
run do |opts, args, cmd|
|
137
|
+
$buckler_verbose_mode = true if opts[:verbose].present?
|
138
|
+
Buckler.discover_aws_credentials!(key_id:opts[:id], key:opts[:secret])
|
139
|
+
Buckler.create_bucket!(name:args.first.to_s, region:opts[:region])
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
Buckler::Commands::Empty = Cri::Command.define do
|
145
|
+
|
146
|
+
name "empty"
|
147
|
+
usage "empty <bucket-name>"
|
148
|
+
summary "Delete all files in a bucket"
|
149
|
+
description %{
|
150
|
+
Discards all objects in the target bucket. The result will be an empty bucket.
|
151
|
+
|
152
|
+
If you have not set up versioning for your bucket,
|
153
|
+
or you have not set up Amazon Glacier backups for your bucket,
|
154
|
+
you will be unable to recover any deleted objects.
|
155
|
+
|
156
|
+
For more information:
|
157
|
+
https://docs.aws.amazon.com/AmazonS3/latest/dev/delete-or-empty-bucket.html
|
158
|
+
}
|
159
|
+
|
160
|
+
option :c, :confirm, "Confirm destructive actions without prompting", argument: :required
|
161
|
+
|
162
|
+
run do |opts, args, cmd|
|
163
|
+
$buckler_verbose_mode = true if opts[:verbose].present?
|
164
|
+
Buckler.discover_aws_credentials!(key_id:opts[:id], key:opts[:secret])
|
165
|
+
Buckler.empty_bucket!(name:args.first.to_s, confirmation:opts[:confirm])
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
Buckler::Commands::Destroy = Cri::Command.define do
|
171
|
+
|
172
|
+
name "destroy"
|
173
|
+
usage "destroy <bucket-name>"
|
174
|
+
summary "Delete all files in a bucket and remove it"
|
175
|
+
description %{
|
176
|
+
Discards all objects in the target bucket and then removes
|
177
|
+
the bucket from Amazon S3.
|
178
|
+
|
179
|
+
Amazon may not immediately make the bucket name
|
180
|
+
available for use again.
|
181
|
+
|
182
|
+
You CANNOT delete a bucket that has versioning enabled.
|
183
|
+
You must first disable versioning on the AWS Mangement Console.
|
184
|
+
|
185
|
+
For more information:
|
186
|
+
https://docs.aws.amazon.com/AmazonS3/latest/dev/delete-or-empty-bucket.html
|
187
|
+
https://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
|
188
|
+
}
|
189
|
+
|
190
|
+
option :c, :confirm, "Confirm destructive actions without prompting", argument: :required
|
191
|
+
|
192
|
+
run do |opts, args, cmd|
|
193
|
+
$buckler_verbose_mode = true if opts[:verbose].present?
|
194
|
+
Buckler.discover_aws_credentials!(key_id:opts[:id], key:opts[:secret])
|
195
|
+
Buckler.destroy_bucket!(name:args.first.to_s, confirmation:opts[:confirm])
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|
199
|
+
|
200
|
+
Buckler::Commands::Sync = Cri::Command.define do
|
201
|
+
|
202
|
+
name "sync"
|
203
|
+
usage "sync <source-bucket> <target-bucket>"
|
204
|
+
summary "Copy the contents of one bucket into another"
|
205
|
+
description %{
|
206
|
+
Copies all objects in the source bucket into the target bucket.
|
207
|
+
Objects in the target bucket that don’t exist in the source bucket will be deleted.
|
208
|
+
The end result will be two buckets with identical objects.
|
209
|
+
|
210
|
+
The following properties on each object are also transfered:
|
211
|
+
ACLs,
|
212
|
+
Amazon S3 metadata,
|
213
|
+
Amazon S3 storage class,
|
214
|
+
Cache-Control header,
|
215
|
+
Content-Type header,
|
216
|
+
Content-Encoding header,
|
217
|
+
Content-Disposition header,
|
218
|
+
Content-Language header,
|
219
|
+
and Expires header.
|
220
|
+
|
221
|
+
The source bucket will not be changed.
|
222
|
+
|
223
|
+
If you have not set up versioning for your bucket,
|
224
|
+
or you have not set up Amazon Glacier archives for your bucket,
|
225
|
+
you will be unable to recover any objects deleted from the target bucket.
|
226
|
+
}
|
227
|
+
|
228
|
+
option :c, :confirm, "Confirm destructive actions without prompting", argument: :required
|
229
|
+
|
230
|
+
run do |opts, args, cmd|
|
231
|
+
$buckler_verbose_mode = true if opts[:verbose].present?
|
232
|
+
Buckler.discover_aws_credentials!(key_id:opts[:id], key:opts[:secret])
|
233
|
+
Buckler.sync_buckets!(source_name:args.first.to_s, target_name:args.second.to_s, confirmation:opts[:confirm])
|
234
|
+
end
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
Buckler::Commands::Help = Cri::Command.define do
|
239
|
+
name "help"
|
240
|
+
usage "buckler help"
|
241
|
+
summary "Show help for a command"
|
242
|
+
description "x"
|
243
|
+
run do |opts, args, cmd|
|
244
|
+
case args.first.to_s
|
245
|
+
when "list"
|
246
|
+
puts Buckler::Commands::List.help
|
247
|
+
when "regions"
|
248
|
+
puts Buckler::Commands::Regions.help
|
249
|
+
when "create"
|
250
|
+
puts Buckler::Commands::Create.help
|
251
|
+
when "empty"
|
252
|
+
puts Buckler::Commands::Empty.help
|
253
|
+
when "destroy"
|
254
|
+
puts Buckler::Commands::Destroy.help
|
255
|
+
when "sync"
|
256
|
+
puts Buckler::Commands::Sync.help
|
257
|
+
else
|
258
|
+
puts Buckler::Commands::Root.help
|
259
|
+
end
|
260
|
+
exit true
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::Version)
|
265
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::Help)
|
266
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::Regions)
|
267
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::List)
|
268
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::Create)
|
269
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::Empty)
|
270
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::Destroy)
|
271
|
+
Buckler::Commands::Root.add_command(Buckler::Commands::Sync)
|