laws 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
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
+