awscli 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ODAzMjhiNjZkOWNhMjE3NWM5NjIzYTY3NzAwMWIyNmYxYWRmYWVjZg==
4
+ NjZmMTc3NTYxZjgzYjg3NTg3NTBlOWQ1NDg3Mjk2ODE4NjEyNjIzZg==
5
5
  data.tar.gz: !binary |-
6
- MDk0ZDMyNDhlMjJlOWIwMjMzYThmMGZlZmUxYzhhNDczNDc3N2MyMQ==
6
+ OGQ1YzUwODYxZjZkYmQzYzY0YmE4OTU1MTJlYzk1MGE5MzZiNzk1YQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- MTM0MjBiOGJlYzk0ZWY3ZDFiNjNjYzdhMGEzOTE2ZDlkMDRlMzhkZTNhOTg2
10
- YmMyYTc1NDdmZDJiYzdlMDA1NzU2NTUxMjdmNDM2YzYwNDg0MjE2MzRiZTM1
11
- ZWU2M2U0MDBmYWIyYjIzNTc0YmNlYmRlNDY2YTljODg1YjAzMzI=
9
+ ZTEwNDU0NWQ4ZjRmMTI0YmI4ZDU0OThmYTYzZjU0YzE4NWJkZjNiYzJmN2I3
10
+ NWQ5MmJjMmI3YjU2MzlmNGI4ZDYyYjFjY2FhZjVhOTFjYTk2OTMxMjA0Y2Qz
11
+ MWM3NzUxMTZkMGM3MzE5MDk3YjM1YWJiYjczOGEzZjUyYjljY2I=
12
12
  data.tar.gz: !binary |-
13
- N2RiYTAzZmY3YjFhZThlOTdkZmY4ZTk5M2FiYzYyNDRkMTRjMzQxMWM2MmVm
14
- ZmE5ZDgyNWNmMTQ2NDZkMGFhNTk0NTgxNGZmNzA1OGMwOTA2MGVhMjRiNGQy
15
- NGQ3ZTAxMzA0NThjN2Q2ZDhhNjczZmJhYjg4MjA3ZDIwYzMzNTM=
13
+ ZTUxN2ZlOTcyMWQyNzUyMjY4Yjk1MTZiZTViZGFhMTU1ZGI4YTU5YzQ5YTBj
14
+ OGQ3NmZjYWZlZmI2MjNiNzRjZjY5ODQ0NmQwM2EzMWQyNzZlNWQ5YTUwN2E1
15
+ YTY4MTRmZjQwYjQzYzMzMWI0NzliOGVmZGRiMWI0MTU0MTAyY2M=
@@ -4,16 +4,19 @@ module AwsCli
4
4
  require 'awscli/cli/ec2'
5
5
  class Ami < Thor
6
6
 
7
- desc "list", "List Images"
7
+ desc "list [OPTIONS]", "List Images"
8
8
  method_option :filter, :aliases => "-f", :type => :hash, :desc => "filter the images based on filters"
9
9
  method_option :amazon_owned, :aliases => "-a", :type => :boolean, :default => false, :desc => "lists amazon owned images"
10
10
  method_option :show_filters, :aliases => "-s", :type => :boolean, :default => false, :desc => "filters available"
11
+ method_option :self_owned, :aliases => "-o", :type => :boolean, :default => false, :desc => "list self owned images"
11
12
  def list
12
13
  create_ec2_object
13
14
  if options[:amazon_owned]
14
15
  @ec2.list_amazon
15
16
  elsif options[:show_filters]
16
17
  @ec2.show_filters
18
+ elsif options[:self_owned]
19
+ @ec2.list_self
17
20
  else
18
21
  @ec2.list options[:filter]
19
22
  end
@@ -29,6 +32,14 @@ module AwsCli
29
32
  @ec2.create_image_from_instance options
30
33
  end
31
34
 
35
+ desc "deregister", "Deregisters the specified AMI. Once deregistered, the AMI cannot be used to launch new instances"
36
+ method_option :image_id, :aliases => "-i", :type => :string, :required => true, :desc => "ID of the AMI to deregister"
37
+ def deregister
38
+ create_ec2_object
39
+ @ec2.deregister options[:image_id]
40
+ end
41
+
42
+
32
43
  private
33
44
 
34
45
  def create_ec2_object
@@ -4,7 +4,7 @@ module AwsCli
4
4
  require 'awscli/cli/ec2'
5
5
  class Ebs < Thor
6
6
 
7
- desc "list", "List ELastic Block Storages"
7
+ desc "list [OPTIONS]", "List ELastic Block Storages"
8
8
  method_option :snapshots, :aliases => "-s", :type => :boolean, :default => false, :desc => "list snapshots"
9
9
  def list
10
10
  create_ec2_object
@@ -48,18 +48,15 @@ module AwsCli
48
48
 
49
49
  desc "delete_detached", "Delete all the volumes that are not in use"
50
50
  def delete_detached
51
- if agree("Are you sure want to delete all the all volumes that are not in use ? ")
52
- puts
53
- create_ec2_object
54
- @ec2.delete_detached
55
- end
51
+ create_ec2_object
52
+ @ec2.delete_detached
56
53
  end
57
54
 
58
55
  desc "create_snapshot", "Create a snapshot from volume"
59
56
  method_option :volume_id, :aliases => "-v", :banner => "VID", :required => true, :type => :string, :desc => "volume to make a snapshot from"
60
57
  def create_snapshot
61
58
  create_ec2_object
62
- @ec2.create_snapshot
59
+ @ec2.create_snapshot options
63
60
  end
64
61
 
65
62
  desc "copy_snapshot", "Copy a snapshot to a different region"
@@ -67,7 +64,7 @@ module AwsCli
67
64
  method_option :snapshot_id, :aliases => "-i", :banner => "ID", :required => true, :type => :string, :desc => "Id of the snapshot"
68
65
  def copy_snapshot
69
66
  create_ec2_object
70
- @ec2.copy_snapshot
67
+ @ec2.copy_snapshot options
71
68
  end
72
69
 
73
70
  desc "delete_snapshot", "Delete SnapShot"
@@ -11,52 +11,52 @@ module AwsCli
11
11
  end
12
12
 
13
13
  desc "create", "Create an new S3 bucket"
14
- method_option :key, :aliases => "-k", :type => :string, :required => true, :desc => "name of the bucket to create(name should be globally unique)"
14
+ method_option :bucket, :aliases => "-b", :type => :string, :required => true, :desc => "name of the bucket to create(name should be globally unique)"
15
15
  method_option :public, :aliases => "-p", :type => :boolean, :default => false, :desc => "makes the bucket publicly availble"
16
16
  # method_option :x_amz_acl, :aliases => "-x", :type => :string, :desc => "Permissions, must be in ['private', 'public-read', 'public-read-write', 'authenticated-read']"
17
17
  def create
18
18
  create_s3_object
19
- @s3.create options
19
+ @s3.create options[:bucket], options[:public]
20
20
  end
21
21
 
22
22
  desc "delete", "Delete existing S3 bucket"
23
- method_option :key, :aliases => "-k", :type => :string, :required => true, :desc => "name of the bucket to delete"
23
+ method_option :bucket, :aliases => "-b", :type => :string, :required => true, :desc => "name of the bucket to delete"
24
24
  def delete
25
25
  create_s3_object
26
- @s3.delete options[:key]
26
+ @s3.delete options[:bucket]
27
27
  end
28
28
 
29
29
  desc "delete_rec", "Delete the bucket and all its contents"
30
- method_option :key, :aliases => "-k", :type => :string, :required => true, :desc => "name of the bucket to delete"
30
+ method_option :bucket, :aliases => "-b", :type => :string, :required => true, :desc => "name of the bucket to delete"
31
31
  def delete_rec
32
32
  create_s3_object
33
- @s3.delete_rec options[:key]
33
+ @s3.delete_rec options[:bucket]
34
34
  end
35
35
 
36
36
  desc "set_acl", "Change access control list for an S3 bucket"
37
- method_option :key, :aliases => "-k", :type => :string, :required => true, :desc => "name of the bucket to change acl"
37
+ method_option :bucket, :aliases => "-b", :type => :string, :required => true, :desc => "name of the bucket to change acl"
38
38
  method_option :acl, :aliases => "-a", :type => :string, :required => true, :desc => "Permissions, must be in ['private', 'public-read', 'public-read-write', 'authenticated-read']"
39
39
  def set_acl
40
40
  create_s3_object
41
- @s3.set_acl options[:key], options[:acl]
41
+ @s3.set_acl options[:bucket], options[:acl]
42
42
  end
43
43
 
44
44
  desc "get_acl", "Get access control list for an S3 bucket"
45
- method_option :key, :aliases => "-k", :type => :string, :required => true, :desc => "name of the bucket to get acl"
45
+ method_option :bucket, :aliases => "-b", :type => :string, :required => true, :desc => "name of the bucket to get acl"
46
46
  def get_acl
47
47
  create_s3_object
48
- @s3.get_acl options[:key]
48
+ @s3.get_acl options[:bucket]
49
49
  end
50
50
 
51
51
  desc "get_logging_status", "Get logging status for an S3 bucket"
52
- method_option :key, :aliases => "-k", :type => :string, :required => true, :desc => "name of the bucket"
52
+ method_option :bucket, :aliases => "-b", :type => :string, :required => true, :desc => "name of the bucket"
53
53
  def get_logging_status
54
54
  create_s3_object
55
- @s3.get_logging_status options[:key]
55
+ @s3.get_logging_status options[:bucket]
56
56
  end
57
57
 
58
58
  # desc "set_logging_status", "Change logging status for an S3 bucket"
59
- # method_option :key, :aliases => "-k", :type => :string, :required => true, :desc => "name of the bucket"
59
+ # method_option :bucket, :aliases => "-b", :type => :string, :required => true, :desc => "name of the bucket"
60
60
  # method_option :owner, :aliases => "-o", :type => :hash, :banner => "ID:NAME", :desc => "set id and displayname of the owner"
61
61
  # method_option :grantee, :aliases => "-g", :type => :hash, :banner => "NAME:ID|EMAIL|URI", :desc => "Grantee hash containing, <Display name of the grantee>: <ID of the grantee (or) Email of the grantee (or) Uri of the group to grant access>"
62
62
  # method_option :permission, :aliases => "-p", :type => :string, :desc => "Permission, in [FULL_CONTROL, WRITE, WRITE_ACP, READ, READ_ACP]"
@@ -69,7 +69,7 @@ module AwsCli
69
69
  # logging_status['AccessControlList'] = acl if acl
70
70
  # puts "Empty logging_status will disable logging" if logging_status.nil?
71
71
  # puts "#{logging_status}"
72
- # @s3.set_logging_status options[:key], logging_status
72
+ # @s3.set_logging_status options[:bucket], logging_status
73
73
  # end
74
74
 
75
75
  private
@@ -19,6 +19,31 @@ module AwsCli
19
19
  @s3.upload_file options[:bucket_name], options[:file_path]
20
20
  end
21
21
 
22
+ desc "put_rec", "put a directory recusively into a specified bucket using multiple threads"
23
+ method_option :bucket_name, :aliases => "-b", :required => true, :desc => "name of the bucket to upload the dir to"
24
+ method_option :dir_path, :aliases => "-p", :required => true, :desc => "path of the dir to upload"
25
+ method_option :dest_path, :aliases => "-d", :desc => "optionally specify destination directory path to create"
26
+ method_option :thread_count, :aliases => "-t", :type => :numeric, :default => 5, :desc => "number of threads to use to upload files"
27
+ method_option :public, :type => :boolean, :default => false, :desc => "set ACL of files to public"
28
+ def put_rec
29
+ create_s3_object
30
+ @s3.upload_file_rec options
31
+ end
32
+
33
+ desc "put_big", "uploads a larger file (> 100 MB) using multipart uploads"
34
+ long_desc <<-DESC
35
+ Takes in a larger file, split the file into chunks and uploads the parts using amazon multipart uploads and the parts are aggregated at the amazons end.
36
+ DESC
37
+ method_option :bucket_name, :aliases => "-b", :required => true, :desc => "name of the bucket to upload the parts to"
38
+ method_option :file_path, :aliases => "-p", :required => true, :desc => "path of the file to upload"
39
+ method_option :tmp_dir, :aliases => "-t", :default => "/tmp", :desc => "path to a temperory location where file will be split into chunks"
40
+ method_option :acl, :aliases => "-a", :default => "private", :desc => "ACL to apply, to the object that is created after completing multipart upload, valid options in private | public-read | public-read-write | authenticated-read | bucket-owner-read | bucket-owner-full-control"
41
+ method_option :dest_path, :aliases => "-d", :desc => "optionally specify destination directory path to create"
42
+ def put_big
43
+ create_s3_object
44
+ @s3.multipart_upload options
45
+ end
46
+
22
47
  desc "get", "get a file from a bucket"
23
48
  method_option :bucket_name, :aliases => "-b", :required => true, :desc => "name of the bucket to download the file from"
24
49
  method_option :file_name, :aliases => "-f", :required => true, :desc => "name of file to download"
data/lib/awscli/ec2.rb CHANGED
@@ -381,7 +381,8 @@ module Awscli
381
381
  if filter.nil?
382
382
  @@conn.images.all.table([:architecture, :id, :is_public, :platform, :root_device_type, :state])
383
383
  else
384
- @@conn.images.all(filter).table([:architecture, :id, :is_public, :platform, :root_device_type, :state])
384
+ data = @@conn.images.all(filter)
385
+ data.empty? ? puts("No AMI's found for provided filters") : data.table([:architecture, :id, :is_public, :platform, :root_device_type, :state])
385
386
  end
386
387
  end
387
388
 
@@ -422,6 +423,11 @@ module Awscli
422
423
  @@conn.images.all('owner-alias' => 'amazon').table([:architecture, :id, :is_public, :platform, :root_device_type, :state])
423
424
  end
424
425
 
426
+ def list_self
427
+ response = @@conn.describe_images({'Owner' => 'self'}).body['imagesSet']
428
+ Formatador.display_table(response, ['architecture', 'imageId', 'isPublic', 'name', 'imageState', 'rootDeviceType', 'imageType'])
429
+ end
430
+
425
431
  def create_image_from_instance options
426
432
  abort "Invalid Instace: #{options[:instance_id]}" unless @@conn.servers.get(options[:instance_id])
427
433
  @@conn.create_image(
@@ -433,6 +439,13 @@ module Awscli
433
439
  puts "Created image from instance: #{options[:instance_id]}"
434
440
  end
435
441
 
442
+ def deregister image_id
443
+ image = @@conn.images.get(image_id)
444
+ abort "Cannot find image with id: #{image_id}" unless image
445
+ @@conn.deregister_image(image_id)
446
+ say "De-registerd image: <%= color('#{image_id}', :green) %>"
447
+ end
448
+
436
449
  end # => AMI
437
450
 
438
451
  class Ebs
@@ -485,12 +498,14 @@ module Awscli
485
498
  def delete_detached
486
499
  vols = @@conn.volumes.all('status' => 'available')
487
500
  unless vols.empty?
488
- puts "Deleting all volumes which are not in use ..."
489
- vols.each do |vol|
490
- vol.destroy
501
+ if agree("Are you sure want to delete all the all volumes that are not in use ? ")
502
+ puts "Deleting all volumes which are not in use ..."
503
+ vols.each do |vol|
504
+ vol.destroy
505
+ end
491
506
  end
492
507
  else
493
- puts "No volumes found, that are not in use found"
508
+ puts "No volumes found, that are 'not in use'"
494
509
  end
495
510
  end
496
511
 
@@ -501,7 +516,7 @@ module Awscli
501
516
  end
502
517
 
503
518
  def copy_snapshot options
504
- abort "Cannot find snapshot: #{options[:snapshot_id]}" unless @@conn.snapshots.get(options[:snapshot_id])
519
+ # abort "Cannot find snapshot: #{options[:snapshot_id]}" unless @@conn.snapshots.get(options[:snapshot_id])
505
520
  @@conn.copy_snapshot(options[:snapshot_id], options[:source_region])
506
521
  puts "Copied snapshot"
507
522
  end
@@ -510,7 +525,7 @@ module Awscli
510
525
  snap = @@conn.snapshots.get(options[:snapshot_id])
511
526
  abort "Cannot find snapshot: #{options[:snapshot_id]}" unless snap
512
527
  snap.destroy
513
- puts "Destroyed snapshot"
528
+ puts "Deleted snapshot"
514
529
  end
515
530
  end # => EBS
516
531
 
data/lib/awscli/s3.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  module Awscli
2
2
  module S3
3
3
  require 'thread'
4
+ require 'digest/md5'
5
+ require 'base64'
6
+ require 'fileutils'
4
7
 
5
8
  class Files
6
9
  def initialize connection, options = {}
@@ -30,6 +33,140 @@ module Awscli
30
33
  puts "Uploaded file: #{file_name} to bucket: #{dir_name}"
31
34
  end
32
35
 
36
+ def upload_file_rec options
37
+ dir_name, dir_path, threads_count, is_public = options[:bucket_name], options[:dir_path], options[:thread_count], options[:public]
38
+ dest_path = options[:dest_path] if options[:dest_path]
39
+ #check if bucket exists
40
+ bucket = @@conn.directories.get(dir_name)
41
+ abort "cannot find bucket: #{dir_name}" unless bucket
42
+ #check if passed path is a dir
43
+ dir = File.expand_path(dir_path)
44
+ abort "dir_path must be a dir" unless File.directory?(dir)
45
+ #add trailing slash to detination dir if is not passed
46
+ if dest_path && !dest_path.end_with?('/')
47
+ dest_path = "#{dest_path}/"
48
+ end
49
+ #remove trailing / from dir_path
50
+ dir = dir.chop if dir.end_with?('/')
51
+ #initializations
52
+ total_size = 0
53
+ files = Queue.new
54
+ threads = Array.new
55
+ semaphore = Mutex.new
56
+ file_number = 0
57
+
58
+ Dir.glob("#{dir}/**/*").select { |f| !File.directory?(f) }.each do |file|
59
+ files << file
60
+ total_size += File.size(file)
61
+ end
62
+
63
+ total_files = files.size
64
+ puts "Starting Upload using #{threads_count} threads"
65
+ threads_count.times do |count|
66
+ threads << Thread.new do
67
+ # Thread.current[:name] = "upload files #{count}"
68
+ # puts "...started thread '#{Thread.current[:name]}'...\n"
69
+ while not files.empty?
70
+ semaphore.synchronize do
71
+ file_number += 1
72
+ end
73
+ file = files.pop
74
+ key = file.gsub(dir, '')[1..-1]
75
+ dest = "#{dest_path}#{key}"
76
+ puts "[#{file_number}/#{total_files}] Uploading #{key} to s3://#{dir_name}/#{dest}"
77
+ bucket.files.create(
78
+ :key => dest,
79
+ :body => File.open(file),
80
+ :public => is_public
81
+ )
82
+ end
83
+ end
84
+ end
85
+ # Wait for the threads to finish.
86
+ threads.each do |t|
87
+ begin
88
+ t.join
89
+ rescue RuntimeError => e
90
+ puts "Failure on thread #{t[:name]}: #{e.message}"
91
+ end
92
+ end
93
+ puts "Uploaded #{total_files} (#{total_size / 1024} KB)"
94
+ end
95
+
96
+ def multipart_upload options
97
+ bucket_name, file_path, tmp_loc, acl = options[:bucket_name], options[:file_path], options[:tmp_dir], options[:acl]
98
+ dir = @@conn.directories.get(bucket_name)
99
+ abort "cannot find bucket: #{bucket_name}" unless dir
100
+ file = File.expand_path(file_path)
101
+ abort "Invalid file path: #{file_path}" unless File.exist?(file)
102
+ dest_path = options[:dest_path] if options[:dest_path]
103
+ if dest_path
104
+ if !dest_path.end_with?('/')
105
+ #add trailing slash to detination dir if is not passed
106
+ dest_path = "#{dest_path}/"
107
+ elsif
108
+ #remove leading slash from destination dir path if exists
109
+ dest_path = dest_path[1..-1]
110
+ end
111
+ end
112
+
113
+ remote_file = if dest_path
114
+ "#{dest_path}#{File.basename(file_path)}"
115
+ else
116
+ "#{File.basename(file_path)}"
117
+ end
118
+
119
+ #get the file and split it
120
+ tmp_dir = "#{tmp_loc}/#{File.basename(file_path)}"
121
+ FileUtils.mkdir_p(tmp_dir)
122
+ #split the file into chunks => use smaller chunk sizes to minimize memory
123
+ puts "Spliting the file into 10M chunks ..."
124
+ `split -a3 -b10m #{file} #{tmp_dir}/#{File.basename(file_path)}`
125
+ abort "Cannot perform split on the file" unless $?.to_i == 0
126
+
127
+ parts = Dir.glob("#{tmp_loc}/#{File.basename(file_path)}/*").sort
128
+
129
+ #initiate the mulitpart upload & store the returned upload_id
130
+ puts "Initializing multipart upload"
131
+ multi_part_up = @@conn.initiate_multipart_upload(
132
+ bucket_name, # name of the bucket to create object in
133
+ remote_file, # name of the object to create
134
+ { 'x-amz-acl' => acl }
135
+ )
136
+ upload_id = multi_part_up.body["UploadId"]
137
+ puts "Upload ID: #{upload_id}"
138
+
139
+ part_ids = []
140
+
141
+ parts.each_with_index do |part, position|
142
+ part_number = (position + 1).to_s
143
+ puts "Uploading #{part} ..."
144
+ File.open part do |part_file|
145
+ response = @@conn.upload_part(
146
+ bucket_name,
147
+ # file[1..-1],
148
+ remote_file,
149
+ upload_id,
150
+ part_number,
151
+ part_file
152
+ )
153
+ part_ids << response.headers['ETag']
154
+ end
155
+ end
156
+
157
+ puts "Completing multipart upload ..."
158
+ response = @@conn.complete_multipart_upload(
159
+ bucket_name,
160
+ # file[1..-1],
161
+ remote_file,
162
+ upload_id,
163
+ part_ids
164
+ )
165
+ puts "Cleaning tmp_dir ..."
166
+ FileUtils.rm_rf(tmp_dir)
167
+ puts "Successfully completed multipart upload"
168
+ end
169
+
33
170
  def download_file dir_name, file_name, path
34
171
  dir = @@conn.directories.get(dir_name)
35
172
  abort "cannot find bucket: #{dir_name}" unless dir
@@ -44,6 +181,7 @@ module Awscli
44
181
  end
45
182
 
46
183
  def delete_file dir_name, file_name
184
+ #TODO: Handle globs for deletions
47
185
  dir = @@conn.directories.get(dir_name)
48
186
  abort "cannot find bucket: #{dir_name}" unless dir
49
187
  remote_file = dir.files.get(file_name)
@@ -71,9 +209,12 @@ module Awscli
71
209
  @@conn.directories.table
72
210
  end
73
211
 
74
- def create options
75
- dir = @@conn.directories.create(options)
76
- puts "Create bucket: #{dir.key}"
212
+ def create bucket_name, is_public
213
+ dir = @@conn.directories.create(
214
+ :key => bucket_name,
215
+ :public => is_public
216
+ )
217
+ puts "Created bucket: #{dir.key}"
77
218
  end
78
219
 
79
220
  def delete dir_name
@@ -1,3 +1,3 @@
1
1
  module Awscli
2
- VERSION = '0.1.0'
2
+ VERSION = '0.1.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awscli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ashrith
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-03-29 00:00:00.000000000 Z
11
+ date: 2013-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake