Cloud Guru Azure Resume Challenge

Cloud Guru Azure Resume Challenge

My Resume Page Hosted On Azure

I am writing this blog a month after I finished the challenge because I kept procrastinating. I decided to take the challenge after reading about it on Gwyn's LinkedIn feed. Gwyn, who is now a Cloud Advocate at Microsoft(congrats Gwyn) was a Training Architect at A Cloud Guru at the time of announcing the challenge.

About the challenge

The challenge was to create a 100% Azure-hosted version of my resume. The website must have a visitors counter implemented using Azure functions, custom domain support using Azure CDN, and HTTPS must also be enabled.

Prerequisites

Why did I take the challenge?

I took the challenge because it was a great opportunity to show my Azure skills and also gain more experience using the platform. Interestingly, I was also preparing to write the Microsoft Azure Administrator Associate exam at the time I read about the challenge, which further incentivized me to take it on. I am also using this opportunity to thank Microsoft for giving me a free exam voucher after I completed the Microsoft Ignite Azure Admin Challenge.

Workflow diagram

pasted image 0.png

Solution

I used VScode with Azure Tools Extension for the challenge, you can find the code in this Github repo.

The challenge solution is in two parts, which are the Frontend and the Backend.

  1. Frontend (HTML,CSS,Javascript)
    • To save time I downloaded a pretty cool and responsive website template from Themezy and edited it to my preference.
    • I added a counter function in Javascript that fetches a count value from a database every time the page is loaded.
//Get count value when Dom content is loaded
window.addEventListener('DOMContentLoaded', (event) => {
    getVisitCount();
});


const funcApi = 'https://resumevisitcounter.azurewebsites.net/api/counterfunction?code=jgAeSzqhStpwaf6yyAVZ24FD6N/ZanUYVDuf4p23huABl9ftAUnHQg==';


const getVisitCount = () => {
    let count = 0;
    fetch(funcApi)
    .then(response => {
        return response.json()
    })
    .then(response => {
        console.log("Website called function API.");
        count = response.count;
        document.getElementById('counter').innerText = count;
    }).catch(function(error) {
        console.log(error);
      });
    return count;
}

Then I displayed the count value on the page in the tag below :

<h3 class="counter-txt" style="font-style: italic;">Site visits:  <a id="counter" style="color:lime"></a></h3>

2. Backend(Javascript, Azure Functions, Azure CosmosDB)

  • First I set up an Azure CosmosDB database. The database has a container with an item containing two fields, "id" and "count" to store the count value. A partition key "/id" with a value "1" was also created. I advise using the Azure CosmosDB emulator during development to avoid unnecessary billing.

Screenshot (8).png note that only the "id" and "count" keys were created by me, others e.g "_rid", "_etag"... are system-generated properties.

  • Next, we need to increase the count value every time the website page is loaded. I achieved this using a simple serverless Azure Function which doesn't need any overhead management, you only pay for the number of times the function is triggered and the cost is usually very low. The function was created in VSCode via the Azure Tools Extension, was written in Javascript and it's triggered via an HTTP request.
module.exports = async function(context) {
    context.log("JavaScript HTTP trigger function processed a request.");

    context.log(context.bindings.inputDocument);
    //For first time creation of record
    context.bindings.outputDocument = context.bindings.inputDocument || { id: "1", count: 0 };

    //Increment by 1
    context.bindings.outputDocument.count = context.bindings.outputDocument.count + 1;
    context.log(context.bindings.outputDocument);
    context.res = {
        // status: 200, /* Defaults to 200 */
        headers: {
            "content-type": "application/json"
        },
        body: {
            id: context.bindings.outputDocument.id,
            count: context.bindings.outputDocument.count
        }
    };
}

The function uses 'bindings' to connect to Azure CosmosDB. The inputDocument gets the current count value in the database while the outputDocument updates the count value.

{
  "bindings": [{
    "authLevel": "function",
    "type": "httpTrigger",
    "direction": "in",
    "name": "req",
    "methods": [
        "get",
        "post"
    ]
},
{
    "type": "http",
    "direction": "out",
    "name": "res"
},
{
    "type": "cosmosDB",
    "direction": "in",
    "name": "inputDocument",
    "databaseName": "resumeCountData",
    "collectionName": "counter",
    "connectionStringSetting": "CosmosDBConnectionString",
    "id": "1",
    "partitionKey": "1"
},
{
    "type": "cosmosDB",
    "direction": "out",
    "name": "outputDocument",
    "databaseName": "resumeCountData",
    "collectionName": "counter",
    "createIfNotExists": "true",
    "connectionStringSetting": "CosmosDBConnectionString"
}
]
}
  • Finally, I deployed the website on Azure Blob Storage, pointed my custom domain(greybeing.com) to the static website, and enabled HTTPS using Azure CDN.

Screenshot (5).png

What was the hardest part?

The hardest part of the challenge for me was getting the function to work. I encountered many roadblocks mostly because it was my first time using Azure Functions or any other serverless computing tool in a real-world scenario. In fact, I almost gave up on the challenge when I couldn't get the inputDocument binding to work in Javascript. Thankfully a video was posted by Gwyn where she used C# to implement the function further simplified the whole challenge. I wrote the function in C# following Gwyn's tutorial and made it work then I tried to find out what I was doing wrong in Javascript. After some debugging, I realized I had been declaring the wrong value for my partition key.

What was the most enjoyable part?

The most enjoyable part of the whole challenge however tough it was, was making the function work. I enjoyed the way I felt when I finally made it work.But all round it was a fun and knowledgeable experience.

My biggest takeaway from the challenge?

I can't pin point what my biggest takeaway is but I know that I have honed a new set of skills in the cloud and I am even more confident about my skills. Also I now have a portfolio/resume website to show for it.

That's all for now, I hope you have learnt something new today!