Friday, April 5, 2024
Cloud Run GCP

Build a Serverless App with Cloud Run that Creates PDF Files

PDF

“Build a Serverless App with Cloud Run that Creates PDF Files”

Pengantar

Cloud Run tidak memiliki server, sehingga mengabstraksikan semua manajemen infrastruktur dan memungkinkan Anda fokus membangun aplikasi alih-alih mengkhawatirkan biaya overhead. Sebagai produk tanpa server Google, produk ini dapat diskalakan ke nol, artinya tidak akan dikenakan biaya saat tidak digunakan. Ini juga memungkinkan Anda menggunakan paket biner khusus berdasarkan wadah, yang berarti membangun artefak terisolasi yang konsisten sekarang layak dilakukan.

Architecture

Enable the Cloud Run API

  • Buka menu APIs & Services > Library
  • enable API

Deploy a simple Cloud Run service

  • Clone repository
git clone https://github.com/rosera/pet-theory.git
  • masuk ke folder
cd pet-theory/lab03
  • Edit bagian ini di package.json
...
"scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
...
npm install express
npm install body-parser
npm install child_process
npm install @google-cloud/storage
gcloud builds submit \
  --tag gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter
  • buka menu Container Registry > Images
  • deploy app
gcloud run deploy pdf-converter \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter \
  --platform managed \
  --region us-central1 \
  --no-allow-unauthenticated \
  --max-instances=1
  • Buat environment
SERVICE_URL=$(gcloud beta run services describe pdf-converter --platform managed --region us-central1 --format="value(status.url)")
echo $SERVICE_URL
  • Buat post request
curl -X POST $SERVICE_URL
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" $SERVICE_URL

Trigger your Cloud Run service when a new file is uploaded

gsutil mb gs://$GOOGLE_CLOUD_PROJECT-upload
gsutil mb gs://$GOOGLE_CLOUD_PROJECT-processed
gsutil notification create -t new-doc -f json -e OBJECT_FINALIZE gs://$GOOGLE_CLOUD_PROJECT-upload
  • Buat new service account dengan Pub/Sub
gcloud iam service-accounts create pubsub-cloud-run-invoker --display-name "PubSub Cloud Run Invoker"
  • Buat permission
gcloud beta run services add-iam-policy-binding pdf-converter --member=serviceAccount:pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com --role=roles/run.invoker --platform managed --region us-central1
  • cek project list
gcloud projects list
  • Buat project_number environment
PROJECT_NUMBER=[project number]
  • enable project
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT --member=serviceAccount:service-$PROJECT_NUMBER@gcp-sa-pubsub.iam.gserviceaccount.com --role=roles/iam.serviceAccountTokenCreator
  • Buat Pub/Sub pdf
gcloud beta pubsub subscriptions create pdf-conv-sub --topic new-doc --push-endpoint=$SERVICE_URL --push-auth-service-account=pubsub-cloud-run-invoker@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
  • Copy beberapa test file ke upload bucket
gsutil -m cp gs://spls/gsp644/* gs://$GOOGLE_CLOUD_PROJECT-upload
gsutil -m rm gs://$GOOGLE_CLOUD_PROJECT-upload/*

Docker containers

Update the Docker container

FROM node:12
RUN apt-get update -y \
    && apt-get install -y libreoffice \
    && apt-get clean
WORKDIR /usr/src/app
COPY package.json package*.json ./
RUN npm install --only=production
COPY . .
CMD [ "npm", "start" ]
  • Edit index.js , tambahkan di top line
const {promisify} = require('util');
const {Storage}   = require('@google-cloud/storage');
const exec        = promisify(require('child_process').exec);
const storage     = new Storage();
  • Replace the app.post('/', async (req, res) with the following code
app.post('/', async (req, res) => {
  try {
    const file = decodeBase64Json(req.body.message.data);
    await downloadFile(file.bucket, file.name);
    const pdfFileName = await convertFile(file.name);
    await uploadFile(process.env.PDF_BUCKET, pdfFileName);
    await deleteFile(file.bucket, file.name);
  }
  catch (ex) {
    console.log(`Error: ${ex}`);
  }
  res.set('Content-Type', 'text/plain');
  res.send('\n\nOK\n\n');
})
  • Tambahkan code libreOffice pada bagian paling bawah line
async function downloadFile(bucketName, fileName) {
  const options = {destination: `/tmp/${fileName}`};
  await storage.bucket(bucketName).file(fileName).download(options);
}
async function convertFile(fileName) {
  const cmd = 'libreoffice --headless --convert-to pdf --outdir /tmp ' +
              `"/tmp/${fileName}"`;
  console.log(cmd);
  const { stdout, stderr } = await exec(cmd);
  if (stderr) {
    throw stderr;
  }
  console.log(stdout);
  pdfFileName = fileName.replace(/\.\w+$/, '.pdf');
  return pdfFileName;
}
async function deleteFile(bucketName, fileName) {
  await storage.bucket(bucketName).file(fileName).delete();
}
async function uploadFile(bucketName, fileName) {
  await storage.bucket(bucketName).upload(`/tmp/${fileName}`);
}
  • Build Container
gcloud builds submit \
  --tag gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter
  • deploy latest app
gcloud run deploy pdf-converter \
  --image gcr.io/$GOOGLE_CLOUD_PROJECT/pdf-converter \
  --platform managed \
  --region us-central1 \
  --memory=2Gi \
  --no-allow-unauthenticated \
  --max-instances=1 \
  --set-env-vars PDF_BUCKET=$GOOGLE_CLOUD_PROJECT-processed

Testing the pdf-conversion service

  • test deployment
curl -X POST -H "Authorization: Bearer $(gcloud auth print-identity-token)" $SERVICE_URL
  • Upload beberapa data
gsutil -m cp gs://spls/gsp644/* gs://$GOOGLE_CLOUD_PROJECT-upload

Penutup

Sahabat Blog Learning & Doing demikianlah penjelasan mengenai Build a Serverless App with Cloud Run that Creates PDF Files. Semoga Bermanfaat . Sampai ketemu lagi di postingan berikut nya.

(Visited 170 times, 1 visits today)

Similar Posts