Skip to content

Instantly share code, notes, and snippets.

@ilyash-b
Created October 21, 2019 10:57
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 ilyash-b/b32c89699cc63ede1a2e0ce572d04e66 to your computer and use it in GitHub Desktop.
Save ilyash-b/b32c89699cc63ede1a2e0ce572d04e66 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ngs
# This script is rough translation of https://gist.github.com/shokoe/e7b4d80b63ea5931ba23bcad1c7684d4
# The translation was made as part of thinking about scripting by both parties: @shokoe, @ilyash-b
# The script was changed to match @ilyash-b's environment
# Starts new instance with same settings as given instances from backup AMI of the given instance
# Syntax: ec2_kamino.ngs <ENV> <ROLE>
# Syntax: ec2_kamino.ngs <INSTNACE_ID>
# If ENV and ROLE are given, finds the latest instance which has backup AMI
# New instance settings can be overriden by OVERRIDES.
# Bugs: `aws ec2 get-launch-template-data` does not return 'CreditSpecification>CpuCredits' for t3.
# template overrides for run-instances
OVERRIDES = %[--placement Tenancy=default]
F main(env:Str, role:Str) {
tags = {'env': env, 'role': role}
log("Cloning ${tags}")
log("Looking for latest instance which has AMI")
instances = AWS2::Instance(tags).Arr().sort('LaunchTime')
not(instances) throws Error("No instances found with tags ${tags}")
instance = instances.reverse().first(F(i) {
log("Checking for AMI for instance ${i.InstanceId}")
AWS2::Image(OwnerId="self", Tags={'instance-id': i.InstanceId})
})
log("Will clone instance ${instance.InstanceId} tagged ${instance.Tags}")
main(instance.InstanceId)
}
F main(instance_id:Str) {
log("Cloning ${instance_id}")
log("Overrides: ${OVERRIDES}")
section "Get latest AMI" {
ami = AWS2::Image(OwnerId="self", Tags={'instance-id': instance_id}).latest().the_one()
ami_age = Time().Int() - Time(ami.CreationDate).Int()
log(" Found AMI '${ami.Name}' (${ami.ImageId}), ${ami_age / 3600} hours old")
}
section "Create Template" {
tmpl_source = ``aws ec2 get-launch-template-data --instance-id ${instance_id}``.LaunchTemplateData
# removals are required to launch template from an ami
tmpl_fix = tmpl_source.without('BlockDeviceMappings')
tmpl_fix.NetworkInterfaces .= map(X.without('PrivateIpAddresses'))
tmpl_fix .= without('CpuOptions')
tmpl_name = "${instance_id}-tmp-clone"
output_create=``aws ec2 create-launch-template --launch-template-name "${tmpl_name}" --launch-template-data ${tmpl_fix.encode_json()}``
exit_hook.delete_template = {
$(aws ec2 delete-launch-template --launch-template-name "${tmpl_name}")
}
}
section "Run Instance" {
F tags_to_stupid(h:Hash) h.map(F(k, v) {
{"Key": k, "Value": v}
})
relevant_tags = ami.Tags.filterk(/^i:/).mapk(X[2..null])
tag_specs = [
{
"ResourceType": "instance"
"Tags": relevant_tags.tags_to_stupid()
}
{
"ResourceType": "volume"
"Tags": relevant_tags.filterk(OneOf('proj', 'env', 'role')).tags_to_stupid()
}
]
$(log: aws ec2 run-instances --launch-template LaunchTemplateName=${tmpl_name},Version=1 --image-id ${ami.ImageId} $*OVERRIDES --tag-specifications ${tag_specs.encode_json()})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment