Skip to content

Commit

Permalink
Test & cleanup script for Alibaba cloud
Browse files Browse the repository at this point in the history
TODO: cleanup part needs updates b/c initial implementation was
too long ago
  • Loading branch information
atodorov committed Jan 14, 2020
1 parent ca87648 commit 2a1c47e
Show file tree
Hide file tree
Showing 2 changed files with 329 additions and 0 deletions.
150 changes: 150 additions & 0 deletions tests/cleanup/remove_old_objects_alibaba.sh
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
179 changes: 179 additions & 0 deletions tests/cli/test_build_and_deploy_alibaba.sh
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

0 comments on commit 2a1c47e

Please sign in to comment.