Skip to content

Instantly share code, notes, and snippets.

View shentonfreude's full-sized avatar

Chris Shenton shentonfreude

View GitHub Profile
@shentonfreude
shentonfreude / logtest.py
Created November 24, 2015 17:58
Show our app's logs at INFO but suppress boto's INFO logs (only show 3rd party at WARNING)
#!/usr/bin/env python3
# Setup logs so our app shows INFO but boto shows at WARNING
import logging
import boto3
# Don't show boto INFO; if we don't call this our own INFO logs aren't seen!
logging.basicConfig(level=logging.WARNING)
# Define our logger to show INFO logs
@shentonfreude
shentonfreude / development.ini
Created November 30, 2015 15:57
Pyramid suppress boto3 log noise via .ini file
# ...
[loggers]
keys = root, rival, sqlalchemy, boto3
# ...
[logger_boto3]
# boto3.resources.action spews binary contents of file put_object at INFO, suppress
level = WARN
handlers =
@shentonfreude
shentonfreude / cloudsearch_page_size.py
Last active December 7, 2015 20:39
Page through AWS CloudSearch results by pages of a given size with Next and Prev links
#!/usr/bin/env python3
"""
We want to query of a page 'size' of N results and return them, and also a
'next' and 'previous' link. Those CloudSearch 'start' offsets are based on the
page (for our app, starting at 1) and the size. So with size=100: page=1 has
start=0, page=2 has start=100, page=10 has start=100. We don't want to return
'previous' if we're at page=1, and don't want to return 'next' if it's beyond
the maximum results 'found'. So if size=100 and found=543, the last page=5,
there is no page=6. More generally: lastpage = int(found / size).
"""
@shentonfreude
shentonfreude / searchpage.py
Last active December 7, 2015 20:38
AWS CloudSearch with pages: limit of 10,000 results but can go backward and forward
import boto3
# found is always the same
# start is the index into the total results, not a page of size results
cs = boto3.client('cloudsearchdomain',
endpoint_url='https://search-name-xxx.us-east-1.cloudsearch.amazonaws.com',
region_name='us-east-1')
size = 4
@shentonfreude
shentonfreude / searchcursor.py
Created December 7, 2015 20:37
AWS CloudSearch with pages using cursor (can only go forward, not back)
import boto3
# Returned 'cursor' can be of seemingly any length, and changes on each return
cs = boto3.client('cloudsearchdomain',
endpoint_url='https://search-thing-xxx.us-east-1.cloudsearch.amazonaws.com',
region_name='us-east-1')
size = 4
cursor = 'initial'
while True:
@shentonfreude
shentonfreude / dynamodb_read_backoff.py
Created December 11, 2015 17:00
Wrap boto3 dynamodb in an exponential backoff to avoid ProisionedThroughputExceededException
#!/usr/bin/env python
# An exponential backoff around Boto3 DynamoDB, whose own backoff eventually
# fails on long multipage scans. We'd like to use this as a wrapper somehow,
# see: https://gist.github.com/numberoverzero/cec21b8ca715401c5662
from time import sleep
import boto3
from boto3.dynamodb.conditions import Attr
@shentonfreude
shentonfreude / tropo_ec2_vpc_pubip.py
Created December 15, 2015 16:49
EC2 is very different than ASGs, and params in VPC or with NetworkInterfaces are very different than without (inconsistent names of SecurityGroups, SecurityGroupIds, GroupSet, etc)
# EC2 only
# Can't use (EC2) SecurityGroups with Subnet
# Can't use (VPC) SecurityGroupIds with NetworkInterfaces
# Can't use SubnetId with NetworkInterfaces
def add_ec2(self):
name, tags = self._name_tags('ec2')
self.ec2 = self.t.add_resource(
ec2.Instance(
name,
@shentonfreude
shentonfreude / aws_cloudsearch_field.py
Created April 19, 2016 17:54
Get the endpoints by the human name, then search on a single field with structured query
aws_region = config['AWS']['region']
search_domain_name = config['AWS']['cloudsearch_domain_name'] # e.g., avail-search-dev
cs = boto3.client("cloudsearch")
cs_domain = cs.describe_domains(DomainNames=[search_domain_name])['DomainStatusList'][0]
cs_doc_ep = cs_domain['DocService']['Endpoint']
cs_doc = boto3.client('cloudsearchdomain',
endpoint_url='https://' + cs_doc_ep,
region_name=aws_region)
cs_search_ep = cs_domain['SearchService']['Endpoint']
cs_search = boto3.client('cloudsearchdomain',
@shentonfreude
shentonfreude / dynamodb_update_item.py
Created July 19, 2016 14:58
DynamoDB update_item() is convoluted, requiring placeholders and name maps to avoid 572 reserved keywords; this seems a pretty concise approach to mapping a dict to names it will accept.
def asset_update(asset_id, state, extra={}):
asset = extra.copy()
asset.update({'dt': datetime.now().isoformat(),
'state': state})
# We need update_item placeholder and values like:
# UpdateExpression='SET dt = :dt, #state = :state' # 'state' is a reserved word
# ExpressionAttributeNames={'#state': 'state'} # proxy for reserved word 'state'
# ExpressionAttributeValues={':dt': datetime.now().isoformat(), ':state': 'uploaded'}
# We can't use "reserved words" like 'state' use EAN for *all* names,
@shentonfreude
shentonfreude / create_et_preset.py
Created November 3, 2016 16:33
Create AWS ElasticTranscoder preset that preserves frames per second based on their 1080p preset.
# Create AWS ElasticTranscoder preset based on AWS 1080p with 'auto' framerate.
# This uses same output FPS as incoming, so we don't up/down sample.
import boto3
et = boto3.client('elastictranscoder')
res = et.read_preset(Id='1351620000001-000001') # Generic 1080p
preset = res['Preset']
del preset['Type']