<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jordan Mccowan</title>
    <description>The latest articles on Forem by Jordan Mccowan (@jordan_mccowan_9694df3193).</description>
    <link>https://forem.com/jordan_mccowan_9694df3193</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1796990%2Fa9afea50-9a91-4a41-b821-d20d16cc4254.jpg</url>
      <title>Forem: Jordan Mccowan</title>
      <link>https://forem.com/jordan_mccowan_9694df3193</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jordan_mccowan_9694df3193"/>
    <language>en</language>
    <item>
      <title>Azure Cloud Resume Challenge</title>
      <dc:creator>Jordan Mccowan</dc:creator>
      <pubDate>Wed, 24 Jul 2024 20:04:45 +0000</pubDate>
      <link>https://forem.com/jordan_mccowan_9694df3193/azure-cloud-resume-challenge-3lep</link>
      <guid>https://forem.com/jordan_mccowan_9694df3193/azure-cloud-resume-challenge-3lep</guid>
      <description>&lt;p&gt;In the ever-evolving world of technology, standing out as a professional requires not only theoretical knowledge but also Hands-on experience.&lt;br&gt;
The &lt;a href="https://cloudresumechallenge.dev/docs/the-challenge/azure/" rel="noopener noreferrer"&gt;Cloud Resume Challenge&lt;/a&gt; offers a unique opportunity to showcase these skills by building and deploying a fully functional, cloud-based resume website. In this article, I will walk you through my journey of completing the Cloud Resume Challenge using Microsoft Azure. &lt;br&gt;
From setting up a static website and implementing a visitor counter with Azure Functions, to Implementing CI/CD Automation with GitHub Actions and securing a custom domain with HTTPS, this challenge not only enhanced my technical expertise but also demonstrated my ability to solve real-world problems using cloud technologies.&lt;/p&gt;
&lt;h2&gt;
  
  
  HTML/CSS
&lt;/h2&gt;

&lt;p&gt;Staring this Section out, I am nowhere near a Web Developer so I found my Template from &lt;a href="https://html5up.net/" rel="noopener noreferrer"&gt;HTML5up&lt;/a&gt; and started tweaking the template within Visual Studio Code.&lt;/p&gt;

&lt;p&gt;Tweaking the code, I wanted to view the changes I made as I progressed, and in my research, I found  the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer" rel="noopener noreferrer"&gt;Live Server&lt;/a&gt; VSC Extension to deploy the site Locally and edited the Code to my liking. (PS. If you are unsure how to edit HTML &amp;amp; CSS for the creation of the website, ChatGPT or Copilot are great resources to use to not only gain the knowledge, but implement it's recommendations to learn how to interact with these resources.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg3fj36f25mo4c68i2vj.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg3fj36f25mo4c68i2vj.JPG" alt="Site/VSC" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Static Website
&lt;/h2&gt;

&lt;p&gt;With my index.html file ready and styled to my liking, the next step was to deploy it as a static website on Azure. To achieve this, I created an Storage Account specifically configured to host static websites. Azure Storage provides a robust and scalable solution for hosting static content, ensuring that my resume website would be highly available and performant. Within the storage account, I enabled static website hosting and uploaded my index.html &amp;amp; it's assets to the designated $web container. This container acts as the root directory for the static website, allowing Azure to serve my resume directly to users.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fesee06msg9r6dw73yjfa.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fesee06msg9r6dw73yjfa.JPG" alt="Storage Account" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  DNS/HTTPS
&lt;/h2&gt;

&lt;p&gt;Using Azure DNS Zone, I was able to implement a Custom Domain for my site for a better user experience. I achieved this by purchasing my domain from &lt;a href="https://www.namecheap.com/" rel="noopener noreferrer"&gt;NameCheap&lt;/a&gt; configuring the DNS Zone with this &lt;a href="https://learn.microsoft.com/en-us/azure/dns/dns-delegate-domain-azure-dns" rel="noopener noreferrer"&gt;Article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsp4fug4u5nnt38g9zzub.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsp4fug4u5nnt38g9zzub.JPG" alt="DNS Zone" width="620" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After configuring the Domain, the next essential step was to secure it with HTTPS. To achieve this, I utilized Azure's Content Delivery Network (CDN) service. I did this by linking a CDN Endpoint to my Static Site URL as its Origin. Once Complete I was able to point to my custom domain to this endpoint. For SSL Encryption to use HTTPS I used a Certificate from &lt;a href="https://zerossl.com/" rel="noopener noreferrer"&gt;ZeroSSL&lt;/a&gt; and Imported the .pfx file into Azure Key vault and linked the Certificate to the Domain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6ukgm1r1wh3dic89eb4.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy6ukgm1r1wh3dic89eb4.JPG" alt="DNS Zone" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmx2hr27kevd7xfqlapg8.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmx2hr27kevd7xfqlapg8.JPG" alt="CDN" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Database
&lt;/h2&gt;

&lt;p&gt;For the Visitor Counter, I chose Azure CosmosDb for Table as it is  ideal for storing structured, non-relational data, making it a perfect fit for tracking simple metrics like tracking Visitors to my Site.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx2gukad7fs0enyfu8zs.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx2gukad7fs0enyfu8zs.JPG" alt="CosmosDB" width="800" height="264"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  API
&lt;/h2&gt;

&lt;p&gt;This was without a doubt the most Painful / Rewarding part of this challenge, I don't even want to think about the amount of time I put in to complete this Section.&lt;/p&gt;

&lt;p&gt;I went about this by reviewing the &lt;a href="https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-python?pivots=python-mode-decorators" rel="noopener noreferrer"&gt;QuickStart&lt;/a&gt; Guide to setup my VSC to work with Python HTTP Triggers. After I used &lt;a href="https://pypi.org/project/azure-data-tables/" rel="noopener noreferrer"&gt;Python tables Package&lt;/a&gt; to call my CosmosDB Table. Lastly, I used This &lt;a href="https://stackoverflow.com/questions/58535162/how-to-access-local-setting-json-db-connection-string-with-python" rel="noopener noreferrer"&gt;Article&lt;/a&gt; to understand how to call my CosmosDbConnectionSetting Variable within local.settings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import azure.functions as func

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="http_trigger")

def main(req: func.HttpRequest) -&amp;gt; func.HttpResponse:

    import logging
    from azure.data.tables import TableClient, UpdateMode
    import os

    logging.info('Python HTTP trigger function processed a request.')

    conn_str = os.getenv("CosmosDbConnectionSetting")
    table_client = TableClient.from_connection_string(conn_str=conn_str, table_name="Visitors")
    entity = table_client.get_entity(partition_key="PageViewCount", row_key='1')
    entity['Count'] += 1
    table_client.update_entity(mode=UpdateMode.REPLACE, entity=entity)

    return func.HttpResponse(f"{entity['Count']}")



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Javascript
&lt;/h2&gt;

&lt;p&gt;To make the visitor counter functional and dynamic, integrating JavaScript into my index.html was the next step in this process. JavaScript enabled me to fetch and display the visitor count in real-time, enhancing the interactivity of my resume website. I wrote a script that made an request to the Function URL which triggered the Python Function listed in the previous section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const counter = document.querySelector(".counter-number");
async function updateCounter() {
    let response = await fetch(&amp;lt;"Function URL"&amp;gt;);
    let data = await response.json();
    counter.innerHTML = ` Views: ${data}`;
}

updateCounter();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I reference this code in my HTML by doing the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;li&amp;gt;&amp;lt;div class="counter-number"&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;script src="Path to JavaScript"&amp;gt;&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Source Control / Infrastructure as Code
&lt;/h2&gt;

&lt;p&gt;Source control played a pivotal role in managing the development and deployment of my Cloud Resume Challenge project. By using GitHub, I ensured that all changes to my project files were tracked, versioned, and easily revertible if needed. I created a repository named &lt;a href="https://github.com/Jmccowan992/Azure_Cloud_Resume_Project" rel="noopener noreferrer"&gt;Azure_Cloud_Resume_Project&lt;/a&gt;, where I stored my index.html, CSS files, JavaScript scripts, and infrastructure as code (IaC) configurations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zhfmu3agz5s6ucs6cle.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zhfmu3agz5s6ucs6cle.JPG" alt="Repo" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the IaC, I have the ARM Templates for the resources I deployed and created a baseline so if I need to rollback or make edits, I can do so using code.&lt;br&gt;
I plan to expand this section in the future using &lt;a href="https://cloudresumechallenge.dev/docs/extensions/terraform-getting-started/" rel="noopener noreferrer"&gt;Terraform.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CI/CD
&lt;/h2&gt;

&lt;p&gt;Implementing Continuous Integration and Continuous Deployment (CI/CD) was an interesting part of the Challenge to simplify my deployment when I decide to make changes in the future. I utilized GitHub Actions to create a CI/CD pipeline, which streamlined the process of deploying changes from my GitHub repository to Azure. The pipeline was configured to trigger on every push to the main branch, running a series of actions that included validating the HTML, CSS, and JavaScript, logging in as a dedicated Service Principal account, and deploying the updated files to my Storage Account.&lt;br&gt;
I also added code to the action to Purge the CDN Endpoint to retrieve the latest code and display as expected to my viewers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2q9sqws0afaju0f2vsye.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2q9sqws0afaju0f2vsye.JPG" alt="Github Action" width="800" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Budget &amp;amp; Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The Cost of this Project using Serverless For CosmosDB &amp;amp; Azure Functions You can expect the Cost per month to be under $1 as is and it may vary depending how many request are generated to your site but in such case I would Highly recommend setting up &lt;a href="https://learn.microsoft.com/en-us/azure/cost-management-billing/costs/cost-mgt-alerts-monitor-usage-spending" rel="noopener noreferrer"&gt;Cost Alerts&lt;/a&gt; to monitor the Azure Spend and adjust accordingly.&lt;/p&gt;

&lt;p&gt;The Domain was purchased under $10 from Namecheap and in the future I do Plan to implement a SSL Certificate once the ZeroSSL Certificate expires which should cost around $10-$15.&lt;/p&gt;

&lt;p&gt;To wrap it up, As someone who uses Azure Daily for work, This Project provide me with a better insight into the services I support for clients and was indeed a Challenge. I look to expand on this in terms of Security and Terraform for IaC and will provide updates accordingly. I recommend anyone interested in Cloud either early in their career or looking to expand their knowledge to take on the challenge to put themselves to the test.&lt;/p&gt;

&lt;p&gt;Here are the Links to my &lt;a href="https://jrmcc.cloud/" rel="noopener noreferrer"&gt;Resume Site&lt;/a&gt;, &lt;a href="https://github.com/Jmccowan992/Azure_Cloud_Resume_Project" rel="noopener noreferrer"&gt;Github Repo&lt;/a&gt;, &amp;amp; my &lt;a href="https://www.linkedin.com/in/jordanm22123/" rel="noopener noreferrer"&gt;Linkedin&lt;/a&gt;. Feel free to reach out if you have any questions as I am happy to help!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>python</category>
      <category>cloud</category>
      <category>microsoft</category>
    </item>
  </channel>
</rss>
