-
Notifications
You must be signed in to change notification settings - Fork 158
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Test & cleanup script for Alibaba cloud
TODO: cleanup part needs updates b/c initial implementation was too long ago
- Loading branch information
Showing
2 changed files
with
329 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
#!/bin/bash | ||
# Script removes ECS Instances, Custom Images and OSS files older than | ||
# HOURS_LIMIT (24 hours by default) from Alibaba cloud | ||
# | ||
# Objects with the "keep_me" tag will not be affected | ||
|
||
. /usr/share/beakerlib/beakerlib.sh | ||
|
||
|
||
rlJournalStart | ||
rlPhaseStartSetup | ||
ALI_DIR=`mktemp -d /tmp/alicloud.XXXXX` | ||
|
||
if [ -z "$ALICLOUD_ACCESS_KEY" ]; then | ||
rlFail "ALICLOUD_ACCESS_KEY is empty!" | ||
else | ||
rlLogInfo "ALICLOUD_ACCESS_KEY is configured" | ||
fi | ||
|
||
if [ -z "$ALICLOUD_SECRET_KEY" ]; then | ||
rlFail "ALICLOUD_SECRET_KEY is empty!" | ||
else | ||
rlLogInfo "ALICLOUD_SECRET_KEY is configured" | ||
fi | ||
|
||
# VMs older than HOURS_LIMIT will be deleted | ||
HOURS_LIMIT="${HOURS_LIMIT:-24}" | ||
export TIMESTAMP=`date -u -d "$HOURS_LIMIT hours ago" '+%FT%T'` | ||
ALICLOUD_BUCKET="${ALICLOUD_BUCKET:-composer-test}" | ||
|
||
rlLogInfo "HOURS_LIMIT=$HOURS_LIMIT" | ||
rlLogInfo "TIMESTAMP=$TIMESTAMP" | ||
|
||
# we prefer to use Ansible. | ||
# note: the underlying footmark library is Py2 only | ||
pip2 install --upgrade pip | ||
pip2 install ansible ansible_alicloud | ||
|
||
# however not everything is available as ansible modules | ||
# https://github.com/ansible/ansible/pull/55765 | ||
# so we have to use CLI as well | ||
TAR_FILE="aliyun-cli-linux-amd64.tar.gz" | ||
curl -L https://github.com/aliyun/aliyun-cli/releases/download/v3.0.15/$TAR_FILE > $ALI_DIR/$TAR_FILE | ||
tar -C $ALI_DIR/ -xzvf $ALI_DIR/$TAR_FILE | ||
chmod a+x $ALI_DIR/aliyun | ||
mkdir ~/.aliyun/ | ||
cat > ~/.aliyun/config.json << __EOF__ | ||
{ | ||
"current": "", | ||
"profiles": [ | ||
{ | ||
"mode": "AK", | ||
"access_key_id": "$ALICLOUD_ACCESS_KEY", | ||
"access_key_secret": "$ALICLOUD_SECRET_KEY", | ||
"region_id": "us-east-1", | ||
"output_format": "json", | ||
"language": "en" | ||
} | ||
], | ||
"meta_path": "" | ||
} | ||
__EOF__ | ||
|
||
|
||
rlPhaseEnd | ||
|
||
# Check all regions | ||
#for region in `$ALI_DIR/aliyun Ecs DescribeRegions | grep RegionId | cut -f2 -d: | tr -d '", '`; do | ||
for region in us-east-1; do | ||
rlPhaseStartTest "Delete old VMs in region $region" | ||
cat > $ALI_DIR/delete-vms.yml << __EOF__ | ||
- name: Delete old VMs | ||
hosts: localhost | ||
tasks: | ||
- name: Find all instances in region $region | ||
ali_instance_facts: | ||
alicloud_region: "$region" | ||
register: vms_facts | ||
- name: List all VMs | ||
debug: | ||
var: vms_facts | ||
- name: Delete old instances in region $region | ||
ali_instance: | ||
instance_ids: "{{item.instance_id}}" | ||
alicloud_region: "$region" | ||
state: absent | ||
loop: "{{vms_facts.instances}}" | ||
when: (('Composer-' in item.host_name) or ('Composer-' in item.instance_name)) and (item.creation_time < lookup('env','TIMESTAMP')) and (item.tags['keep_me'] is not defined) | ||
loop_control: | ||
label: "{{item.instance_id}}" | ||
__EOF__ | ||
# NOTE: ^^^ host_name is what we configure when selecting instance properties | ||
# instance_name is what is shown in the web console tables in top-left column | ||
|
||
rlLogInfo "Removing instances in region $region created before $TIMESTAMP" | ||
rlRun -t -c "ansible-playbook $ALI_DIR/delete-vms.yml" | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "Delete old Custom Images in region $region" | ||
cat > $ALI_DIR/delete-custom-images.yml << __EOF__ | ||
- name: Delete old Custom Images | ||
hosts: localhost | ||
tasks: | ||
- name: Get Custom Images in region $region | ||
ali_image_facts: | ||
alicloud_region: "$region" | ||
register: ami_facts | ||
- name: List all Custom Images in region $region | ||
debug: | ||
var: ami_facts | ||
- name: Delete old Custom Images in region $region | ||
ali_image: | ||
image_id: "{{item.image_id}}" | ||
region: "$region" | ||
state: absent | ||
loop: "{{ami_facts.images}}" | ||
when: ('Composer-' in item.image_name) and (item.creation_time < lookup('env','TIMESTAMP')) and (item.tags['keep_me'] is not defined) | ||
loop_control: | ||
label: "{{item.image_id}}" | ||
__EOF__ | ||
# ^^^ for the creation_time attribute see https://github.com/alibaba/ansible-provider/pull/164 | ||
rlLogInfo "Removing Custom Images in region $region created before $TIMESTAMP" | ||
rlRun -t -c "ansible-playbook $ALI_DIR/delete-custom-images.yml" | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "Delete unused composer key pairs in region $region" | ||
# todo | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "Delete old snapshots in region $region" | ||
# todo | ||
rlPhaseEnd | ||
done | ||
|
||
rlPhaseStartTest "Delete old OSS objects" | ||
# todo | ||
rlPhaseEnd | ||
|
||
rlPhaseStartCleanup | ||
rlRun -t -c "rm -rf $ALI_DIR" | ||
rlPhaseEnd | ||
|
||
rlJournalEnd | ||
rlJournalPrintText |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
#!/bin/bash | ||
# Note: execute this file from the project root directory | ||
|
||
##### | ||
# | ||
# Make sure we can build an image and deploy it inside Alibaba cloud! | ||
# | ||
##### | ||
|
||
set -e | ||
|
||
. /usr/share/beakerlib/beakerlib.sh | ||
. $(dirname $0)/lib/lib.sh | ||
|
||
CLI="${CLI:-./src/bin/composer-cli}" | ||
|
||
|
||
rlJournalStart | ||
rlPhaseStartSetup | ||
if [ -z "$ALICLOUD_ACCESS_KEY" ]; then | ||
rlFail "ALICLOUD_ACCESS_KEY is empty!" | ||
else | ||
rlLogInfo "ALICLOUD_ACCESS_KEY is configured" | ||
fi | ||
|
||
if [ -z "$ALICLOUD_SECRET_KEY" ]; then | ||
rlFail "ALICLOUD_SECRET_KEY is empty!" | ||
else | ||
rlLogInfo "ALICLOUD_SECRET_KEY is configured" | ||
fi | ||
|
||
ALICLOUD_BUCKET="${ALICLOUD_BUCKET:-composer-test}" | ||
ALICLOUD_REGION="${ALICLOUD_REGION:-us-east-1}" | ||
|
||
rlLogInfo "ALICLOUD_BUCKET=$ALICLOUD_BUCKET" | ||
rlLogInfo "ALICLOUD_REGION=$ALICLOUD_REGION" | ||
|
||
for package in python3-pip; do | ||
if ! rlCheckRpm "$package"; then | ||
rlRun -t -c "dnf -y install $package" | ||
rlAssertRpm "$package" | ||
fi | ||
done | ||
|
||
rlRun -t -c "pip install ansible ansible_alicloud" | ||
|
||
ALI_DIR=`mktemp -d /tmp/alicloud.XXXXX` | ||
# not everything is available as ansible modules | ||
# so we have to use CLI as well | ||
TAR_FILE="aliyun-cli-linux-3.0.32-amd64.tgz" | ||
curl -L https://github.com/aliyun/aliyun-cli/releases/download/v3.0.32/$TAR_FILE > $ALI_DIR/$TAR_FILE | ||
tar -C $ALI_DIR/ -xzvf $ALI_DIR/$TAR_FILE | ||
chmod a+x $ALI_DIR/aliyun | ||
|
||
# configure | ||
[ -d ~/.aliyun/ ] || mkdir ~/.aliyun/ | ||
|
||
if [ -f ~/.aliyun/config.json ]; then | ||
rlLogInfo "Reusing existing ~/.aliyun/config.json" | ||
else | ||
rlLogInfo "Creating ~/.aliyun/config.json" | ||
cat > ~/.aliyun/config.json << __EOF__ | ||
{ | ||
"current": "", | ||
"profiles": [ | ||
{ | ||
"mode": "AK", | ||
"access_key_id": "$ALICLOUD_ACCESS_KEY", | ||
"access_key_secret": "$ALICLOUD_SECRET_KEY", | ||
"region_id": "$ALICLOUD_REGION", | ||
"output_format": "json", | ||
"language": "en" | ||
} | ||
], | ||
"meta_path": "" | ||
} | ||
__EOF__ | ||
fi | ||
|
||
TMP_DIR=$(mktemp -d) | ||
PLAYBOOKS_DIR=$(dirname "$0")/playbooks/alibaba | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "compose start" | ||
rlAssertEquals "SELinux operates in enforcing mode" "$(getenforce)" "Enforcing" | ||
UUID=`$CLI compose start example-http-server alibaba` | ||
rlAssertEquals "exit code should be zero" $? 0 | ||
|
||
UUID=`echo $UUID | cut -f 2 -d' '` | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "compose finished" | ||
wait_for_compose $UUID | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "Import image in Alibaba cloud" | ||
rlRun -t -c "$CLI compose image $UUID" | ||
|
||
rlRun -t -c "mv $UUID-disk.qcow2 Composer-Test-$UUID-disk.qcow2" | ||
IMAGE="Composer-Test-$UUID-disk.qcow2" | ||
|
||
# upload to OSS | ||
rlRun -t -c "$ALI_DIR/aliyun oss cp --retry-count 20 $IMAGE oss://$ALICLOUD_BUCKET/$IMAGE" | ||
|
||
# now import as machine image | ||
rlRun -t -c "$ALI_DIR/aliyun ecs ImportImage \ | ||
--OSType linux --Platform RedHat \ | ||
--Architecture x86_64 \ | ||
--DiskDeviceMapping.1.DiskImageSize 10 \ | ||
--DiskDeviceMapping.1.Format qcow2 \ | ||
--DiskDeviceMapping.1.OSSBucket $ALICLOUD_BUCKET \ | ||
--DiskDeviceMapping.1.OSSObject $IMAGE \ | ||
--ImageName $IMAGE" | ||
|
||
# wait for status to become available | ||
while $ALI_DIR/aliyun ecs DescribeImages --ImageName $IMAGE --Status Available | grep $IMAGE; do | ||
rlLogInfo "Waiting for import to complete ..." | ||
sleep 60 | ||
done | ||
|
||
rlRun -t -c "$ALI_DIR/aliyun ecs DescribeImages --ImageName $IMAGE" | ||
IMAGE_ID=$($ALI_DIR/aliyun ecs DescribeImages --ImageName $IMAGE | grep ImageId | cut -f4 -d'"') | ||
|
||
if [ -z "$IMAGE_ID" ]; then | ||
rlFail "IMAGE_ID is empty!" | ||
else | ||
rlLogInfo "IMAGE_ID=$IMAGE_ID" | ||
fi | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "Start ECS instance" | ||
INSTANCE_TYPE="ecs.n1.medium" | ||
|
||
# generate & import new ssh key | ||
KEY_NAME=Composer-Test-$UUID | ||
SSH_KEY_DIR=`mktemp -d /tmp/composer-ssh-keys.XXXXXX` | ||
rlRun -t -c "ssh-keygen -t rsa -N '' -f $SSH_KEY_DIR/id_rsa" | ||
SSH_PUB_KEY=$(cat $SSH_KEY_DIR/id_rsa.pub) | ||
rlRun -t -c "$ALI_DIR/aliyun ecs ImportKeyPair --KeyPairName $KEY_NAME --PublicKeyBody '$SSH_PUB_KEY'" | ||
|
||
RELEASE_TIME=$(date -u -d "24 hours" '+%FT%TZ') | ||
|
||
rlRun -t -c "$ALI_DIR/aliyun ecs RunInstances --Amount 1 --ImageId $IMAGE_ID \ | ||
--InstanceType=$INSTANCE_TYPE --InstanceName Composer-Test-VM-$UUID \ | ||
--SecurityGroupId sg-0xi4w9isg0p1ytj1qbhf | ||
--AutoReleaseTime $RELEASE_TIME" | ||
|
||
|
||
## .... not implemented below | ||
INSTANCE_ID=$(cat $TMP_DIR/instance_id) | ||
IP_ADDRESS=$(cat $TMP_DIR/public_ip) | ||
|
||
rlLogInfo "Running INSTANCE_ID=$INSTANCE_ID with IP_ADDRESS=$IP_ADDRESS" | ||
rlPhaseEnd | ||
|
||
rlPhaseStartTest "Verify EC2 instance" | ||
# cloud-init default config differs between RHEL and Fedora | ||
# and ami.ks will create ec2-user only on RHEL | ||
CLOUD_USER="ec2-user" | ||
if [ -f "/etc/fedora-release" ]; then | ||
CLOUD_USER="fedora" | ||
fi | ||
|
||
# run generic tests to verify the instance | ||
verify_image "$CLOUD_USER" "$IP_ADDRESS" "-i $SSH_KEY_DIR/id_rsa" | ||
rlPhaseEnd | ||
|
||
rlPhaseStartCleanup | ||
rlRun -t -c "ansible localhost -m ec2_instance -a 'state=terminated instance_ids=$INSTANCE_ID'" | ||
rlRun -t -c "ansible localhost -m ec2_key -a 'state=absent name=$KEY_NAME'" | ||
rlRun -t -c "ansible localhost -m ec2_ami -a 'state=absent image_id=$IMAGE_ID delete_snapshot=True'" | ||
rlRun -t -c "ansible localhost -m aws_s3 -a 'mode=delobj bucket=$ALICLOUD_BUCKET object=$IMAGE'" | ||
rlRun -t -c "$CLI compose delete $UUID" | ||
rlRun -t -c "rm -rf $IMAGE $SSH_KEY_DIR containers.json $TMP_DIR $ALI_DIR" | ||
#todo: do we need this TMP_DIR ? | ||
rlPhaseEnd | ||
|
||
rlJournalEnd | ||
rlJournalPrintText |