Skip to content

Commit

Permalink
Adjusted cleanup logic to make sure that databases are always cleaned…
Browse files Browse the repository at this point in the history
… up properly
  • Loading branch information
reggeenr committed Jan 17, 2024
1 parent c07290e commit f878a3a
Showing 1 changed file with 104 additions and 89 deletions.
193 changes: 104 additions & 89 deletions cloudant-change-listener/run
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
#!/bin/bash

# Ensure that jq tool is installed
if ! command -v jq &>/dev/null; then
echo "FAILED - 'jq' tool is not installed"
exit 1
fi

# Ensure that latest versions of used IBM Cloud ClI is installed
ibmcloud update --force

# Ensure that latest versions of used IBM Cloud CLI plugins are installed
# Ensure that latest versions of used IBM Cloud CLI plugins are installed
echo "Install necessary ibmcloud cli plugins ..."
ibmcloud plugin install cloudant -f
ibmcloud plugin install code-engine -f
Expand All @@ -21,87 +27,97 @@ function clean() {

ibmcloud ce configmap delete --name cloudant-change-listener-job-config --force
ibmcloud ce secret delete --name cloudant-change-listener-credentials --force

ibmcloud ce project delete --name ce-sample-cloudant-change-listener-project --force --hard --no-wait
ibmcloud iam service-id-delete ce-sample-cloudant-change-listener-api-credentials --force
ibmcloud resource service-key-delete cloudant-creds-ce-project --force
ibmcloud resource service-instance-delete CE-Cloudant-SampleDB --force
) > /dev/null 2>&1

# Iterate over all service instances that are called 'CE-Cloudant-SampleDB' and delete them
cloudant_dbs=$(ibmcloud resource search 'name:CE-Cloudant-SampleDB' --output JSON | jq -r '.items')
if [[ $cloudant_dbs == '[]' ]]; then
echo "No Cloudant instances that needs to get cleaned up!"
else
# Encoding each line as base64 helps to iterate over JSON objects within a bash script
for cloudant_db in $(echo "${cloudant_dbs}" | jq -r '.[] | @base64'); do
# Use this inner function to decode the base64 encoded JSON object and extract property values
# from the Cloudant instance, such as name, or crn
_jqCloudantDb() {
echo ${cloudant_db} | base64 --decode | jq -r ${1}
}
ibmcloud resource service-instance-delete $(_jqCloudantDb '.crn') --force
done
fi

) >/dev/null 2>&1
}

clean

# In case this script has been executed with `./run clean`, we stop right after the cleanup
[[ "$1" == "clean" ]] && exit 0

# Ensure that jq tool is installed
if ! command -v jq &> /dev/null ; then
echo "FAILED - 'jq' tool is not installed"
exit 1
fi


# echo "Create a new Cloudant instance ..."
# ibmcloud resource service-instance-create CE-Cloudant-SampleDB cloudantnosqldb standard eu-de -p '{"legacyCredentials":"false"}'
ibmcloud resource service-instance-create CE-Cloudant-SampleDB cloudantnosqldb standard eu-de -p '{"legacyCredentials":"false"}'

echo "Wait for the Cloudant instance to get properly initialized ..."
COUNTER=0

while ! ibmcloud resource service-instance CE-Cloudant-SampleDB | grep "active" ; do
while ! ibmcloud resource service-instance CE-Cloudant-SampleDB | grep "active"; do
sleep 5
# wait max 3 min to get a cloudant DB instance
COUNTER=$((COUNTER+1))
if (( COUNTER > 36 )); then
# wait max 3 min to get a cloudant DB instance
COUNTER=$((COUNTER + 1))
if ((COUNTER > 36)); then
echo "FAILED - Cloudant DB instance cannot be created"
exit 1
fi
done

# Obtain the created Cloudant instance
cloudant_instances=$(ibmcloud resource service-instance CE-Cloudant-SampleDB --output JSON)
cloudant_instance_name=$(echo $cloudant_instances|jq -r '.[0]|.name')
cloudant_instance_guid=$(echo $cloudant_instances|jq -r '.[0]|.guid')
cloudant_instance_name=$(echo $cloudant_instances | jq -r '.[0]|.name')
cloudant_instance_guid=$(echo $cloudant_instances | jq -r '.[0]|.guid')

if [ -z "$cloudant_instances" ]; then
if [ -z "$cloudant_instances" ]; then
echo "FAILED - Cloudant DB instances info cannot be retrieved"
exit 1
fi

echo "Obtain the service URL of the newly created Cloudant instance '$cloudant_instance_name' (id: $cloudant_instance_guid) ..."
cloudant_url=$(ibmcloud cloudant url --resource-id $cloudant_instance_guid --output JSON)
echo "$cloudant_url"
if [ -z "$cloudant_url" ]; then
if [ -z "$cloudant_url" ]; then
echo "FAILED - Cloudant DB URL cannot be retrieved"
exit 1
fi

echo "Creating the database 'sample-db' within Cloudant instance '$cloudant_instance_name' ..."
echo "using cloudant API https://cloud.ibm.com/apidocs/cloudant#putdatabase"
iam_access_token=$(ibmcloud iam oauth-tokens --output JSON|jq -r '.iam_token')
if [ -z "$iam_access_token" ]; then
iam_access_token=$(ibmcloud iam oauth-tokens --output JSON | jq -r '.iam_token')
if [ -z "$iam_access_token" ]; then
echo "FAILED - The IAM access token of the current CLI session could not be obtained"
exit 1
fi
curl -H "Authorization: $iam_access_token" -X PUT "$cloudant_url/sample-db"
if [ $? != 0 ]; then
echo "FAILED - The creation of the Cloudant database failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - The creation of the Cloudant database failed"
exit 1
fi

echo "Creating Code Engine project 'ce-sample-cloudant-change-listener-project' ..."
ibmcloud ce proj create --name ce-sample-cloudant-change-listener-project
if [ $? != 0 ]; then
echo "FAILED - The creation of a Code Engine project failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - The creation of a Code Engine project failed"
exit 1
fi

ce_project_guid=$(ibmcloud ce proj current --output json|jq -r '.guid')
if [ -z "$ce_project_guid" ]; then
ce_project_guid=$(ibmcloud ce proj current --output json | jq -r '.guid')
if [ -z "$ce_project_guid" ]; then
echo "FAILED - obtaining the project GUID failed"
exit 1
fi
ce_project_region=$(ibmcloud ce proj current --output json|jq -r '.region_id')
if [ -z "$ce_project_region" ]; then
ce_project_region=$(ibmcloud ce proj current --output json | jq -r '.region_id')
if [ -z "$ce_project_region" ]; then
echo "FAILED - Obtaining the project region failed"
exit 1
fi
Expand All @@ -117,14 +133,13 @@ ce_fn_endpoint="null"
ce_fn_endpoint_internal="null"

COUNTER=0
while [ "$ce_fn_endpoint" == "null" ]
do
while [ "$ce_fn_endpoint" == "null" ]; do
ce_fn_endpoint=$(ibmcloud ce fn get --name cloudant-change-listener-function -o json | jq -r '.endpoint')
ce_fn_endpoint_internal=$(ibmcloud ce fn get --name cloudant-change-listener-function -o json | jq -r '.endpoint_internal')
sleep 2
# wait max 3 min to get a cloudant DB instance
COUNTER=$((COUNTER+1))
if (( COUNTER > 90 )); then
# wait max 3 min to get a cloudant DB instance
COUNTER=$((COUNTER + 1))
if ((COUNTER > 90)); then
echo "FAILED - The creation of a Code Engine function failed"
exit 1
fi
Expand All @@ -135,25 +150,25 @@ echo "Creating a config map to store the event state"
ibmcloud ce configmap create \
--name cloudant-change-listener-job-config \
--from-literal DB_LAST_SEQ=now
if [ $? != 0 ]; then
echo "FAILED - The creation of the Code Engine configmap failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - The creation of the Code Engine configmap failed"
exit 1
fi

# See Code Engine docs: Managing user access (https://cloud.ibm.com/docs/codeengine?topic=codeengine-iam#service)
echo "Creating an IAM ServiceID that contains a policy to access the Code Engine project '${ce_project_guid}' ..."
ibmcloud iam service-id-create ce-sample-cloudant-change-listener-api-credentials --description "Service ID to operate towards the Code Engine project ${ce_project_guid}"
if [ $? != 0 ]; then
echo "FAILED - The creation of the IAM serviceID failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - The creation of the IAM serviceID failed"
exit 1
fi
ibmcloud iam service-policy-create ce-sample-cloudant-change-listener-api-credentials --roles Writer --service-name codeengine --service-instance ${ce_project_guid}
if [ $? != 0 ]; then
echo "FAILED - The creation of the IAM serviceID policy failed"
exit 1
fi
ce_api_key=$(ibmcloud iam service-api-key-create codeengine-api-key ce-sample-cloudant-change-listener-api-credentials --description "API key for serviceID ce-${ce_project_guid}-api-credentials for Code Engine project ${ce_project_guid}" --output JSON|jq -r '.apikey')
if [ -z "$ce_api_key" ]; then
if [ $? != 0 ]; then
echo "FAILED - The creation of the IAM serviceID policy failed"
exit 1
fi
ce_api_key=$(ibmcloud iam service-api-key-create codeengine-api-key ce-sample-cloudant-change-listener-api-credentials --description "API key for serviceID ce-${ce_project_guid}-api-credentials for Code Engine project ${ce_project_guid}" --output JSON | jq -r '.apikey')
if [ -z "$ce_api_key" ]; then
echo "FAILED - The creation of the IAM serviceID APIKey failed"
exit 1
fi
Expand All @@ -162,10 +177,10 @@ echo "Creating a secret that stores a serviceID APIKey to enable the job storing
ibmcloud ce secret create \
--name cloudant-change-listener-credentials \
--from-literal CE_API_KEY=$ce_api_key
if [ $? != 0 ]; then
echo "FAILED - The creation of the Code Engine secret failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - The creation of the Code Engine secret failed"
exit 1
fi

echo "Creating the Code Engine daemon job 'cloudant-change-listener-job' ..."
ibmcloud ce job create \
Expand All @@ -178,52 +193,52 @@ ibmcloud ce job create \
--env CE_REGION=$ce_project_region \
--env-from-configmap cloudant-change-listener-job-config \
--env-from-secret cloudant-change-listener-credentials
if [ $? != 0 ]; then
echo "FAILED - The creation of a Code Engine job failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - The creation of a Code Engine job failed"
exit 1
fi

echo "Creating the service credential on the Cloudant database to be able to bind the job and the function ..."
ibmcloud resource service-key-create cloudant-creds-ce-project Reader --instance-id $cloudant_instance_guid
if [ $? != 0 ]; then
echo "FAILED - The creation of the service credential on the Cloudant DB failed"
exit 1
fi
ibmcloud resource service-key-create cloudant-creds-ce-project Reader --instance-id $cloudant_instance_guid
if [ $? != 0 ]; then
echo "FAILED - The creation of the service credential on the Cloudant DB failed"
exit 1
fi

echo "Binding the Cloudant credentials to the Code Engine function to enable that the function code can access the DB via Env vars ..."
ibmcloud ce fn bind \
--name cloudant-change-listener-function \
--service-instance-id $cloudant_instance_guid \
--service-credential cloudant-creds-ce-project
if [ $? != 0 ]; then
echo "FAILED - The binding of a service binding of the Cloudant DB to the CE function failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - The binding of a service binding of the Cloudant DB to the CE function failed"
exit 1
fi

echo "Binding the Cloudant credentials to the Code Engine job ..."
ibmcloud ce job bind \
--name cloudant-change-listener-job \
--service-instance-id $cloudant_instance_guid \
--service-credential cloudant-creds-ce-project
if [ $? != 0 ]; then
echo "FAILED - the binding of a service binding of the Cloudant DB to the CE job failed"
exit 1
fi
if [ $? != 0 ]; then
echo "FAILED - the binding of a service binding of the Cloudant DB to the CE job failed"
exit 1
fi

echo "Starting the daemon job ..."
job_run_name=$(ibmcloud ce jobrun submit --job cloudant-change-listener-job --output json|jq -r '.metadata|.name')
if [ -z "$job_run_name" ]; then
job_run_name=$(ibmcloud ce jobrun submit --job cloudant-change-listener-job --output json | jq -r '.metadata|.name')
if [ -z "$job_run_name" ]; then
echo "FAILED - The submission of the Code Engine daemon job failed"
exit 1
fi

echo "Check whether the job started properly ..."
COUNTER=0
while ! ibmcloud ce jobrun get -n ${job_run_name} | grep "1/1" | grep "Running" ; do
while ! ibmcloud ce jobrun get -n ${job_run_name} | grep "1/1" | grep "Running"; do
sleep 2
COUNTER=$((COUNTER+1))
if (( COUNTER > 90 )); then
echo $( ibmcloud ce jobrun get -n ${job_run_name} )
COUNTER=$((COUNTER + 1))
if ((COUNTER > 90)); then
echo $(ibmcloud ce jobrun get -n ${job_run_name})
echo "FAILED - The job could not be started"
exit 1
fi
Expand All @@ -242,30 +257,30 @@ curl -H "Authorization: $iam_access_token" -X POST "$cloudant_url/sample-db" -H
echo "Verify job receives the Cloudant event by fetching the job run logs ..."

COUNTER=0
while true; do
while true; do
echo "Waiting on job to detect change"
sleep 5
foundDetectedChange=$(ibmcloud ce jobrun logs -n ${job_run_name} | grep "Detected 1 change(s) in the DB")
foundCalledFunction=$(ibmcloud ce jobrun logs -n ${job_run_name} | grep "Successfully called CE function")

if [[ $foundDetectedChange && $foundCalledFunction ]]; then
if [[ $foundDetectedChange && $foundCalledFunction ]]; then
echo ""
echo "That was a success :)"
break;
fi
COUNTER=$((COUNTER+1))
if (( COUNTER > 20 )); then
if [[ ! $foundDetectedChange ]]; then
break
fi
COUNTER=$((COUNTER + 1))
if ((COUNTER > 20)); then
if [[ ! $foundDetectedChange ]]; then
echo "Testing of the sample failed because the change was not detected"
fi
if [[ ! $foundCalledFunction ]]; then
if [[ ! $foundCalledFunction ]]; then
echo "Testing of the sample failed because the ce function was not called "
fi
# Clean up
clean
exit 1;
exit 1
fi
done;
done

# Clean up
clean

0 comments on commit f878a3a

Please sign in to comment.