forked from sig_core/toolkit
formatting, add WSL container variant, support requesting new quotas
This commit is contained in:
parent
173b0ff814
commit
ed2a2999ad
@ -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"],
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user