From ed2a2999ad2d55b6a0b1a24941577790e7570c69 Mon Sep 17 00:00:00 2001 From: Neil Hanlon Date: Fri, 12 May 2023 14:00:52 -0400 Subject: [PATCH] formatting, add WSL container variant, support requesting new quotas --- iso/empanadas/empanadas/common.py | 2 +- iso/empanadas/empanadas/configs/el8.yaml | 2 +- .../empanadas/templates/kube/Job.tmpl | 2 +- mangle/quotas.go | 50 ++- sync/import-snapshot-publish-aws.sh | 333 +++++++++--------- sync/oval.sh | 1 + sync/propagate-image.sh | 230 ++++++------ 7 files changed, 327 insertions(+), 293 deletions(-) diff --git a/iso/empanadas/empanadas/common.py b/iso/empanadas/empanadas/common.py index a33dfc9..a41d8d6 100644 --- a/iso/empanadas/empanadas/common.py +++ b/iso/empanadas/empanadas/common.py @@ -104,7 +104,7 @@ for conf in glob.iglob(f"{_rootdir}/sig/*.yaml"): ALLOWED_TYPE_VARIANTS = { "Azure": ["Base", "LVM"], - "Container": ["Base", "Minimal", "UBI"], + "Container": ["Base", "Minimal", "UBI", "WSL"], "EC2": ["Base", "LVM"], "GenericCloud": ["Base", "LVM"], "Vagrant": ["Libvirt", "Vbox", "VMware"], diff --git a/iso/empanadas/empanadas/configs/el8.yaml b/iso/empanadas/empanadas/configs/el8.yaml index 6c742f7..6aedc2d 100644 --- a/iso/empanadas/empanadas/configs/el8.yaml +++ b/iso/empanadas/empanadas/configs/el8.yaml @@ -88,7 +88,7 @@ primary_variant: 'Base' Container: format: tar.xz - variants: [Base, Minimal, UBI] + variants: [Base, Minimal, UBI, WSL] RPI: format: raw.xz OCP: diff --git a/iso/empanadas/empanadas/templates/kube/Job.tmpl b/iso/empanadas/empanadas/templates/kube/Job.tmpl index 1ddf1f2..ea9f301 100644 --- a/iso/empanadas/empanadas/templates/kube/Job.tmpl +++ b/iso/empanadas/empanadas/templates/kube/Job.tmpl @@ -2,7 +2,7 @@ apiVersion: batch/v1 kind: Job metadata: - name: {{ jobname }}-{{ major }}-{{ architecture }} + name: {{ jobname }}-{{ major }}-{{ architecture }}-{{ buildTime }} namespace: {{ namespace }} spec: template: diff --git a/mangle/quotas.go b/mangle/quotas.go index a088058..b0cc5a2 100644 --- a/mangle/quotas.go +++ b/mangle/quotas.go @@ -7,12 +7,14 @@ import ( "sync" "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/service/ec2" "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{ ServiceCode: aws.String("ec2"), } @@ -71,9 +73,13 @@ func getQuotaInfo(sqSvc *servicequotas.ServiceQuotas, quotaCode string, region s output, err := sqSvc.GetServiceQuota(input) if err != nil { - log.Printf("Error getting quota info for %s: %s\n", region, err) - return nil - // os.Exit(1) + if awsErr, ok := err.(awserr.Error); ok { + if message := awsErr.Code(); message == "UnknownOperationException" { + 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 @@ -116,6 +122,35 @@ func listQuotas(sess *session.Session, quotaCode string, regions []*string) { 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() { // Create session sess := session.Must(session.NewSessionWithOptions(session.Options{ @@ -125,11 +160,8 @@ func main() { // Create EC2 client 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 - quotaCode := getQuotaCode(sqSvc) + quotaCode := getQuotaCode(sess) // Get all regions regions, err := getRegions(ec2Svc) @@ -142,5 +174,5 @@ func main() { listQuotas(sess, quotaCode, regions) // Request quota increase for all regions - // requestQuotaIncrease(sqSvc, quotaCode, regions) + // requestQuotaIncrease(sess, quotaCode, regions) } diff --git a/sync/import-snapshot-publish-aws.sh b/sync/import-snapshot-publish-aws.sh index 432b0e3..4c68f20 100755 --- a/sync/import-snapshot-publish-aws.sh +++ b/sync/import-snapshot-publish-aws.sh @@ -9,145 +9,145 @@ RLVER=$VERSION # shellcheck disable=SC2046,1091,1090 source "$(dirname "${BASH_SOURCE[0]}")/common" - usage() { - echo "usage: $0 VERSION ($0 8.7)" + echo "usage: $0 VERSION ($0 8.7)" } 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 - usage - exit 1 + usage + exit 1 fi download() { - curl -o "$qcow" "https://dl.rockylinux.org/stg/rocky/$VERSION/images/$arch/$qcow" - return $? + curl -o "$qcow" "https://dl.rockylinux.org/stg/rocky/$VERSION/images/$arch/$qcow" + return $? } exists() { - aws s3 ls $2/$1 &>/dev/null - return $? + aws s3 ls $2/$1 &>/dev/null + return $? } upload() { - if exists $raw $BUCKET/$DATE; then - echo "Found existing upload in $BUCKET" - return 0 - fi - aws s3 cp $raw $BUCKET/$DATE/ + if exists $raw $BUCKET/$DATE; then + echo "Found existing upload in $BUCKET" + return 0 + fi + aws s3 cp $raw $BUCKET/$DATE/ } convert() { - qemu-img convert -f qcow2 -O raw "$qcow" $raw - return $? + qemu-img convert -f qcow2 -O raw "$qcow" $raw + return $? } BUCKET="s3://resf-prod-import-use1" 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() { - if ! [[ -f $qcow ]]; then - echo "Downloading $qcow from cdn" - download || exit - fi + if ! [[ -f $qcow ]]; then + echo "Downloading $qcow from cdn" + download || exit + fi - if ! [[ -f ${raw} ]]; then - echo "Converting qcow2 $qcow to RAW $raw" - convert || exit - fi + if ! [[ -f ${raw} ]]; then + echo "Converting qcow2 $qcow to RAW $raw" + convert || exit + fi - echo "Uploading raw image back to s3" - if ! upload; then - echo "Failed to upload" - exit - fi + echo "Uploading raw image back to s3" + if ! upload; then + echo "Failed to upload" + exit + fi } - begin-job() { - import_task_id="$(aws ec2 import-snapshot --disk-container "file://$PWD/$json" --query 'ImportTaskId')" - if [[ -z $import_task_id ]]; then - echo "Failed to import $json" - return 1 - fi - echo $import_task_id - return 0 + import_task_id="$(aws ec2 import-snapshot --disk-container "file://$PWD/$json" --query 'ImportTaskId')" + if [[ -z $import_task_id ]]; then + echo "Failed to import $json" + return 1 + fi + echo $import_task_id + return 0 } is-snapshot-imported() { - snapshot_id=$(aws ec2 describe-import-snapshot-tasks --query 'ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId[]' --import-task-ids $1) - if [[ -z "$snapshot_id" ]]; then - return 1 - fi - return 0 + snapshot_id=$(aws ec2 describe-import-snapshot-tasks --query 'ImportSnapshotTasks[].SnapshotTaskDetail.SnapshotId[]' --import-task-ids $1) + if [[ -z "$snapshot_id" ]]; then + return 1 + fi + return 0 } register-image() { - # Given a snapshot id, register the image - name=$1 - snapshot_id=$2 + # Given a snapshot id, register the image + name=$1 + snapshot_id=$2 - case $(awk -F'.' '{print $NF}'<<<"$name") in - x86_64) - arch=x86_64;; - aarch64) - arch=arm64;; - esac + case $(awk -F'.' '{print $NF}' <<<"$name") in + x86_64) + arch=x86_64 + ;; + aarch64) + 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 - return 1 - fi - return 0 + if [[ -z "$ami_id" ]]; then + return 1 + fi + return 0 } tag-resources() { - local resources="$1" - local tags="$2" - if [[ -z $resources || -z $tags ]]; then - echo "Need to provide tags and resources to tag" - return 1 - fi - aws ec2 create-tags --resources $resources --tags $tags + local resources="$1" + local tags="$2" + if [[ -z $resources || -z $tags ]]; then + echo "Need to provide tags and resources to tag" + return 1 + fi + aws ec2 create-tags --resources $resources --tags $tags } image-exists() { - local RESF_AMI_ACCOUNT_ID=792107900819 - 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) - res=($res) - if [[ ${#res[@]} -eq 0 ]]; then - # Skip empty results - return 1 #not found - fi - id=${res[0]//\"} - name=${res[@]/$id} - found_image_id=$id - return 0 # found + local RESF_AMI_ACCOUNT_ID=792107900819 + 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) + res=($res) + if [[ ${#res[@]} -eq 0 ]]; then + # Skip empty results + return 1 #not found + fi + id=${res[0]//\"/} + name=${res[@]/$id/} + found_image_id=$id + return 0 # found } snapshot-exists() { - local RESF_AMI_ACCOUNT_ID=792107900819 - local filter="$(printf 'Name=tag:Name,Values=%s' "${1}")" - local query='Snapshots[].[SnapshotId][]' - mapfile -t res < <(aws ec2 describe-snapshots --owner-ids $RESF_AMI_ACCOUNT_ID --filter "${filter}" --query "${query}" 2>/dev/null) - res=($res) - if [[ ${#res[@]} -eq 0 ]]; then - # Skip empty results - return 1 #not found - fi - id=${res[0]//\"} - found_snapshot_id=$id - return 0 # found + local RESF_AMI_ACCOUNT_ID=792107900819 + local filter="$(printf 'Name=tag:Name,Values=%s' "${1}")" + local query='Snapshots[].[SnapshotId][]' + mapfile -t res < <(aws ec2 describe-snapshots --owner-ids $RESF_AMI_ACCOUNT_ID --filter "${filter}" --query "${query}" 2>/dev/null) + res=($res) + if [[ ${#res[@]} -eq 0 ]]; then + # Skip empty results + return 1 #not found + fi + id=${res[0]//\"/} + found_snapshot_id=$id + return 0 # found } declare -A import_jobs @@ -158,110 +158,109 @@ TARGET_ARCHES=(x86_64 aarch64) TARGET_VARIANTS=(Base LVM) for variant in "${TARGET_VARIANTS[@]}"; do - for arch in "${TARGET_ARCHES[@]}"; do - 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) - qcow=${latest}.qcow2 - raw=${name}.raw - json=${name}.json + for arch in "${TARGET_ARCHES[@]}"; do + 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) + qcow=${name}.qcow2 + raw=${name}.raw + json=${name}.json - if image-exists $name; then - echo "Found existing AMI in us-east-1. Skipping. ($found_image_id,$name)" - continue - fi + if image-exists $name; then + echo "Found existing AMI in us-east-1. Skipping. ($found_image_id,$name)" + continue + fi - if snapshot-exists $name; then - # If the snapshot exists, we can skip the import task and just do the image registration - echo "Found existing snapshot: ($found_snapshot_id,$name)" - snapshot_ids[$name]="${found_snapshot_id}" - continue - fi + if snapshot-exists $name; then + # If the snapshot exists, we can skip the import task and just do the image registration + echo "Found existing snapshot: ($found_snapshot_id,$name)" + snapshot_ids[$name]="${found_snapshot_id}" + continue + fi - # Download latest artifacts from CDN, convert from qcow2 to raw, and upload to the proper bucket - echo "Downloading/converting artifacts for $name" - download-convert-upload + # Download latest artifacts from CDN, convert from qcow2 to raw, and upload to the proper bucket + echo "Downloading/converting artifacts for $name" + download-convert-upload + echo "Writing disk container json file" + write-container-file - echo "Writing disk container json file" - write-container-file - - jobid=$(begin-job) - echo "Beginning snapshot import task with id $jobid" - import_jobs[$name]=$jobid - done + jobid=$(begin-job) + echo "Beginning snapshot import task with id $jobid" + import_jobs[$name]=$jobid + done done # wait for all import jobs to complete, then tag the resultant images finished=false while ! $finished; do - for name in "${!import_jobs[@]}"; do - import_task_id="${import_jobs[${name}]}" - if ! is-snapshot-imported $import_task_id; then - echo "Snapshot for $import_task_id ($name) is not yet finished" - continue - fi + for name in "${!import_jobs[@]}"; do + import_task_id="${import_jobs[${name}]}" + if ! is-snapshot-imported $import_task_id; then + echo "Snapshot for $import_task_id ($name) is not yet finished" + continue + fi - # await finalization - sleep 2 + # await finalization + sleep 2 - if [[ -z $snapshot_id ]]; then - echo "Snapshot ID is null.. exiting" - exit 2 - fi + if [[ -z $snapshot_id ]]; then + echo "Snapshot ID is null.. exiting" + exit 2 + fi - echo "Tagging snapshot with name" - tag-resources $snapshot_id "Key=Name,Value=$name" + echo "Tagging snapshot with name" + tag-resources $snapshot_id "Key=Name,Value=$name" - unset import_jobs[${name}] - snapshot_ids[${name}]=$snapshot_id - done - # Check if we're done, if so, great! - if [[ ${#import_jobs[@]} -gt 0 ]]; then - echo "Sleeping for 1m" - sleep 1m - continue - else - finished=true - break - fi + unset import_jobs[${name}] + snapshot_ids[${name}]=$snapshot_id + done + # Check if we're done, if so, great! + if [[ ${#import_jobs[@]} -gt 0 ]]; then + echo "Sleeping for 1m" + sleep 1m + continue + else + finished=true + break + fi done finished=false while ! $finished; do - for name in "${!snapshot_ids[@]}"; do - # If the snapshot is imported, turn it into an AMI - snapshot_id="${snapshot_ids[${name}]}" + for name in "${!snapshot_ids[@]}"; do + # If the snapshot is imported, turn it into an AMI + snapshot_id="${snapshot_ids[${name}]}" - echo "Creating AMI from snapshot $snapshot_id ($name)" - if ! register-image $name $snapshot_id; then - echo "ERROR: Failed to create image for $name with snapshot id $snapshot_id" - continue - fi + echo "Creating AMI from snapshot $snapshot_id ($name)" + if ! register-image $name $snapshot_id; then + echo "ERROR: Failed to create image for $name with snapshot id $snapshot_id" + continue + fi - echo "Tagging AMI - Name=$name" - tag-resources $ami_id "Key=Name,Value=$name" + echo "Tagging AMI - Name=$name" + tag-resources $ami_id "Key=Name,Value=$name" - if [[ -z $ami_id ]]; then - echo "AMI ID is null. continuing..."; - continue - fi + if [[ -z $ami_id ]]; then + echo "AMI ID is null. continuing..." + continue + fi - unset snapshot_ids[${name}] - ami_ids[$name]=$ami_id - done - if [[ ${#snapshot_ids[@]} -gt 0 ]]; then - sleep 1m - continue - else - finished=true - break - fi + unset snapshot_ids[${name}] + ami_ids[$name]=$ami_id + done + if [[ ${#snapshot_ids[@]} -gt 0 ]]; then + sleep 1m + continue + else + finished=true + break + fi done res="" for name in "${!ami_ids[@]}"; do - ami_id="${ami_ids[${name}]}" - res="${res}\n$(printf '%s\t%s\n' $name $ami_id)" + ami_id="${ami_ids[${name}]}" + res="${res}\n$(printf '%s\t%s\n' $name $ami_id)" done printf "$res\n" diff --git a/sync/oval.sh b/sync/oval.sh index 2197bf4..607673b 100644 --- a/sync/oval.sh +++ b/sync/oval.sh @@ -26,3 +26,4 @@ popd > /dev/null || exit 2 log "Copying to staging directory $TEMP => $OUTPUT_DIR" sudo rsync -vrSHP "$TEMP/" "$OUTPUT_DIR" sudo chown -Rv 10004:10005 "$OUTPUT_DIR" + diff --git a/sync/propagate-image.sh b/sync/propagate-image.sh index 68524dd..18c9981 100644 --- a/sync/propagate-image.sh +++ b/sync/propagate-image.sh @@ -1,23 +1,24 @@ -#!/bin/bash +#!/bin/bash source_ami="$1" source_region="${2:-us-east-1}" if [[ -z $source_ami || -z $source_region ]]; then - echo "usage: $0 source_ami source_region" - exit 2 + echo "usage: $0 source_ami source_region" + exit 2 fi RESF_AMI_ACCOUNT_ID=792107900819 REGIONS=$(aws --profile resf-ami ec2 describe-regions \ - --all-regions \ - --query "Regions[].{Name:RegionName}" \ - --output text | grep -vE "$source_region") + --all-regions \ + --query "Regions[].{Name:RegionName}" \ + --output text | grep -vE "$source_region") +REGIONS="ap-southeast-4" SOURCE_AMI_NAME=$(aws --profile resf-ami ec2 describe-images \ - --region "$source_region" --image-ids "$source_ami" --query 'Images[0].Name'\ - --output text ) + --region "$source_region" --image-ids "$source_ami" --query 'Images[0].Name' \ + --output text) # Enforce a name structure # 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 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 - echo "Bad source ami (${SOURCE_AMI_NAME}). Exiting." - exit 1 + echo "Bad source ami (${SOURCE_AMI_NAME}). Exiting." + exit 1 fi -function copy(){ - for region in $REGIONS; do - if find_image_by_name $region; then - echo "Found copy of $source_ami in $region - $found_image_id - Skipping" - unset ami_ids[$region] - ami_ids[$region]=$(echo $found_image_id | tr -d "'") - continue - fi - echo -n "Creating copy job for $region..." - ami_id=$(aws --profile resf-ami ec2 copy-image \ - --region $region \ - --name "${SOURCE_AMI_NAME}" \ - --source-image-id "${source_ami}" \ - --source-region "${source_region}" \ - --output text 2>&1) - if [[ $? -eq 0 ]]; then - unset ami_ids[$region] - echo ". $ami_id" - if [[ ! -z "$ami_id" ]]; then - ami_ids[$region]="$ami_id" - fi - continue - fi - echo ".an error occurred (likely region is not signed up). Skipping." - done +function copy() { + for region in $REGIONS; do + if find_image_by_name $region; then + echo "Found copy of $source_ami in $region - $found_image_id - Skipping" + unset ami_ids[$region] + ami_ids[$region]=$(echo $found_image_id | tr -d "'") + continue + fi + echo -n "Creating copy job for $region..." + ami_id=$(aws --profile resf-ami ec2 copy-image \ + --region $region \ + --name "${SOURCE_AMI_NAME}" \ + --source-image-id "${source_ami}" \ + --source-region "${source_region}" \ + --output text 2>&1) + if [[ $? -eq 0 ]]; then + unset ami_ids[$region] + echo ". $ami_id" + if [[ ! -z "$ami_id" ]]; then + ami_ids[$region]="$ami_id" + fi + continue + fi + echo ".an error occurred (likely region is not signed up). Skipping." + done } -function change_privacy(){ - local status="$1" - local launch_permission - case $status in - Private) - launch_permission="Remove=[{Group=all}]" - ;; - Public) - launch_permission="Add=[{Group=all}]" - ;; - esac - local finished=false - while ! $finished; do - for region in "${!ami_ids[@]}"; do - image_id=${ami_ids[$region]} - echo -n "Making ${image_id} in $region $status..." - if aws --profile resf-ami ec2 modify-image-attribute \ - --region $region \ - --image-id "$image_id" \ - --launch-permission "${launch_permission}" 2>/dev/null; then +function change_privacy() { + local status="$1" + local launch_permission + case $status in + Private) + launch_permission="Remove=[{Group=all}]" + ;; + Public) + launch_permission="Add=[{Group=all}]" + ;; + esac + local finished=false + ami_ids[${source_region}]="${source_ami}" + while ! $finished; do + for region in "${!ami_ids[@]}"; do + image_id=${ami_ids[$region]} + echo -n "Making ${image_id} in $region $status..." + if aws --profile resf-ami ec2 modify-image-attribute \ + --region $region \ + --image-id "$image_id" \ + --launch-permission "${launch_permission}" 2>/dev/null; then - snapshot_id=$(aws --profile resf-ami ec2 describe-images \ - --region $region \ - --image-ids "${image_id}" \ - --query 'Images[*].BlockDeviceMappings[0].Ebs.SnapshotId' \ - --output text 2>&1) - permissions=$(aws --profile resf-ami ec2 describe-snapshot-attribute \ - --region $region \ - --snapshot-id "${snapshot_id}" \ - --attribute createVolumePermission \ - --query 'CreateVolumePermissions[0].Group' \ - --output text 2>&1) - if [[ "$permissions" == "all" ]] || aws --profile resf-ami ec2 modify-snapshot-attribute \ - --region $region \ - --snapshot-id "${snapshot_id}" \ - --create-volume-permission "${launch_permission}" 2>/dev/null; then - unset ami_ids[$region] - echo ". Done" - continue - fi - fi - echo ". Still pending" - done - if [[ ${#ami_ids[@]} -gt 0 ]]; then - echo -n "Sleeping for one minute... " - for (( i=0; i<60; i++ )); do - if [[ $((i%10)) -eq 0 ]]; then - echo -n "$i" - else - echo -n "." - fi - sleep 1 - done - echo "" - else - finished=true - break - fi - done - echo "Completed!" + snapshot_id=$(aws --profile resf-ami ec2 describe-images \ + --region $region \ + --image-ids "${image_id}" \ + --query 'Images[*].BlockDeviceMappings[0].Ebs.SnapshotId' \ + --output text 2>&1) + permissions=$(aws --profile resf-ami ec2 describe-snapshot-attribute \ + --region $region \ + --snapshot-id "${snapshot_id}" \ + --attribute createVolumePermission \ + --query 'CreateVolumePermissions[0].Group' \ + --output text 2>&1) + if [[ "$permissions" == "all" ]] || aws --profile resf-ami ec2 modify-snapshot-attribute \ + --region $region \ + --snapshot-id "${snapshot_id}" \ + --create-volume-permission "${launch_permission}" 2>/dev/null; then + unset ami_ids[$region] + echo ". Done" + continue + fi + fi + echo ". Still pending" + done + if [[ ${#ami_ids[@]} -gt 0 ]]; then + echo -n "Sleeping for one minute... " + for ((i = 0; i < 60; i++)); do + if [[ $((i % 10)) -eq 0 ]]; then + echo -n "$i" + else + echo -n "." + fi + sleep 1 + done + echo "" + else + finished=true + break + fi + done + echo "Completed!" } -function find_image_by_name(){ - # found_ami_ids[region]=ami_id - # ami-id "name" - local query="$(printf 'Images[?Name==`%s`]|[?Public==`true`].[ImageId,Name][]' "${SOURCE_AMI_NAME}")" - mapfile -t res < <( - aws --profile resf-ami ec2 describe-images --region $region --owners $RESF_AMI_ACCOUNT_ID \ - --query "${query}" 2>/dev/null \ - | jq -r '.|@sh' - ) - res=($res) - if [[ ${#res[@]} -eq 0 ]]; then - # Skip empty results - return 1 #not found - fi - id=${res[0]//\"} - name=${res[@]/$id} - # printf "Found public image: %s in %s with name '%s'\n" "$id" "$region" "${name//\"}" - found_image_id=$id - return 0 # found +function find_image_by_name() { + # found_ami_ids[region]=ami_id + # ami-id "name" + local query="$(printf 'Images[?Name==`%s`]|[?Public==`true`].[ImageId,Name][]' "${SOURCE_AMI_NAME}")" + mapfile -t res < <( + aws --profile resf-ami ec2 describe-images --region $region --owners $RESF_AMI_ACCOUNT_ID \ + --query "${query}" 2>/dev/null | + jq -r '.|@sh' + ) + res=($res) + if [[ ${#res[@]} -eq 0 ]]; then + # Skip empty results + return 1 #not found + fi + id=${res[0]//\"/} + name=${res[@]/$id/} + # printf "Found public image: %s in %s with name '%s'\n" "$id" "$region" "${name//\"}" + found_image_id=$id + return 0 # found } declare -A ami_ids copy -change_privacy Public # uses ami_ids +change_privacy Public # uses ami_ids