Monitor and Manage Google Cloud Resources
Solution for Monitor and Manage Google Cloud Resources. 1 lab: ARC101. Fast copy-paste commands for Google Cloud.
ARC101 — Monitor and Manage Google Cloud Resources: Challenge Lab
Estimated time: 1 hour 15 minutes
# 🚀 Monitor and Manage Google Cloud Resources: Challenge Lab > ⚠️ **Disclaimer:** This is an independent, community-made walkthrough built to help you understand why each step works. Attempt the challenge yourself first. This guide is provided for educational purposes only and is not affiliated with or endorsed by Google Cloud or Google Cloud Skills Boost. Always follow the official Google Cloud and Qwiklabs terms of service, lab instructions, and usage policies. > > **Walkthrough by Orbit of
# ==============================================================================
# ORBIT OF OPS - ARC101 (COMMAND 1 OF 2: INFRASTRUCTURE & IAM FIX)
# ==============================================================================
CYAN='\e[1;36m'
BLUE='\e[1;34m'
YELLOW='\e[1;33m'
GREEN='\e[1;32m'
RESET='\e[0m'
BOLD='\e[1m'
clear
echo -e "${CYAN}${BOLD}>>> ORBIT OF OPS: ARC101 INITIATED (PART 1) <<<${RESET}\n"
export PROJECT_ID=$(gcloud config get-value project 2>/dev/null)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)' 2>/dev/null)
echo -e "${YELLOW}${BOLD}--- REQUIRED LAB INPUTS ---${RESET}"
read -p "1. Enter the Region (e.g., us-central1): " REGION
read -p "2. Enter the Bucket Name: " BUCKET_NAME
read -p "3. Enter the User 2 Email: " USER_2
read -p "4. Enter the Pub/Sub Topic Name: " TOPIC_NAME
read -p "5. Enter the Cloud Run Function Name: " FUNCTION_NAME
read -p "6. Enter an Alert Notification Email: " ALERT_EMAIL
export REGION BUCKET_NAME USER_2 TOPIC_NAME FUNCTION_NAME ALERT_EMAIL
echo -e "\n${BLUE}${BOLD}[Orbit of Ops] Enabling APIs...${RESET}"
gcloud services enable artifactregistry.googleapis.com cloudfunctions.googleapis.com cloudbuild.googleapis.com eventarc.googleapis.com run.googleapis.com pubsub.googleapis.com storage.googleapis.com monitoring.googleapis.com --quiet
echo -e "${BLUE}${BOLD}[Orbit of Ops] Force-Patching IAM Roles to fix Eventarc 403 Errors...${RESET}"
GCS_SA="service-${PROJECT_NUMBER}@gs-project-accounts.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:${GCS_SA}" --role="roles/pubsub.publisher" --quiet >/dev/null 2>&1
COMPUTE_SA="${PROJECT_NUMBER}[email protected]"
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:${COMPUTE_SA}" --role="roles/eventarc.eventReceiver" --quiet >/dev/null 2>&1
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:${COMPUTE_SA}" --role="roles/artifactregistry.reader" --quiet >/dev/null 2>&1
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:${COMPUTE_SA}" --role="roles/storage.admin" --quiet >/dev/null 2>&1
EVENTARC_SA="service-${PROJECT_NUMBER}@gcp-sa-eventarc.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:${EVENTARC_SA}" --role="roles/eventarc.serviceAgent" --quiet >/dev/null 2>&1
gcloud projects add-iam-policy-binding $PROJECT_ID --member="serviceAccount:${EVENTARC_SA}" --role="roles/storage.admin" --quiet >/dev/null 2>&1
echo -e "\n${CYAN}${BOLD}[Orbit of Ops] Task 1: Creating Storage Bucket and Granting User 2 Access...${RESET}"
gcloud storage buckets create gs://$BUCKET_NAME --location=$REGION --quiet 2>/dev/null
gcloud projects add-iam-policy-binding $PROJECT_ID --member="user:$USER_2" --role="roles/storage.objectViewer" --quiet
echo -e "${CYAN}${BOLD}[Orbit of Ops] Task 2: Creating the Pub/Sub Topic...${RESET}"
gcloud pubsub topics create $TOPIC_NAME --quiet 2>/dev/null
echo -e "${CYAN}${BOLD}[Orbit of Ops] Preparing Cloud Run Function Code...${RESET}"
mkdir -p ~/thumbnail_app && cd ~/thumbnail_app
cat > index.js <<EOF
/* globals exports, require */
//jshint strict: false
//jshint esversion: 6
"use strict";
const crc32 = require("fast-crc32c");
const { Storage } = require('@google-cloud/storage');
const gcs = new Storage();
const { PubSub } = require('@google-cloud/pubsub');
const imagemagick = require("imagemagick-stream");
exports.thumbnail = (event, context) => {
const fileName = event.name;
const bucketName = event.bucket;
const size = "64x64"
const bucket = gcs.bucket(bucketName);
const topicName = "${TOPIC_NAME}";
const pubsub = new PubSub();
if ( fileName.search("64x64_thumbnail") == -1 ){
var filename_split = fileName.split('.');
var filename_ext = filename_split[filename_split.length - 1];
var filename_without_ext = fileName.substring(0, fileName.length - filename_ext.length );
if (filename_ext.toLowerCase() == 'png' || filename_ext.toLowerCase() == 'jpg'){
console.log(\`Processing Original: gs://\${bucketName}/\${fileName}\`);
const gcsObject = bucket.file(fileName);
let newFilename = filename_without_ext + size + '_thumbnail.' + filename_ext;
let gcsNewObject = bucket.file(newFilename);
let srcStream = gcsObject.createReadStream();
let dstStream = gcsNewObject.createWriteStream();
let resize = imagemagick().resize(size).quality(90);
srcStream.pipe(resize).pipe(dstStream);
return new Promise((resolve, reject) => {
dstStream
.on("error", (err) => {
console.log(\`Error: \${err}\`);
reject(err);
})
.on("finish", () => {
console.log(\`Success: \${fileName} → \${newFilename}\`);
gcsNewObject.setMetadata(
{
contentType: 'image/'+ filename_ext.toLowerCase()
}, function(err, apiResponse) {});
pubsub
.topic(topicName)
.publisher()
.publish(Buffer.from(newFilename))
.then(messageId => {
console.log(\`Message \${messageId} published.\`);
})
.catch(err => {
console.error('ERROR:', err);
});
});
});
}
}
};
EOF
cat > package.json <<EOF
{
"name": "thumbnails",
"version": "1.0.0",
"description": "Create Thumbnail of uploaded image",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"@google-cloud/pubsub": "^2.0.0",
"@google-cloud/storage": "^5.0.0",
"fast-crc32c": "1.0.4",
"imagemagick-stream": "4.1.1"
},
"devDependencies": {},
"engines": {
"node": ">=4.3.2"
}
}
EOF
echo -e "${YELLOW}${BOLD}Installing npm dependencies...${RESET}"
npm install --quiet
echo -e "\n${GREEN}${BOLD}🎉 COMMAND 1 COMPLETE! Check progress for Tasks 1 & 2, then proceed to Command 2.${RESET}"# ==============================================================================
# ORBIT OF OPS - ARC101 (COMMAND 2 OF 2: DEPLOY & ALERTING)
# ==============================================================================
CYAN='\e[1;36m'
YELLOW='\e[1;33m'
GREEN='\e[1;32m'
MAGENTA='\e[1;35m'
RESET='\e[0m'
BOLD='\e[1m'
cd ~/thumbnail_app
echo -e "${YELLOW}${BOLD}[Orbit of Ops] Waiting 60 seconds for IAM policies to propagate...${RESET}"
sleep 60
echo -e "${MAGENTA}${BOLD}[Orbit of Ops] Task 3: Deploying Cloud Run Function (Takes ~3 mins)...${RESET}"
gcloud functions deploy $FUNCTION_NAME \
--gen2 \
--runtime=nodejs22 \
--region=$REGION \
--source=. \
--entry-point=thumbnail \
--trigger-bucket=$BUCKET_NAME \
--max-instances=1 \
--quiet
echo -e "\n${CYAN}${BOLD}[Orbit of Ops] Testing Infrastructure (Triggering the function)...${RESET}"
wget -q https://storage.googleapis.com/cloud-training/arc101/travel.jpg
gcloud storage cp travel.jpg gs://$BUCKET_NAME/ --quiet 2>/dev/null
echo -e "\n${YELLOW}${BOLD}[Orbit of Ops] Task 4: Creating Alert Policy...${RESET}"
CHANNEL_ID=$(gcloud beta monitoring channels create \
--display-name="Personal Email" \
--type=email \
--channel-labels=email_address=${ALERT_EMAIL} \
--format="value(name)")
cat > active-instances-policy.json <<EOF
{
"displayName": "Active Cloud Run Function Instances",
"combiner": "OR",
"conditions": [
{
"displayName": "Cloud Function Active Instances",
"conditionThreshold": {
"filter": "resource.type=\"cloud_function\" AND metric.type=\"cloudfunctions.googleapis.com/function/active_instances\"",
"aggregations": [
{
"alignmentPeriod": "60s",
"perSeriesAligner": "ALIGN_MAX"
}
],
"comparison": "COMPARISON_GT",
"thresholdValue": 0,
"duration": "0s"
}
}
],
"notificationChannels": ["$CHANNEL_ID"]
}
EOF
gcloud alpha monitoring policies create --policy-from-file="active-instances-policy.json" --quiet
echo -e "${GREEN}✅ Alerting Policy created successfully!${RESET}"
echo -e "\n${GREEN}${BOLD}🎉 PIPELINE AUTOMATION COMPLETE! You can now safely click 'Check my progress' on Tasks 3 and 4.${RESET}"