laws 0.0.11

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.
Files changed (3) hide show
  1. data/bin/laws +388 -0
  2. data/lib/laws/aws_utils.rb +194 -0
  3. metadata +94 -0
data/bin/laws ADDED
@@ -0,0 +1,388 @@
1
+ #!/usr/bin/env ruby
2
+ require 'cri'
3
+ require 'awes/aws_utils'
4
+
5
+ include AWSAccess
6
+
7
+ #TODO swap back out
8
+ #DefaultPaths = %w(aws.yml ~/.aws.yml)
9
+ DefaultPaths = ["#{ENV['HOME']}/.aws.yml"]
10
+ def configure_user(opts)
11
+ aws_id = opts[:id]
12
+ aws_key = opts[:key]
13
+ config_path = opts[:config]
14
+
15
+ if config_path && (aws_id || aws_key)
16
+ puts 'Received both a path to a config file and command-line credentials.'
17
+ puts 'Please use either --config or the credential arguments.'
18
+ exit 1
19
+ end
20
+
21
+ if aws_id || aws_key
22
+ unless aws_id
23
+ puts 'Please provide an id with your key.'
24
+ puts 'Try awes -h for more information.'
25
+ exit 1
26
+ end
27
+ unless aws_key
28
+ puts 'Please provide a key with your id.'
29
+ puts 'Try awes -h for more information.'
30
+ exit 1
31
+ end
32
+ configure_aws(aws_id, aws_key)
33
+ return
34
+ end
35
+
36
+ if config_path
37
+ exit 1 unless load_config_file(config_path)
38
+ return true
39
+ end
40
+ DefaultPaths.each do |p|
41
+ if File.exists?(p)
42
+ exit 1 unless load_config_file(p)
43
+ return true
44
+ end
45
+ end
46
+ puts "Unable to locate an AWS config file. Exiting."
47
+ exit 1
48
+ end
49
+
50
+ s3_cmd = Cri::Command.define do
51
+ #fig
52
+ name 's3'
53
+ usage 's3 <subcommand> [options] <arguments>'
54
+ summary 'provides command line tools for manipulating Amazon\'s S3 service'
55
+ description 'Provides several commands for interacting with s3; allows ' +
56
+ 'creation, deletion, and listing of buckets, as well as uploading and' +
57
+ 'downloading of objects.'
58
+
59
+ end
60
+
61
+ s3_create_cmd = Cri::Command.define do
62
+ name 'create'
63
+ usage 'create <bucket_name>'
64
+ summary 'creates the named bucket in s3'
65
+ description 'creates a bucket with the provided name in s3, given the' +
66
+ 'bucket doesn\'t already exist.'
67
+
68
+ run do |opts, args, cmd|
69
+ bucket_name = args.shift
70
+ unless bucket_name
71
+ puts "create requires a bucket name."
72
+ puts "try awes s3 create -h for more information"
73
+ exit 1
74
+ end
75
+ unless args.empty?
76
+ puts "too many arguments to create."
77
+ puts "try awes s3 create -h for more information"
78
+ exit 1
79
+ end
80
+ configure_user(opts)
81
+ s3_create_bucket(bucket_name)
82
+ end
83
+ end
84
+ s3_cmd.add_command s3_create_cmd
85
+
86
+ s3_list_cmd = Cri::Command.define do
87
+ name 'list'
88
+ usage 'list <bucket_name>'
89
+ summary 'lists the contents of the given bucket'
90
+ description 'outsputs the key of each object in the given bucket'
91
+
92
+ run do |opts, args, cmd|
93
+ bucket_name = args.shift
94
+ unless bucket_name
95
+ puts 'list requires a bucket name.'
96
+ puts 'Try awes s3 list -h for more information'
97
+ exit 1
98
+ end
99
+ unless args.empty?
100
+ puts "too many arguments to list."
101
+ puts "try awes s3 list -h for more information"
102
+ exit 1
103
+ end
104
+ configure_user(opts)
105
+ s3_list_contents(bucket_name)
106
+ end
107
+ end
108
+ s3_cmd.add_command s3_list_cmd
109
+
110
+ s3_buckets_cmd = Cri::Command.define do
111
+ name 'buckets'
112
+ usage 'buckets'
113
+ summary 'lists all available buckets in s3'
114
+ description 'lists all readable buckets for the loaded account in S3'
115
+
116
+ run do |opts, args, cmd|
117
+ unless args.empty?
118
+ puts "too many arguments to buckets."
119
+ puts "try awes s3 buckets -h for more information"
120
+ exit 1
121
+ end
122
+ configure_user(opts)
123
+ s3_list_buckets
124
+ end
125
+ end
126
+ s3_cmd.add_command s3_buckets_cmd
127
+
128
+ s3_exists_cmd = Cri::Command.define do
129
+ name 'exists'
130
+ usage 'exists <bucket_name> [object_key]'
131
+ summary 'Checks if a bucket or object exists in s3'
132
+ description 'Checks the existence of the given bucket, and, if provided' +
133
+ ' the given object'
134
+
135
+ run do |opts, args, cmd|
136
+ bucket_name, object_key = args.shift, args.shift
137
+ unless bucket_name
138
+ puts 'Exists requires a bucket name.'
139
+ exit 1
140
+ end
141
+ unless args.empty?
142
+ puts "too many arguments to exists."
143
+ puts "try awes s3 exists -h for more information"
144
+ exit 1
145
+ end
146
+ configure_user(opts)
147
+ puts s3_exists?(bucket_name, object_key)
148
+ end
149
+ end
150
+ s3_cmd.add_command s3_exists_cmd
151
+
152
+ s3_upload_cmd = Cri::Command.define do
153
+ name 'upload'
154
+ usage 'upload [options] <bucket_name> <file_path>'
155
+ summary 'uploads a file to an s3 bucket'
156
+ description 'Uploads the given file to the named s3 bucket. If object-key' +
157
+ ' is provided, uploads it under that name, otherwise the name is the same' +
158
+ ' as the base filepath.'
159
+
160
+ option :k, ':key', 'object key to upload the file under', :argument => :required
161
+ flag :c, :create, 'create bucket if it doesn\'t exist.'
162
+
163
+ run do |opts, args, cmd|
164
+ bucket_name, file_path = args.shift, args.shift
165
+ unless bucket_name
166
+ puts 'upload requires a bucket name.'
167
+ exit 1
168
+ end
169
+ unless file_path
170
+ puts 'upload requires a filepath.'
171
+ exit 1
172
+ end
173
+ unless args.empty?
174
+ puts "too many arguments to upload."
175
+ puts "try awes s3 upload -h for more information"
176
+ exit 1
177
+ end
178
+ configure_user(opts)
179
+ s3_upload_object(bucket_name, file_path, opts[:key], opts[:create])
180
+ end
181
+ end
182
+ s3_cmd.add_command s3_upload_cmd
183
+
184
+ s3_download_cmd = Cri::Command.define do
185
+ name 'download'
186
+ usage 'download [options] <bucket_name> <object_key>'
187
+ summary 'downloads an object from s3'
188
+ description 'Downloads the object with the provided key from the named' +
189
+ ' bucket. If a filepath is provided, saves it with that name. Otherwise ' +
190
+ 'saves with the object-key as the filename'
191
+
192
+ option :f, :filename, 'filename to save the object under', :argument => :required
193
+
194
+ run do |opts, args, cmd|
195
+ bucket_name, obj_key = args.shift, args.shift
196
+ unless bucket_name
197
+ puts 'download requires a bucket name'
198
+ exit 1
199
+ end
200
+ unless obj_key
201
+ puts 'download requires an object key'
202
+ exit 1
203
+ end
204
+ unless args.empty?
205
+ puts "too many arguments to download."
206
+ puts "try awes s3 download -h for more information"
207
+ exit 1
208
+ end
209
+ configure_user(opts)
210
+ s3_download_object(bucket_name, obj_key, opts[:filename])
211
+ end
212
+ end
213
+ s3_cmd.add_command s3_download_cmd
214
+
215
+ s3_delete_cmd = Cri::Command.define do
216
+ name 'delete'
217
+ usage 'delete <bucket_name> <object_key>'
218
+ summary 'deletes a bucket or object from s3'
219
+ description 'If an object key is provided, deletes that object from the ' +
220
+ 'named bucket. Otherwise deletes the entire bucket.'
221
+
222
+ run do |opts, args, cmd|
223
+ bucket_name, obj_key = args.shift, args.shift
224
+ unless bucket_name
225
+ puts 'delete requires a bucket name'
226
+ exit 1
227
+ end
228
+ unless args.empty?
229
+ puts "too many arguments to delete."
230
+ puts "try awes s3 delete -h for more information"
231
+ exit 1
232
+ end
233
+ configure_user(opts)
234
+ s3_delete(bucket_name, obj_key)
235
+ end
236
+ end
237
+ s3_cmd.add_command s3_delete_cmd
238
+
239
+ sdb_cmd = Cri::Command.define do
240
+ name 'sdb'
241
+ usage 'sdb <subcommand> [options] <arguments>'
242
+ summary 'provides command line tools for manipulating Amazon\'s SimpleDB service'
243
+ description 'Provides several commands for interacting with SimpleDB; allows ' +
244
+ 'creation, deletion, and listing of domains, as well as inserting and querying ' +
245
+ 'records.'
246
+ end
247
+
248
+ sdb_domains_cmd = Cri::Command.define do
249
+ name 'domains'
250
+ usage 'domains'
251
+ summary 'lists all readable domains for the loaded user'
252
+ description 'prints one domain name per line'
253
+
254
+ run do |opts, args, cmd|
255
+ unless args.empty?
256
+ puts "too many arguments to domains."
257
+ puts "try awes sdb domains -h for more information"
258
+ exit 1
259
+ end
260
+ configure_user(opts)
261
+ sdb_list_domains
262
+ end
263
+ end
264
+
265
+ sdb_cmd.add_command sdb_domains_cmd
266
+
267
+ sdb_select_cmd = Cri::Command.define do
268
+ name 'select'
269
+ usage 'select <domain> [options]'
270
+ summary 'selects records from a domain'
271
+ description 'Selects an optional subset of attributes from the given domain' +
272
+ ' matching an optional query.'
273
+
274
+ option :a, :attributes, 'list of attributes to select: attr1[attr2,...]',
275
+ :argument => :required
276
+ option :w, :where, 'where clause for select. escape in quotations to avoid ' +
277
+ 'conflicting with BASH syntax.', :argument => :required
278
+
279
+ run do |opts, args, cmd|
280
+ domain = args.shift
281
+ unless domain
282
+ puts 'select requires a domain'
283
+ exit 1
284
+ end
285
+ unless args.empty?
286
+ puts "too many arguments to select."
287
+ puts "try awes sdb select -h for more information"
288
+ exit 1
289
+ end
290
+ configure_user(opts)
291
+ attributes = opts[:attributes] || []
292
+ sdb_print_items(domain, attributes, opts[:where])
293
+ end
294
+ end
295
+ sdb_cmd.add_command sdb_select_cmd
296
+
297
+ sdb_insert_cmd = Cri::Command.define do
298
+ name 'insert'
299
+ usage 'insert <key> <domain> <attributes>'
300
+ summary 'inserts data into SimpleDB'
301
+ description 'Inserts a list of attributes into a SimpleDB domain with the ' +
302
+ 'given key. Note that at least one attribute=value pair must be present' +
303
+ ' in the list, or SimpleDB won\'t persist the item.'
304
+
305
+ run do |opts, args, cmd|
306
+ attr_list = args.shift
307
+ unless attr_list
308
+ puts 'insert requires at least one attribute pair.'
309
+ exit 1
310
+ end
311
+ attr_vals = {}
312
+ attr_list.split(',').each do |assignment|
313
+ s = assignment.split('=')
314
+ attr_vals[s[0]] = s[1]
315
+ end
316
+ if attr_vals.empty?
317
+ puts "Unable to collect attributes from \"#{attr_list}\"."
318
+ exit 1
319
+ end
320
+
321
+ key, domain = args.shift, args.shift
322
+ unless key
323
+ puts 'insert requires a key'
324
+ exit 1
325
+ end
326
+ unless domain
327
+ puts 'insert requires a domain'
328
+ exit 1
329
+ end
330
+ unless args.empty?
331
+ puts "too many arguments to insert."
332
+ puts "try awes sdb insert -h for more information"
333
+ exit 1
334
+ end
335
+ configure_user(opts)
336
+ sdb_insert(domain, key, attr_vals)
337
+ end
338
+ end
339
+ sdb_cmd.add_command sdb_insert_cmd
340
+
341
+ sdb_delete_cmd = Cri::Command.define do
342
+ name 'delete'
343
+ usage 'delete [key] <domain>'
344
+ summary 'delete a domain or record from SimpleDB'
345
+ description 'Deletes the row with the given key from the given SimpleDB' +
346
+ ' domain. If no key is provided, deletes the domain'
347
+
348
+ run do |opts, args, cmd|
349
+ domain, key = args.pop, args.pop
350
+ unless domain
351
+ puts 'delete requires a domain'
352
+ exit 1
353
+ end
354
+ unless args.empty?
355
+ puts "too many arguments to delete."
356
+ puts "try awes sdb delete -h for more information"
357
+ exit 1
358
+ end
359
+ configure_user(opts)
360
+ sdb_delete(domain, key)
361
+ end
362
+ end
363
+ sdb_cmd.add_command sdb_delete_cmd
364
+
365
+ run_cmd = Cri::Command.define do
366
+ name 'awes'
367
+ usage 'awes <command>'
368
+ summary 'A CLI tool for interacting with Amazon Web Services'
369
+ description 'Support command-line interaction with both S3 and SimpleDB.'
370
+
371
+ flag :h, :help, 'show help for this command' do |value, cmd|
372
+ puts cmd.help
373
+ exit 0
374
+ end
375
+
376
+ option :c, :config, 'location of YAML config file for AWS keys', :argument => :required
377
+ option :i, :id, 'specify aws id on command line', :argument => :required
378
+ option :s, :secret, 'specifify aws secret key on command line', :argument => :required
379
+ end
380
+
381
+ #handling exceptions between here and s3
382
+ #handle extra/missing args (just print help and exit)
383
+ #usage examples?
384
+
385
+ run_cmd.add_command sdb_cmd
386
+ run_cmd.add_command s3_cmd
387
+
388
+ run_cmd.run(ARGV)
@@ -0,0 +1,194 @@
1
+ #!/user/bin/env ruby
2
+
3
+ require 'yaml'
4
+ require 'aws-sdk'
5
+
6
+ module AWSAccess
7
+
8
+ def configure_aws(key, id)
9
+ AWS.config(:access_key_id => key,
10
+ :secret_access_key => id)
11
+ end
12
+
13
+ def load_config_file(file_name)
14
+ unless File.exist?(file_name)
15
+ puts "Unable to locate config file #{file_name}."
16
+ return false
17
+ end
18
+ config = YAML.load_file(file_name)
19
+ configure_aws(config["aws_id"], config["aws_key"])
20
+ true
21
+ end
22
+
23
+ ###################SimpleDB logic ###############################
24
+ #TODO rescue query exceptions and print a better error
25
+ def sdb_print_items(domain_name, attributes = [], where_clause = nil)
26
+ db = AWS::SimpleDB.new
27
+ dom = db.domains[domain_name]
28
+ unless dom.exists?
29
+ puts "Unable to locate domain #{domain_name}."
30
+ return false
31
+ end
32
+
33
+ items = dom.items.select(attributes)
34
+ items = items.where(where_clause) unless where_clause.nil?
35
+
36
+ items.each do |i|
37
+ print i.name
38
+ print_attributes = attributes.empty? ? i.attributes.keys : attributes
39
+ print_attributes.each do |a|
40
+ print ",#{a}=#{i.attributes[a]}"
41
+ end
42
+ print "\n"
43
+ end
44
+ true
45
+ end
46
+
47
+ def sdb_list_domains
48
+ AWS::SimpleDB.new.domains.each {|d| puts d.name}
49
+ end
50
+
51
+ def sdb_create_domain(name)
52
+ db = AWS::SimpleDB.new
53
+ if db.domains[name].exists?
54
+ puts "Domain #{name} already exists in SimpleDB."
55
+ return false
56
+ end
57
+
58
+ db.domains.create(name)
59
+ true
60
+ end
61
+
62
+ def sdb_insert(domain_name, key, attributes)
63
+ db = AWS::SimpleDB.new
64
+ dom = db.domains[domain_name]
65
+ unless dom.exists?
66
+ puts "Unable to locate domain #{domain_name}."
67
+ return false
68
+ end
69
+
70
+ new_item = dom.items[key]
71
+ attributes.each do |k, v|
72
+ new_item.attributes[k] = v
73
+ end
74
+ true
75
+ end
76
+
77
+ def sdb_delete(domain_name, item_key = nil)
78
+ db = AWS::SimpleDB.new
79
+ dom = db.domains[domain_name]
80
+ unless dom.exists?
81
+ puts "Unable to locate domain #{domain_name}."
82
+ return false
83
+ end
84
+
85
+ if item_key.nil?
86
+ dom.delete! #TODO consider adding force support
87
+ else
88
+ item = dom.items[item_key]
89
+ item.delete
90
+ end
91
+ end
92
+
93
+ ###################S3 Logic#################################
94
+
95
+ def s3_list_buckets
96
+ AWS::S3.new.buckets.each {|b| puts b.name}
97
+ end
98
+
99
+ #TODO show more than just the item name
100
+ def s3_list_contents(bucket_name)
101
+ bucket = AWS::S3.new.buckets[bucket_name]
102
+ unless bucket.exists?
103
+ puts "Unable to locate bucket #{bucket_name}."
104
+ return false
105
+ end
106
+
107
+ bucket.objects.each do |o|
108
+ puts o.key
109
+ end
110
+ true
111
+ end
112
+
113
+ def s3_create_bucket(name)
114
+ s3 = AWS::S3.new
115
+ if s3.buckets[name].exists?
116
+ puts "Bucket #{name} already exists in S3."
117
+ return false
118
+ end
119
+ s3.buckets.create(name)
120
+ true
121
+ end
122
+
123
+ def s3_exists?(bucket_name, s3_key = nil)
124
+ bucket = AWS::S3.new.buckets[bucket_name]
125
+ unless bucket.exists?
126
+ puts "Unable to locate bucket #{bucket_name}."
127
+ return false
128
+ end
129
+
130
+ if s3_key.nil?
131
+ true
132
+ else
133
+ bucket[s3_key].exists?
134
+ end
135
+ end
136
+
137
+ def s3_upload_object(bucket_name, filepath, s3_key = nil, create_bucket = false)
138
+ s3_key ||= File.basename(filepath)
139
+ unless File.exists?(filepath)
140
+ puts "Unable to locate file at #{filepath}."
141
+ return false
142
+ end
143
+
144
+ s3 = AWS::S3.new
145
+ bucket = s3.buckets[bucket_name]
146
+ unless bucket.exists?
147
+ if create_bucket
148
+ s3.buckets.create(bucket_name)
149
+ else
150
+ puts "Unable to locate bucket #{bucket_name}."
151
+ return false
152
+ end
153
+ end
154
+
155
+ bucket.objects[s3_key].write(File.open(filepath){|f| f.read})
156
+ end
157
+
158
+ def s3_download_object(bucket_name, s3_key, filepath = nil)
159
+ filepath ||= "./#{s3_key}"
160
+ bucket = AWS::S3.new.buckets[bucket_name]
161
+ unless bucket.exists?
162
+ puts "Unable to locate bucket #{bucket_name}."
163
+ return false
164
+ end
165
+
166
+ obj = bucket.objects[s3_key]
167
+ unless obj.exists?
168
+ puts "Unable to locate item #{s3_key} in bucket #{bucket_name}."
169
+ return false
170
+ end
171
+
172
+ File.open(filepath, 'w') {|f| f.write(obj.read)}
173
+ end
174
+
175
+ def s3_delete(bucket_name, obj_key = nil)
176
+ bucket = AWS::S3.new.buckets[bucket_name]
177
+ unless bucket.exists?
178
+ puts "Unable to locate bucket #{bucket_name}."
179
+ return false
180
+ end
181
+
182
+ if obj_key.nil?
183
+ bucket.delete! #TODO consider adding force support
184
+ else
185
+ obj = bucket.objects[obj_key]
186
+ unless obj.exists?
187
+ puts "Unable to locate item #{obj_key} in bucket #{bucket_name}"
188
+ return false
189
+ end
190
+ obj.delete
191
+ end
192
+ end
193
+ end
194
+
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: laws
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 11
9
+ version: 0.0.11
10
+ platform: ruby
11
+ authors:
12
+ - Brian Fults
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-10-22 00:00:00 -04:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: aws-sdk
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 5
31
+ - 4
32
+ version: 1.5.4
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: cri
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - "="
42
+ - !ruby/object:Gem::Version
43
+ segments:
44
+ - 2
45
+ - 3
46
+ - 0
47
+ version: 2.3.0
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ description: A CLI for interfacing with S3 and SimpleDB using the sdk.
51
+ email: xclite@gmail.com
52
+ executables:
53
+ - laws
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - lib/laws/aws_utils.rb
60
+ - bin/laws
61
+ has_rdoc: true
62
+ homepage:
63
+ licenses: []
64
+
65
+ post_install_message:
66
+ rdoc_options: []
67
+
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 0
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project:
89
+ rubygems_version: 1.3.7
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: CLI for managing Amazon Web Services
93
+ test_files: []
94
+