The Cloud Resume Challenge - GCP :)
Tags: devops, python, cloud, gcp
Published: 2022-09-11 08:11:41

## Intro 😎
In July 2022 I came across the [cloud resume challenge](https://cloudresumechallenge.dev/docs/the-challenge/) by [Forrest Brazeal](https://forrestbrazeal.com) shortly after completing my [Cloud Engineer](https://www.credential.net/fe0fe2ad-e16f-4f2f-ac73-f44b3f937eec) Certification by Google Cloud. The challenge was forwarded to me by mentor [Martin](https://www.linkedin.com/in/martin-kariuki) and immediately after having an overview of the tasks I knew the challenge was good enough to piece together all I had learned about GCP.   

The Resume challenge itself is simple but enables one to stitch together different functionalities of the cloud and come up with a complete workflow of building a static website which is fully hosted on cloud resources. Below is how I did the challenge:


## 1. Certification 🌱
The challenge required one to have at least completed [Google Cloud Digital Leader](https://cloud.google.com/certification/cloud-digital-leader) by Google. Fortunately I had completed [Associate Cloud Engineer](https://www.credential.net/fe0fe2ad-e16f-4f2f-ac73-f44b3f937eec) by Google early July 2022 and I was comfortable building and hosting applications on GCP.  

## 2. Static Website 🎯
The challenge prompted one to write a static site for their resume in HTML & CSS. This was a quick task for me having done a bit of systems development early on in my career, picked up a template online for the look and feel of the site and created custom CSS to make it look better. 


![My Resume site](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4k7323c8xgco9kx6leae.png)

## 3. Site Hosting 👨🏽‍💻
The static site (Resume) is supposed to be hosted on [Google Cloud Storage](https://cloud.google.com/storage) and use a cloud load balancer for traffic flow. I used GCP storage bucket to host the site while Cloud Load Balancing via HTTP(S) Load Balancer on GCP. 

- **bucket creation config**
```yaml
resources:
#site bucket
- name: resume.hexorsec.com
  type: gcp-types/storage-v1:buckets
  properties:
    zone: us-central1-f
    website:
      mainPageSuffix: index.html
      notFoundPage: index.html
    iamConfiguration:
      uniformBucketLevelAccess:
        enabled: true
    labels:
      app: davisresume
``` 
- **HTTPS certificate**
```yaml
# Put the bucket as a backend service
- name: davis-resume-backend-bucket
  type: gcp-types/compute-v1:backendBuckets
  properties:
    bucketName: $(ref.hexorsec.resume.com.name)
    description: Backend bucket for the CDN
    enableCdn: true

# Create an HTTPS certificate
- name: davis-resume-https-cert
  type: gcp-types/compute-v1:sslCertificates
  properties:
    type: MANAGED
    managed:
      domains:
        - $(ref.resume.hexorsec.com.dnsName)
```

## 4. DNS 🌍
The site is supposed to be pointed to a custom DNS domain name. My domain is already registered on Godaddy and I had just to add an entry for the site. Using the IP address of the Load balancer  I created an entry for my [resume](https://resume.hexorsec.com). 
  
## 5. Visitor Count 🌏

![Visitor Counter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tr0nfwttqp39hk86m178.png)


The challenge prompted one to have a section on the site for number of visitors who visit the site. For this I wrote a simple JavaScript code to fetch JSON content from endpoints and update visitor count on my site. 

**Firestore**
I used Firestore to store and update visitor count object on the site. The database is automatically created by a script when the first visitor reaches the website.

**API**
The communication between JavaScript code and database is managed by a cloud function on GCP which I created. The function depends on HTTP triggers to invoke an event. The function:

1. reads the visitor count from firestore database
2. increments it by one
3. saves it to the database
4. returns the value to the client.

## 6. Python & Tests 🧩
The challenge prompts us to use python to write the serverless function and then perform some tests on our written code.
For this I used Python3.6 to write the serverless function and the communication between code and the backend db uses the google-cloud-firestore Python library. 

## 7. Tests & Security 🎳
I used [Pylint](https://pylint.pycqa.org/en/latest) to perform basic test on the code and for the security bit I used [snyk](https://snyk.io/) SCM to check for vulnerabilities within my code and it's dependencies. 

## 8. IAC, CI/CD & Source Control 🎮
The challenge goes a head and prompt us to do a bit of IAC for automation purposes between the function, firestore and API gateway. The IAC allows one to replicate and do updates easily on the infra being provisioned. I opted to go with Deployment Manager as is an easy way to do quick deployments.

**Static Site Syncing**
```yaml
steps:
# Copy the Site content to a GS bucket
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:latest'
  id: Sync the website content
  args: ['gsutil', '-m', 'rsync', '-r', 'site/', 'gs://resume.hexorsec.com']
``` 

![Static Site Trigger](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ib64td1a7scrqf8x3jsv.png)


 **Pylint Scanning**
```yaml
steps:
# Pylint SAST
- name: python:3.6
  id: Check the python package
  entrypoint: 'bash'
  args:
    - '-c'
    - |-
      pip install pylint
      pip install -r scripts/visitor_count/requirements.txt
      pylint scripts/
```

![Pylint checking Packages](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80o81zirn07uwcjv1e02.png)



 **Infra as Code**
```yaml
# Deploy
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:latest'
  id: Deploy the infrastructure
  entrypoint: 'bash'
  args:
    - '-c'
    - |-
      apt install -y zip
      pushd scripts/visitor_count
      zip -r ../visitor_count.zip .
      cd ..
      file_name="count_$(md5sum visitor_count.zip | awk '{print $1}').zip"
      mv visitor_count.zip ${file_name}
      gsutil cp ${file_name} gs://hexorsec-XXXX-YYYYYYY
      popd
      gcloud deployment-manager deployments update resume-xxx-depl
```
 **Cloud Build**
For the build I created two triggers for Infra and static site. With the two build triggers once changes are made to github and action is triggered for syncing and pushing changes.

![Cloud Build Triggers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/26z2tq6090ph860b4yyy.png)

## 9. Blog Post 🎲
Finally the challenge prompted one to create a blog post describing the entire process of the challenge. Here is the post for that :) 

## Outro 🙏🙏
Going through the challenge is one of the best things have done after acquiring the associate cloud engineer cert from google. The entire process showed me how things work in the cloud and how use-cases can be created in such scenarios. I'm so grateful to [Forrest Brazeal 👏](https://forrestbrazeal.com/) for setting up such a great challenge and my Mentor [Martin 🫡](https://www.linkedin.com/in/martin-kariuki) for pointing me to such amazing resource for learning.