Skip to content

Instantly share code, notes, and snippets.

@theukedge
Last active May 7, 2016 00:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save theukedge/382dc5e97f85d651198d0fffcaa0a923 to your computer and use it in GitHub Desktop.
Save theukedge/382dc5e97f85d651198d0fffcaa0a923 to your computer and use it in GitHub Desktop.
Creates snapshots of your DigitalOcean droplets automatically and deletes the oldest snapshots to ensure you only maintain the most recent "x" snapshots (where x is configurable). Forked from https://www.digitalocean.com/community/tutorials/how-to-use-digitalocean-snapshots-to-automatically-backup-your-droplets
#!/usr/bin/env ruby
require 'rest-client'
require 'json'
require 'colorize'
$api_token = "xxxxxxxx"
$baseUrl = "https://api.digitalocean.com/v2/"
$headers = {:content_type => :json, "Authorization" => "Bearer #{$api_token}"}
$snapshots_to_keep = 10
class ResponseError < StandardError; end
def droplet_on?(droplet_id)
url = $baseUrl + "droplets/#{droplet_id}"
droplet = get(url)['droplet']
droplet['status'] == 'active'
end
def power_off(droplet_id)
url = $baseUrl + "droplets/#{droplet_id}/actions"
params = {'type' => 'shutdown'}
post(url, params)
end
def snapshot(droplet_id)
url = $baseUrl + "droplets/#{droplet_id}/actions"
params = {'type' => 'snapshot', 'name' => Time.now.strftime("%Y%m%d %H:%M")}
post(url, params)
end
def count_snapshots(droplet_id)
url = $baseUrl + "droplets/#{droplet_id}/snapshots"
snapshots = get(url)
return snapshots['meta']['total']
end
def get(url)
response = RestClient.get(url, $headers){|response, request, result| response }
puts response.code
if response.code == 200
JSON.parse(response)
else
raise ResponseError, JSON.parse(response)["message"]
end
end
def post(url, params)
response = RestClient.post(url, params.to_json, $headers){|response, request, result| response }
if response.code == 201
JSON.parse(response)
else
raise ResponseError, JSON.parse(response)["message"]
end
end
def delete(url)
response = RestClient.delete(url, $headers){|response, request, result| response }
puts response.code
if response.code != 204
raise ResponseError, JSON.parse(response)["message"]
end
end
droplets = ARGV
droplets.each do |droplet_id|
puts "Attempting snapshot of #{droplet_id}".green
begin
if droplet_on?(droplet_id)
power_off(droplet_id)
$i = 0
while droplet_on?(droplet_id) && $i < 12 do
sleep 10
$i +=1
end
if droplet_on?(droplet_id)
puts "Droplet #{droplet_id} didn't shut down within 2 minutes".red
exit
end
puts "Powered off #{droplet_id}".green
sleep 10
end
snapshot(droplet_id)
puts "Started snapshot of #{droplet_id}. Droplet will automatically restart once snapshot is complete.".green
if $snapshots_to_keep < count_snapshots(droplet_id) + 1
url = $baseUrl + "droplets/#{droplet_id}/snapshots"
snapshots = get(url)
number_to_delete = count_snapshots(droplet_id) - $snapshots_to_keep + 1
$i = 0
while $i < number_to_delete do
snapshot_id = snapshots['snapshots'][$i]['id']
delete_url = $baseUrl+ "images/" + snapshot_id.to_s
puts "Deleting snapshot #{snapshot_id}".yellow
delete(delete_url)
$i +=1
end
puts "Old snapshots cleaned up".green
end
rescue ResponseError => e
puts "Error creating a snapshot of #{droplet_id} - #{e.message}".red
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment