Skip to content

Instantly share code, notes, and snippets.

@moziauddin
Last active July 4, 2018 21:00
Show Gist options
  • Save moziauddin/92e8fa7ecc40c3602b088f5b7c16a95d to your computer and use it in GitHub Desktop.
Save moziauddin/92e8fa7ecc40c3602b088f5b7c16a95d to your computer and use it in GitHub Desktop.
AWS
#------------------------------------------------------------------------------------------------------
# Copy files using S3 while adding a Key with Date
mo@linux-jzir:~> export AWS_DATE=`date +"%Y-%m-%d"`
mo@linux-jzir:~> echo $AWS_DATE
2018-06-18
mo@linux-jzir:~> aws s3 cp initscript.sh s3://nxlbackup/NAQS/dailycopy/`date +"%Y-%m-%d"`/ --profile s3user
#------------------------------------------------------------------------------------------------------
# EBS-Snapshot-Backup-Script-Retention-Tag.sh
import logging
from datetime import date
import boto3
from dateutil.relativedelta import relativedelta
VERSION = '1.0.1'
logger = logging.getLogger()
logger.setLevel(logging.INFO)
ec2 = boto3.resource('ec2')
client = boto3.client('ec2')
def lambda_handler(event, context):
logger.info('Start ebs-backup v{}'.format(VERSION))
backup()
expire()
def backup():
instances = ec2.instances.filter(Filters=[{'Name': 'tag-key',
'Values': ['LambdaBackupConfiguration']}])
for instance in instances:
try:
backup_instance(instance)
except:
logging.exception('Error creating snapshot for {}'.format(instance.id))
def backup_instance(instance):
instance_tags = dict(map(lambda x: (x['Key'], x['Value']), instance.tags or []))
instance_name = instance_tags.get('Name', '[unnamed]')
backup_cfg_str = instance_tags['LambdaBackupConfiguration']
backup_cfg = parse_config(instance, instance_name, backup_cfg_str)
backup_label, retention = calc_retention(backup_cfg)
if not backup_label:
logger.info('Skip backup of instance {} ({}); LambdaBackupConfiguration is {}'
.format(instance.id, instance_name, backup_cfg_str))
return
delete_date_fmt = (date.today() + retention).strftime('%Y-%m-%d')
logger.info('Work on instance {} ({}); Create {} backups to be deleted on {}'
.format(instance.id, instance_name, backup_label, delete_date_fmt))
snapshot_ids = []
for device_mapping in instance.block_device_mappings:
volume_id = device_mapping['Ebs']['VolumeId']
device_name = device_mapping['DeviceName']
logger.info('Create snapshot of volume {} (mounted at {})'.format(volume_id, device_name))
snapshot = client.create_snapshot(VolumeId=volume_id, Description='Backup of {} {}'
.format(instance_name, device_name))
snapshot_ids.append(snapshot['SnapshotId'])
if snapshot_ids:
logger.info('Create tags for snapshots {}'.format(snapshot_ids))
tags = {
'Name': 'lambda-backup',
'BackupLabel': backup_label,
'InstanceId': instance.instance_id,
'InstanceName': instance_name,
'DeleteOn': delete_date_fmt
}
tag_list = list(map(lambda kv: {'Key': kv[0], 'Value': kv[1]}, list(tags.items())))
client.create_tags(Resources=snapshot_ids, Tags=tag_list)
def parse_config(instance, instance_name, config):
try:
backup_configuration = list(map(int, config.split(',')))
if any(i < 0 for i in backup_configuration):
raise ValueError('Values must be >= 0')
return backup_configuration
except:
raise ValueError('Syntax error in LambdaBackupConfiguration of {} ({}): {}'
.format(instance.id, instance_name, config))
def calc_retention(backup_configuration):
today = date.today()
r_daily, r_weekly, r_monthly, r_yearly = backup_configuration
if today.day == 1:
if today.month == 1 and r_yearly > 0:
return 'yearly', relativedelta(years=r_yearly)
if r_monthly > 0:
return 'monthly', relativedelta(months=r_monthly)
if today.weekday() == 6 and r_weekly > 0:
return 'weekly', relativedelta(weeks=r_weekly)
if r_daily > 0:
return 'daily', relativedelta(days=r_daily)
return None, None
def expire():
delete_fmt = date.today().strftime('%Y-%m-%d')
snapshots = ec2.snapshots.filter(OwnerIds=['self'],
Filters=[{'Name': 'tag:DeleteOn', 'Values': [delete_fmt]}])
for snapshot in snapshots:
logger.info('Remove snapshot {} (of volume {}) created at {}'
.format(snapshot.id, snapshot.volume_id, snapshot.start_time))
snapshot.delete()
#------------------------------------------------------------------------------------------------------
# Swap volumes of ebs backed instances on AWS
# SwapVolumesEC2Inshance.sh
#!/bin/bash
# Set variables below
export awsInstanceId=*instance-id-value*
export snapId=*snapshot-name*
export tagEnvSwap=dev
export tagAppSwap=*app-name*
echo "Create New Volume"
echo "-----------------------------------------------------------------------"
export awsAZone=`aws ec2 describe-volumes --filters Name=attachment.instance-id,Values=$awsInstanceId | jq '.Volumes[0].AvailabilityZone' | sed -e 's/"//g'`
echo "Create New Volume"
echo "-----------------------------------------------------------------------"
export awsNewVolId=`aws ec2 create-volume --availability-zone $awsAZone --snapshot-id $snapId --volume-type gp2 --size 80 --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=tagEnvSwap-tagAppSwap},{Key=app,Value=$tagAppSwap},{Key=env,Value=$tagEnvSwap}]' | jq '.VolumeId' | sed -e 's/"//g'`
echo "Getting Old Volume Information"
echo "-----------------------------------------------------------------------"
export awsOldVolId=`aws ec2 describe-volumes --filters Name=attachment.instance-id,Values=$awsInstanceId | jq '.Volumes[0].Attachments[0].VolumeId' | sed -e 's/"//g'`
echo "Stopping Instance"
echo "-----------------------------------------------------------------------"
aws ec2 stop-instances --instance-ids $awsInstanceId
aws ec2 wait instance-stopped --instance-ids $awsInstanceId
echo "Detaching Old Volume"
echo "-----------------------------------------------------------------------"
aws ec2 detach-volume --volume-id $awsOldVolId
echo "Ataching New Volume"
echo "-----------------------------------------------------------------------"
aws ec2 attach-volume --volume-id $awsNewVolId --instance-id $awsInstanceId --device /dev/sda1
echo "Starting the instance"
echo "-----------------------------------------------------------------------"
aws ec2 start-instances --instance-ids $awsInstanceId
aws ec2 wait instance-running --instance-ids $awsInstanceId
echo "Final Output"
echo "-----------------------------------------------------------------------"
echo "The old volume $awsOldVolId was swapped with new volume $awsNewVolId for instance $awsInstanceId"
#------------------------------------------------------------------------------------------------------
#Add DNS Entry in Route53 dynamically
#add-dns-entry-dynamiclly.sh
#!/bin/bash -eo pipefail
## Allows for creation of "Basic" DNS records in a Route53 hosted zone
function main() {
record_name=$1
record_value=$2
[[ -z $record_name ]] && echo "record_name is: $record_name" && exit 1
[[ -z $record_value ]] && echo "record_value is: $record_value" && exit 1
## set some defaults if variables haven't been overridden on script execute
zone_name=${zone_name:-$ROUTE53_DEFAULT_HOSTED_ZONE_NAME}
action=${action:-CREATE}
record_type=${record_type:-A}
ttl=${ttl:-300}
wait_for_sync=${wait_for_sync:-false}
change_id=$(submit_resource_record_change_set) || exit 1
echo "Record change submitted! Change Id: $change_id"
if $wait_for_sync; then
echo -n "Waiting for all Route53 DNS to be in sync..."
until [[ $(get_change_status $change_id) == "INSYNC" ]]; do
echo -n "."
sleep 5
done
echo "!"
echo "Your record change has now propogated."
fi
echo 'Thank you for using "The Cloud".'
}
function change_batch() {
jq -c -n "{\"Changes\": [{\"Action\": \"$action\", \"ResourceRecordSet\": {\"Name\": \"$record_name\", \"Type\": \"$record_type\", \"TTL\": $ttl, \"ResourceRecords\": [{\"Value\": \"$record_value\"} ] } } ] }"
}
function get_change_status() {
aws route53 get-change --id $1 | jq -r '.ChangeInfo.Status'
}
function hosted_zone_id() {
aws route53 list-hosted-zones | jq -r ".HostedZones[] | select(.Name == \"${zone_name}\") | .Id" | cut -d'/' -f3
}
function submit_resource_record_change_set() {
aws route53 change-resource-record-sets --hosted-zone-id $(hosted_zone_id) --change-batch $(change_batch) | jq -r '.ChangeInfo.Id' | cut -d'/' -f3
}
function usage() {
echo "usage: $0 <record_name> <record_value>"
echo ""
echo "possible env config settings and their defaults:"
echo " - action=CREATE"
echo " - ttl=300"
echo " - record_type=A"
echo " - wait_for_sync=false"
echo ""
}
main $1 $2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment