<?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: Larry Claman</title>
    <description>The latest articles on DEV Community by Larry Claman (@larryclaman).</description>
    <link>https://dev.to/larryclaman</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%2F367510%2F7d5c1496-cf82-4de7-b3fa-b57f0cc81f76.jpeg</url>
      <title>DEV Community: Larry Claman</title>
      <link>https://dev.to/larryclaman</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/larryclaman"/>
    <language>en</language>
    <item>
      <title>Querying for Azure Regional Pairs</title>
      <dc:creator>Larry Claman</dc:creator>
      <pubDate>Mon, 20 Apr 2020 17:17:25 +0000</pubDate>
      <link>https://dev.to/larryclaman/querying-for-azure-regional-pairs-4ac3</link>
      <guid>https://dev.to/larryclaman/querying-for-azure-regional-pairs-4ac3</guid>
      <description>&lt;p&gt;A teammate recently posted a question on our Team's channel, asking how to programmatically query to find out an Azure Region's pair.  Easy I thought - except it turns out, this isn't exposed in the standard PowerShell commands, nor in the Azure CLI.&lt;/p&gt;

&lt;p&gt;The PowerShell command &lt;strong&gt;Get-AzLocation&lt;/strong&gt; only returns the Location, DisplayName, and Providers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS C:\&amp;gt; Get-AzLocation|ft

Location           DisplayName          Providers
--------           -----------          ---------
eastasia           East Asia            {Microsoft.Media, Microsoft.HDInsight, Microsoft.SqlVirtualMachine, Microsoft.DevOps...}
southeastasia      Southeast Asia       {Microsoft.Media, Microsoft.HDInsight, Microsoft.DataShare, Microsoft.SqlVirtualMachine...}
centralus          Central US           {Microsoft.Media, Microsoft.HDInsight, Microsoft.SqlVirtualMachine, Microsoft.DevOps...}
eastus             East US              {Microsoft.Media, Microsoft.HDInsight, Microsoft.DataShare, Microsoft.SqlVirtualMachine...}
[snip]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Meanwhile, the Azure CLI returns more info, but not the pair:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PS C:\&amp;gt; az account list-locations
DisplayName           Latitude    Longitude    Name
--------------------  ----------  -----------  ------------------
East Asia             22.267      114.188      eastasia
Southeast Asia        1.283       103.833      southeastasia
Central US            41.5908     -93.6208     centralus
East US               37.3719     -79.8164     eastus
East US 2             36.6681     -78.3889     eastus2
West US               37.783      -122.417     westus
[snip]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All hope is not lost!  You can find the region's pair, but you need to query the Azure REST api directly, as documented at &lt;a href="https://docs.microsoft.com/en-us/rest/api/resources/Subscriptions/ListLocations"&gt;https://docs.microsoft.com/en-us/rest/api/resources/Subscriptions/ListLocations&lt;/a&gt;.  In the past, you'd need to fire up your favorite REST client (eg, &lt;a href="https://github.com/projectkudu/ARMClient"&gt;armclient&lt;/a&gt;, Vscode + &lt;a href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client"&gt;rest client extension&lt;/a&gt;, Postman, etc), but in exploring this, I learned an easier way:  You can now make Azure REST calls directly from the CLI!  Here's what that looks like:   &lt;em&gt;(Replace {yoursubid} with your specific subscription id)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az rest --method GET --uri https://management.azure.com/subscriptions/{yoursubid}/locations?api-version=2020-01-01 --output json
{
  "value": [
    {
      "displayName": "East US",
      "id": "/subscriptions/{yoursubid}/locations/eastus",
      "metadata": {
        "geographyGroup": "US",
        "latitude": "37.3719",
        "longitude": "-79.8164",
        "pairedRegion": [
          {
            "id": "/subscriptions/{yoursubid}/locations/westus",
            "name": "westus"
          }
        ],
        "physicalLocation": "Virginia",
        "regionCategory": "Recommended",
        "regionType": "Physical"
      },
      "name": "eastus",
      "regionalDisplayName": "(US) East US"
    },
[snip]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What's really cool is you can use the CLI's built-in jmespath query engine to filter and massage the results, eg: &lt;em&gt;(Column1 is the region, and Column2 is the pair)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az rest --method GET --uri https://management.azure.com/subscriptions/{yoursubid}/locations?api-version=2020-01-01 --output table --query 'value[].[name,metadata.pairedRegion[].name]'

Column1              Column2
-------------------  ----------------------
eastus               ['westus']
eastus2              ['centralus']
southcentralus       ['northcentralus']
westus2              ['westcentralus']
australiaeast        ['australiasoutheast']
[snip]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(I'm still working on my jmespath ninja skills, so there's still a little cleanup to be done on this table, but it gets the point across.)&lt;/p&gt;

</description>
      <category>azure</category>
    </item>
    <item>
      <title>Trigger Azure DevOps Build pipeline from Docker image update</title>
      <dc:creator>Larry Claman</dc:creator>
      <pubDate>Sat, 18 Apr 2020 00:52:37 +0000</pubDate>
      <link>https://dev.to/larryclaman/trigger-azure-devops-build-pipeline-from-docker-image-update-5d3i</link>
      <guid>https://dev.to/larryclaman/trigger-azure-devops-build-pipeline-from-docker-image-update-5d3i</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://larryclaman.github.io/post/2019-11-10-trigger-docker-build-azdo/"&gt;Larry Claman's Blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to trigger a build?
&lt;/h2&gt;

&lt;p&gt;I was recently asked how to trigger a classic (gui) Azure DevOps build pipeline when a Docker base image updates.  You might want to do this, for example, if your build pipeline includes unit, functional, or security tests.&lt;/p&gt;

&lt;p&gt;My immediate answer was "you can't."  However, after a little investigation and a little hacking, I was able to prototype a solution using the &lt;a href="https://docs.microsoft.com/en-us/azure/container-registry/container-registry-tutorial-base-image-update"&gt;automated trigger &amp;amp; build feature&lt;/a&gt; of Azure Container Registry (ACR).  The hint for how to do this was buried in the &lt;a href="https://github.com/MicrosoftDocs/azure-docs/issues/34480"&gt;Q&amp;amp;A&lt;/a&gt; on documentation page, where it's suggested to use a dummy image to trigger the AzDo pipeline.  Here's a walkthrough of how I did this:&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Repo &amp;amp; Pipeline
&lt;/h2&gt;

&lt;p&gt;As a sample repo, I used the canonical &lt;a href="https://dev.azure.com/larrydevopstest/_git/AzureVotingApp"&gt;Azure voting app&lt;/a&gt;, but I simplified it a bit to suit my needs. My Dockerfile is pretty simple; my goal is for the build pipeline to run whenever the base python:3.6-slim image is updated on Dockerhub.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1:  Create a dummy base image and task in ACR
&lt;/h3&gt;

&lt;p&gt;As I mentioned above, I'm going to build a dummy base image using ACR, and then use a webhook when this image updates to trigger my Azure DevOps pipeline.&lt;/p&gt;

&lt;p&gt;First, I'll need to follow the instructions &lt;a href="https://docs.microsoft.com/en-us/azure/container-registry/container-registry-tutorial-base-image-update"&gt;here&lt;/a&gt; to create a dummy base image and a task to update it when its reference base updates on Dockerhub.&lt;/p&gt;

&lt;p&gt;Dummy Dockerfile for base image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:3.6-slim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To start, build the base image in ACR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ACR_NAME=larrymsvoting
REPO="https://larrydevopstest@dev.azure.com/larrydevopstest/AzureVotingApp/_git/AzureVotingApp"
DOCKER_FILE="azure-vote/Dockerfile-pythonbase"

az acr build --registry $ACR_NAME -t baseimages/python-3.6-slim-base \
    --file $DOCKER_FILE $REPO

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



&lt;h3&gt;
  
  
  Step 2: Create a task
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az acr task create \
    --registry $ACR_NAME \
    --name taskpythonbase \
    -t baseimages/python-3.6-slim-base:{{.Run.ID}} \
    --arg REGISTRY_NAME=$ACR_NAME.azurecr.io \
    --context $REPO \
    --file Dockerfile-pythonbase \
    --commit-trigger-enabled false \
    -o table
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Assuming it runs successfully, you'll see output like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NAME            PLATFORM    STATUS    SOURCE REPOSITORY                                                                         TRIGGERS
--------------  ----------  --------  ----------------------------------------------------------------------------------------  ----------
taskpythonbase  linux       Enabled   https://larrydevopstest@dev.azure.com/larrydevopstest/AzureVotingApp/_git/AzureVotingApp  BASE_IMAGE
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Logic App
&lt;/h3&gt;

&lt;p&gt;Now comes the fun part: getting the base image update to trigger a build in Azure DevOps.  We'll start by creating a logic app.&lt;br&gt;
In the portal, create a logic app and give it a relevant name, eg 'pythonbasetrigger'.  In the Logic Apps Designer pane, use "When an HTTP Request is Received" as the trigger.&lt;/p&gt;

&lt;p&gt;Add a new step, then type 'Azure DevOps' in the search field, then choose 'Queue a new build' as the action.  After authenticating, choose the account name, project name, and build id (eg, pipleline).  Once it's saved, it should like like:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WyAKMNnj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vfhuzzx2tc6uh6f7q4be.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WyAKMNnj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vfhuzzx2tc6uh6f7q4be.png" alt="logic app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can test the logic app by pressing 'Run', which should kick off an Azure DevOps pipeline build.&lt;/p&gt;

&lt;p&gt;Finally, in your logic apps's first step 'When an HTTP request is received', find the post URL and copy it, as it will be needed for the next step.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: ACR webhook
&lt;/h2&gt;

&lt;p&gt;Next, we'll create an ACR webhook which fires whenever the base image updates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;URI=&amp;lt;webhook post url from prior step&amp;gt;

az acr webhook create -n pythonbasehook -r $ACR_NAME \
    --scope baseimages/python-3.6-slim-base \
    --actions push --uri $URI
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Enjoy!
&lt;/h2&gt;

&lt;p&gt;We've done it!  We now have a set up a set of integrations that does the following:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yLMfspvw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hrazfxxyvx183myqsxat.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yLMfspvw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hrazfxxyvx183myqsxat.png" alt="flow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6: Test
&lt;/h2&gt;

&lt;p&gt;Since the Dockerhub base image is only going to be updated periodically, you can test your integration by manually running a build in ACR:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;az acr build --registry $ACR_NAME -t baseimages/python-3.6-slim-base \
    --file $DOCKER_FILE $REPO
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If all is working, this should trigger a build in Azure DevOps.&lt;/p&gt;

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

&lt;p&gt;An alternative to using a webhook would be to use an Event Grid to trigger the Logic App.  This is slightly more work to set up, but it might better if you have a number of different pipelines that want to receive notifications when a base image updates.  With a webhook, you'd need to set up a trigger for each and every one of them.  Eventgrid, having a pubsub architecture, would fan-out one:many more effectively than webhooks.  &lt;/p&gt;

</description>
      <category>azure</category>
      <category>azuredevops</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
