formatting, add WSL container variant, support requesting new quotas

This commit is contained in:
Neil Hanlon 2023-05-12 14:00:52 -04:00
parent 173b0ff814
commit ed2a2999ad
Signed by untrusted user: neil
GPG Key ID: 705BC21EC3C70F34
7 changed files with 327 additions and 293 deletions

View File

@ -104,7 +104,7 @@ for conf in glob.iglob(f"{_rootdir}/sig/*.yaml"):
ALLOWED_TYPE_VARIANTS = { ALLOWED_TYPE_VARIANTS = {
"Azure": ["Base", "LVM"], "Azure": ["Base", "LVM"],
"Container": ["Base", "Minimal", "UBI"], "Container": ["Base", "Minimal", "UBI", "WSL"],
"EC2": ["Base", "LVM"], "EC2": ["Base", "LVM"],
"GenericCloud": ["Base", "LVM"], "GenericCloud": ["Base", "LVM"],
"Vagrant": ["Libvirt", "Vbox", "VMware"], "Vagrant": ["Libvirt", "Vbox", "VMware"],

View File

@ -88,7 +88,7 @@
primary_variant: 'Base' primary_variant: 'Base'
Container: Container:
format: tar.xz format: tar.xz
variants: [Base, Minimal, UBI] variants: [Base, Minimal, UBI, WSL]
RPI: RPI:
format: raw.xz format: raw.xz
OCP: OCP:

View File

@ -2,7 +2,7 @@
apiVersion: batch/v1 apiVersion: batch/v1
kind: Job kind: Job
metadata: metadata:
name: {{ jobname }}-{{ major }}-{{ architecture }} name: {{ jobname }}-{{ major }}-{{ architecture }}-{{ buildTime }}
namespace: {{ namespace }} namespace: {{ namespace }}
spec: spec:
template: template:

View File

@ -7,12 +7,14 @@ import (
"sync" "sync"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/servicequotas" "github.com/aws/aws-sdk-go/service/servicequotas"
) )
func getQuotaCode(sqSvc *servicequotas.ServiceQuotas) string { func getQuotaCode(sess *session.Session) string {
sqSvc := servicequotas.New(sess)
input := &servicequotas.ListServiceQuotasInput{ input := &servicequotas.ListServiceQuotasInput{
ServiceCode: aws.String("ec2"), ServiceCode: aws.String("ec2"),
} }
@ -71,9 +73,13 @@ func getQuotaInfo(sqSvc *servicequotas.ServiceQuotas, quotaCode string, region s
output, err := sqSvc.GetServiceQuota(input) output, err := sqSvc.GetServiceQuota(input)
if err != nil { if err != nil {
log.Printf("Error getting quota info for %s: %s\n", region, err) if awsErr, ok := err.(awserr.Error); ok {
return nil if message := awsErr.Code(); message == "UnknownOperationException" {
// os.Exit(1) log.Printf("[sdk] Region %s does not appear to support Service Quotas: %v", region, message)
return nil
}
log.Fatalf("[sdk] Error getting quota info for %s: %v\n", region, awsErr)
}
} }
currentValue := *output.Quota.Value currentValue := *output.Quota.Value
@ -116,6 +122,35 @@ func listQuotas(sess *session.Session, quotaCode string, regions []*string) {
wg.Wait() wg.Wait()
} }
func requestQuotaIncrease(sess *session.Session, quotaCode string, regions []string, quota float64) {
var wg sync.WaitGroup
wg.Add(len(regions))
for _, region := range regions {
go func(region string) {
defer wg.Done()
regionSqSvc := servicequotas.New(sess, &aws.Config{Region: aws.String(region)})
quotaInfo := getQuotaInfo(regionSqSvc, quotaCode, region)
if quotaInfo.CurrentQuota >= quota {
fmt.Printf("Quota for Public AMIs in region %s is already set to %.0f, skipping request.\n", region, quotaInfo.CurrentQuota)
} else {
input := &servicequotas.RequestServiceQuotaIncreaseInput{
ServiceCode: aws.String("ec2"),
QuotaCode: aws.String(quotaCode),
DesiredValue: aws.Float64(quota),
}
output, err := regionSqSvc.RequestServiceQuotaIncrease(input)
if err != nil {
fmt.Println("Error requesting quota increase:", err)
os.Exit(1)
}
fmt.Printf("Successfully submitted request with ID: %s\n", aws.StringValue(output.RequestedQuota.Id))
}
}(region)
}
wg.Wait()
}
func main() { func main() {
// Create session // Create session
sess := session.Must(session.NewSessionWithOptions(session.Options{ sess := session.Must(session.NewSessionWithOptions(session.Options{
@ -125,11 +160,8 @@ func main() {
// Create EC2 client // Create EC2 client
ec2Svc := ec2.New(sess, &aws.Config{Region: aws.String("us-east-1")}) ec2Svc := ec2.New(sess, &aws.Config{Region: aws.String("us-east-1")})
// Create Service Quotas client
sqSvc := servicequotas.New(sess)
// Get the quota code for Public AMIs once // Get the quota code for Public AMIs once
quotaCode := getQuotaCode(sqSvc) quotaCode := getQuotaCode(sess)
// Get all regions // Get all regions
regions, err := getRegions(ec2Svc) regions, err := getRegions(ec2Svc)
@ -142,5 +174,5 @@ func main() {
listQuotas(sess, quotaCode, regions) listQuotas(sess, quotaCode, regions)
// Request quota increase for all regions // Request quota increase for all regions
// requestQuotaIncrease(sqSvc, quotaCode, regions) // requestQuotaIncrease(sess, quotaCode, regions)
} }

View File

@ -9,145 +9,145 @@ RLVER=$VERSION
# shellcheck disable=SC2046,1091,1090 # shellcheck disable=SC2046,1091,1090
source "$(dirname "${BASH_SOURCE[0]}")/common" source "$(dirname "${BASH_SOURCE[0]}")/common"
usage() { usage() {
echo "usage: $0 VERSION ($0 8.7)" echo "usage: $0 VERSION ($0 8.7)"
} }
aws() { aws() {
command aws --region us-east-1 --profile resf-ami --output text $@ command aws --region us-east-1 --profile resf-ami --output text $@
} }
DATE=$(date +%Y%m%d) DATE=${DATE:-$(date +%Y%m%d)}
if [[ -z $VERSION ]]; then if [[ -z $VERSION ]]; then
usage usage
exit 1 exit 1
fi fi
download() { download() {
curl -o "$qcow" "https://dl.rockylinux.org/stg/rocky/$VERSION/images/$arch/$qcow" curl -o "$qcow" "https://dl.rockylinux.org/stg/rocky/$VERSION/images/$arch/$qcow"
return $? return $?
} }
exists() { exists() {
aws s3 ls $2/$1 &>/dev/null aws s3 ls $2/$1 &>/dev/null
return $? return $?
} }
upload() { upload() {
if exists $raw $BUCKET/$DATE; then if exists $raw $BUCKET/$DATE; then
echo "Found existing upload in $BUCKET" echo "Found existing upload in $BUCKET"
return 0 return 0
fi fi
aws s3 cp $raw $BUCKET/$DATE/ aws s3 cp $raw $BUCKET/$DATE/
} }
convert() { convert() {
qemu-img convert -f qcow2 -O raw "$qcow" $raw qemu-img convert -f qcow2 -O raw "$qcow" $raw
return $? return $?
} }
BUCKET="s3://resf-prod-import-use1" BUCKET="s3://resf-prod-import-use1"
write-container-file() { write-container-file() {
printf '{"Description": "%s", "Format": "raw", "Url": "%s/%s"}\n' $name "$BUCKET/$DATE" $raw > $json printf '{"Description": "%s", "Format": "raw", "Url": "%s/%s"}\n' $name "$BUCKET/$DATE" $raw >$json
} }
download-convert-upload() { download-convert-upload() {
if ! [[ -f $qcow ]]; then if ! [[ -f $qcow ]]; then
echo "Downloading $qcow from cdn" echo "Downloading $qcow from cdn"
download || exit download || exit
fi fi
if ! [[ -f ${raw} ]]; then if ! [[ -f ${raw} ]]; then
echo "Converting qcow2 $qcow to RAW $raw" echo "Converting qcow2 $qcow to RAW $raw"
convert || exit convert || exit
fi fi
echo "Uploading raw image back to s3" echo "Uploading raw image back to s3"
if ! upload; then if ! upload; then
echo "Failed to upload" echo "Failed to upload"
exit exit
fi fi
} }
begin-job() { begin-job() {
import_task_id="$(aws ec2 import-snapshot --disk-container "file://$PWD/$json" --query 'ImportTaskId')" import_task_id="$(aws ec2 import-snapshot --disk-container "file://$PWD/$json" --query 'ImportTaskId')"
if [[ -z $import_task_id ]]; then if [[ -z $import_task_id ]]; then
echo "Failed to import $json" echo "Failed to import $json"
return 1 return 1
fi fi
echo $import_task_id echo $import_task_id
return 0 return 0
} }
is-snapshot-imported() { is-snapshot-imported() {
snapshot_id=$(aws ec2 describe-import-snapshot-tasks --query 'ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId[]' --import-task-ids $1) snapshot_id=$(aws ec2 describe-import-snapshot-tasks --query 'ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId[]' --import-task-ids $1)
if [[ -z "$snapshot_id" ]]; then if [[ -z "$snapshot_id" ]]; then
return 1 return 1
fi fi
return 0 return 0
} }
register-image() { register-image() {
# Given a snapshot id, register the image # Given a snapshot id, register the image
name=$1 name=$1
snapshot_id=$2 snapshot_id=$2
case $(awk -F'.' '{print $NF}'<<<"$name") in case $(awk -F'.' '{print $NF}' <<<"$name") in
x86_64) x86_64)
arch=x86_64;; arch=x86_64
aarch64) ;;
arch=arm64;; aarch64)
esac arch=arm64
;;
esac
ami_id=$(aws --query "ImageId" ec2 register-image --name "$name" --description "$name" --block-device-mappings DeviceName="/dev/sda1",Ebs={SnapshotId="$snapshot_id"} --root-device-name "/dev/sda1" --virtualization-type hvm --architecture $arch --ena-support) ami_id=$(aws --query "ImageId" ec2 register-image --name "$name" --description "$name" --block-device-mappings DeviceName="/dev/sda1",Ebs={SnapshotId="$snapshot_id"} --root-device-name "/dev/sda1" --virtualization-type hvm --architecture $arch --ena-support)
if [[ -z "$ami_id" ]]; then if [[ -z "$ami_id" ]]; then
return 1 return 1
fi fi
return 0 return 0
} }
tag-resources() { tag-resources() {
local resources="$1" local resources="$1"
local tags="$2" local tags="$2"
if [[ -z $resources || -z $tags ]]; then if [[ -z $resources || -z $tags ]]; then
echo "Need to provide tags and resources to tag" echo "Need to provide tags and resources to tag"
return 1 return 1
fi fi
aws ec2 create-tags --resources $resources --tags $tags aws ec2 create-tags --resources $resources --tags $tags
} }
image-exists() { image-exists() {
local RESF_AMI_ACCOUNT_ID=792107900819 local RESF_AMI_ACCOUNT_ID=792107900819
local query="$(printf 'Images[?Name==`%s`].[ImageId,Name][]' "${1}")" local query="$(printf 'Images[?Name==`%s`].[ImageId,Name][]' "${1}")"
mapfile -t res < <(aws ec2 describe-images --owners $RESF_AMI_ACCOUNT_ID --query "${query}" 2>/dev/null) mapfile -t res < <(aws ec2 describe-images --owners $RESF_AMI_ACCOUNT_ID --query "${query}" 2>/dev/null)
res=($res) res=($res)
if [[ ${#res[@]} -eq 0 ]]; then if [[ ${#res[@]} -eq 0 ]]; then
# Skip empty results # Skip empty results
return 1 #not found return 1 #not found
fi fi
id=${res[0]//\"} id=${res[0]//\"/}
name=${res[@]/$id} name=${res[@]/$id/}
found_image_id=$id found_image_id=$id
return 0 # found return 0 # found
} }
snapshot-exists() { snapshot-exists() {
local RESF_AMI_ACCOUNT_ID=792107900819 local RESF_AMI_ACCOUNT_ID=792107900819
local filter="$(printf 'Name=tag:Name,Values=%s' "${1}")" local filter="$(printf 'Name=tag:Name,Values=%s' "${1}")"
local query='Snapshots[].[SnapshotId][]' local query='Snapshots[].[SnapshotId][]'
mapfile -t res < <(aws ec2 describe-snapshots --owner-ids $RESF_AMI_ACCOUNT_ID --filter "${filter}" --query "${query}" 2>/dev/null) mapfile -t res < <(aws ec2 describe-snapshots --owner-ids $RESF_AMI_ACCOUNT_ID --filter "${filter}" --query "${query}" 2>/dev/null)
res=($res) res=($res)
if [[ ${#res[@]} -eq 0 ]]; then if [[ ${#res[@]} -eq 0 ]]; then
# Skip empty results # Skip empty results
return 1 #not found return 1 #not found
fi fi
id=${res[0]//\"} id=${res[0]//\"/}
found_snapshot_id=$id found_snapshot_id=$id
return 0 # found return 0 # found
} }
declare -A import_jobs declare -A import_jobs
@ -158,110 +158,109 @@ TARGET_ARCHES=(x86_64 aarch64)
TARGET_VARIANTS=(Base LVM) TARGET_VARIANTS=(Base LVM)
for variant in "${TARGET_VARIANTS[@]}"; do for variant in "${TARGET_VARIANTS[@]}"; do
for arch in "${TARGET_ARCHES[@]}"; do for arch in "${TARGET_ARCHES[@]}"; do
latest=$(printf "Rocky-%s-EC2-%s.latest.%s" "$VERSION" $variant $arch) latest=$(printf "Rocky-%s-EC2-%s.latest.%s" "$VERSION" $variant $arch)
name=$(printf "Rocky-%s-EC2-%s-%s-%s.%s.%s" "$VERSION" $variant $REVISION $DATE $EPOCH $arch) name=$(printf "Rocky-%s-EC2-%s-%s-%s.%s.%s" "$VERSION" $variant $REVISION $DATE $EPOCH $arch)
qcow=${latest}.qcow2 qcow=${name}.qcow2
raw=${name}.raw raw=${name}.raw
json=${name}.json json=${name}.json
if image-exists $name; then if image-exists $name; then
echo "Found existing AMI in us-east-1. Skipping. ($found_image_id,$name)" echo "Found existing AMI in us-east-1. Skipping. ($found_image_id,$name)"
continue continue
fi fi
if snapshot-exists $name; then if snapshot-exists $name; then
# If the snapshot exists, we can skip the import task and just do the image registration # If the snapshot exists, we can skip the import task and just do the image registration
echo "Found existing snapshot: ($found_snapshot_id,$name)" echo "Found existing snapshot: ($found_snapshot_id,$name)"
snapshot_ids[$name]="${found_snapshot_id}" snapshot_ids[$name]="${found_snapshot_id}"
continue continue
fi fi
# Download latest artifacts from CDN, convert from qcow2 to raw, and upload to the proper bucket # Download latest artifacts from CDN, convert from qcow2 to raw, and upload to the proper bucket
echo "Downloading/converting artifacts for $name" echo "Downloading/converting artifacts for $name"
download-convert-upload download-convert-upload
echo "Writing disk container json file"
write-container-file
echo "Writing disk container json file" jobid=$(begin-job)
write-container-file echo "Beginning snapshot import task with id $jobid"
import_jobs[$name]=$jobid
jobid=$(begin-job) done
echo "Beginning snapshot import task with id $jobid"
import_jobs[$name]=$jobid
done
done done
# wait for all import jobs to complete, then tag the resultant images # wait for all import jobs to complete, then tag the resultant images
finished=false finished=false
while ! $finished; do while ! $finished; do
for name in "${!import_jobs[@]}"; do for name in "${!import_jobs[@]}"; do
import_task_id="${import_jobs[${name}]}" import_task_id="${import_jobs[${name}]}"
if ! is-snapshot-imported $import_task_id; then if ! is-snapshot-imported $import_task_id; then
echo "Snapshot for $import_task_id ($name) is not yet finished" echo "Snapshot for $import_task_id ($name) is not yet finished"
continue continue
fi fi
# await finalization # await finalization
sleep 2 sleep 2
if [[ -z $snapshot_id ]]; then if [[ -z $snapshot_id ]]; then
echo "Snapshot ID is null.. exiting" echo "Snapshot ID is null.. exiting"
exit 2 exit 2
fi fi
echo "Tagging snapshot with name" echo "Tagging snapshot with name"
tag-resources $snapshot_id "Key=Name,Value=$name" tag-resources $snapshot_id "Key=Name,Value=$name"
unset import_jobs[${name}] unset import_jobs[${name}]
snapshot_ids[${name}]=$snapshot_id snapshot_ids[${name}]=$snapshot_id
done done
# Check if we're done, if so, great! # Check if we're done, if so, great!
if [[ ${#import_jobs[@]} -gt 0 ]]; then if [[ ${#import_jobs[@]} -gt 0 ]]; then
echo "Sleeping for 1m" echo "Sleeping for 1m"
sleep 1m sleep 1m
continue continue
else else
finished=true finished=true
break break
fi fi
done done
finished=false finished=false
while ! $finished; do while ! $finished; do
for name in "${!snapshot_ids[@]}"; do for name in "${!snapshot_ids[@]}"; do
# If the snapshot is imported, turn it into an AMI # If the snapshot is imported, turn it into an AMI
snapshot_id="${snapshot_ids[${name}]}" snapshot_id="${snapshot_ids[${name}]}"
echo "Creating AMI from snapshot $snapshot_id ($name)" echo "Creating AMI from snapshot $snapshot_id ($name)"
if ! register-image $name $snapshot_id; then if ! register-image $name $snapshot_id; then
echo "ERROR: Failed to create image for $name with snapshot id $snapshot_id" echo "ERROR: Failed to create image for $name with snapshot id $snapshot_id"
continue continue
fi fi
echo "Tagging AMI - Name=$name" echo "Tagging AMI - Name=$name"
tag-resources $ami_id "Key=Name,Value=$name" tag-resources $ami_id "Key=Name,Value=$name"
if [[ -z $ami_id ]]; then if [[ -z $ami_id ]]; then
echo "AMI ID is null. continuing..."; echo "AMI ID is null. continuing..."
continue continue
fi fi
unset snapshot_ids[${name}] unset snapshot_ids[${name}]
ami_ids[$name]=$ami_id ami_ids[$name]=$ami_id
done done
if [[ ${#snapshot_ids[@]} -gt 0 ]]; then if [[ ${#snapshot_ids[@]} -gt 0 ]]; then
sleep 1m sleep 1m
continue continue
else else
finished=true finished=true
break break
fi fi
done done
res="" res=""
for name in "${!ami_ids[@]}"; do for name in "${!ami_ids[@]}"; do
ami_id="${ami_ids[${name}]}" ami_id="${ami_ids[${name}]}"
res="${res}\n$(printf '%s\t%s\n' $name $ami_id)" res="${res}\n$(printf '%s\t%s\n' $name $ami_id)"
done done
printf "$res\n" printf "$res\n"

View File

@ -26,3 +26,4 @@ popd > /dev/null || exit 2
log "Copying to staging directory $TEMP => $OUTPUT_DIR" log "Copying to staging directory $TEMP => $OUTPUT_DIR"
sudo rsync -vrSHP "$TEMP/" "$OUTPUT_DIR" sudo rsync -vrSHP "$TEMP/" "$OUTPUT_DIR"
sudo chown -Rv 10004:10005 "$OUTPUT_DIR" sudo chown -Rv 10004:10005 "$OUTPUT_DIR"

View File

@ -1,23 +1,24 @@
#!/bin/bash #!/bin/bash
source_ami="$1" source_ami="$1"
source_region="${2:-us-east-1}" source_region="${2:-us-east-1}"
if [[ -z $source_ami || -z $source_region ]]; then if [[ -z $source_ami || -z $source_region ]]; then
echo "usage: $0 source_ami source_region" echo "usage: $0 source_ami source_region"
exit 2 exit 2
fi fi
RESF_AMI_ACCOUNT_ID=792107900819 RESF_AMI_ACCOUNT_ID=792107900819
REGIONS=$(aws --profile resf-ami ec2 describe-regions \ REGIONS=$(aws --profile resf-ami ec2 describe-regions \
--all-regions \ --all-regions \
--query "Regions[].{Name:RegionName}" \ --query "Regions[].{Name:RegionName}" \
--output text | grep -vE "$source_region") --output text | grep -vE "$source_region")
REGIONS="ap-southeast-4"
SOURCE_AMI_NAME=$(aws --profile resf-ami ec2 describe-images \ SOURCE_AMI_NAME=$(aws --profile resf-ami ec2 describe-images \
--region "$source_region" --image-ids "$source_ami" --query 'Images[0].Name'\ --region "$source_region" --image-ids "$source_ami" --query 'Images[0].Name' \
--output text ) --output text)
# Enforce a name structure # Enforce a name structure
# Rocky-8-ec2-8.6-20220515.0.x86_64 # Rocky-8-ec2-8.6-20220515.0.x86_64
@ -25,120 +26,121 @@ SOURCE_AMI_NAME=$(aws --profile resf-ami ec2 describe-images \
# Rocky-10-EC2-10.2-20260530.0.x86_64 # Rocky-10-EC2-10.2-20260530.0.x86_64
pat="Rocky-[0-9]{,2}-[Ee][Cc]2-(Base|LVM)-[0-9]{,2}\.[0-9]{,2}-[0-9]+\.[0-9]+\.((aarch|x86_)64)" pat="Rocky-[0-9]{,2}-[Ee][Cc]2-(Base|LVM)-[0-9]{,2}\.[0-9]{,2}-[0-9]+\.[0-9]+\.((aarch|x86_)64)"
if [[ ! "${SOURCE_AMI_NAME}" =~ $pat ]]; then if [[ ! "${SOURCE_AMI_NAME}" =~ $pat ]]; then
echo "Bad source ami (${SOURCE_AMI_NAME}). Exiting." echo "Bad source ami (${SOURCE_AMI_NAME}). Exiting."
exit 1 exit 1
fi fi
function copy(){ function copy() {
for region in $REGIONS; do for region in $REGIONS; do
if find_image_by_name $region; then if find_image_by_name $region; then
echo "Found copy of $source_ami in $region - $found_image_id - Skipping" echo "Found copy of $source_ami in $region - $found_image_id - Skipping"
unset ami_ids[$region] unset ami_ids[$region]
ami_ids[$region]=$(echo $found_image_id | tr -d "'") ami_ids[$region]=$(echo $found_image_id | tr -d "'")
continue continue
fi fi
echo -n "Creating copy job for $region..." echo -n "Creating copy job for $region..."
ami_id=$(aws --profile resf-ami ec2 copy-image \ ami_id=$(aws --profile resf-ami ec2 copy-image \
--region $region \ --region $region \
--name "${SOURCE_AMI_NAME}" \ --name "${SOURCE_AMI_NAME}" \
--source-image-id "${source_ami}" \ --source-image-id "${source_ami}" \
--source-region "${source_region}" \ --source-region "${source_region}" \
--output text 2>&1) --output text 2>&1)
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
unset ami_ids[$region] unset ami_ids[$region]
echo ". $ami_id" echo ". $ami_id"
if [[ ! -z "$ami_id" ]]; then if [[ ! -z "$ami_id" ]]; then
ami_ids[$region]="$ami_id" ami_ids[$region]="$ami_id"
fi fi
continue continue
fi fi
echo ".an error occurred (likely region is not signed up). Skipping." echo ".an error occurred (likely region is not signed up). Skipping."
done done
} }
function change_privacy(){ function change_privacy() {
local status="$1" local status="$1"
local launch_permission local launch_permission
case $status in case $status in
Private) Private)
launch_permission="Remove=[{Group=all}]" launch_permission="Remove=[{Group=all}]"
;; ;;
Public) Public)
launch_permission="Add=[{Group=all}]" launch_permission="Add=[{Group=all}]"
;; ;;
esac esac
local finished=false local finished=false
while ! $finished; do ami_ids[${source_region}]="${source_ami}"
for region in "${!ami_ids[@]}"; do while ! $finished; do
image_id=${ami_ids[$region]} for region in "${!ami_ids[@]}"; do
echo -n "Making ${image_id} in $region $status..." image_id=${ami_ids[$region]}
if aws --profile resf-ami ec2 modify-image-attribute \ echo -n "Making ${image_id} in $region $status..."
--region $region \ if aws --profile resf-ami ec2 modify-image-attribute \
--image-id "$image_id" \ --region $region \
--launch-permission "${launch_permission}" 2>/dev/null; then --image-id "$image_id" \
--launch-permission "${launch_permission}" 2>/dev/null; then
snapshot_id=$(aws --profile resf-ami ec2 describe-images \ snapshot_id=$(aws --profile resf-ami ec2 describe-images \
--region $region \ --region $region \
--image-ids "${image_id}" \ --image-ids "${image_id}" \
--query 'Images[*].BlockDeviceMappings[0].Ebs.SnapshotId' \ --query 'Images[*].BlockDeviceMappings[0].Ebs.SnapshotId' \
--output text 2>&1) --output text 2>&1)
permissions=$(aws --profile resf-ami ec2 describe-snapshot-attribute \ permissions=$(aws --profile resf-ami ec2 describe-snapshot-attribute \
--region $region \ --region $region \
--snapshot-id "${snapshot_id}" \ --snapshot-id "${snapshot_id}" \
--attribute createVolumePermission \ --attribute createVolumePermission \
--query 'CreateVolumePermissions[0].Group' \ --query 'CreateVolumePermissions[0].Group' \
--output text 2>&1) --output text 2>&1)
if [[ "$permissions" == "all" ]] || aws --profile resf-ami ec2 modify-snapshot-attribute \ if [[ "$permissions" == "all" ]] || aws --profile resf-ami ec2 modify-snapshot-attribute \
--region $region \ --region $region \
--snapshot-id "${snapshot_id}" \ --snapshot-id "${snapshot_id}" \
--create-volume-permission "${launch_permission}" 2>/dev/null; then --create-volume-permission "${launch_permission}" 2>/dev/null; then
unset ami_ids[$region] unset ami_ids[$region]
echo ". Done" echo ". Done"
continue continue
fi fi
fi fi
echo ". Still pending" echo ". Still pending"
done done
if [[ ${#ami_ids[@]} -gt 0 ]]; then if [[ ${#ami_ids[@]} -gt 0 ]]; then
echo -n "Sleeping for one minute... " echo -n "Sleeping for one minute... "
for (( i=0; i<60; i++ )); do for ((i = 0; i < 60; i++)); do
if [[ $((i%10)) -eq 0 ]]; then if [[ $((i % 10)) -eq 0 ]]; then
echo -n "$i" echo -n "$i"
else else
echo -n "." echo -n "."
fi fi
sleep 1 sleep 1
done done
echo "" echo ""
else else
finished=true finished=true
break break
fi fi
done done
echo "Completed!" echo "Completed!"
} }
function find_image_by_name(){ function find_image_by_name() {
# found_ami_ids[region]=ami_id # found_ami_ids[region]=ami_id
# ami-id "name" # ami-id "name"
local query="$(printf 'Images[?Name==`%s`]|[?Public==`true`].[ImageId,Name][]' "${SOURCE_AMI_NAME}")" local query="$(printf 'Images[?Name==`%s`]|[?Public==`true`].[ImageId,Name][]' "${SOURCE_AMI_NAME}")"
mapfile -t res < <( mapfile -t res < <(
aws --profile resf-ami ec2 describe-images --region $region --owners $RESF_AMI_ACCOUNT_ID \ aws --profile resf-ami ec2 describe-images --region $region --owners $RESF_AMI_ACCOUNT_ID \
--query "${query}" 2>/dev/null \ --query "${query}" 2>/dev/null |
| jq -r '.|@sh' jq -r '.|@sh'
) )
res=($res) res=($res)
if [[ ${#res[@]} -eq 0 ]]; then if [[ ${#res[@]} -eq 0 ]]; then
# Skip empty results # Skip empty results
return 1 #not found return 1 #not found
fi fi
id=${res[0]//\"} id=${res[0]//\"/}
name=${res[@]/$id} name=${res[@]/$id/}
# printf "Found public image: %s in %s with name '%s'\n" "$id" "$region" "${name//\"}" # printf "Found public image: %s in %s with name '%s'\n" "$id" "$region" "${name//\"}"
found_image_id=$id found_image_id=$id
return 0 # found return 0 # found
} }
declare -A ami_ids declare -A ami_ids
copy copy
change_privacy Public # uses ami_ids change_privacy Public # uses ami_ids