s3cp 1.1.17 → 1.1.18

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/History.txt CHANGED
@@ -1,3 +1,27 @@
1
+ === 1.1.18 (2013-02-05)
2
+
3
+ * Fixed: Add new `s3lifecycle` command to manage object transtion rules.
4
+
5
+ A few examples:
6
+
7
+ # Show lifecycle rules for bucket
8
+ % s3lifecycle s3://bucket
9
+
10
+ # Add expiration rule (expire after 180 days)
11
+ % s3lifecycle --name "Optional name" --expire 180 s3://bucket/below/some/path/
12
+
13
+ # Transition objects to Glacier after 180 days
14
+ % s3lifecycle --glacier 180 s3://bucket/below/some/path/
15
+
16
+ # Transition objects to Glacier after 2013-03-29
17
+ % s3lifecycle --glacier 2013-03-29 s3://bucket/below/some/path/
18
+
19
+ # Enable rule by path (you can use --name to enable by name)
20
+ % s3lifecycle --enable s3://bucket/below/some/path/
21
+
22
+ # Disable rule by name
23
+ % s3lifecycle --disable --name "Some rule" s3://bucket
24
+
1
25
  === 1.1.17 (2013-02-05)
2
26
 
3
27
  * Fixed: Speed-up `s3du` (same dealio as s3ls -l from version 1.1.14)
data/bin/s3lifecycle ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 's3cp/s3lifecycle'
3
+
4
+
@@ -0,0 +1,168 @@
1
+ # Copyright (C) 2010-2012 Alex Boisvert and Bizo Inc. / All rights reserved.
2
+ #
3
+ # Licensed to the Apache Software Foundation (ASF) under one or more contributor
4
+ # license agreements. See the NOTICE file distributed with this work for
5
+ # additional information regarding copyright ownership. The ASF licenses this
6
+ # file to you under the Apache License, Version 2.0 (the "License"); you may not
7
+ # use this file except in compliance with the License. You may obtain a copy of
8
+ # the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
+ # License for the specific language governing permissions and limitations under
16
+ # the License.
17
+
18
+ require 's3cp/utils'
19
+
20
+ # Default options
21
+ options = { :verbose => false }
22
+
23
+ # Setup cli params
24
+ op = OptionParser.new do |opts|
25
+ opts.banner = <<-BANNER
26
+ s3lifecycle [COMMANDS] prefix
27
+ BANNER
28
+ opts.separator ''
29
+
30
+ opts.on("--verbose", "Verbose mode") do
31
+ options[:verbose] = true
32
+ end
33
+
34
+ opts.on("--name NAME", "Rule identifier optionally used in combination with --expire/glacier/enable/disable/remove") do |name|
35
+ options[:name] = name
36
+ end
37
+
38
+ opts.on("--expire DAYS_OR_DATE", "Expire object(s) after given number of days or specific date (YYYY-MM-DD)") do |time|
39
+ options[:expire] = S3CP.parse_days_or_date(time)
40
+ end
41
+
42
+ opts.on("--glacier DAYS_OR_DATE", "Transition objects to Glacier after given number of days or specific date (YYYY-MM-DD)") do |time|
43
+ options[:glacier] = S3CP.parse_days_or_date(time)
44
+ end
45
+
46
+ opts.on("--enable", "Enable rule(s) for expiration/glacier object transition") do
47
+ options[:enable] = true
48
+ end
49
+
50
+ opts.on("--disable", "Disable rule(s) for expiration/glacier object transition") do
51
+ options[:disable] = true
52
+ end
53
+
54
+ opts.on("--delete", "Delete rule(s) for expiration/glacier object transition") do
55
+ options[:delete] = true
56
+ end
57
+
58
+ opts.on_tail("-h", "--help", "Show this message") do
59
+ puts op
60
+ exit
61
+ end
62
+ end
63
+
64
+ p options.inspect if options[:verbose]
65
+
66
+ op.parse!(ARGV)
67
+ paths = ARGV
68
+
69
+ if ARGV.size == 0
70
+ puts op
71
+ exit
72
+ end
73
+
74
+ S3CP.load_config()
75
+ @s3 = S3CP.connect()
76
+
77
+ def time_or_date_str(msg, t)
78
+ if t.is_a?(Fixnum) || t.to_s =~ /^\d+$/
79
+ "%s after %d days" % [msg, t.to_i]
80
+ else
81
+ "%s on %s" % [msg, t]
82
+ end
83
+ end
84
+
85
+ def rule_to_str(r)
86
+ if r.expiration_time
87
+ [ r.prefix, r.id, r.status, time_or_date_str("Expire", r.expiration_time)]
88
+ elsif r.glacier_transition_time
89
+ [ r.prefix, r.id, r.status, time_or_date_str("Glacier", r.glacier_transition_time)]
90
+ else
91
+ [ r.prefix, r.id, r.status, "???"]
92
+ end
93
+ end
94
+
95
+ paths.each do |path|
96
+ bucket,key = S3CP.bucket_and_key(path)
97
+ fail "Invalid bucket/key: #{path}" unless key
98
+
99
+ case
100
+
101
+ when options[:expire]
102
+ @s3.buckets[bucket].lifecycle_configuration.update do
103
+ rule_options = {}
104
+ rule_options[:id] = options[:name] if options[:name]
105
+ rule_options[:expiration_time] = S3CP.parse_days_or_date(options[:expire])
106
+ add_rule(key, rule_options)
107
+ end
108
+
109
+ when options[:glacier]
110
+ @s3.buckets[bucket].lifecycle_configuration.update do
111
+ rule_options = {}
112
+ rule_options[:id] = options[:name] if options[:name]
113
+ rule_options[:glacier_transition_time] = S3CP.parse_days_or_date(options[:glacier])
114
+ add_rule(key, rule_options)
115
+ end
116
+
117
+ when options[:enable]
118
+ success = false
119
+ @s3.buckets[bucket].lifecycle_configuration.update do
120
+ self.rules.each do |r|
121
+ if (r.prefix == key) || (r.id == options[:name])
122
+ r.enable!
123
+ puts "Enabled rule: "
124
+ puts S3CP.tableify([rule_to_str(r)])
125
+ success = true
126
+ end
127
+ end
128
+ end
129
+ fail "Rule or prefix not found" unless success
130
+
131
+ when options[:disable]
132
+ success = false
133
+ @s3.buckets[bucket].lifecycle_configuration.update do
134
+ self.rules.each do |r|
135
+ if (r.prefix == key) || (r.id == options[:name])
136
+ r.disabled!
137
+ puts "Disabled rule: "
138
+ puts S3CP.tableify([rule_to_str(r)])
139
+ success = true
140
+ end
141
+ end
142
+ end
143
+ fail "Rule or prefix not found" unless success
144
+
145
+ when options[:delete]
146
+ success = false
147
+ @s3.buckets[bucket].lifecycle_configuration.update do
148
+ self.rules.each do |r|
149
+ if (r.prefix == key) || (r.id == options[:name])
150
+ remove_rule(r)
151
+ puts "Deleted rule: "
152
+ puts S3CP.tableify([rule_to_str(r)])
153
+ success = true
154
+ end
155
+ end
156
+ end
157
+ fail "Rule or prefix not found" unless success
158
+
159
+ else
160
+ puts "Lifecycle rules:"
161
+ rules = @s3.buckets[bucket].lifecycle_configuration.rules.to_a
162
+ if rules.empty?
163
+ puts "No lifecycle rules"
164
+ else
165
+ puts S3CP.tableify(rules.map { |r| rule_to_str(r) })
166
+ end
167
+ end
168
+ end
data/lib/s3cp/utils.rb CHANGED
@@ -91,6 +91,24 @@ module S3CP
91
91
  headers
92
92
  end
93
93
 
94
+ # Convert a series of rows [["one", "two", "three3"], ["foo", "bar", "baz"], ...]
95
+ # into a table-format.
96
+ def tableify(rows)
97
+ return "" if rows.nil? || rows.empty?
98
+ cols = rows[0].size
99
+ widths = (1..cols).map { |c| rows.map { |r| r[c-1].length }.max }
100
+ format = widths[0..-2].map { |w| "%-#{w}s" }.join(" ") + " %s"
101
+ rows.map { |r| format % r }.join("\n")
102
+ end
103
+
104
+ def parse_days_or_date(d)
105
+ if d.to_s =~ /^\d+$/
106
+ d.to_i
107
+ else
108
+ Date.parse(d)
109
+ end
110
+ end
111
+
94
112
  # Round a number at some `decimals` level of precision.
95
113
  def round(n, decimals = 0)
96
114
  (n * (10.0 ** decimals)).round * (10.0 ** (-decimals))
data/lib/s3cp/version.rb CHANGED
@@ -16,5 +16,5 @@
16
16
  # the License.
17
17
 
18
18
  module S3CP
19
- VERSION = "1.1.17"
19
+ VERSION = "1.1.18"
20
20
  end
data/lib/s3cp.rb ADDED
@@ -0,0 +1 @@
1
+ require 's3cp/utils'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: s3cp
3
3
  version: !ruby/object:Gem::Version
4
- hash: 49
4
+ hash: 55
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 17
10
- version: 1.1.17
9
+ - 18
10
+ version: 1.1.18
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alex Boisvert
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2013-02-05 00:00:00 Z
18
+ date: 2013-02-06 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  version_requirements: &id001 !ruby/object:Gem::Requirement
@@ -54,12 +54,12 @@ dependencies:
54
54
  requirements:
55
55
  - - ~>
56
56
  - !ruby/object:Gem::Version
57
- hash: 9
57
+ hash: 53
58
58
  segments:
59
59
  - 1
60
- - 6
61
- - 3
62
- version: 1.6.3
60
+ - 8
61
+ - 1
62
+ version: 1.8.1
63
63
  requirement: *id003
64
64
  type: :runtime
65
65
  prerelease: false
@@ -123,6 +123,7 @@ executables:
123
123
  - s3dir
124
124
  - s3du
125
125
  - s3edit
126
+ - s3lifecycle
126
127
  - s3ls
127
128
  - s3mod
128
129
  - s3mv
@@ -136,6 +137,7 @@ extra_rdoc_files:
136
137
  - README.md
137
138
  - History.txt
138
139
  files:
140
+ - lib/s3cp.rb
139
141
  - lib/s3cp/s3cat.rb
140
142
  - lib/s3cp/s3tree.rb
141
143
  - lib/s3cp/#Untitled-5#
@@ -148,6 +150,7 @@ files:
148
150
  - lib/s3cp/s3cp.rb
149
151
  - lib/s3cp/s3stat.rb
150
152
  - lib/s3cp/utils.rb
153
+ - lib/s3cp/s3lifecycle.rb
151
154
  - lib/s3cp/s3rm.rb
152
155
  - lib/s3cp/s3up.rb
153
156
  - History.txt
@@ -165,6 +168,7 @@ files:
165
168
  - bin/s3cp_complete
166
169
  - bin/s3du
167
170
  - bin/s3cp
171
+ - bin/s3lifecycle
168
172
  - bin/s3rm
169
173
  - bin/s3stat
170
174
  homepage: