On Sun, Jan 9, 2011 at 17:59, Jim Popovitch <jim...@gmail.com> wrote:
> Attached is a short script I hacked together from details at
> http://tomatohater.com/2010/10/22/cloudfront-object-invalidation-python/
>
> I'd love to see that functionality in s3cmd, and I am working to learn
> more about s3cmd in hopes of providing a patch to do that.  In the
> mean time if anyone is looking for a quick way to invalidate a file(s)
> you can use the attached.

Attached is an update to this script, it takes input via stdin (cat
list-of-files | ./s3invalidate.py) as well as files passed on the
cmdline (./s3invalidate.py file1.html file2.html ....).  If you run
the script without any parameters it will report on current/recent
invalidations, listing the comment, status, and files.   Further this
script now reads s3 access credentials from ~/.s3cfg.  You still have
to define "aws_dist_id" in the script for now.

-Jim P.
#!/usr/bin/python
##

## 400 Bad Request probably means too many currently open requests
##

import urllib2
import base64
import datetime
import hmac
import hashlib
from xml.dom import minidom
import sys, os
import ConfigParser


## TODO: read the bucket name from the last cmdline param
## convert the bucketname into a distro ID
## until then it has to be hardcoded here:
aws_dist_id = ""

if not aws_dist_id:
    print "You first need to define aws_dist_id in this script.\n"
    sys.exit()

## parse ~/.s3cmd for access and secret keys
config = ConfigParser.RawConfigParser()
config.read(os.path.expanduser('~/.s3cfg'))

host = 'cloudfront.amazonaws.com'
path = '/2010-11-01/distribution/%s/invalidation' % aws_dist_id

def get_aws_auth():
    date = datetime.datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
    auth = 'AWS %s:%s' % (
        config.get('default','access_key'),
        base64.b64encode(
            hmac.new(
                config.get('default','secret_key').encode('utf-8'),
                date.encode('utf-8'),
                hashlib.sha1
            ).digest()
        )
    )
    return date, auth


if sys.stdin.isatty() and len(sys.argv) < 2:
    date, auth = get_aws_auth()
    # define required http headers
    headers = {
        'Host': host,
        'Authorization' : auth,
        'Date': date,
    }

    # send REST request
    request_url = 'https://%s%s' % (host, path)
    req = urllib2.Request(request_url, headers=headers)
    response = urllib2.urlopen(req)
    invalidationDoc = minidom.parseString(response.read())
    ##print invalidationDoc.toprettyxml(indent='\t')

    idValue = None
    statValue = None
    commentValue = None
    fileValue = None
    print "Current Invalidations:"
    print "Id\t\tStatus\t\tComment"
    for summary in invalidationDoc.getElementsByTagName('InvalidationSummary'):
        for summaryChild in summary.childNodes:
            for value in summaryChild.childNodes:
                if value.nodeType == summaryChild.TEXT_NODE:
                   if summaryChild.nodeName == "Id":
                       idValue = value.nodeValue
                   elif summaryChild.nodeName == "Status":
                       statValue = value.nodeValue

        if idValue:
            fileValue = None
            # lookup the comment on the invalidation ID
            request_url = 'https://%s%s/%s/' % (host, path, idValue)
            req = urllib2.Request(request_url, headers=headers)
            response = urllib2.urlopen(req)
            batchDoc = minidom.parseString(response.read())
            for invalidation in batchDoc.getElementsByTagName('InvalidationBatch'):
                for invalidationChild in invalidation.childNodes:
                    for value in invalidationChild.childNodes:
                        if value.nodeType == invalidationChild.TEXT_NODE:
                           if invalidationChild.nodeName == "Path":
                               if fileValue:
                                   fileValue = str(fileValue) + ", " + value.nodeValue
                               else:
                                   fileValue = value.nodeValue
                           elif invalidationChild.nodeName == "CallerReference":
                               commentValue = value.nodeValue

        output = '%s\t%s\t%s\t' % (idValue, statValue, commentValue)
        print output, fileValue, "\n"

    sys.exit()

# create authentication signature
date, auth = get_aws_auth()

files = []
if sys.stdin.isatty():
    files = sys.argv[1:]
else:
    files = sys.stdin.read().split()

# create xml data to post
data = ['<?xml version="1.0" encoding="UTF-8"?>']
data.append('<InvalidationBatch>') 
data.append('%s' % ''.join(['<Path>/%s</Path>' % urllib2.quote(f) for f in files]))
data.append('<CallerReference>%s</CallerReference>' % date)
data.append('</InvalidationBatch>')
data = ''.join(data)

# define required http headers
headers = {
        'Host': host,
        'Authorization' : auth,
        'Date': date,
        'Content-Type': 'text/xml',
        'Content-Length': len(data),
    }

# make REST request, capture 201 (success) response
request_url = 'https://%s%s' % (host, path)
req = urllib2.Request(request_url, data, headers=headers)
try:
    response = urllib2.urlopen(req)
    #print minidom.parseString(response.read()).toprettyxml(indent=' '*4)
except urllib2.HTTPError, e:
    print e
    if not e.code == 201:
        print "---------------------------------"
        print "URL:", request_url
        print ""
        print "Headers:"
        print headers
        print ""
        print "Data:"
        print minidom.parseString(str(data)).toprettyxml(indent=' '*4)
        print "---------------------------------"

------------------------------------------------------------------------------
The modern datacenter depends on network connectivity to access resources
and provide services. The best practices for maximizing a physical server's
connectivity to a physical network are well understood - see how these
rules translate into the virtual world? 
http://p.sf.net/sfu/oracle-sfdevnlfb
_______________________________________________
S3tools-general mailing list
S3tools-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/s3tools-general

Reply via email to