Resume website on Azure

https://profile.sankethiyer.in

Recently I took part in the #cloudguruchallenge to create an Azure-hosted version of your resume. I have briefly explained the steps I followed to complete this challenge. For more details on the challenge, refer to https://acloudguru.com/blog/engineering/cloudguruchallenge-your-resume-in-azure

My web version of my resume hosted in Azure: profile.sankethiyer.in

My Github repository: github.com/sankethiyer/sankethiyer-functions && github.com/sankethiyer/sankethiyer.github.io

Things you will need for the solution

Step 1: Write your HTML file

I used a template for this purpose and modified the colour scheme and my details - startbootstrap.com/previews/resume. Create a Github repository and push the code inside it.

Step 2: Create your Azure Functions locally

Please install the following software in your developer machine - Visual studio code, Azure CLI, Azure Functions CLI, Cosmos DB emulator. I created my functions in JavaScript since I am more familiar with the language. You can choose any other language as per your preference. Please see docs.microsoft.com/en-us/azure/azure-functi.. for more details. After you start your cosmosDB emulator on your developer machine, create a new Database and collection and use the localhost connection string provided in your local.settings.json file. Create a new attribute CosmosDBConnectionString

local.settings.json


{
    "IsEncrypted": false,
    "Values": {
        "FUNCTIONS_WORKER_RUNTIME": "node",
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "CosmosDBConnectionString": "<UPDATE LOCAL COSMOS DB CONNECTION STRING HERE>"
    },
    "Host": {
        "LocalHttpPort": 7071,
        "CORS": "*",
        "CORSCredentials": false
    }
}

Create a function with 2 input and 2 output bindings. In the cosmosDB create only 1 entry with hardcoded ID=1 and maintain the count in another attribute. The logic for the function is to create an entry if it doesn't exist and if it exists then increment the count by 1 and return it in the HTTP response.

functions.json

    "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": "Visits",
            "collectionName": "Counter",
            "connectionStringSetting": "CosmosDBConnectionString",
            "id": "1"
        },
        {
            "type": "cosmosDB",
            "direction": "out",
            "name": "outputDocument",
            "databaseName": "Visits",
            "collectionName": "Counter",
            "createIfNotExists": "true",
            "connectionStringSetting": "CosmosDBConnectionString"
        }
    ]
}

index.js

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
        }
    };
}

Test out your locally created API logic in Postman or the browser. You should see the count is incremented by 1 and the value being updated in the cosmosDB local emulator database as well.

Create a Github repository and push the code inside it.

Step 3: Create your Azure resources and deploy your code

Create the following resources:

Step 4: Deploy your static HTML page and Functions to Azure and test if it works well

  • Run the following command from your command line at the root of your Functions App path
func azure functionapp publish "FUNCTIONS_APP_NAME" --node
  • Run the following command from your command line at the root of your HTML page
az storage blob upload-batch --source . --destination '$web' --account-name "STORAGE_ACCOUNT_NAME"
  • Once your static webpage and functions are deployed, connect to the CDN endpoint you configured in Step 3 and confirm if all changes are working as expected. URL should be .azureedge.net

  • In case you see the CORS error in your browser console, configure allowed origins in functions app CORS configuration: docs.microsoft.com/en-us/azure/azure-functi..

Step 5: Purchase Custom domain (Skip to Step 6 if you already have a custom domain)

I purchased mine from Godaddy. The steps to follow are quite easy and GoDaddy documentation is quite good.

Check out the following links for more details:

Step 6: Map custom domain to CDN endpoint

Please follow the steps as described by Azure documentation:

Once completed you should be able to access your custom domain and find your resume site working as expected. You can find my resume site here - profile.sankethiyer.in Note: You need to add this custom domain to the Functions App CORS allowed origins as described in Step 4

Step 7: Setup Github Actions:

Please follow the steps as described by Azure documentation

In case you want to see a live example you can refer to my Github workflow: Functions App & Static Website

Why did you take on the challenge?

I recently started on a role that is primarily focused on Azure. This is the first time I have done any technology challenge and was excited when I read about it. I wanted to explore and end to end solution which could give me the experience of understanding all the minor nuances of the Cloud and Azure

What was the hardest part?

Mostly if you follow the documentation, none of the steps are difficult or challenging. For me, the most challenging was the "functions binding" with CosmosDB. In this case, I have used a double incoming and double outgoing binding. The documentation does not share this use case with you, so I had to do some trial and error to get it to work right.

Which part did you enjoy the most?

Seeing your webpage displayed on your custom domain for the first time was a pleasure. This is the first time I have purchased and used my domain for any personal project. Surprisingly for me, it was quite easy to do since the documentation is very clear

What are your biggest takeaways?

You learn more by doing than reading or watching tutorials. There are minor details and pain points which you will only experience when you try things out on your own