CloudGuruChallange Resume in Azure

Cloud Guru posted a Azure Resume Challenge to show your resume using Azure and serverless components (Blob storage, Azure Content Delivery Network with SSL endpoints and a custom domain, Azure Functions and Comsmos DB to host a page counter).

My resultant CV is displayed at the root of my domain at matthewt.com and here is my Linkedin Profile.

Why did you take on the challenge?

Exercise the legs with Azure. I've build more complex solutions on AWS and integrated to Azure but not written an Azure Function before (AWS Lambda is my goto with Java or Node), likewise I've used AWS S3 but not utilised Azure's blob storage and I have experience with AWS Dynamodb noSQL but not Azure Cosmos db.

I followed the broad architecture outlined (Blob Storage, Azure Function and Cosmos db) including CI/CD from VS Code -> Git -> Git Action -> Blob Storage -> Azure CDN.

Client

I used a Bootstrap 4.0 template for the CV layout. The client side Javascript uses Axios to call the webservice which simply returns a HTTP 200 and the counter. value I used the pathname (replacing "/" with "-" to comply with syntax) rather than just using the filename so I can multiple file names i.e. index.htm as a counter (with a different path). If the index value doesn't exist I create a new entry in Cosmosdb with an upsert.

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

async function getcounter (e) {

fileName=window.location.pathname;

if (fileName){
      fileName = fileName.replaceAll("/", "-");    
}

// root domain serves index without it appearing in url
if ((fileName==null || fileName=="")|| fileName=="#"){
    fileName="index.html";
}

var url = "https://cvcounter.azurewebsites.net/api/counter?page=";

const response = await axios({ 
        method: 'GET', 
        url: url+fileName
      })
document.getElementById("counter").innerHTML = "page count "+ response.data;
}

Server

I used the Cosmos javascript client with in Node.

const { CosmosClient } = require("@azure/cosmos");

This gave me greater control on the Cosmos db calls.

 // load page counter
 const {resource : readitem} = await container.item(pagecounter).read();
 var pagecount = 1;

if (readitem==null) {
    console.log("page " + pagecounter + " not found, will create with 1"); 
} else {
     console.log("page " + pagecounter + " count of " + readitem.count);
     pagecount=readitem.count+1;
}

const updatetoitem = {id:pagecounter, count:pagecount};
const { resource: updateditem } = await container.items.upsert(updatetoitem);

What was the hardest part?

I wanted to get the apex domain name i.e. matthewt.com to point to the HTTPS CDN. To do that I had to switch my DNS to Azure DNS from the lite version that comes with Microsoft 365. I also had to create a few rules to forward traffic on the CDN from the apex and non SSL requests to the SSL domain which the cert is attached to. Not hard just takes a bit of time for DNS to propagate and make sure all the layers line up and the cert matches.

Getting the Azure Cosmosdb api syntax right takes time as the Node (Javascript examples) aren't that thorougher.

Which part did you enjoy the most?

Liked the fact that SSL is free for the Azure CDN. Best part was the CI/CD. As directed from Code I can sync to Git and the git action written in a ymal script writes to azures blob storage and also clears the CDN cache. While I've used VS Code and the Azure extensions I hadn't used Git actions before. The code debugger within the azure extension works well for Azure Functions.

What are your biggest takeaways?

It's worth taking the time to get the CI/CD pipeline going even for a small project. Doesn't have to be complicated. CDN setup takes time (8 hours to apply an SSL cert...) and not all features are support which every DNS provider.

If you’ve done this challenge before with another cloud, what differences did you notice?

Not the exact challenge. I find the AWS components (javascript client through to Lambda) log more effectively. Some of the Azure components fail safe but its not always easy to figure out what is going on.