Removing and purging all Rackspace Cloud Files from all containers

So, this one comes up a lot at work, and thanks to knowitnot.com I came accross this example using ruby and fog, its simple, dont runnaway!

Regex lets you define the exact things you want to delete, but be careful. I’m using .* , I’ve removed it and replaced it with some_regex, to make sure people don’t accidentally nuke their cloud files 😀

Install first

yum install rubygem-fog.noarch
#!/usr/bin/env ruby
# Author: Jason Barnett 

require 'fog'

def delete_file(container, file_num, max_tries)
  max_retries ||= max_tries
  try = 0
  puts "(#{file_num} of #{container.files.count}) Removing #{container.files[file_num].key}"
  begin
    container.files[file_num].destroy
  rescue Excon::Errors::NotFound, Excon::Errors::Timeout, Fog::Storage::Rackspace::NotFound => e
    if try == max_retries
      $stderr.puts e.message
    else
      try += 1
      puts "Retry \##{try}"
      retry
    end
  end
end

def equal_div(first, last, num_of_groups)
  total      = last - first
  group_size = total / num_of_groups + 1

  top    = first
  bottom = top + group_size
  blocks = 1.upto(num_of_groups).inject([]) do |result, x|
    bottom = last if bottom > last
    result << [ top, bottom ]

    top    += group_size + 1
    bottom =  top + group_size

    result
  end

  blocks
end

service = Fog::Storage.new({
    :provider             => 'Rackspace',               # Rackspace Fog provider
    :rackspace_username   => 'your_rackspace_username', # Your Rackspace Username
    :rackspace_api_key    => 'your_api_key',            # Your Rackspace API key
    :rackspace_region     => :ord,                      # Defaults to :dfw
    :connection_options   => {},                        # Optional
    :rackspace_servicenet => false                      # Optional, only use if you're the Rackspace Region Data Center
})

containers = service.directories.select do |s|
  s.key =~ /^some_regex/  # Only delete containers that match the regexp
end

TOT_THREADS = 4
threads     = []

containers.each do |container|
  puts
  puts "-----------------------------------------"
  puts "-- Removing _ALL_ objects from #{container.key}"
  puts "-----------------------------------------"
  puts

  #puts "container.files.count: #{container.files.count}"

  ## separates the number of files into equal groups to distribute to each thread
  mygroups = equal_div(0, container.files.count - 1, TOT_THREADS)

  0.upto(TOT_THREADS - 1) do |thread|
    threads << Thread.new([ container, mygroups[thread] ]) { |tObject|
      tObject[1][0].upto(tObject[1][1]) do |x|
        delete_file(tObject[0], x, 5)
      end
    }

  end
  threads.each { |aThread|  aThread.join }
  puts "Deleting #{container.key}"
  container.destroy
end

The script works, supporting multiple threads:

(8178 of 10000) Removing conv/2015/04/15/08/bdce78e4cab875e9e17eeeae051b1128.log.gz
(3183 of 10000) Removing conv/2015/03/17/18/0ea71bf7a834fc02b01c7f65c4eb23b0.log.gz
(5685 of 10000) Removing conv/2015/04/01/08/e4d6a7a2ee83d0be116cca6b1a92ad2a.log.gz
(682 of 10000) Removing conv/2015/02/26/07/163f33cf4e33c64139ab3bd7092a9478.log.gz
(8179 of 10000) Removing conv/2015/04/15/09/09ef6c4ecaa9341e76648b6e175db888.log.gz
(5686 of 10000) Removing conv/2015/04/01/09/23fa1dce145c8343efd8e0227fd41e35.log.gz
(3184 of 10000) Removing conv/2015/03/17/18/66cb5ac707c40777a1a78b1486e1c4f3.log.gz
(683 of 10000) Removing conv/2015/02/26/07/35f28368ed45b2fb7c7076c3b78eb008.log.gz
(5687 of 10000) Removing conv/2015/04/01/09/42882b705c2d7cfe5c726ddec3e457fc.log.gz
(3185 of 10000) Removing conv/2015/03/17/18/73dbb421db0093279138b6f69f246c06.log.gz
(8180 of 10000) Removing conv/2015/04/15/09/1a01e6b1779b76b5221b1c8c08398b00.log.gz
(684 of 10000) Removing conv/2015/02/26/07/44a59e91f6632383f18ff253e4404dba.log.gz
(3186 of 10000) Removing conv/2015/03/17/18/8f8ba5791ab0c1979b168517b229ef74.log.gz
(5688 of 10000) Removing conv/2015/04/01/09/8ff43c8a5de8a41ee9890686150c8c19.log.gz
(8181 of 10000) Removing conv/2015/04/15/09/28035bc7882fe36bb33da670e6c71ac0.log.gz
(685 of 10000) Removing conv/2015/02/26/07/7947d1b3f712d175281d33a6073531d9.log.gz
(8182 of 10000) Removing conv/2015/04/15/09/34a597377f63709a75c9fd6e8a68e073.log.gz
(3187 of 10000) Removing conv/2015/03/17/18/a92a58f166cc9bd1ff54a5f996bb776b.log.gz
(5689 of 10000) Removing conv/2015/04/01/09/9a728570208bcac32fd11f1581a57fbb.log.gz