<?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: Janne Mattila</title>
    <description>The latest articles on DEV Community by Janne Mattila (@janne_mattila).</description>
    <link>https://dev.to/janne_mattila</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%2F174458%2F7b8a6ac3-697a-4924-b291-a53cfe1e7664.jpeg</url>
      <title>DEV Community: Janne Mattila</title>
      <link>https://dev.to/janne_mattila</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/janne_mattila"/>
    <language>en</language>
    <item>
      <title>Debugging microservices running in Azure Kubernetes Service (AKS) using Azure Dev Spaces</title>
      <dc:creator>Janne Mattila</dc:creator>
      <pubDate>Tue, 10 Dec 2019 17:21:40 +0000</pubDate>
      <link>https://dev.to/janne_mattila/debugging-microservices-running-in-azure-kubernetes-service-aks-using-azure-dev-spaces-2d7i</link>
      <guid>https://dev.to/janne_mattila/debugging-microservices-running-in-azure-kubernetes-service-aks-using-azure-dev-spaces-2d7i</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Debugging microservices can be hard. Are you going to run all those services at your own development machine, or do you mock your dependencies? Wouldn't it be nice to just debug and work on single service and use other services directly from your Azure Kubernetes Service (AKS) cluster? Luckily, &lt;a href="https://docs.microsoft.com/en-us/azure/dev-spaces/"&gt;Azure Dev Spaces&lt;/a&gt; enables you to do just that.&lt;/p&gt;

&lt;p&gt;In this blog post I'm going to show how you can try it yourself. I'll show one demo application which I have been showing to my customers when I've wanted to explain how dev spaces works and how can you use it to improve your workflows. &lt;/p&gt;

&lt;p&gt;I recommend that you first check the official documentation pages &lt;a href="https://docs.microsoft.com/en-us/azure/dev-spaces/how-to/install-dev-spaces"&gt;how to install Azure Dev Spaces on AKS&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/en-us/azure/dev-spaces/how-to/install-dev-spaces#install-the-client-side-tooling"&gt;how to get client-side tooling installed&lt;/a&gt; to your local dev machine. With those instructions you should now have working AKS cluster with dev spaces enabled namespace that we can use in this example.&lt;/p&gt;

&lt;p&gt;Before we jump into my demo application, I want to still go through this diagram:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sj-FdQiv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/wejw8yll267rkihf59i3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sj-FdQiv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/wejw8yll267rkihf59i3.png" alt="Team development with dev spaces"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above diagram tries to illustrate more complex scenario with dev spaces. You can use dev spaces to share different microservices between your team members.&lt;br&gt;
In above example services &lt;code&gt;A&lt;/code&gt;, &lt;code&gt;B&lt;/code&gt;, &lt;code&gt;C&lt;/code&gt;, &lt;code&gt;D&lt;/code&gt;, &lt;code&gt;E&lt;/code&gt; and &lt;code&gt;F&lt;/code&gt; are baseline&lt;br&gt;
versions of the services. In this example these are running in dev spaces&lt;br&gt;
enabled namespace &lt;code&gt;integration&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Those baseline services are then overridden in feature specific dev space&lt;br&gt;
with services &lt;code&gt;feature-C&lt;/code&gt;, &lt;code&gt;feature-D&lt;/code&gt; and &lt;code&gt;feature-E&lt;/code&gt;. These are running&lt;br&gt;
in child dev space &lt;code&gt;integration/feature&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Developer working in this feature has created another child dev space to&lt;br&gt;
override one specific service with &lt;code&gt;feature-D-dev&lt;/code&gt; and that is running&lt;br&gt;
in child dev space &lt;code&gt;integration/feature/dev&lt;/code&gt;. This means that developer working on this individual service can debug and iterate on the code much faster.&lt;/p&gt;

&lt;p&gt;If you think that above would be helpful also in your development, then I recommend that you try it out.&lt;/p&gt;
&lt;h2&gt;
  
  
  Try this yourself
&lt;/h2&gt;

&lt;p&gt;This example application is &lt;code&gt;tiny-node-app&lt;/code&gt; and you can find it from GitHub:&lt;br&gt;
&lt;/p&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--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/JanneMattila"&gt;
        JanneMattila
      &lt;/a&gt; / &lt;a href="https://github.com/JanneMattila/tiny-node-app"&gt;
        tiny-node-app
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demonstrates how you can debug your microservices apps running Azure Kubernetes Service using Azure Dev Spaces
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;It's simple application and it has 3 different services &lt;code&gt;web&lt;/code&gt;, &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;db&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cpyvRHw4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rdl3g0ez1mrfmqtqd84j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cpyvRHw4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rdl3g0ez1mrfmqtqd84j.png" alt="web-api-db"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;web&lt;/code&gt; is frontend service which is exposed to internet and &lt;code&gt;api&lt;/code&gt; and &lt;code&gt;db&lt;/code&gt; are backend services and they are not exposed to internet. Call chain is simple and it goes directly as in above diagram: &lt;code&gt;web&lt;/code&gt; makes http request to &lt;code&gt;api&lt;/code&gt; service which then does next request to the &lt;code&gt;db&lt;/code&gt; service. Information then flows back and &lt;code&gt;web&lt;/code&gt; plots the data to the simple web view.&lt;/p&gt;

&lt;p&gt;In order to deploy this to your own Dev Spaces enabled AKS you can run following commands. &lt;em&gt;Note&lt;/em&gt;: This means that we now deploy our team shared &lt;code&gt;integration&lt;/code&gt; namespace directly from our development machine but in real life you should use &lt;a href="https://docs.microsoft.com/en-us/azure/dev-spaces/how-to/setup-cicd"&gt;Azure DevOps&lt;/a&gt; or &lt;a href="https://docs.microsoft.com/en-us/azure/dev-spaces/how-to/github-actions"&gt;GitHub Actions&lt;/a&gt; to do that. Here are the steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/JanneMattila/tiny-node-app.git
&lt;span class="nb"&gt;cd &lt;/span&gt;tiny-node-app

&lt;span class="c"&gt;# web&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;web
npm &lt;span class="nb"&gt;install
&lt;/span&gt;azds up &lt;span class="nt"&gt;--detach-after&lt;/span&gt; Listening

&lt;span class="c"&gt;# db&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ../db
npm &lt;span class="nb"&gt;install
&lt;/span&gt;azds up &lt;span class="nt"&gt;--detach-after&lt;/span&gt; Listening

&lt;span class="c"&gt;# api&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ../api
npm &lt;span class="nb"&gt;install
&lt;/span&gt;azds up &lt;span class="nt"&gt;--detach-after&lt;/span&gt; Listening
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you missed the url of the application (it was printed when &lt;code&gt;web&lt;/code&gt; was started) then you can get it using &lt;code&gt;azds&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;azds list-uris
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If you open that in your browser, you should see something like this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_IXxHRS4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0cfrb1zwwaa1miy0zj3u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_IXxHRS4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0cfrb1zwwaa1miy0zj3u.png" alt="homepage of the app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that you can see your namespace and service name directly in the url (in my example &lt;code&gt;demospace&lt;/code&gt; and actual exposed service &lt;code&gt;web&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;If you then click on that people icon next to the title you'll see this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7XBIY3Ub--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i7ialsh2ocooa9vxr906.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7XBIY3Ub--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/i7ialsh2ocooa9vxr906.png" alt="people view in the web app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can right away see that table does not contain data like it should.&lt;br&gt;
So now it's time to take our debugging gloves and try dev spaces out!&lt;/p&gt;

&lt;p&gt;Let's start debugging from our &lt;code&gt;api&lt;/code&gt; layer because it's hidden behind the &lt;code&gt;web&lt;/code&gt; layer and it tries to fetch data from the backend. We want to achieve this kind of debugging experience:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0efb4KX2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/29b60rglf9so7sdq0yld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0efb4KX2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/29b60rglf9so7sdq0yld.png" alt="debug api by creating private clone"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without dev spaces you would have to think how to debug this since &lt;code&gt;db&lt;/code&gt; is running inside the cluster and it's not available from your local development machine. Similarly, you would have to think that how would you flow exact same request to your &lt;code&gt;api&lt;/code&gt; from the &lt;code&gt;web&lt;/code&gt; service. &lt;/p&gt;

&lt;p&gt;Let's start by opening our Visual Studio Code workspace in Visual Studio Code from our repo root:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;code tiny-node-app.code-workspace
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This should enable required extensions (such as &lt;a href="https://marketplace.visualstudio.com/items?itemName=azuredevspaces.azds"&gt;Azure Dev Spaces&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;Now we have the code available and now we need to ask dev spaces to do the magic for us. We start that by using Visual Studio Command palette:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OgjJUxTp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j5osuwtdzx13nppoyk2i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OgjJUxTp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j5osuwtdzx13nppoyk2i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's use the "Redirect an existing Kubernetes service to my machine".&lt;/p&gt;

&lt;p&gt;Next we need to select service that we want to redirect to our development machine. Choose &lt;code&gt;api&lt;/code&gt; as we want to debug that specific service:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6RSSlV3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/v1j18rkfuyq7obb4oq1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6RSSlV3h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/v1j18rkfuyq7obb4oq1h.png" alt="choose service"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we need to select mode. In this case we want to debug our &lt;code&gt;api&lt;/code&gt; service without impacting anybody else in our team so therefore we'll choose "Clone" as our mode:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YjCXSFvO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cmvozfglhokwolwjrtjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YjCXSFvO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cmvozfglhokwolwjrtjc.png" alt="replace mode or clone mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since we chose clone it now asks which child dev space this clone should be now created (remember the diagram earlier in this blog post showing that you can use this to create multiple child dev spaces). In my demo I'll use my own developer specific namespace:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6iJnbCyb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4drrpp0jlipbgl1zwbof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6iJnbCyb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4drrpp0jlipbgl1zwbof.png" alt="choose child dev space"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next it will ask port to which the incoming traffic should be redirected:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FRRnhsnf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hmod8e7vzb24gstet8mo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FRRnhsnf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hmod8e7vzb24gstet8mo.png" alt="choose local service port"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose &lt;code&gt;3001&lt;/code&gt; to be our local service port (you'll see soon why):&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H2nwxW7l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6s89ptj0kqixbzpi6il6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H2nwxW7l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6s89ptj0kqixbzpi6il6.png" alt="choose port 3001 for local service port"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the selections dev spaces prepares the connections and then shows at the toolbar that it has successfully connected to that service:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h3sYVqPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/o8ghhca96nyfljpzjuko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h3sYVqPX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/o8ghhca96nyfljpzjuko.png" alt="dev spaces connected"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Note&lt;/em&gt;: Dev spaces might request that you let it modify your hosts file so that it's able to connect back to the other services such as &lt;code&gt;db&lt;/code&gt; in our demo scenario.&lt;/p&gt;

&lt;p&gt;Here's small snipped from my &lt;code&gt;hosts&lt;/code&gt; file (&lt;code&gt;C:\Windows\System32\drivers\etc\hosts&lt;/code&gt;) after dev spaces has modified it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Added by Azure DevSpaces
127.1.1.8 kubernetes.default.svc.cluster.local
127.1.1.8 kubernetes.default
127.1.1.8 kubernetes
# ...
127.1.1.2 db.demospace.svc.cluster.local
127.1.1.2 db.demospace
127.1.1.2 db
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;When we configured dev spaces, we set that application will run in port &lt;code&gt;3001&lt;/code&gt;. That is the default port in &lt;code&gt;api&lt;/code&gt; application when running locally. This means that you can just run your app normally (verify that you have correct profile selected at Visual Studio Code) and dev spaces will route incoming request to that port. When you click the debug button your application is started and it's ready to receive incoming calls:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TO-tVK0z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1ehhkpvwoj91pjtzs2kc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TO-tVK0z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1ehhkpvwoj91pjtzs2kc.png" alt="start debugging in Visual Studio Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To find out our correct application url for that given child namespace, you can click on the "Dev spaces" toolbar:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ttMK1kMf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oekkp04c6zu2s90fpr6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ttMK1kMf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oekkp04c6zu2s90fpr6a.png" alt="dev spaces toolbar in debug"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It opens menu which allows you navigate to your own child namespace.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TvWFvDqw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yuug2mti6q4vr3lub0e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TvWFvDqw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yuug2mti6q4vr3lub0e4.png" alt="dev spaces navigation to the child dev space specific web"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's set breakpoint to our service. Open &lt;code&gt;api\routes\users.js&lt;/code&gt; and set breakpoint to line &lt;code&gt;24&lt;/code&gt;. Now browse to the "people" view in your child dev space version of the app. You should now be paused in debugger in Visual Studio Code:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cPeD6odm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/duy5vdfa0fwp6g4qg1fz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cPeD6odm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/duy5vdfa0fwp6g4qg1fz.png" alt="breakpoint hit in Visual Studio Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this line &lt;em&gt;we have already received data from our &lt;code&gt;db&lt;/code&gt; backend which is still running inside the AKS cluster somewhere and not at our development machine&lt;/em&gt;! You can now freely debug and analyze the full http response from &lt;code&gt;db&lt;/code&gt; and step through the different lines to see what's going on in our service. You can now see that the actual bug is at the line &lt;code&gt;32&lt;/code&gt; which is clearly copy-paste from the above error scenario and it should really be &lt;code&gt;res.json(data);&lt;/code&gt; instead. You can now change that line and restart debugging and see the correct output at the view:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xOTLFvRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yh80b5qwu4vjwga3zzf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xOTLFvRk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yh80b5qwu4vjwga3zzf5.png" alt="correct people view at the app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now when you have fixed the bug you can create pull request etc. to finalize the actual bug fix. After it gets merged it will be them automatically deployed via CI/CD to the shared &lt;code&gt;integration&lt;/code&gt; dev space. &lt;/p&gt;

&lt;p&gt;You can also try the shared namespace specific application while you're debugging  your &lt;code&gt;api&lt;/code&gt; service and you'll see that it's not impacted at all. &lt;/p&gt;

&lt;p&gt;How does that routing work then? You can see all my source code in GitHub and analyze this further but one key part is the routing http header &lt;code&gt;azds-route-as&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D4BHpI7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/75fvlren26bpl3li5spf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D4BHpI7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/75fvlren26bpl3li5spf.png" alt="dev spaces routing http header"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This routing header makes it possible to route the requests between different services running in dev spaces. Of course if you have other dependent services (e.g. Azure Service Bus) and you communicate via them then you need to take that into consideration when building these debugging capabilities. &lt;/p&gt;

&lt;p&gt;I hope that I got you interested in trying out dev spaces. I really think it's big step forward. Not just in debugging front but also in &lt;a href="https://docs.microsoft.com/en-us/azure/dev-spaces/how-to/github-actions#view-the-child-space-with-your-changes"&gt;pull request and code reviews&lt;/a&gt; when you can use dev spaces for testing out the changes implemented right away. I think really good example is code reviewing tons of HTML and CSS changes. It's so much easier to open the deployed app and side-by-side see code changes and the actual running application.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to fail the demo (like I have done 😊)
&lt;/h4&gt;

&lt;p&gt;This blog post would be too official if I wouldn't also mention how I have managed to fail my fancy dev spaces demos. So word of caution (&lt;em&gt;note&lt;/em&gt; at the time of writing this blog post) you might get into trouble when showing this to people and you have zoomed in using Visual Studio Code because you won't find dev spaces command menu at the toolbar. I created issue about this to the dev spaces repository so hopefully in the future this won't happen.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/Azure/dev-spaces/issues/249"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg"&gt;
      &lt;span class="issue-title"&gt;
        VS Code extension and long text in toolbar causes dev spaces to disappear
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#249&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/JanneMattila"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s---tJYq1IX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars3.githubusercontent.com/u/2357647%3Fv%3D4" alt="JanneMattila avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/JanneMattila"&gt;JanneMattila&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/Azure/dev-spaces/issues/249"&gt;&lt;time&gt;Nov 27, 2019&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Dev spaces has quite long text in toolbar when connected:
&lt;a href="https://user-images.githubusercontent.com/2357647/69716030-ed34d400-1111-11ea-8a35-f81be416a166.png" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SGHzc2Kj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2357647/69716030-ed34d400-1111-11ea-8a35-f81be416a166.png" alt="Connected image"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately this means that if you zoom even a bit in VS Code your dev spaces functionality disappears:
&lt;a href="https://user-images.githubusercontent.com/2357647/69716078-03db2b00-1112-11ea-927e-7cf35e67c45b.png" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--50ZX60s1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2357647/69716078-03db2b00-1112-11ea-927e-7cf35e67c45b.png" alt="Dev spaces hidden"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This means that you cannot access easily "Go to ..." functionality:
&lt;a href="https://user-images.githubusercontent.com/2357647/69716167-2ff6ac00-1112-11ea-90a6-073a510ccf08.png" rel="nofollow"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vqTcD1Pe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-images.githubusercontent.com/2357647/69716167-2ff6ac00-1112-11ea-90a6-073a510ccf08.png" alt="go to"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is quite confusing for end user so maybe better option would be clip that in case it doesn't fit in long text mode (believe me I was confused when given demo and couldn't find the button I was looking for 😆).&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Azure/dev-spaces/issues/249"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>azure</category>
      <category>devspaces</category>
      <category>microservices</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Azure PowerShell and ARM template deployment from GitHub actions</title>
      <dc:creator>Janne Mattila</dc:creator>
      <pubDate>Wed, 28 Aug 2019 19:35:04 +0000</pubDate>
      <link>https://dev.to/janne_mattila/azure-powershell-and-arm-template-deployment-from-github-actions-2038</link>
      <guid>https://dev.to/janne_mattila/azure-powershell-and-arm-template-deployment-from-github-actions-2038</guid>
      <description>&lt;p&gt;Earlier this month &lt;a href="https://github.blog/2019-08-08-github-actions-now-supports-ci-cd/"&gt;GitHub Actions support for CI/CD was announced&lt;/a&gt;. After that I have been thinking that this is something I need to learn more. So I decided to check how easy it would be to add Azure PowerShell support (which I can then use for my ARM template deployments). There was already az cli action available: &lt;br&gt;
&lt;/p&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--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Azure"&gt;
        Azure
      &lt;/a&gt; / &lt;a href="https://github.com/Azure/actions"&gt;
        actions
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Automate your GitHub workflows using Azure Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
GitHub Actions for deploying to Azure&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://help.github.com/en/articles/about-github-actions"&gt;GitHub Actions&lt;/a&gt;  gives you the flexibility to build an automated software development lifecycle workflow.&lt;/p&gt;
&lt;p&gt;With &lt;a href="https://docs.microsoft.com/azure/developer/github/" rel="nofollow"&gt;GitHub Actions for Azure&lt;/a&gt; you can create workflows that you can set up in your repository to build, test, package, release and &lt;strong&gt;deploy&lt;/strong&gt; to Azure. &lt;a href="http://aka.ms/GitHubonAzure" rel="nofollow"&gt;Learn more about all other integrations with Azure.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Get started today with a &lt;a href="https://azure.com/free/open-source" rel="nofollow"&gt;free Azure account&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;To easily create GitHub CI/CD workflows targeting Azure, use our &lt;a href="https://github.com/Azure/actions-workflow-samples"&gt;Azure starter templates&lt;/a&gt; to deploy your apps created with popular languages and frameworks such as .NET, Node.js, Java, PHP, Ruby or Python, in containers or running on any operating system. Also the individual Action repos have a sample workflow included in their Readme file to help you quickly get started.&lt;/p&gt;
&lt;p&gt;Please try out the &lt;a href="https://docs.microsoft.com/azure/developer/github/github-actions" rel="nofollow"&gt;GitHub Actions for Azure&lt;/a&gt; and share your feedback via Twitter on &lt;a href="https://twitter.com/azuredevops" rel="nofollow"&gt;@Azure&lt;/a&gt;. If you encounter a problem, please open an issue on…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Azure/actions"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
 

&lt;p&gt;But I wanted to replicate similar setup that I've used in Azure DevOps for many years. Therefore I decided to try to create my own action (and at the same time of course learn how these actions work). &lt;/p&gt;

&lt;p&gt;I created GitHub repository for my actions: &lt;br&gt;
&lt;/p&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--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/JanneMattila"&gt;
        JanneMattila
      &lt;/a&gt; / &lt;a href="https://github.com/JanneMattila/actions"&gt;
        actions
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      GitHub actions for Azure PowerShell and ARM template deployment
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Azure PowerShell action&lt;/h1&gt;
&lt;p&gt;You can use this GitHub action for executing Azure PowerShell in your own GitHub workflows
Similarly as &lt;a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-powershell?view=azure-devops" rel="nofollow"&gt;Azure PowerShell task&lt;/a&gt; in
Azure DevOps.&lt;/p&gt;
&lt;p&gt;Primary use case is to call ARM template deployments using &lt;code&gt;deploy.ps1&lt;/code&gt; (deployment entrypoint)
to make your template deployments easy but you can of course use this for
any Azure automation scenarios you might on your mind.&lt;/p&gt;
&lt;p&gt;Read more about it in &lt;a href="https://dev.to/janne_mattila/azure-powershell-and-arm-template-deployment-from-github-actions-2038" rel="nofollow"&gt;this blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
Example&lt;/h3&gt;
&lt;p&gt;Here's small &lt;a href="https://github.com/JanneMattila/AzurePwshARMActionDemo/blob/master/.github/workflows/main.yml"&gt;example&lt;/a&gt; how to execute Azure PowerShell in your own workflow:&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml"&gt;&lt;pre&gt;&lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;Azure Deployment example&lt;/span&gt;
&lt;span class="pl-ent"&gt;on&lt;/span&gt;: &lt;span class="pl-s"&gt;[push]&lt;/span&gt;
&lt;span class="pl-ent"&gt;jobs&lt;/span&gt;
  &lt;span class="pl-ent"&gt;build-and-deploy&lt;/span&gt;:
    &lt;span class="pl-ent"&gt;runs-on&lt;/span&gt;: &lt;span class="pl-s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="pl-ent"&gt;steps&lt;/span&gt;:
    - &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;actions/checkout@v1&lt;/span&gt;

    - &lt;span class="pl-ent"&gt;uses&lt;/span&gt;: &lt;span class="pl-s"&gt;jannemattila/actions/azurepowershell@master&lt;/span&gt;
      &lt;span class="pl-ent"&gt;with&lt;/span&gt;:
        &lt;span class="pl-ent"&gt;creds&lt;/span&gt;: &lt;span class="pl-s"&gt;${{ secrets.AZURE_CREDENTIALS }}&lt;/span&gt;
        
    - &lt;span class="pl-ent"&gt;name&lt;/span&gt;: &lt;span class="pl-s"&gt;Azure PowerShell &amp;amp; ARM template deployment&lt;/span&gt;
      &lt;span class="pl-ent"&gt;run&lt;/span&gt;: &lt;span class="pl-s"&gt;./deploy/deploy.ps1 -ResourceGroupName "pwsh-dev-rg" -Location "North Europe"&lt;/span&gt;
      &lt;span class="pl-ent"&gt;shell&lt;/span&gt;: &lt;span class="pl-s"&gt;pwsh&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example you first checkout your codebase and then execute &lt;code&gt;/deploy/deploy.ps1&lt;/code&gt;
PowerShell script…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/JanneMattila/actions"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
 I looked  the az cli repository so that I would better understand the implementation details of their action. I decided to reuse their login instructions so that you can easily jump between az cli and Azure PowerShell. After learning the setup from az cli repository I decided to use a bit simpler setup. It means that I didn't use the components that are provided in the &lt;a href="https://github.com/actions/toolkit"&gt;GitHub Action Toolkit&lt;/a&gt; but instead I just implemented simple 45 line solution that consist only 3 files. But clearly toolkit repository is the place to go when you're doing some serious development for your actions. 

&lt;p&gt;When I had my Azure PowerShell action ready I then created repository for demo application: &lt;br&gt;
&lt;/p&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--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/JanneMattila"&gt;
        JanneMattila
      &lt;/a&gt; / &lt;a href="https://github.com/JanneMattila/AzurePwshARMActionDemo"&gt;
        AzurePwshARMActionDemo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Demo how to use Azure PowerShell GitHub action to deploy ARM template using PowerShell.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Azure PowerShell ARM template deployment using action demo&lt;/h1&gt;
&lt;p&gt;Demo how to use Azure PowerShell GitHub action to deploy
ARM template using PowerShell.&lt;/p&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/JanneMattila/AzurePwshARMActionDemo"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;It has my favorite setup from Azure infrastructure point of view:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BZSoD3wT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2f0ef7phnoe7wd12t24e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BZSoD3wT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2f0ef7phnoe7wd12t24e.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That of course means &lt;code&gt;deploy&lt;/code&gt; folder and &lt;code&gt;deploy.ps1&lt;/code&gt; and &lt;code&gt;azuredeploy*.json&lt;/code&gt; files. This demo doesn't (yet?) have any application code in it but for example there are already actions to manage web apps so it would be easy thing to add:&lt;br&gt;
&lt;/p&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--vJ70wriM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://practicaldev-herokuapp-com.freetls.fastly.net/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Azure"&gt;
        Azure
      &lt;/a&gt; / &lt;a href="https://github.com/Azure/appservice-actions"&gt;
        appservice-actions
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Enable GitHub developers to deploy to Azure WebApps using GitHub Actions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;IMPORTANT NOTICE:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Actions hosted in this repo are now moved to new GitHub repositories. Please update your existing workflows with the new actions as these old actions will be ARCHIVED and will not receive any updates. Refer to &lt;a href="https://github.com/Azure/actions"&gt;https://github.com/Azure/actions&lt;/a&gt; for updated action repo details.&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;For example, the action &lt;code&gt;azure/appservice-actions/webapp@master&lt;/code&gt; should be replaced with &lt;code&gt;azure/webapps-deploy@v1&lt;/code&gt; in your workflows.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Old Action&lt;/th&gt;
&lt;th&gt;New Action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://github.com/Azure/webapps-deploy"&gt;Azure WebApp&lt;/a&gt; (Windows / Linux WebApps)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;azure/appservice-actions/webapp@master&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;azure/webapps-deploy@v1&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://github.com/Azure/webapps-container-deploy"&gt;Azure Web app for containers&lt;/a&gt; (Single / multi-container apps)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;azure/appservice-actions/webapp-container@master&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;azure/webapps-container-deploy@v1&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h1&gt;
Contributing&lt;/h1&gt;
&lt;p&gt;This project welcomes contributions and suggestions.  Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit &lt;a href="https://cla.opensource.microsoft.com" rel="nofollow"&gt;https://cla.opensource.microsoft.com&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment)…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Azure/appservice-actions"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Those files under &lt;code&gt;deploy&lt;/code&gt; folder are exactly the same kind of ones I have been talking and presenting last years. Next step is to create new workflow that uses my previously created Azure PowerShell action. Here's example &lt;a href="https://github.com/JanneMattila/AzurePwshARMActionDemo/blob/master/.github/workflows/main.yml"&gt;worklow&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Azure Deployment&lt;/span&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;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="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@v1&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;jannemattila/actions/azurepowershell@master&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="s"&gt;Azure PowerShell &amp;amp; ARM template deployment&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./deploy/deploy.ps1 -ResourceGroupName "pwsh-dev-rg" -Location "North Europe"&lt;/span&gt;
      &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pwsh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Important part is &lt;code&gt;jannemattila/actions/azurepowershell@master&lt;/code&gt; which means that I now reuse the action in my other repository in this workflow. So now it's suddenly super easy to user Azure PowerShell in your actions. That's the last step in my above workflow.&lt;/p&gt;

&lt;p&gt;Remember that you need to have the Azure credentials correctly set before the workflow can even work:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BdlU4-8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/k51isnxwjhd2ppn06nyl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BdlU4-8y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/k51isnxwjhd2ppn06nyl.png" alt="Azure credentials managed in secrets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Above workflow starts automatically based on event: &lt;code&gt;on: [push]&lt;/code&gt; (in workflow definition). I can also view my worklow executions under Actions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IpfpJPbd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/eo282thqzhwv7xku4b5q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IpfpJPbd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/eo282thqzhwv7xku4b5q.png" alt="Workflow runs visible under Actions menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can further drill-down to the details of each run: &lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dZOtBiXD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/p4flh6y0nbpef6jkq4hw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dZOtBiXD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/p4flh6y0nbpef6jkq4hw.png" alt="Workflow execution log"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And since I'm using ARM template deployments inside my PowerShell file I can see my deployments in Azure Portal as well:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_LFNwYyC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/o003umhsdsp3m3c7n9uq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_LFNwYyC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/o003umhsdsp3m3c7n9uq.png" alt="Resource group deployments in Azure Portal"&gt;&lt;/a&gt;&lt;br&gt;
That weird looking deployment name is coming from &lt;code&gt;GITHUB_SHA&lt;/code&gt; environment variable which maps to the commit SHA in that repository. It means that you can fully backtrack to the actual change and investigate what has happened in detail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kd"&gt;master&lt;/span&gt; ≡&lt;span class="o"&gt;]&lt;/span&gt; # &lt;span class="kd"&gt;git&lt;/span&gt; &lt;span class="kd"&gt;checkout&lt;/span&gt; &lt;span class="m"&gt;933307&lt;/span&gt;&lt;span class="kd"&gt;a62df143ccfebab4aadd5925af22484d9c&lt;/span&gt; &lt;span class="na"&gt;-b &lt;/span&gt;&lt;span class="kd"&gt;investigate&lt;/span&gt;&lt;span class="na"&gt;-dev
&lt;/span&gt;&lt;span class="kd"&gt;Switched&lt;/span&gt; &lt;span class="kd"&gt;to&lt;/span&gt; &lt;span class="kd"&gt;a&lt;/span&gt; &lt;span class="kd"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;branch&lt;/span&gt; &lt;span class="s1"&gt;'investigate-dev'&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="kd"&gt;investigate&lt;/span&gt;&lt;span class="na"&gt;-dev&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; # &lt;span class="kd"&gt;git&lt;/span&gt; &lt;span class="kd"&gt;log&lt;/span&gt;
&lt;span class="kd"&gt;commit&lt;/span&gt; &lt;span class="m"&gt;933307&lt;/span&gt;&lt;span class="kd"&gt;a62df143ccfebab4aadd5925af22484d9c&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;HEAD&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;investigate&lt;/span&gt;&lt;span class="na"&gt;-dev&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;Author&lt;/span&gt;: &lt;span class="kd"&gt;Janne&lt;/span&gt; &lt;span class="kd"&gt;Mattila&lt;/span&gt;
&lt;span class="kd"&gt;Date&lt;/span&gt;:   &lt;span class="kd"&gt;Wed&lt;/span&gt; &lt;span class="kd"&gt;Aug&lt;/span&gt; &lt;span class="m"&gt;28&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;:37:24 &lt;span class="m"&gt;2019&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="m"&gt;0300&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I hope you find this post interesting!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; If you thought that I managed to do this in one go... well no 😊:&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9-PLtUHI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/iq7h22b0faemqy14d1l9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9-PLtUHI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/iq7h22b0faemqy14d1l9.png" alt="Trial &amp;amp; error implementation"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>azure</category>
      <category>powershell</category>
      <category>arm</category>
    </item>
    <item>
      <title>To ARM, or not to ARM, that is the question</title>
      <dc:creator>Janne Mattila</dc:creator>
      <pubDate>Thu, 13 Jun 2019 18:51:02 +0000</pubDate>
      <link>https://dev.to/janne_mattila/to-arm-or-not-to-arm-that-is-the-question-420i</link>
      <guid>https://dev.to/janne_mattila/to-arm-or-not-to-arm-that-is-the-question-420i</guid>
      <description>&lt;p&gt;Over the last few years I have got this same question &lt;em&gt;maaaany&lt;/em&gt; times. &lt;br&gt;
It's all about how do choose your Infrastructure-as-Code (IaC) solution when you're working with Azure. These questions come in different shapes and forms but many of them can be summarized into this simple question:&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;Should I use &lt;strong&gt;&amp;lt;placeholder&amp;gt;&lt;/strong&gt; instead of ARM templates?&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;Of course you can replace &lt;strong&gt;&amp;lt;placeholder&amp;gt;&lt;/strong&gt; with different options but most commonly offered ones are Terraform and Azure CLI based solutions.&lt;/p&gt;

&lt;p&gt;Typically people expect that I give them one simple answer like "&lt;em&gt;do this or do that&lt;/em&gt;" but I don't think this is one of those questions that can be answered like that. &lt;/p&gt;

&lt;p&gt;Let's start from the existing experience within your development team. Is there already people that know one of these options better than others? Is it single person or are there even more people with similar expertise? Do you plan to reuse single applications IaC assets to different applications or are you actually purchasing these different applications from different vendors and they bring their expertise always to the table and you don't want or can't be too much involved with that? Etc.&lt;/p&gt;

&lt;p&gt;Above expertise and experience related questions can already mean that you decide to re-use existing knowledge because that enables you to move faster. I actually compare this often to programming language selection in software development: If you know e.g. Node.js well then why would you use e.g. Python in your next app if there is nothing pushing you to that direction (and of course you can swap these programming languages with any programming languages in this example).&lt;/p&gt;

&lt;p&gt;If you don't have expertise or you are looking to evaluate these different options then I highly recommend you to try out ARM templates. There are couple of reasons which you should know before choosing one or another. &lt;/p&gt;

&lt;p&gt;Let's first compare three different simple deployments for (as simple resource as) Application Insights and see how the resource groups look after the deployment.&lt;/p&gt;

&lt;p&gt;Azure CLI method (&lt;a href="https://docs.microsoft.com/en-us/cli/azure/ext/application-insights/monitor/app-insights/component?view=azure-cli-latest#ext-application-insights-az-monitor-app-insights-component-create"&gt;example&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9K7VS0B4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3uavybvpfs3hrm46z6u8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9K7VS0B4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3uavybvpfs3hrm46z6u8.png" alt="Azure CLI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terraform method (&lt;a href="https://www.terraform.io/docs/providers/azurerm/r/application_insights.html"&gt;example&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ke7FlU2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bpkzbd7ppzdka96i7zou.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ke7FlU2l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/bpkzbd7ppzdka96i7zou.png" alt="Terraform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ARM template method (&lt;a href="https://gist.github.com/JanneMattila/2293534f4f8d5e2d0303bec8e353fc21"&gt;example&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--225hufRt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/osu8a4ui7kczrxc8kq3c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--225hufRt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/osu8a4ui7kczrxc8kq3c.png" alt="ARM template"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay so the end result looks the same. Or does it? Can you spot the difference? If you take a closer look at the ARM template deployment screenshot you should notice &lt;code&gt;Deployments: 1 Succeeded&lt;/code&gt; (top right). This is important difference between these different deployment methods. ARM template deployments update the resource group about the deployment and thus it's capable of showing history of these deployments and details of each deployment. Read more about template deployment from &lt;a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/resource-group-overview#template-deployment"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This might look like a small thing but if you then combine it with deployments from Azure DevOps you have now easy way to map these two together. &lt;/p&gt;

&lt;p&gt;See "Dev" environment deployments for our demo application called "app" in Azure Portal (you can derive "Dev" directly from resource group naming &lt;em&gt;serviceshortname-environment-rg&lt;/em&gt;):&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hFlyXE4Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fz55n3cjlvu3bte2bf1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hFlyXE4Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/fz55n3cjlvu3bte2bf1h.png" alt="Azure Portal deployments"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See "Dev" environment deployment in Azure DevOps side:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ReKysaq4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hz2mvnveq4jwm45mhdq8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ReKysaq4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hz2mvnveq4jwm45mhdq8.png" alt="Azure DevOps Releases"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And as you can see they map directly one-to-one.&lt;/p&gt;

&lt;p&gt;This becomes extremely handy when &lt;em&gt;PIIP&lt;/em&gt; hits the fan and you're troubleshooting this from Azure side and you need to quickly identify the actual deployment that has been done for the application. With this solution it's trivial to see what is the last deployment done and when for production environment:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GM54mTld--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/w4vthp38b8if835mdg3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GM54mTld--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/w4vthp38b8if835mdg3m.png" alt="Production deployment history"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This enables you to quickly jump into Azure DevOps side and see the content of the release and difference between previous and current release from source control and work item perspectives.&lt;/p&gt;



&lt;p&gt;If you still decide to use Azure CLI script based deployment then they typically follow this pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;add resource x&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;add resource y&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;add resource z&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;etc.&lt;/p&gt;

&lt;p&gt;Have you thought what happens if you decide to get rid of &lt;em&gt;resource y&lt;/em&gt;? You have to get rid of it manually since the script doesn't magically remove it (unless you have code that does that). And you should not even have access rights to production to do removal (and not to even think how scary and risky that operation would be!). Terraform and ARM template deployments do manage this situation correctly. Just remember to use &lt;code&gt;-Mode Complete&lt;/code&gt; in your ARM template deployment for the &lt;a href="https://docs.microsoft.com/en-us/azure/azure-resource-manager/deployment-modes"&gt;deployment mode&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;New-AzResourceGroupDeployment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-DeploymentName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$deploymentName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-TemplateFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$Template&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;additionalParameters&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-Mode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Complete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;-Verbose&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This means that resources that are not anymore part of your template will be removed automatically from the target resource group.&lt;/p&gt;




&lt;p&gt;One other comment I hear a lot is that "&lt;em&gt;ARM templates are static&lt;/em&gt;" and that "&lt;em&gt;there is no place for custom logic in them&lt;/em&gt;". I agree and I think it's a good thing. I like my ARM templates nicely controlled via parameters but otherwise they are just plain static files. But that's also the reason why I always bundle PowerShell &lt;code&gt;deploy.ps1&lt;/code&gt; file next to them (and here you can swap PowerShell to e.g. Bash). I think this makes good combination between these two: PowerShell is the entrypoint for the deployment and actual infrastructure assets are described in the actual ARM templates. This also enables very nice development experience. Imagine that you get new developer to the team and they want to spin up your infrastructure to their sandbox subscription. This is what they have to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nf"&gt;Login-AzAccount&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Select-AzSubscription&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SubscriptionName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;YourSubName&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nf"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\YourPathToApp\deploy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;\deploy.ps1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Isn't that crazy easy? It's easy because &lt;code&gt;deploy.ps1&lt;/code&gt; has meaningful default values for the deployment. See example of this kind of setup from &lt;a href="https://github.com/JanneMattila/118-FrontDoorApp/blob/master/deploy/deploy.ps1#L1-L21"&gt;here&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Now developer doesn't have to know/remember how to set up the parameters correctly to the &lt;code&gt;New-AzResourceGroupDeployment&lt;/code&gt; because all these are handled inside the &lt;code&gt;deploy.ps1&lt;/code&gt; file. And of course all the parameters that needs to be overridden per environment can be overridden by providing parameter value to it.&lt;/p&gt;

&lt;p&gt;Above also means that you can use this same method in your deployment pipelines. So instead of this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z9k-cqnd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/86u4y3q8vc33utmqemhd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z9k-cqnd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/86u4y3q8vc33utmqemhd.png" alt="Resource group deployment task"&gt;&lt;/a&gt;&lt;br&gt;
(screenshot is clipped since it's soooo long!)&lt;/p&gt;

&lt;p&gt;You can just use this:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aESpkiSS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sb9e7a9w3i5hn8jrnl98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aESpkiSS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sb9e7a9w3i5hn8jrnl98.png" alt="deployment using deploy.ps1"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;I hope that I managed to demonstrate that you should give ARM a spin if you haven't previously tried it. Or at least you now should know why I like ARM. To summarize:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not underestimate the power of &lt;del&gt;Dark side&lt;/del&gt; ARM templates!&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>azure</category>
      <category>arm</category>
      <category>automation</category>
      <category>infrastructureascode</category>
    </item>
  </channel>
</rss>
