Class: BundleDeleter

Inherits:
AMITool show all
Defined in:
lib/ec2/amitools/deletebundle.rb

Constant Summary

Constants inherited from AMITool

AMITool::BACKOFF_PERIOD, AMITool::MAX_TRIES, AMITool::PROMPT_TIMEOUT

Instance Method Summary collapse

Methods inherited from AMITool

#get_parameters, #handle_early_exit_parameters, #interactive?, #interactive_prompt, #retry_s3, #run, #warn_confirm

Instance Method Details

#delete(bucket, key, retry_delete) ⇒ Object

Delete the specified file.



56
57
58
59
60
61
62
63
64
65
66
# File 'lib/ec2/amitools/deletebundle.rb', line 56

def delete(bucket, key, retry_delete)
  retry_s3(retry_delete) do
    begin
      response = @s3_conn.delete(bucket, key)
      return if response.success?
      raise "HTTP DELETE returned #{response.code}"
    rescue => e
      raise TryFailed.new("Failed to delete \"#{key}\": #{e.message}")
    end
  end
end

#delete_bundle(url, bucket, keyprefix, user, pass, manifest, prefix, yes, clear, retry_stuff, sigv, region) ⇒ Object

——————————————————————————#



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/ec2/amitools/deletebundle.rb', line 118

def delete_bundle(url, bucket, keyprefix, user, pass, manifest, prefix, yes, clear, retry_stuff, sigv, region)
  begin
    # Get the S3 URL.
    s3_uri = URI.parse(url)
    s3_url = uri2string(s3_uri)
    retry_delete = retry_stuff
    v2_bucket = EC2::Common::S3Support::bucket_name_s3_v2_safe?(bucket)
    @s3_conn = make_s3_connection(s3_url, user, pass, (v2_bucket ? nil : :path), sigv, region)
    
    files_to_delete = []
    
    if manifest
      # Get list of files to delete from the AMI manifest.
      xml = String.new
      manifest_path = manifest
      File.open(manifest_path) { |f| xml << f.read }
      files_to_delete << File::basename(manifest)
      get_part_filenames( xml ).each do |part_info|
        files_to_delete << part_info
      end
    else
      files_to_delete = get_file_list_from_s3(bucket, keyprefix, prefix)
    end
    
    if files_to_delete.empty?
      $stdout.puts "No files to delete."
    else
      $stdout.puts "Deleting files:"
      files_to_delete.each { |file| $stdout.puts("   - #{file}") }
      continue = yes
      unless continue
        begin
          $stdout.print "Continue [y/N]: "
          $stdout.flush
          Timeout::timeout(PROMPT_TIMEOUT) do
            continue = gets.strip =~ /^y/i
          end
        rescue Timeout::Error
          $stdout.puts "\nNo response given, skipping the files."
          continue = false
        end
      end
      if continue
        files_to_delete.each do |file|
          delete(bucket, keyprefix+file, retry_delete)
          $stdout.puts "Deleted #{file}"
        end
      end
    end
    
    if clear
      $stdout.puts "Attempting to delete bucket #{bucket}..."
      @s3_conn.delete(bucket)
    end
  rescue EC2::Common::HTTP::Error => e
    $stderr.puts e.backtrace if @debug
    raise S3Error.new(e.message)
  end  
  $stdout.puts "#{DELETE_BUNDLE_NAME} complete."
end

#get_file_list_from_s3(bucket, keyprefix, prefix) ⇒ Object

——————————————————————————#



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/ec2/amitools/deletebundle.rb', line 90

def get_file_list_from_s3(bucket, keyprefix, prefix)
  s3prefix = keyprefix+prefix
  files_to_delete = []
  response = @s3_conn.list_bucket(bucket, s3prefix)
  unless response.success?
    raise "unable to list contents of bucket #{bucket}: HTTP #{response.code} response: #{response.body}"
  end
  REXML::XPath.each(REXML::Document.new(response.body), "//Key/text()") do |entry|
    entry = entry.to_s
    if entry[0,s3prefix.length] == s3prefix
      test_str = entry[(s3prefix.length)..-1]
      if (test_str =~ /^\.part\.[0-9]+$/ or
          test_str =~ /^\.manifest(\.xml)?$/)
        files_to_delete << entry[(keyprefix.length)..-1]
      end
    end
  end
  files_to_delete
end

#get_manualObject

——————————————————————————# Overrides ——————————————————————————#



183
184
185
# File 'lib/ec2/amitools/deletebundle.rb', line 183

def get_manual()
  DELETE_BUNDLE_MANUAL
end

#get_nameObject



187
188
189
# File 'lib/ec2/amitools/deletebundle.rb', line 187

def get_name()
  DELETE_BUNDLE_NAME
end

#get_part_filenames(manifest) ⇒ Object

Return a list of bundle part filenames from the manifest.



71
72
73
74
75
76
77
78
# File 'lib/ec2/amitools/deletebundle.rb', line 71

def get_part_filenames(manifest)
  parts = []
  manifest_doc = REXML::Document.new(manifest).root
  REXML::XPath.each(manifest_doc, 'image/parts/part/filename/text()') do |part|
    parts << part.to_s
  end
  return parts
end

#main(p) ⇒ Object



191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/ec2/amitools/deletebundle.rb', line 191

def main(p)
  delete_bundle(p.url,
                p.bucket,
                p.keyprefix,
                p.user,
                p.pass,
                p.manifest,
                p.prefix,
                p.yes,
                p.clear,
                p.retry,
                p.sigv,
                p.region)
end

#make_s3_connection(s3_url, user, pass, method, sigv, region) ⇒ Object

——————————————————————————#



112
113
114
# File 'lib/ec2/amitools/deletebundle.rb', line 112

def make_s3_connection(s3_url, user, pass, method, sigv, region)
  EC2::Common::S3Support.new(s3_url, user, pass, method, @debug, sigv, region)
end

#uri2string(uri) ⇒ Object

——————————————————————————#



82
83
84
85
86
# File 'lib/ec2/amitools/deletebundle.rb', line 82

def uri2string(uri)
  s = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}"
  # Remove the trailing '/'.
  return (s[-1..-1] == "/" ? s[0..-2] : s)
end