<?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>DEV Community: Andrea Grillo</title>
    <description>The latest articles on DEV Community by Andrea Grillo (@andreagrillo96).</description>
    <link>https://dev.to/andreagrillo96</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%2F779184%2F9dc545f9-d3a0-4c17-85d2-b01c06a49d83.jpg</url>
      <title>DEV Community: Andrea Grillo</title>
      <link>https://dev.to/andreagrillo96</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andreagrillo96"/>
    <language>en</language>
    <item>
      <title>Avoid name conflicts in Terraform workspaces</title>
      <dc:creator>Andrea Grillo</dc:creator>
      <pubDate>Tue, 22 Aug 2023 12:11:28 +0000</pubDate>
      <link>https://dev.to/andreagrillo96/avoid-name-conflicts-in-terraform-workspaces-241i</link>
      <guid>https://dev.to/andreagrillo96/avoid-name-conflicts-in-terraform-workspaces-241i</guid>
      <description>&lt;p&gt;Terraform workspaces are a feature of some backends to associate many terraform states to the same configuration. It is convenient to have a workspace where you can try changes to infrastructure. When the changes have been tested, you can switch to the production workspace and apply the changes.&lt;/p&gt;

&lt;p&gt;Since the configuration files are the same for all workspaces, there may be conflicts among the names of the cloud resources.&lt;/p&gt;

&lt;p&gt;For instance, you want to create a AWS security group named &lt;code&gt;allow_http&lt;/code&gt;. You switch to the &lt;strong&gt;lab workspace&lt;/strong&gt; and apply the configuration. Now you have a security group named “allow_http” in your AWS account.&lt;/p&gt;

&lt;p&gt;You switch to the &lt;strong&gt;prod&lt;/strong&gt; &lt;strong&gt;workspace&lt;/strong&gt; and apply the terraform configuration again. However, Terraform complains that the security group &lt;code&gt;allow_http&lt;/code&gt; already exists!&lt;/p&gt;

&lt;p&gt;When you use terraform workspaces, you should pay attention to clashes among the names of cloud resources.&lt;/p&gt;

&lt;p&gt;At the time of writing this post, the latest version of Terraform is 1.5.5.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create a terraform resource with a fixed name
&lt;/h2&gt;

&lt;p&gt;You have a Terraform configuration that creates a security group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;resource "aws_security_group" "allow_http" {&lt;/span&gt;
  &lt;span class="s"&gt;name        = "allow_http"&lt;/span&gt;
  &lt;span class="s"&gt;description = "Allow HTTP inbound traffic"&lt;/span&gt;

  &lt;span class="s"&gt;ingress {&lt;/span&gt;
    &lt;span class="s"&gt;description = "HTTP"&lt;/span&gt;
    &lt;span class="s"&gt;from_port   = &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="s"&gt;to_port     = &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="s"&gt;protocol    = "tcp"&lt;/span&gt;
    &lt;span class="s"&gt;cidr_blocks = ["0.0.0.0/0"]&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;

  &lt;span class="s"&gt;egress {&lt;/span&gt;
    &lt;span class="s"&gt;from_port   = &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="s"&gt;to_port     = &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="s"&gt;protocol    = "-1"&lt;/span&gt;
    &lt;span class="s"&gt;cidr_blocks = ["0.0.0.0/0"]&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the resources in the workspace “dev”
&lt;/h3&gt;

&lt;p&gt;First you create the terraform workspace &lt;code&gt;dev&lt;/code&gt; and then you apply the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;terraform workspace new dev
&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the id of the &lt;code&gt;security_group&lt;/code&gt; somewhere because it will be needed later:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;terraform state show aws_security_group.allow_http
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;id = "sg-0a89544d88354a70b"
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create the resources in the workspace “prod”
&lt;/h3&gt;

&lt;p&gt;Then you want to create the resources in the new terraform workspace &lt;code&gt;prod&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;terraform workspace new prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you make a &lt;code&gt;terraform plan&lt;/code&gt;, terraform wants to create the security group again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;terraform plan
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;Plan: 1 to add, 0 to change, 0 to destroy.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you try to apply the changes, it fails because the resource already exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;terraform apply
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;Error: creating Security Group (allow_http): InvalidGroup.Duplicate: The security group 'allow_http' already exists for VPC 'vpc-0688682e4898523a4'
&lt;/span&gt;&lt;span class="c"&gt;...
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solution 1: Import resources already existing
&lt;/h2&gt;

&lt;p&gt;First solution is to import the existing resource in this workspace as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;terraform import aws_security_group.allow_http sg-0a89544d88354a70b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, in larger terraform configurations may be complex to import all resources that cannot be duplicated in other workspaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 2: Use terraform.workspace in resource names
&lt;/h2&gt;

&lt;p&gt;The second approach is to use the &lt;code&gt;terraform.workspace&lt;/code&gt; variable in resource names to avoid duplicate errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;resource "aws_security_group" "allow_http" {&lt;/span&gt;
  &lt;span class="s"&gt;name        = "allow_http_${terraform.workspace}"&lt;/span&gt;
  &lt;span class="s"&gt;description = "Allow HTTP inbound traffic"&lt;/span&gt;

  &lt;span class="s"&gt;ingress {&lt;/span&gt;
    &lt;span class="s"&gt;description = "HTTP"&lt;/span&gt;
    &lt;span class="s"&gt;from_port   = &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="s"&gt;to_port     = &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
    &lt;span class="s"&gt;protocol    = "tcp"&lt;/span&gt;
    &lt;span class="s"&gt;cidr_blocks = ["0.0.0.0/0"]&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;

  &lt;span class="s"&gt;egress {&lt;/span&gt;
    &lt;span class="s"&gt;from_port   = &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="s"&gt;to_port     = &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="s"&gt;protocol    = "-1"&lt;/span&gt;
    &lt;span class="s"&gt;cidr_blocks = ["0.0.0.0/0"]&lt;/span&gt;
  &lt;span class="s"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Terraform workspaces are a convenient feature to manage many terraform states related to the same configuration. However, you should use the &lt;code&gt;terraform.workspace&lt;/code&gt; variable to avoid conflicts with the resources created by other workspaces.&lt;/p&gt;

&lt;p&gt;Discover more posts about &lt;a href="https://andregri.com/tags/#terraform"&gt;Terraform&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>workspace</category>
    </item>
    <item>
      <title>Change Kubernetes service type from LoadBalancer to NodePort and viceversa</title>
      <dc:creator>Andrea Grillo</dc:creator>
      <pubDate>Fri, 11 Aug 2023 13:55:18 +0000</pubDate>
      <link>https://dev.to/andreagrillo96/change-kubernetes-service-type-from-loadbalancer-to-nodeport-and-viceversa-2d3</link>
      <guid>https://dev.to/andreagrillo96/change-kubernetes-service-type-from-loadbalancer-to-nodeport-and-viceversa-2d3</guid>
      <description>&lt;p&gt;Changing the Service type from NodePort to LoadBalancer and viceversa is useful depending on the cluster you are working on. If you are doing experiments in a local development cluster, like Kind, you don't have a real load balancer in front of your cluster and you need to expose your services externally using a NodePort service. On contrary, if you are working on a kubernetes cluster with a proper load balancer, you can expose your services through a LoadBalancer service type that uses the load balancer domain name and port.&lt;/p&gt;

&lt;h2&gt;
  
  
  Convert to a LoadBalancer service
&lt;/h2&gt;

&lt;p&gt;It is very likely to have a load balancer in front of your kubernetes services when you are working in a production cluster or on a kubernetes cluster hosted by a cloud provider. The load balancer is useful to expose your services using a single domain name, the load balancer domain name.&lt;/p&gt;

&lt;p&gt;The command to convert a service type to a LoadBalancer service type is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl patch svc &amp;lt;service-name&amp;gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;namespace&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{"spec": {"type": "LoadBalancer"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Convert to a NodePort service
&lt;/h2&gt;

&lt;p&gt;If you are working on a development kubernetes cluster you probably don't have a load balancer to forward the incoming requests to the services. To connect to your services you have to expose them using a Node Port service type that open the same port on each node of the cluster. So to connect to the service in a multi-node cluster, you type the name of a node and the exposed port. Compared to a load balancer, you should know the node names before connecting to the service.&lt;/p&gt;

&lt;p&gt;The command to convert a service type to a NodePort service type is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl patch svc &amp;lt;service-name&amp;gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;namespace&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s1"&gt;'{"spec": {"type": "NodePort"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  kubectl port-forward to expose a service locally
&lt;/h2&gt;

&lt;p&gt;kubectl tool contains the port-forward command to expose a service locally on the port we choose. It means you can connect to the service using &lt;code&gt;localhost:port&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The command to expose the service locally is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl port-forward svc/&amp;lt;service-name&amp;gt; &amp;lt;local-port&amp;gt;:&amp;lt;service-port&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For instance, if you have the service frontend on port 80, to expose it locally on port 8080:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;kubectl&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;forward&lt;/span&gt; &lt;span class="nx"&gt;svc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;frontend&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;kubectl port-forward&lt;/code&gt; is a process running on the foreground. So you need to open a new terminal if you want to issue new commands.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://argo-cd.readthedocs.io/en/stable/getting_started/#3-access-the-argo-cd-api-server"&gt;Argo CD Getting Started guide&lt;/a&gt; shows different methods to access the Argo CD Api Server: using a LoadBalancer service type or a exposing the service locally using &lt;code&gt;kubectl port-forward&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I personally used the combination of a NodePort service and kubectl port-forward command when working with Istio Gateways. Istio creates a LoadbBalancer service when you create a Gateway. Since I was working in a Kind cluster, I first changed the service type and then I exposed it locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Depending if you a have load balancer or not, you may need to change service type to connect to them.&lt;/p&gt;

&lt;p&gt;Discover more posts about &lt;a href="https://andregri.com/tags/#kubernetes"&gt;Kubernetes&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Don't waste your food again with AiFame</title>
      <dc:creator>Andrea Grillo</dc:creator>
      <pubDate>Tue, 08 Mar 2022 21:13:14 +0000</pubDate>
      <link>https://dev.to/andreagrillo96/dont-waste-your-food-again-with-aifame-3nli</link>
      <guid>https://dev.to/andreagrillo96/dont-waste-your-food-again-with-aifame-3nli</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;How many times did you forget to eat you food before expiring? Not only it is a waste of money, but also a waste of food that you could have eaten, used to prepare a dinner with your friends or gifted to someone.&lt;/p&gt;

&lt;p&gt;We built a web application called AiFame made for the Microsoft Azure Trial Hackathon on DEV 2022. Don't waste your food again!&lt;/p&gt;

&lt;p&gt;AiFame allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take a picture of your shopping and computer vision algorithms will detect foods automatically&lt;/li&gt;
&lt;li&gt;Manage your food inventory like modifying quantity and expiration date.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try it live &lt;a href="http://aifame.azurewebsites.net"&gt;here&lt;/a&gt;!&lt;br&gt;
Try to manage your inventory or scan foods from a test image.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/FRcXb6Eim50"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;We chose to participate in the &lt;strong&gt;Computing Captains&lt;/strong&gt; category because the app was deployed using &lt;strong&gt;Azure App Service&lt;/strong&gt;. The container image is saved in the &lt;strong&gt;Azure Container Registry&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Link to Code on GitHub
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/andregri"&gt;
        andregri
      &lt;/a&gt; / &lt;a href="https://github.com/andregri/AiFame"&gt;
        AiFame
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      AiFame is Flask application made for the Microsoft Azure Trial Hackathon on DEV 2022
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
AiFame&lt;/h1&gt;
&lt;p&gt;AiFame is web application made for the Microsoft Azure Trial Hackathon on DEV 2022. Don't waste your food again!&lt;/p&gt;
&lt;p&gt;AiFame allows you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Take a picture of your shopping and computer vision algorithms will analyze it for you to detect food automatically&lt;/li&gt;
&lt;li&gt;Manage your food inventory like quantity and expiration date&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Try it live &lt;a href="http://aifame.azurewebsites.net" rel="nofollow"&gt;here&lt;/a&gt;!&lt;/p&gt;

  
    
    

    &lt;span class="m-1"&gt;output.mp4&lt;/span&gt;
    
  

  

  


&lt;h2&gt;
Our tech stack&lt;/h2&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/f171a08b66bbd0039498aa8a3f6c1ced5622ab237e5db267ca8f2f8f5ca817a8/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f707974686f6e2d342e737667"&gt;&lt;img src="https://camo.githubusercontent.com/f171a08b66bbd0039498aa8a3f6c1ced5622ab237e5db267ca8f2f8f5ca817a8/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f707974686f6e2d342e737667" title="Python" alt="Python Logo" width="70"&gt;&lt;/a&gt; 
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/e82da0bf915a6b7afce478f81d3a8c602d7d80a987871821c2a319ef1af589cf/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f646f636b65722e737667"&gt;&lt;img src="https://camo.githubusercontent.com/e82da0bf915a6b7afce478f81d3a8c602d7d80a987871821c2a319ef1af589cf/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f646f636b65722e737667" title="Docker" alt="Docker Logo" width="80"&gt;&lt;/a&gt; 
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/e389b106dc5824dba23cb4da292b5053e6c3d1760605ecdbfa2710d086968e30/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f617a7572652d322e737667"&gt;&lt;img src="https://camo.githubusercontent.com/e389b106dc5824dba23cb4da292b5053e6c3d1760605ecdbfa2710d086968e30/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f617a7572652d322e737667" title="Docker" alt="Azure Logo" width="80"&gt;&lt;/a&gt; 
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/7556b1a645de5ffc419acc30d58fdbd28e5a19bd14e045f8cb2d3531e2b1ab4c/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f67756e69636f726e2e737667"&gt;&lt;img src="https://camo.githubusercontent.com/7556b1a645de5ffc419acc30d58fdbd28e5a19bd14e045f8cb2d3531e2b1ab4c/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f67756e69636f726e2e737667" title="Docker" alt="Gunicorn Logo" width="100"&gt;&lt;/a&gt; 
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/c61346fb6ea6a25b03315c7a3655fdf3f0368efed773cc2cf393b3ff26a4a8d2/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f68746d6c2d312e737667"&gt;&lt;img src="https://camo.githubusercontent.com/c61346fb6ea6a25b03315c7a3655fdf3f0368efed773cc2cf393b3ff26a4a8d2/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f68746d6c2d312e737667" title="Docker" alt="HTML Logo" width="70"&gt;&lt;/a&gt; 
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/119b29ca4b9d31cf3969a94eb57fcfbbea0879b493c09c89dc6d4b7fb9e0dc37/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f6373732d332e737667"&gt;&lt;img src="https://camo.githubusercontent.com/119b29ca4b9d31cf3969a94eb57fcfbbea0879b493c09c89dc6d4b7fb9e0dc37/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f6373732d332e737667" title="Docker" alt="CSS Logo" width="70"&gt;&lt;/a&gt; 
&lt;a rel="noopener noreferrer" href="https://camo.githubusercontent.com/e0a32498daaa1846d9a28912df654f2b2cc0a1891f4cb964836bc71a3fbc3362/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f6c6f676f2d6a6176617363726970742e737667"&gt;&lt;img src="https://camo.githubusercontent.com/e0a32498daaa1846d9a28912df654f2b2cc0a1891f4cb964836bc71a3fbc3362/68747470733a2f2f63646e2e776f726c64766563746f726c6f676f2e636f6d2f6c6f676f732f6c6f676f2d6a6176617363726970742e737667" title="Docker" alt="JS Logo" width="70"&gt;&lt;/a&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The backend is built with Python Flask and containerized with Docker.&lt;/li&gt;
&lt;li&gt;Docker images are pushed to Azure Container Registry and deployed with Azure App Service&lt;/li&gt;
&lt;li&gt;User data are stored in Azure SQL Database&lt;/li&gt;
&lt;li&gt;Images are uploaded to Azure Storage Account and analyzed with Azure Computer Vision&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
Authors&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/andregri"&gt;andregri&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/CaptainMich"&gt;CaptainMich&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Dadigno"&gt;Dadigno&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/andregri/AiFame"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h3&gt;
  
  
  Azure Services we used
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kfs9oXQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbxjqx2yx9i1yuhqujny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kfs9oXQM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qbxjqx2yx9i1yuhqujny.png" alt="project diagram" width="560" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app deployed with App Service interacts with a SQL database to store user data and a storage blob to store the images uploaded by users.&lt;/p&gt;

&lt;p&gt;Whenever an image is pushed to the blob, Azure Computer Vision analyzes it to detect objects bounding box. Then, for each bounding box we used again Computer Vision to obtain the food name of the object.&lt;/p&gt;

&lt;p&gt;The CICD pipeline uses both GitHub Actions and Azure App Service.&lt;br&gt;
Every push or pull request on development branch triggers the workflow that builds and tests the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This is a basic workflow to help you get started with Actions&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ci&lt;/span&gt;

&lt;span class="c1"&gt;# Controls when the workflow will run&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Triggers the workflow on push or pull request events but only for the main branch&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dev&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;dev&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="c1"&gt;# Allows you to run this workflow manually from the Actions tab&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="c1"&gt;# A workflow run is made up of one or more jobs that can run sequentially or in parallel&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# This workflow contains a single job called "build"&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# The type of runner that the job will run on&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="c1"&gt;# Steps represent a sequence of tasks that will be executed as part of the job&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Python&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v2.3.1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="c1"&gt;# Version range or exact version of a Python version to use, using SemVer's version range syntax.&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3.9&lt;/span&gt;
          &lt;span class="c1"&gt;# The target architecture (x86, x64) of the Python interpreter.&lt;/span&gt;
          &lt;span class="na"&gt;architecture&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;x64&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;python -m pip install --upgrade pip&lt;/span&gt;
          &lt;span class="s"&gt;if [ -f requirements.txt ]; then pip install -r requirements.txt; fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every push on the main branch, the Docker image is built and pushed automatically to the Azure Container Registry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cd&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build-and-deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# checkout the repo&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Checkout&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;GitHub&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Action'&lt;/span&gt;
          &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@main&lt;/span&gt;

        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Login&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;via&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Azure&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CLI'&lt;/span&gt;
          &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/login@v1&lt;/span&gt;
          &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;creds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AZURE_CREDENTIALS }}&lt;/span&gt;

        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;push&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;image'&lt;/span&gt;
          &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/docker-login@v1&lt;/span&gt;
          &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;login-server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.REGISTRY_LOGIN_SERVER }}&lt;/span&gt;
            &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.REGISTRY_USERNAME }}&lt;/span&gt;
            &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.REGISTRY_PASSWORD }}&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;docker build . -t ${{ secrets.REGISTRY_LOGIN_SERVER }}/aifame --file Dockerfile.prod&lt;/span&gt;
            &lt;span class="s"&gt;docker push ${{ secrets.REGISTRY_LOGIN_SERVER }}/aifame&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to that, it is necessary to enable the "Continuous Deployment" option on App Service as show in the image below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZkuC0onc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dy597r9jyg5kuijfzga9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZkuC0onc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dy597r9jyg5kuijfzga9.png" alt="App Service Continuous Deployment" width="857" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below there is the list of all resources we used:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ik6oqSBe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ln9lzdff0dmngrkyesug.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ik6oqSBe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ln9lzdff0dmngrkyesug.png" alt="azure resources" width="880" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Authors
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/andregri"&gt;andregri&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/CaptainMich"&gt;CaptainMich&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Dadigno"&gt;Dadigno&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azuretrialhack</category>
      <category>python</category>
      <category>azure</category>
      <category>docker</category>
    </item>
    <item>
      <title>Explore how countries produce energy for MongoDB Atlas Hackathon</title>
      <dc:creator>Andrea Grillo</dc:creator>
      <pubDate>Sat, 01 Jan 2022 17:03:51 +0000</pubDate>
      <link>https://dev.to/andreagrillo96/explore-how-countries-produce-energy-4i2e</link>
      <guid>https://dev.to/andreagrillo96/explore-how-countries-produce-energy-4i2e</guid>
      <description>&lt;h3&gt;
  
  
  Overview of My Submission
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;climate change&lt;/strong&gt; is an important topic we should all care to protect our planet. So, I wanted to create a simple web application to explore how countries produce energy, if they rely on renewable energy or fossil fuels.&lt;/p&gt;

&lt;p&gt;To visit my web application click &lt;a href="https://secure-castle-44065.herokuapp.com/" rel="noopener noreferrer"&gt;here&lt;/a&gt;! Similarly to the TV show &lt;em&gt;Our Planet&lt;/em&gt;, I wanted to call my app &lt;em&gt;Our Energy&lt;/em&gt; because it is a resource we all should be care of!&lt;/p&gt;

&lt;p&gt;Below you can see the homepage:&lt;/p&gt;

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

&lt;p&gt;You can look the amount of MegaWatts of energy produced by a country. To find the countries in the Mongo Database I used &lt;a href="https://docs.atlas.mongodb.com/atlas-search/" rel="noopener noreferrer"&gt;&lt;strong&gt;Atlas Search&lt;/strong&gt; service&lt;/a&gt;. Below you can see the values for my country, &lt;a href="https://secure-castle-44065.herokuapp.com/country/Italy" rel="noopener noreferrer"&gt;Italy&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjtp3p8lldojwkezyzgr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzjtp3p8lldojwkezyzgr.png" alt="italy energy production"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, from the homepage you can explore the &lt;strong&gt;top 5 countries&lt;/strong&gt; producing energy using a particular renewable source. You can choose among solar, wind, waves and tidal, and hydro. Below there is a screenshot for the &lt;a href="https://secure-castle-44065.herokuapp.com/fuel/Wind" rel="noopener noreferrer"&gt;wind energy&lt;/a&gt;: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqu9dwtpbmp532ujhv5gq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqu9dwtpbmp532ujhv5gq.png" alt="top 5 wind"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Data preparation
&lt;/h3&gt;

&lt;p&gt;The original dataset was in &lt;code&gt;.csv&lt;/code&gt; format. Firstly I removed many columns that were not necessary to my scope to reduce the size. Then I converted it to a JSON file which is easy to be uploaded to MongoDB Atlas.&lt;/p&gt;

&lt;p&gt;Connecting to Atlas Cloud is as easy as connecting to any local database thank you to this &lt;a href="https://docs.mongodb.com/guides/cloud/connectionstring/" rel="noopener noreferrer"&gt;official guide&lt;/a&gt;. To upload the dataset onto Mongo Cloud I used literally one function: &lt;code&gt;insert_many()&lt;/code&gt;. You can explore the full code &lt;a href="https://github.com/andregri/OurEnergy/blob/main/db_preparation/upload.py" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atlas Search
&lt;/h3&gt;

&lt;p&gt;To search data by country I had to match the input string with the &lt;code&gt;country_long&lt;/code&gt; field of the dataset. I used the &lt;strong&gt;Atlas UI&lt;/strong&gt; to create an index with &lt;em&gt;static mapping&lt;/em&gt; for this field. You can refer to this &lt;a href="https://docs.atlas.mongodb.com/atlas-search/" rel="noopener noreferrer"&gt;guide&lt;/a&gt; to create one. &lt;/p&gt;

&lt;h3&gt;
  
  
  Aggregation pipeline
&lt;/h3&gt;

&lt;p&gt;The dataset consists of many power plants located in many countries. To retrieve a summary information for a certain country I exploited the power &lt;strong&gt;aggregation pipeline&lt;/strong&gt; feature of MongoDB. Look at this &lt;a href="https://github.com/andregri/OurEnergy/blob/main/db.py" rel="noopener noreferrer"&gt;code snippet&lt;/a&gt; that I use to find the 5 countries producing the biggest quantity of energy from a particular &lt;code&gt;fuel&lt;/code&gt; (oil, gas, wind, solar, etc..., renewable energy sources are considered fuels as well):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;aggregate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$match&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;primary_fuel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fuel&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="c1"&gt;# Accumulate capacity by fuel type
&lt;/span&gt;         &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$group&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$country_long&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;totCapacity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$sum&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$toDecimal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$capacity_mw&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
         &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$sort&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;totCapacity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$limit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;A &lt;strong&gt;pipeline&lt;/strong&gt; is made of many stages that performs different operations to extract the data we want from the database. The output of a stage is the input of the next stage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first step find all the entries whose field &lt;code&gt;'primary_fuel'&lt;/code&gt; matches the string &lt;code&gt;fuel&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$match&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;primary_fuel&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;fuel&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;This step groups the output of the previous step by country (using the field &lt;code&gt;country_long&lt;/code&gt;, the country name) and accumulate the energy production of a power plant. Up to now, we know the amount of wind energy produced by each country.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$group&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$country_long&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;totCapacity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$sum&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$toDecimal&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$capacity_mw&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;We sort the output in descending order
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$sort&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;totCapacity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;    
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Eventually, we limit the output to only 5 results
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;$limit&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And in the web app we can see the Top 5 countries producing that kind of energy. For instance, if you want to discover who are the 5 biggest producer of energy from &lt;a href="https://secure-castle-44065.herokuapp.com/fuel/Wave%20and%20Tidal" rel="noopener noreferrer"&gt;waves and tydal&lt;/a&gt; are:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fme054y8xm3s4zb0ttjyd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fme054y8xm3s4zb0ttjyd.png" alt="top 5 wave"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;It was exciting to produce a simple web application from scratch to production using Python and MongoDB.&lt;/p&gt;

&lt;p&gt;If you want to contribute to my project or propose some improvements, visit the &lt;a href="https://github.com/andregri/OurEnergy" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Submission Category:
&lt;/h3&gt;

&lt;p&gt;Choose Your Own Adventure&lt;/p&gt;
&lt;h3&gt;
  
  
  GitHub repository
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/andregri" rel="noopener noreferrer"&gt;
        andregri
      &lt;/a&gt; / &lt;a href="https://github.com/andregri/OurEnergy" rel="noopener noreferrer"&gt;
        OurEnergy
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Climate Care is Flask application made for the MongoDB Atlas Hackathon 2021
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🌍 OurEnergy&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;em&gt;OurEnergy&lt;/em&gt; is a web application to explore some meaningful data about the
&lt;a href="https://datasets.wri.org/dataset/globalpowerplantdatabase" rel="nofollow noopener noreferrer"&gt;Global Power Plant Dataset&lt;/a&gt;. You can explore either how each country is producing
energy or little charts comparing the top 5 countries that are distinguishing for
producing green energy 🌱&lt;/p&gt;
&lt;p&gt;&lt;a href="https://secure-castle-44065.herokuapp.com/" rel="nofollow noopener noreferrer"&gt;Live Demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/andregri/OurEnergyscreenshots/homepage.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fandregri%2FOurEnergyscreenshots%2Fhomepage.png" alt="OurEnergy Homepage"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🔧 Tech Stack&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Python Flask&lt;/li&gt;
&lt;li&gt;MongoDB Atlas&lt;/li&gt;
&lt;li&gt;Heroku&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;🔌 Run Locally&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Preparation of the dataset on MongoDB&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Environment variables:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;export&lt;/span&gt; MONGODB_URI=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&amp;lt;your connection string to MongoDB&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
&lt;span class="pl-k"&gt;export&lt;/span&gt; GPPDB_PATH=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;path/to/dataset/csvfile&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Do not write the extension '.csv'&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;For example my &lt;code&gt;GPPDB_PATH&lt;/code&gt; env variable for the file &lt;code&gt;./data/global_power_plant_database.csv&lt;/code&gt; is:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;export&lt;/span&gt; GPPDB_PATH=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;./data/global_power_plant_database&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Finally you can run two scripts to convert the dataset to JSON and to upload
it to MongoDB Atlas:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;python db_preparation/convert.py
python db_preparation/upload.py --cloud&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Run Flask app&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;FLASK_ENV=development FLASK_DEBUG=true FLASK_APP=app flask run
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Deploy to production&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file with the following variables:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;export&lt;/span&gt; MONGODB_URI=&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;&amp;lt;your&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/andregri/OurEnergy" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://datasets.wri.org/dataset/globalpowerplantdatabase" rel="noopener noreferrer"&gt;Global Power Plant Database&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>atlashackathon</category>
      <category>python</category>
      <category>flask</category>
      <category>mongodb</category>
    </item>
  </channel>
</rss>
