<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[ankurcharan]]></title><description><![CDATA[ankurcharan]]></description><link>https://ankurcharan.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Thu, 05 Nov 2026 02:17:40 GMT</lastBuildDate><atom:link href="https://ankurcharan.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Singleton Pattern in C#]]></title><description><![CDATA[The singleton pattern is a creational design pattern that restricts the instantiation of a class to a single object.All singleton implementation have 4…]]></description><link>https://ankurcharan.hashnode.dev/singleton-pattern-in-csharp</link><guid isPermaLink="true">https://ankurcharan.hashnode.dev/singleton-pattern-in-csharp</guid><category><![CDATA[C#]]></category><category><![CDATA[c sharp]]></category><category><![CDATA[design patterns]]></category><category><![CDATA[Design]]></category><category><![CDATA[LLD]]></category><dc:creator><![CDATA[Ankur Charan]]></dc:creator><pubDate>Fri, 20 Jun 2025 11:30:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1750286590502/5abbbe4a-70e5-44d4-98f5-60023595f91f.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The singleton pattern is a creational design pattern that restricts the instantiation of a class to a single object.<br />All singleton implementation have 4 common characteristics</p>
<ul>
<li><p>A single default (parameter less) private constructor.<br />  It prevents other classes from instantiating it. It also prevent subclassing. If it gets subclasses, then those classes can create an instance and pattern is violated. Factory pattern can be used if you need single instance of the base type, but the exact type is known until runtime.</p>
</li>
<li><p>The class is sealed. Unnecessary, due to the above point, but may help the JIT to optimise.</p>
</li>
<li><p>A static variable which holds a reference to the single created instance.</p>
</li>
<li><p>A public static means of getting the reference to the single created instance</p>
</li>
</ul>
<h2 id="heading-naive-singleton">Naive Singleton</h2>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">NaiveSingleton</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> NaiveSingleton? _instance;

    <span class="hljs-comment">// private constructor to prevent instantiation from outside</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">NaiveSingleton</span>(<span class="hljs-params"></span>)</span> { }

    <span class="hljs-comment">// public method to get the instance of the singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> NaiveSingleton <span class="hljs-title">GetInstance</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (_instance == <span class="hljs-literal">null</span>)
        {
            _instance = <span class="hljs-keyword">new</span> NaiveSingleton();
        }
        <span class="hljs-keyword">return</span> _instance;
    }
}
</code></pre>
<p>This particular method isn’t thread safe. Two different threads can evaluate <code>_instance == null</code> as <code>true</code> and then both of those threads will create a new instance of the Singleton.</p>
<h2 id="heading-thread-safe-using-double-check-locking">Thread Safe Using Double-Check Locking</h2>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton? _instance;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">object</span> _lock = <span class="hljs-keyword">new</span> <span class="hljs-keyword">object</span>();

    <span class="hljs-comment">// private constructor to prevent instantiation from outside</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span>(<span class="hljs-params"></span>)</span> { }

    <span class="hljs-comment">// Public method to get the instance of the singleton</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">GetInstance</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (_instance == <span class="hljs-literal">null</span>)
        {
            <span class="hljs-keyword">lock</span> (_lock)
            {
                <span class="hljs-keyword">if</span> (_instance == <span class="hljs-literal">null</span>)
                {
                    _instance = <span class="hljs-keyword">new</span> Singleton();
                }
            }
        }
        <span class="hljs-keyword">return</span> _instance;
    }
}
</code></pre>
<p>Imagine that the program has just been launched.<br />Since, there's no Singleton instance yet, multiple threads can simultaneously pass the first <code>if (_instance == null)</code> conditional and reach to the point where it request a lock on the object <code>lock(_lock)</code> almost at the same time. The first of them will acquire lock and will proceed further, while the rest will wait here.<br />The first thread to acquire the lock, reaches the second <code>if (_instance == null)</code>conditional, goes inside and creates the Singleton instance. Once it leaves the lock block, a thread that might have been waiting for the lock release may then enter this section. But since the Singleton field is already initialized, the thread won't create a new object.</p>
<p>Sometimes, you might find the first conditional missing and directly locking the object. But this attempts to reduce the overhead of locking by first checking if the instance exists outside of the lock, and only locking if it's not instantiated already.</p>
<p><strong>Volatile with Java</strong></p>
<p>It doesn't work in Java. Odd thing to mention here, but if there’s a chances you’ll be writing playing around Java too.<br />Java allowed instruction reordering by Java compiler. So another thread could see <code>_instance != null</code> before the constructor is finished running, leading to strange bugs like using an incompletely constructed object. (chatgpt if you’re curious here).<br />To prevent this redording you must use <code>volatile</code> keyword in Java to prevent this reordering.</p>
<p>for your reference, java code with double check locking and using volatile keyword.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">volatile</span> Singleton instance;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>{ }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">synchronized</span> (Singleton.class) {
                <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
                    instance = <span class="hljs-keyword">new</span> Singleton();
                }
            }
        }
        <span class="hljs-keyword">return</span> instance;
    }
}
</code></pre>
<h2 id="heading-somewhat-lazy-thread-safe-without-locks">Somewhat Lazy, Thread-safe without locks</h2>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> Singleton _instance = <span class="hljs-keyword">new</span> Singleton ();

    <span class="hljs-comment">// - Explicit static constructor to tell C# compiler not to mark type as beforefieldinit.</span>
    <span class="hljs-comment">// - static constructors in C# are specified to execute only </span>
    <span class="hljs-comment">//   when an instance of the class is created or a static member is referenced, </span>
    <span class="hljs-comment">//   and to execute only once per AppDomain </span>
    <span class="hljs-comment">// - not as lazy. if you have static members other than Instance, </span>
    <span class="hljs-comment">//   the first reference to those members will involve creating the instance.</span>
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-title">Singleton</span> (<span class="hljs-params"></span>)</span> { }

    <span class="hljs-comment">// private constructor to prevent instantiation from outside</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span> (<span class="hljs-params"></span>)</span> { }
}
</code></pre>
<p><strong>But why is it thread-safe and how lazy is it?</strong><br />In C#, a static constructor runs automatically the first time you either create an object of the class or access one of its static members—and it only runs once for the entire lifetime of the application (within each AppDomain).<br />It is not as lazy, i.e. if you have static members other than <code>_instance</code>, the first reference to those members will involve creating the instance.</p>
<h2 id="heading-full-lazy-instantiation">Full Lazy Instantiation</h2>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span>
{
    <span class="hljs-comment">// private so no one can create an instance of this class</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span>(<span class="hljs-params"></span>)</span> { }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton Instance
    {
        <span class="hljs-keyword">get</span>
        {
            <span class="hljs-comment">// instantiation is triggered by the first </span>
            <span class="hljs-comment">// reference to the static member of the nested class,</span>
            <span class="hljs-comment">// which only occurs in Instance.</span>
            <span class="hljs-keyword">return</span> Nested.Instance;
        }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Nested</span>
    {
        <span class="hljs-comment">// static constructor is called only once, when the type is first accessed.</span>
        <span class="hljs-comment">// it ensures that the instance is created in a thread-safe manner.</span>
        <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-title">Nested</span>(<span class="hljs-params"></span>)</span> { }

        <span class="hljs-keyword">internal</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> Singleton Instance = <span class="hljs-keyword">new</span> Singleton();
    }
}
</code></pre>
<p>Read comments inline. Instantiation is triggered by the first reference to the static member of the nested class. So this only run the static constructor of Nested class when the <code>Nested.Instance</code> is referenced and it is only referenced in the enclosing class.</p>
<h2 id="heading-using-lazylttgt">Using Lazy&lt;T&gt;</h2>
<p>It provides lazy initialization with access from multiple threads.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">sealed</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> Lazy&lt;Singleton&gt; _lazyInstance =
        <span class="hljs-keyword">new</span> Lazy&lt;Singleton&gt;(() =&gt; <span class="hljs-keyword">new</span> Singleton());

    <span class="hljs-comment">// private constructor to prevent instantiation from outside</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span>(<span class="hljs-params"></span>)</span> { }

    <span class="hljs-comment">// Public method to get the instance of the singleton</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton Instance
    {
        <span class="hljs-keyword">get</span>
        {
            <span class="hljs-keyword">return</span> _lazyInstance.Value;
        }
    }
}
</code></pre>
<p>Use lazy initialization to defer the creation of a large or resource-intensive object, or the execution of a resource-intensive task, particularly when such creation or execution might not occur during the lifetime of the program.<br /><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.lazy-1?view=net-9.0">Lazy&lt;T&gt;</a> initialization occurs the first time the <code>Lazy.Value</code> property is accessed.</p>
<p>You can use <strong>LazyThreadSafetyMode</strong> to specify how <strong>Lazy&lt;T&gt;</strong> instance synchronizes access among multiple threads.<br /><code>Lazy&lt;Singleton&gt; _lazy = new Lazy&lt;Singleton&gt;(() =&gt; new Singleton(), LazyThreadSafetyMode.ExecutionAndPublication);</code></p>
<ul>
<li><p><strong>LazyThreadSafetyMode.None</strong> - The Lazy&lt;T&gt; instance is not thread safe; if the instance is accessed from multiple threads, its behavior is undefined.</p>
</li>
<li><p><strong>LazyThreadSafetyMode.PublicationOnly</strong> - When multiple threads try to initialize a Lazy&lt;T&gt; instance simultaneously, all threads are allowed to run the initialization method (or the parameterless constructor, if there is no initialization method). The first thread to complete initialization sets the value of the Lazy instance.This is referred to as <code>Publication</code> in the field names. That value is returned to any other threads that were simultaneously running the initialization method, unless the initialization method throws exceptions on those threads. Any instances of T that were created by the competing threads are discarded. Effectively, the publication of the initialized value is thread-safe in the sense that only one of the initialized values can be published and used by all threads.</p>
</li>
<li><p><strong>LazyThreadSafetyMode.ExecutionAndPublication</strong> - Locks are used to ensure that only a single thread can initialize a Lazy instance in a thread-safe manner. Effectively, the initialization method is executed in a thread-safe manner (referred to as Execution in the field name). Publication of the initialized value is also thread-safe in the sense that only one value may be published and used by all threads.</p>
</li>
</ul>
<hr />
<p>References:<br />- <a target="_blank" href="https://refactoring.guru/design-patterns/singleton">https://refactoring.guru/design-patterns/singleton</a><br />- <a target="_blank" href="https://csharpindepth.com/Articles/Singleton">https://csharpindepth.com/Articles/Singleton</a></p>
<hr />
<p>Thanks for reading.</p>
<p>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/ankurcharan">https://www.linkedin.com/in/ankurcharan</a><br />Twitter: <a target="_blank" href="https://twitter.com/ankurcharan">https://twitter.com/ankurcharan</a></p>
]]></content:encoded></item><item><title><![CDATA[Swagger Export from .NETCore]]></title><description><![CDATA[If you have an ASP.NET Web API project. Chances are you are using Swashbuckle.AspNet.Core to generate swagger documentation for the application. Now if you…]]></description><link>https://ankurcharan.hashnode.dev/swagger-export-from-netcore</link><guid isPermaLink="true">https://ankurcharan.hashnode.dev/swagger-export-from-netcore</guid><category><![CDATA[swagger]]></category><category><![CDATA[.net core]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[Web API]]></category><dc:creator><![CDATA[Ankur Charan]]></dc:creator><pubDate>Sun, 03 Mar 2024 18:48:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709491626348/3aa39288-429a-42d5-90a4-5fcec520e83e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you have an <a target="_blank" href="http://ASP.NET">ASP.NET</a> Web API project. Chances are you are using <code>Swashbuckle.AspNet.Core</code> to generate swagger documentation for the application.</p>
<p>Now if you need some way to export the swagger api documentation during your build for CI/CD or any other things, this is for you.</p>
<h2 id="heading-pre-requisite">Pre-requisite</h2>
<p>I am assuming you already have a service from which you can access the swagger JSON/UI.</p>
<h3 id="heading-generating-swagger-on-build">Generating Swagger on Build</h3>
<h4 id="heading-set-up-dotnet-tools">set up dotnet-tools</h4>
<ul>
<li><p>Run <code>dotnet new tool-manifest</code> at root of your project.</p>
</li>
<li><p>it will create a <code>.config</code> directory with <code>dotnet-tools.json</code> in it. this file will have references to the packages that you've installed.</p>
</li>
<li><p>install swashbuckle cli. run <code>dotnet tool install --local Swashbuckle.AspNetCore.Cli</code></p>
</li>
</ul>
<h4 id="heading-add-post-build-step">add post build step</h4>
<ul>
<li><p>in the project csproj file, add a new post build step.</p>
</li>
<li><p>add step</p>
</li>
</ul>
<pre><code class="lang-xml"><span class="hljs-tag">&lt;<span class="hljs-name">Target</span> <span class="hljs-attr">Name</span>=<span class="hljs-string">"SwaggerGenerate"</span> <span class="hljs-attr">AfterTargets</span>=<span class="hljs-string">"PostBuildEvent"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Exec</span> <span class="hljs-attr">Command</span>=<span class="hljs-string">"dotnet tool restore"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Exec</span> <span class="hljs-attr">Command</span>=<span class="hljs-string">"dotnet swagger tofile --output /path/to/swagger.json .\$(OutputPath)$(AssemblyName).dll v1"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Target</span>&gt;</span>
</code></pre>
<ul>
<li><p>OutputPath and AssemblyName are the project variable, and they have the path to where the build is and <code>.dll</code> is generated.</p>
</li>
<li><p>If you have multiple version of the APIs, you can have <code>v1</code> or <code>v2</code> in the second command.</p>
</li>
<li><p>Build your csproj and your openapi spec (swagger json) is created during the build.</p>
</li>
</ul>
<h3 id="heading-postscript">PostScript</h3>
<p>Feel free to reach out to me if you need any help.</p>
<p><a target="_blank" href="http://linkedin.com/in/ankurcharan">linkedin.com/in/ankurcharan</a><br /><a target="_blank" href="http://instagram.com/ankurcharan">instagram.com/ankurcharan</a><br /><a target="_blank" href="http://dev.to/ankurcharan">dev.to/ankurcharan</a><br /><a target="_blank" href="http://twitter.com/ankurcharan">twitter.com/ankurcharan</a><br /><a target="_blank" href="http://ankurcharan.hashnode.dev">ankurcharan.hashnode.dev</a></p>
]]></content:encoded></item><item><title><![CDATA[Azure API Management DevOps]]></title><description><![CDATA[explain how to set up api management devops ci-cd to automatically deploy your APIs and publish them on APIM. It help set up policies and using APIM.]]></description><link>https://ankurcharan.hashnode.dev/azure-api-management-devops</link><guid isPermaLink="true">https://ankurcharan.hashnode.dev/azure-api-management-devops</guid><category><![CDATA[azureapimanagement]]></category><category><![CDATA[ci-cd]]></category><category><![CDATA[Devops]]></category><category><![CDATA[API Management]]></category><dc:creator><![CDATA[Ankur Charan]]></dc:creator><pubDate>Sat, 02 Mar 2024 00:01:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1709337737427/da120d47-79ca-4520-99e0-a94c31d4db20.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I tried to automate API Management automation and came across <a target="_blank" href="https://github.com/Azure/azure-api-management-devops-resource-kit">Azure API Management DevOps Resource Kit</a> repository on GitHub. It has a creator and an extractor tool but has some things broken and is not very convenient to work with.</p>
<p>Here we'll automate the entire API deployment using bicep scripts.</p>
<p>If you're not too familiar with BICEP, you can use the <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/overview?tabs=bicep">Microsoft Bicep Docs</a></p>
<h2 id="heading-azure-resource-group">Azure Resource Group</h2>
<p>Create a resource group on <a target="_blank" href="https://portal.azure.com/">azure portal</a> that you want to deploy APIM into. I have created <code>api-devops</code> resource group.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ixhnhc7od0tzcsqh0aj7.png" alt="screenshot of azure resource group created" /></p>
<h2 id="heading-virtual-network">Virtual Network</h2>
<h3 id="heading-without-virtual-network-vnet">Without Virtual Network (VNet)</h3>
<p>You can skip the <code>virtualNetworkConfiguration</code> and <code>virtualNetworkType</code> properties <code>modules\apiManagement.bicep</code> when creating the APIM instance.</p>
<p>For this article, I am going to create this in a private VNet.</p>
<h3 id="heading-within-private-virtual-network-vnet">Within Private Virtual Network (VNet)</h3>
<ul>
<li><p>Create a VNet and a subnet for APIM within the VNet.</p>
</li>
<li><p>Created subnet <code>apim-subnet</code> in VNet that I will use.</p>
<p>  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b680uvzy3xn9bqpwfpf0.png" alt="screenshot of vnet in subnet" /></p>
</li>
<li><p>Get the resource id of the subnet using az-cli.</p>
<p>  <img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/id2wk8mx2y2ri8rv8uuc.png" alt="screenshot of resourceId received from az-cli" /></p>
</li>
<li><p>Copy the <code>id</code> (resourceId) of the subnet. You will need it later.</p>
</li>
</ul>
<h2 id="heading-bicep-refresher">Bicep Refresher</h2>
<p>This is a very basic refresher of what we need. Please refer <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/">Bicep Docs</a> for more in-depth documentation.</p>
<ul>
<li><p><code>param &lt;param-name&gt; &lt;param-type&gt;</code><br />  this is to tell that the template accepts a parameter <code>&lt;param-name&gt;</code> of type <code>&lt;param-type&gt;</code><br />  Ex. <code>param x string</code> - accepts a parameter <code>x</code> of type <code>string</code>.<br />  type can be <code>array</code>, <code>object</code>, <code>int</code>, <code>string</code></p>
</li>
<li><p><code>param &lt;param-name&gt; &lt;param-type&gt; = &lt;default-value&gt;</code><br />  if a value is not passed for the parameter, its default value is used.</p>
</li>
<li><p><code>module &lt;symobolic-name&gt; &lt;path-to-file&gt; = &lt;params&gt;</code><br />  we can declare the resources in modules and re-use the module in templates.</p>
</li>
<li><p><code>[for i in list]</code> - add a for loop to the templates</p>
</li>
<li><p><code>if (condition)</code> - only deploy resources if the condition is true</p>
</li>
</ul>
<h2 id="heading-deployment">Deployment</h2>
<p>After each step, you can verify your deployment using az-cli.<br /><code>az deployment group create --resource-group api-devops --template-file apim.bicep --parameters ./apim.parameters.json</code></p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgptmqqkmj6hrz3p3iyp.png" alt="screenshot of terminal using az-cli to deploy resources" /></p>
<h2 id="heading-create-apim-instance">Create APIM Instance</h2>
<ul>
<li><p>Check the code at <a target="_blank" href="https://github.com/ankurcharan/azure-api-management-devops/tree/createApim">https://github.com/ankurcharan/azure-api-management-devops/tree/createApim</a></p>
</li>
<li><p>At <code>modules/apiManagement.bicep</code> it accepts multiple parameters and then we can create the instance of APIM.</p>
</li>
</ul>
<pre><code class="lang-plaintext">resource apiManagementService 'Microsoft.ApiManagement/service@2021-08-01' = {
  name: apiManagementInstanceName
  location: location
  tags: tags
  sku: {
    capacity: skuCount
    name: sku
  }
  properties: {
    publisherEmail: 'ankurcharan@outlook.com'
    publisherName: 'Ankur Charan'
    virtualNetworkConfiguration: {
      subnetResourceId: subnetResourceId
    }
    virtualNetworkType: virtualNetworkType
  }
}
</code></pre>
<p>Parameters:</p>
<ul>
<li><p>name: name of the apim instance</p>
</li>
<li><p>location: azure region you want the instance to be created in</p>
</li>
<li><p>sku:</p>
<ul>
<li><p>capacity: capacity of the sku (number of deployed units of the sku)</p>
</li>
<li><p>name: name of the sku</p>
</li>
</ul>
</li>
<li><p>properties:</p>
<ul>
<li><p>publisherEmail: email of publisher</p>
</li>
<li><p>publisherName: name of publisher</p>
</li>
</ul>
</li>
</ul>
<blockquote>
<p>Note: You can skip the below VNet configurations if you want to use a public-facing backend. If you want to use a private VNet then you can use these two configurations.</p>
</blockquote>
<ul>
<li><p>virtualNetworkType: The type of VPN in which API Management service needs to be configured in. None (Default Value) means the API Management service is not part of any Virtual Network, External means the API Management deployment is set up inside a Virtual Network having an Internet Facing Endpoint, and Internal means that API Management deployment is setup inside a Virtual Network having an Intranet Facing Endpoint only.<br />  Allowed values are 'External', 'Internal' and 'None'.</p>
</li>
<li><p>virtualNetworkConfiguration.subnetResourceId: it takes the resource id of the subnet if you want this to have a private VNet.</p>
</li>
</ul>
<p>With this much, you will have an API Management instance running in your resource group.</p>
<ul>
<li>and then we have declared the output values of the instance created</li>
</ul>
<pre><code class="lang-plaintext">output name string = apiManagementInstanceName
output resourceId string = apiManagementService.id
output apimGatewayUrl string = apiManagementService.properties.gatewayUrl
</code></pre>
<ul>
<li>this module is used at <code>apim.bicep</code></li>
</ul>
<pre><code class="lang-plaintext">module apiManagementService 'modules/apiManagement.bicep' = {
    name: apiManagementServiceName
    params: {
        tags: tags
        apiManagementInstanceName: apiManagementServiceName
        location: location
        subnetResourceId: subnetResourceId
        virtualNetworkType: 'External'
    }
}
</code></pre>
<p>To create the APIM instance, it used the module defined above. Also the outputs received from this module can be used later.</p>
<ul>
<li><p>Parameters file</p>
<ul>
<li><p>We also have parameters file <code>apim.parameters.json</code> which currently only has two parameters.</p>
</li>
<li><p><code>apiManagementServiceName</code> will be the name of your APIM instance.</p>
</li>
<li><p><code>subnetResourceId</code> is the resource id of your apim subnet.</p>
</li>
</ul>
</li>
<li><p>APIM instance created</p>
</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z20he3gl5fbrvmaxcnlp.png" alt="screenshot of APIM instance created" /></p>
<h2 id="heading-adding-global-policy">Adding global policy</h2>
<p>We will add a global policy that will apply to all APIs in the APIM. I have kept it empty and would just forward all requests as it is. You can read more about APIM policies at <a target="_blank" href="https://learn.microsoft.com/en-us/azure/api-management/api-management-policies">https://learn.microsoft.com/en-us/azure/api-management/api-management-policies</a></p>
<ul>
<li><p>Check the code at <a target="_blank" href="https://github.com/ankurcharan/azure-api-management-devops/tree/globalPolicy">https://github.com/ankurcharan/azure-api-management-devops/tree/globalPolicy</a></p>
</li>
<li><p>Added a new xml file <code>policies/global-policy.xml</code> this is the global policy xml.</p>
</li>
<li><p>A new step is added at <code>modules/apiManagement.bicep</code></p>
</li>
</ul>
<pre><code class="lang-plaintext">resource globalPolicy 'Microsoft.ApiManagement/service/policies@2021-12-01-preview' = {
  name: 'policy'
  parent: apiManagementService
  properties: {
    value: loadTextContent('../policies/global-policy.xml')
    format: 'rawxml'
  }
}
</code></pre>
<ul>
<li><p>Parameters</p>
<ul>
<li><p><code>parent</code> is given the APIM instance. it is used to create resource names for ARM templates. You can read more at <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/child-resource-name-type">https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/child-resource-name-type</a></p>
</li>
<li><p><code>format</code> is the format of the policy. It supports different formats. We are giving it XML. So it's <code>rawxml</code></p>
</li>
<li><p><code>value</code> is the contents of the policy.</p>
</li>
</ul>
</li>
<li><p><code>loadTextContent('path/to/file')</code> is a bicep function that loads the contents of the file to the bicep.</p>
</li>
<li><p>You can check the global policy from the Azure portal. Go to <code>API</code> from the left nav. Click on <code>All APIs</code>. and that is where your contents of global policy would reflect.</p>
</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/18c48hp2qryvvi6s20xn.jpg" alt="screenshot of where to check global policy deployed on APIM instance" /></p>
<h2 id="heading-swagger">Swagger</h2>
<ul>
<li><p>Check the code at <a target="_blank" href="https://github.com/ankurcharan/azure-api-management-devops/tree/swaggerFile">https://github.com/ankurcharan/azure-api-management-devops/tree/swaggerFile</a></p>
</li>
<li><p>Added a swagger specification at <code>api-spec/jsonplaceholder.json</code></p>
</li>
<li><p>Normally, you would create this file in the build pipeline and then use it to deploy APIs. I have added this explicitly for simplicity.</p>
</li>
<li><p>Swagger is an api-specification tool, checkout <a target="_blank" href="http://swagger.io">swagger.io</a>. And you can have a demo at <a target="_blank" href="https://editor.swagger.io/">https://editor.swagger.io/</a></p>
</li>
</ul>
<h2 id="heading-adding-apis">Adding APIs</h2>
<ul>
<li><p>Checkout the code at <a target="_blank" href="https://github.com/ankurcharan/azure-api-management-devops/tree/api">https://github.com/ankurcharan/azure-api-management-devops/tree/api</a></p>
</li>
<li><p>Now here is a new module at <code>modules/apiManagement.api.bicep</code></p>
</li>
</ul>
<pre><code class="lang-plaintext">resource api 'Microsoft.ApiManagement/service/apis@2021-01-01-preview' = {
  parent: service
  name: apiServiceName
  properties: {
    description: apiServiceDescription
    type: 'http'
    isCurrent: true
    subscriptionRequired: false
    displayName: apiServiceDisplayName
    serviceUrl: apiServiceUrl
    path: suffix
    protocols: [
      protocol
    ]
    value: apiSpecification
    format: specificationFormat
    apiType: 'http'
  }
}
</code></pre>
<ul>
<li><p><code>value</code> is the api-specification content. In our case the swagger file.</p>
</li>
<li><p><code>format</code> is the format of the api-spec used. If its OpenApi3.0 (openapi / openapi+json) or if its Swagger2.0 (swagger-json) of it its link to the swagger.</p>
</li>
<li><p>We have used this module in <code>apim.bicep</code></p>
</li>
<li><p>There is a new parameter <code>apiInformation</code> with the default value being array of api information objects. You can pass the value of this from the parameter file but then you have to serialize the swagger specification file in a string and then pass it. Using bicep, it gives us a function <code>loadTextContent('path')</code> which does that for you. And since this is not going to change much if you're doing this for same application (or multi-region / multi-tenant) then we can use this default value of the parameters.</p>
</li>
<li><p>this also has another resource declaration</p>
</li>
</ul>
<pre><code class="lang-plaintext">resource service 'Microsoft.ApiManagement/service@2021-08-01' existing = {
  name: apiManagementServiceName
}
</code></pre>
<ul>
<li><p><code>existing</code> keyword checks for existing resources.</p>
</li>
<li><p>this checks the api management instance that exists with the name <code>apiManagementServiceName</code> and then proceeds with creating the API.</p>
</li>
<li><p>using this module from <code>apim.bicep</code></p>
</li>
</ul>
<pre><code class="lang-plaintext">module apisDeploy 'modules/apiManagement.api.bicep' = [for (config, i) in apiInformation: {
    name: '${i}-${config.apiName}-import-${apiManagementServiceName}'
    params: {
        apiSpecification: config.apiSpecContent
        apiServiceUrl: config.serviceUrl
        apiServiceDisplayName: config.apiDisplayName
        apiServiceName: config.apiName
        suffix: config.suffix
        apiManagementServiceName: apiManagementServiceName
        specificationFormat: config.specificationFormat
    }
}]
</code></pre>
<ul>
<li><p>we have traversed the array of api information and used it to create all the apis that are defined in the array. this is useful if you have multiple microservices that you want to expose to the customers and manage through APIM i.e. if you're going to add more apis add another item in <code>apiInformation</code> array and you're done.</p>
</li>
<li><p><code>apiInfomation[0]</code> object is</p>
</li>
</ul>
<pre><code class="lang-json">{
    apiName: 'json-placeholder'
    apiDisplayName: 'JsonPlaceholder'
    specificationFormat: 'openapi+json'
    suffix: '/jp'
    serviceUrl: 'https:<span class="hljs-comment">//jsonplaceholder.typicode.com/'</span>
    apiSpecContent: loadTextContent('api-spec/jsonplaceholder.json')
}
</code></pre>
<ul>
<li><p><code>apiName</code> is the name of the api to be used for referencing it if you want to create products or policies etc.</p>
</li>
<li><p><code>apiDisplayName</code> is what you'll see on the portal.</p>
</li>
<li><p><code>specificationFormat</code> is the format of the api-specification.</p>
</li>
<li><p><code>serviceUrl</code> is the backend url of the service.</p>
</li>
<li><p><code>apiSpecContent</code> is the specification content of the apis.</p>
</li>
<li><p><code>dependsOn</code> - this is an array of resources that your current resource is dependent on.</p>
</li>
</ul>
<pre><code class="lang-plaintext">dependsOn: [
    apiManagementService
]
</code></pre>
<p>this means that current resource deployment depends on the resource represented by the symbolic name <code>apiManagementService</code> (apim instance, cause obviously, you'd want to create the APIs only if APIM exists).</p>
<ul>
<li>APIs added to APIM instance</li>
</ul>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j92pmh2y4lx4473nbtg1.png" alt="screenshot of APIs deployed and operations added in APIM" /></p>
<p>you can also see all the operations (endpoints/routes) are added to APIM.</p>
<h2 id="heading-adding-api-policy">Adding API Policy</h2>
<ul>
<li><p>You might want to add api-specific policies on APIM.</p>
</li>
<li><p>Check code at <a target="_blank" href="https://github.com/ankurcharan/azure-api-management-devops/tree/apiPolicy">https://github.com/ankurcharan/azure-api-management-devops/tree/apiPolicy</a></p>
</li>
<li><p>In <code>apim.bicep</code> we have added a new line in <code>apiInformation</code> to load the contents of the policy. <code>policyContents: loadTextContent('policies/apiPolicy-jsonplaceholder.xml')</code></p>
</li>
<li><p>added a new API policy at <code>policies/apiPolicy-jsonplaceholder.xml</code></p>
</li>
<li><p>added a policy deployment module at <code>modules/apiManagement.api.policy.bicep</code></p>
</li>
<li><p>api policy is deployed against an api so it first checks that the particular API already exists in the APIM</p>
</li>
</ul>
<pre><code class="lang-plaintext">// checks if API exists
resource api 'Microsoft.ApiManagement/service/apis@2021-01-01-preview' existing = {
  parent: service
  name: apiServiceName
}

// add APIs policy
resource apiPolicy 'Microsoft.ApiManagement/service/apis/policies@2021-01-01-preview' = {
  parent: api
  name: 'policy'
  properties: {
    value: policyXML
    format: xmlFormat
  }
}
</code></pre>
<ul>
<li><p>notice how we have added <code>api</code> as the parent of <code>apiPolicy</code>. So now we don't have to explicitly add a <code>dependsOn</code> property for the resource.</p>
</li>
<li><p>this module is used at <code>apim.bicep</code></p>
</li>
</ul>
<pre><code class="lang-plaintext">module apiPolicyDeploy 'modules/apiManagement.api.policy.bicep' = [for (config, i) in apiInformation: {
    name: '${i}-${config.apiName}-policy'
    params: {
        apiManagementServiceName: apiManagementServiceName
        apiServiceName: config.apiName
        policyXML: config.policyContents
    }
    dependsOn: [
        apisDeploy
    ]
}]
</code></pre>
<ul>
<li><p><code>apiServiceName</code> is the api name in the APIM instance for which to deploy policies.</p>
</li>
<li><p><code>policyXML</code> is the contents of the policy. You can read more about APIM policies at <a target="_blank" href="https://learn.microsoft.com/en-us/azure/api-management/api-management-policies">https://learn.microsoft.com/en-us/azure/api-management/api-management-policies</a>.</p>
</li>
<li><p>You can see the API policy at</p>
</li>
<li><p>Whatever policy you have added for your API will be updated here.</p>
</li>
</ul>
<h2 id="heading-final-code">Final Code</h2>
<p>You can browse through the final code at <a target="_blank" href="https://github.com/ankurcharan/azure-api-management-devops/tree/main">https://github.com/ankurcharan/azure-api-management-devops/tree/main</a></p>
<p>You can run this template and this would automate your APIM creation and API deployment using Swagger.</p>
<p>Let me know if you want to add more features of the APIM to this template like Products, Subscriptions, Groups, LogAnalytics Workspace etc.</p>
<p><em>Thanks for reading.**</em>Ankur Charan**</p>
<p>LinkedIn: <a target="_blank" href="https://www.linkedin.com/in/ankurcharan/">https://www.linkedin.com/in/ankurcharan</a><br />Twitter: <a target="_blank" href="https://twitter.com/ankurcharan">https://twitter.com/ankurcharan</a></p>
]]></content:encoded></item><item><title><![CDATA[ARM template vs Bicep]]></title><description><![CDATA[ARM template for Bicep conversion and why is it easier to use bicep than ARM templates.]]></description><link>https://ankurcharan.hashnode.dev/arm-template-vs-bicep</link><guid isPermaLink="true">https://ankurcharan.hashnode.dev/arm-template-vs-bicep</guid><category><![CDATA[arm template]]></category><category><![CDATA[Bicep]]></category><category><![CDATA[Azure Resource Manager]]></category><category><![CDATA[ci-cd]]></category><dc:creator><![CDATA[Ankur Charan]]></dc:creator><pubDate>Fri, 01 Mar 2024 23:41:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/A9_IsUtjHm4/upload/70ddbd19682b106f4c7e92ebca101583.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you've used ARM templates to deploy resources, you must have seen it gets a little messy to maintain if there are a lot of resource.<br />Bicep is a new language that offers the same capabilities as ARM templates but with a syntax that's easier to use.</p>
<p>You can have modules to divide your arm templates into multiple groups. And you refer the existing resources to get their property values. (You can do this in ARM also, the syntax is easier in Bicep).</p>
<p>You also have a VSCode extension with intelli-sense to help you write Bicep templates. <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-bicep">BicepExtension</a></p>
<h2 id="heading-arm-to-bicep">ARM to Bicep</h2>
<h3 id="heading-with-cli">with CLI</h3>
<p>Once, you have installed <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/install">bicep-tools</a>, you can use the command <code>az bicep decompile --file &lt;armTemplateFile&gt;.json</code> to convert them to bicep.<br />Although it is a best effort decompilation. It attempts to convert the file, but there is no guaranteed mapping from ARM template JSON to Bicep. You may need to fix warnings and errors in the generated Bicep file. Or, decompilation can fail if an accurate conversion isn't possible.</p>
<h3 id="heading-manual">manual</h3>
<p>Once you have decompiled, you can manually reduce the errors and warnings. Or you can convert the entire template.</p>
<p>If you have worked with ARM template, there format is</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"$schema"</span>: <span class="hljs-string">"https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"</span>,

  <span class="hljs-attr">"parameters"</span>: {
    <span class="hljs-comment">// parameters</span>
  },
  <span class="hljs-attr">"resources"</span>: [
    {
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"&lt;resourceType&gt;"</span>,
      <span class="hljs-attr">"apiVersion"</span>: <span class="hljs-string">"&lt;apiVersion&gt;"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"&lt;resourceName&gt;"</span>,
      <span class="hljs-attr">"location"</span>: <span class="hljs-string">"&lt;resourceLocation&gt;"</span>,
      <span class="hljs-attr">"properties"</span>: {
        <span class="hljs-comment">// resource properties</span>
      }
    }
  ],
  <span class="hljs-attr">"outputs"</span>: {
    <span class="hljs-comment">// trimmed</span>
  }
}
</code></pre>
<p>So all of the properties and values are still the same. But the syntax is a little different. (bicep syntax highlighting is not available here)</p>
<pre><code class="lang-plaintext">resource &lt;resourceSymbolicName&gt; '&lt;resourceType&gt;@&lt;apiVersion&gt;' = {
  name: '&lt;resourceName&gt;'
  location: 'resourceLocation'
  properties: {
    // properties
  }
}
</code></pre>
<h2 id="heading-example">Example</h2>
<p>Lets say you want to create key azure key vault.</p>
<h3 id="heading-with-arm">with ARM</h3>
<pre><code class="lang-json">{
  <span class="hljs-attr">"$schema"</span>: <span class="hljs-string">"https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#"</span>,
  <span class="hljs-attr">"parameters"</span>: {
    <span class="hljs-attr">"name"</span>: {
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>,
      <span class="hljs-attr">"metadata"</span>: {
        <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Required. key vault name."</span>
      }
    },
    <span class="hljs-attr">"location"</span>: {
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>,
      <span class="hljs-attr">"metadata"</span>: {
        <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Required. location of the key vault"</span>
      }
    }
  },
  <span class="hljs-attr">"resources"</span>: [
    {
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"Microsoft.KeyVault/vaults"</span>,
      <span class="hljs-attr">"apiVersion"</span>: <span class="hljs-string">"2023-02-01"</span>,
      <span class="hljs-attr">"name"</span>: <span class="hljs-string">"[parameters('name')]"</span>,
      <span class="hljs-attr">"location"</span>: <span class="hljs-string">"[parameters('location')]"</span>,
      <span class="hljs-attr">"properties"</span>: {
        <span class="hljs-attr">"sku"</span>: {
          <span class="hljs-attr">"family"</span>: <span class="hljs-string">"A"</span>,
          <span class="hljs-attr">"name"</span>: <span class="hljs-string">"standard"</span>
        },
        <span class="hljs-attr">"tenantId"</span>: <span class="hljs-string">"[subscription().tenantId]"</span>,
        <span class="hljs-attr">"enabledForDeployment"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">"enabledForTemplateDeployment"</span>: <span class="hljs-literal">true</span>,
        <span class="hljs-attr">"enabledForDiskEncryption"</span>: <span class="hljs-literal">false</span>,
        <span class="hljs-attr">"enableSoftDelete"</span>: <span class="hljs-literal">true</span>
      }
    }
  ],
  <span class="hljs-attr">"outputs"</span>: {
    <span class="hljs-attr">"name"</span>: {
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>,
      <span class="hljs-attr">"value"</span>: <span class="hljs-string">"[parameters('name')]"</span>
    },
    <span class="hljs-attr">"vaultUri"</span>: {
      <span class="hljs-attr">"type"</span>: <span class="hljs-string">"string"</span>,
      <span class="hljs-attr">"value"</span>: <span class="hljs-string">"[reference(resourceId('Microsoft.KeyVault/vaults', parameters('name')), '2023-02-01').vaultUri]"</span>
    }
  }
}
</code></pre>
<p>This template deploys the key vault and has some properties set for the resource.</p>
<h3 id="heading-with-bicep">with Bicep</h3>
<p>You can have the same template as above in Bicep as below. (again no syntax highlighting for Bicep yet)</p>
<pre><code class="lang-plaintext">@description('Required. key vault name.')
param name string

@description('Required. location of the key vault')
param location string

resource kv 'Microsoft.KeyVault/vaults@2023-02-01' = {
  name: name
  location: location
  properties: {
    sku: {
      family: 'A'
      name: 'standard'
    }
    tenantId: subscription().tenantId
    enabledForDeployment: true
    enabledForTemplateDeployment: true
    enabledForDiskEncryption: false
    enableSoftDelete: true
  }
}

// outputs
output name string = kv.name
output vaultUri string = kv.properties.vaultUri
</code></pre>
<p>Now if you match, you can see this is just easier to write and the intelli-sense from VSCode Bicep Extension will help alot.</p>
<p>And all the other things that Bicep brings, like modules and using dot operator to access the properties of existing resource.</p>
<h1 id="heading-postscript">PostScript</h1>
<p>Read more at <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/">bicep-documentation</a>. Feel free to reach out to me if you need any help.</p>
<p><a target="_blank" href="https://www.linkedin.com/in/ankurcharan/">linkedin.com/in/ankurcharan/</a><br /><a target="_blank" href="https://www.instagram.com/ankurcharan/">instagram.com/ankurcharan/</a><br /><a target="_blank" href="https://dev.to/ankurcharan">dev.to/ankurcharan</a><br /><a target="_blank" href="https://twitter.com/ankurcharan">twitter.com/ankurcharan</a></p>
]]></content:encoded></item></channel></rss>