<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Leonard Soetedjo</title>
    <description>The latest articles on Forem by Leonard Soetedjo (@leonards).</description>
    <link>https://forem.com/leonards</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%2F551251%2F6bfcd6c6-daf2-4c09-8203-438f7bc28b55.png</url>
      <title>Forem: Leonard Soetedjo</title>
      <link>https://forem.com/leonards</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/leonards"/>
    <language>en</language>
    <item>
      <title>Customising Mermaid diagram font and colors</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Tue, 13 Feb 2024 02:35:21 +0000</pubDate>
      <link>https://forem.com/leonards/customising-mermaid-diagram-font-and-colors-4pm9</link>
      <guid>https://forem.com/leonards/customising-mermaid-diagram-font-and-colors-4pm9</guid>
      <description>&lt;p&gt;In the past, I've been using Microsoft Powerpoint to draw diagrams. However, recently I've been intrigued to try out diagram-as-code as it fits well to my mode of working: I can organise my code, docs (in markdown) and diagrams together in a single repository, and be able to update them easily when I'm on Linux. I find updating Powerpoint on Linux or on mobile is difficult even with Powerpoint web version.&lt;/p&gt;

&lt;p&gt;I've been reading up the book &lt;a href="https://play.google.com/store/books/details?id=8IK0EAAAQBAJ"&gt;Creating Software with Modern Diagramming Techniques by Ashley Peacock&lt;/a&gt; which covers mermaid diagramming and I've grown to love the benefit that diagram-as-code provides. However, not all diagrams can be drawn easily / clearly with mermaid. Sometimes I still need to use Powerpoint. The only issue is how do I get both mermaid diagram to be consistent with my Powerpoint diagram (especially fonts as it's not mentioned in mermaid docs).&lt;/p&gt;

&lt;p&gt;After looking at &lt;a href="https://mermaid.js.org/syntax/flowchart.html#css-classes"&gt;Mermaid flowchart CSS documentation&lt;/a&gt; and digging into the html page containing the diagram, below are the configuration that I use inside my markdown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nc"&gt;.nodeLabel&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.flowchartTitleText&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'firago'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;'trebuchet ms'&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.GreenShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.GreenShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt; &lt;span class="nc"&gt;.GreenShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.GreenShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;circle&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.GreenShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;polygon&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#009245&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.YellowShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.YellowShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt; &lt;span class="nc"&gt;.YellowShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.YellowShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;circle&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.YellowShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;polygon&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#f7931e&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.RedShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.RedShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt; &lt;span class="nc"&gt;.RedShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.RedShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;circle&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.RedShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;polygon&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#cb4b4f&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.BlueShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.BlueShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt; &lt;span class="nc"&gt;.BlueShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.BlueShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;circle&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.BlueShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;polygon&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#0071bc&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.PurpleShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.PurpleShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt; &lt;span class="nc"&gt;.PurpleShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.PurpleShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;circle&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.PurpleShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;polygon&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#9200c2&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.GreyShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;rect&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.GreyShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;g&lt;/span&gt; &lt;span class="o"&gt;*,&lt;/span&gt; &lt;span class="nc"&gt;.GreyShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;path&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.GreyShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;circle&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;.GreyShape&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;polygon&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#eee&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.Boundary&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;rect&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#000&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#aaa&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-dasharray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="py"&gt;stroke-linecap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;round&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;style&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above, I can set my mermaid diagram using the &lt;code&gt;classDef&lt;/code&gt; directive as per mermaid docs.&lt;/p&gt;

&lt;p&gt;So far I've tried (&amp;amp; specified in the css):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;rect&amp;gt;&lt;/code&gt; for node with round edges&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;polygon&amp;gt;&lt;/code&gt; for rhombus&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;path&amp;gt;&lt;/code&gt; for cylindrical and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;circle&amp;gt;&lt;/code&gt; for circular shapes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another item is the directive &lt;code&gt;.GreenShape &amp;gt; g *&lt;/code&gt;. It's required to set the shape's text color because the structure of each shape is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;g&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"GreenShape"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;rect&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/rect&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;g&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"label"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;foreignObject...&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
               &lt;span class="nt"&gt;&amp;lt;span...&amp;gt;&lt;/span&gt;Shape label&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
           &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/foreignObject&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/g&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/g&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Liquid template in Logic App</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Fri, 06 May 2022 04:37:41 +0000</pubDate>
      <link>https://forem.com/leonards/liquid-template-in-logic-app-4217</link>
      <guid>https://forem.com/leonards/liquid-template-in-logic-app-4217</guid>
      <description>&lt;p&gt;I was testing out Shopify liquid template to perform XML to XML/JSON data transformation. Liquid template is one of the templating tool mentioned in &lt;a href="https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-enterprise-integration-liquid-transform"&gt;Microsoft's website&lt;/a&gt; to perform data transformation in Logic App (the other tool being the venerable XSLT).&lt;/p&gt;

&lt;p&gt;I've not used XSLT before, but comparing to liquid template, the latter seems more friendly. As such, I embarked on using liquid template for my research.&lt;/p&gt;

&lt;p&gt;Below are the 2 observations I found, and the workaround I need to do to fulfill the task on hand.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Syntax differences between liquid and dotliquid (used by Microsoft):&lt;br&gt;
a. Capitalisation of first letter, i.e. &lt;code&gt;Append&lt;/code&gt; instead of &lt;code&gt;append&lt;/code&gt;.&lt;br&gt;
b. Different naming, i.e. &lt;code&gt;DividedBy&lt;/code&gt; instead of &lt;code&gt;divided_by&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The problem for syntax differences is that there's no error. The script just run successfully, but the filter functions are not executed 🙄.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Unable to differentiate single child node vs. list of child nodes. To give an example, below are 2 valid snippets that can be interpreted differently.&lt;/p&gt;

&lt;p&gt;Snippet 1&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;order&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;orderItem&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;itemName&amp;gt;&lt;/span&gt;Item 1&lt;span class="nt"&gt;&amp;lt;/itemName&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/orderItem&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/order&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Snippet 2&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;order&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;orderItem&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;itemName&amp;gt;&lt;/span&gt;Item 1&lt;span class="nt"&gt;&amp;lt;/itemName&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/orderItem&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;orderItem&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;itemName&amp;gt;&lt;/span&gt;Item 2&lt;span class="nt"&gt;&amp;lt;/itemName&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/orderItem&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/order&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;The first snippet interprets &lt;code&gt;order&lt;/code&gt; as an object containing &lt;code&gt;orderItem&lt;/code&gt;. On the other hand, the second snippet interprets &lt;code&gt;order&lt;/code&gt; as an &lt;strong&gt;_array _&lt;/strong&gt;of `orderItem 😅&lt;/p&gt;

&lt;p&gt;Fortunately, Microsoft has &lt;a href="https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-enterprise-integration-liquid-transform#transform-xml-to-json"&gt;JSONArrayFor&lt;/a&gt;. Using JSONArrayFor instead of For loop, we're able to force &lt;code&gt;order&lt;/code&gt; to be treated as an array regardless of the number of &lt;code&gt;orderItem&lt;/code&gt; insider &lt;code&gt;order&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>azure</category>
      <category>logicapps</category>
      <category>liquid</category>
    </item>
    <item>
      <title>Parameterising Logic App (Standard) connections.json with bicep - Part 3</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Tue, 03 May 2022 13:11:50 +0000</pubDate>
      <link>https://forem.com/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-3-57d7</link>
      <guid>https://forem.com/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-3-57d7</guid>
      <description>&lt;p&gt;In my previous 2 posts &lt;a href="https://dev.to/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-1-2mhi"&gt;here&lt;/a&gt; and &lt;a href="https://dev.to/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-2-hdl"&gt;here&lt;/a&gt;, I briefly showed how we can create the bicep snippet to create API connection resources and subsequently use that to parameterise our Logic App's connections.json. However, I've come to realise that I've missed out one configuration: API access policy. 😨&lt;/p&gt;

&lt;p&gt;The API access policy dictates the object (in my case it's the Logic App) that can access the API connection. In this post, I'm covering this additional configuration as well as an observation on the behaviour of bicep.&lt;/p&gt;

&lt;p&gt;Creating the API access policy is simple. We've to create &lt;code&gt;Microsoft.Web/connections/accessPolicies&lt;/code&gt;, and add the bind our Logic App to this new access policy.&lt;/p&gt;

&lt;p&gt;The snippet below creates the API access policy resource given that we've retrieved the particular Logic App resource that we want to allow access to.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource apiAccessPolicy 'Microsoft.Web/connections/accessPolicies@2016-06-01' = {
  name: '${logicApp.name}-${guid(resourceGroup().name)}'
  location: location
  parent: serviceBusConnApiConnection
  properties: {
    principal: {
      type: 'ActiveDirectory'
      identity: {
        tenantId: subscription().tenantId
        objectId: reference(logicApp.id, logicApp.apiVersion, 'Full').identity.principalId
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. &lt;del&gt;The only peculiar behaviour that I've seen is the naming of this resource. For a service bus API access policy, we need to name it with the prefix of the service bus connection name as in the above snippet. However, that is not the case for azure blob.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;del&gt;For azure blob, using the naming structure above will give us an error ~~&lt;code&gt;Expected resource name to not contain any "/" characters. Child resources with a parent resource reference (via the parent property or via nesting) must not contain a fully-qualified name.bicep(BCP170)&lt;/code&gt;. ~~Turns out we can just name it without the prefix of the API connection's name 🙄, i.e. it's simply&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;name: '${logicApp.name}-${guid(resourceGroup().name)}'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;del&gt;I'm still trying to understand the reason for this, but well, it is what it is 😄&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;UPDATE: Turns out I missed out the parent keyword which indicates what's the connection resource for the access policy 😄. Once the parent is specified, we can name the access policy without the prefix.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>bicep</category>
      <category>logicapps</category>
    </item>
    <item>
      <title>Parameterising Logic App (Standard) connections.json with bicep - Part 2</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Sun, 01 May 2022 03:18:41 +0000</pubDate>
      <link>https://forem.com/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-2-hdl</link>
      <guid>https://forem.com/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-2-hdl</guid>
      <description>&lt;p&gt;Continuing from &lt;a href="https://dev.to/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-1-2mhi"&gt;where we left off&lt;/a&gt;, the next step is to update the appsettings, and set connections.json to read from appsettings.&lt;/p&gt;

&lt;p&gt;This is where it gets interesting. After lots of searching thru' the internet and testing, there are a couple of points to highlight:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We can't replace the &lt;code&gt;managedApiConnections&lt;/code&gt; information &lt;u&gt;as a whole string&lt;/u&gt;, i.e. the below setting won't work&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"managedApiConnections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"azureblob_1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@appsetting('azureBlobApiId')"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ManagedServiceIdentity"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"connection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@appsetting('azureBlobConnectionId')"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"connectionRuntimeUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@appsetting('azureBlobConnectionRuntimeUrl')"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;With the above, our connections seems to be working. Looking at the API connections' status, it reports "Connected". All is well, it seems...until we try to save a workflow. When we try to save the workflow, we're shown a puzzling error:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Workflow saved successfully. Workflow validation failed for the workflow 'xxxxxxxxxx'. The file 'connections.json' contains invalid expressions. The allowed expression functions are 'xxxxxxxxxx'.
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To workaround the above issue, we can find the hint from this doc &lt;a href="https://docs.microsoft.com/en-us/azure/logic-apps/create-parameters-workflows?tabs=standard#parameterize-connections-file"&gt;Create cross-environment parameters for workflow inputs in Azure Logic Apps&lt;/a&gt;. In essence, rather than the above, we should instead create the following (the below code will &lt;u&gt;still cause an error&lt;/u&gt; when saving a workflow. see step 3 for the last observation and workaround)&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"managedApiConnections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"azureblob_1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/@{appsetting('WORKFLOW_SUBSCRIPTION_ID')}/providers/Microsoft.Web/locations/@{appsetting('WORKFLOW_LOCATION')}/managedApis/azureblob"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ManagedServiceIdentity"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"connection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/@{appsetting('WORKFLOW_SUBSCRIPTION_ID')}/resourceGroups/@{appsetting('WORKFLOW_RG_NAME')}/providers/Microsoft.Web/connections/azureblob"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"connectionRuntimeUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@appsetting('azureBlobConnectionRuntimeUrl')"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;u&gt;Note:&lt;/u&gt; only &lt;code&gt;connectionRuntimeUrl&lt;/code&gt; can successfully use appsettings. &lt;code&gt;apiId&lt;/code&gt; and &lt;code&gt;connectionId&lt;/code&gt; can &lt;strong&gt;somehow&lt;/strong&gt; be partially parameterised.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Last observation, the above Microsoft doc recommendation for interpolated format by enclosing expression using curly brackets &lt;code&gt;{}&lt;/code&gt; doesn't seem to work. In the end, we have to remove the curly brackets so that the final &lt;code&gt;connections.json&lt;/code&gt; will look like this:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"managedApiConnections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"azureblob_1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/@appsetting('WORKFLOW_SUBSCRIPTION_ID')/providers/Microsoft.Web/locations/@appsetting('WORKFLOW_LOCATION')/managedApis/azureblob"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ManagedServiceIdentity"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"connection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/@appsetting('WORKFLOW_SUBSCRIPTION_ID')/resourceGroups/@appsetting('WORKFLOW_RG_NAME')/providers/Microsoft.Web/connections/azureblob"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"connectionRuntimeUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@appsetting('azureBlobConnectionRuntimeUrl')"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once the above settings are done, we're now able to make use of the API connections and save workflows successfully.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>bicep</category>
      <category>logicapps</category>
    </item>
    <item>
      <title>Parameterising Logic App (Standard) connections.json with bicep - Part 1</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Sun, 01 May 2022 02:45:35 +0000</pubDate>
      <link>https://forem.com/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-1-2mhi</link>
      <guid>https://forem.com/leonards/parameterising-logic-app-standard-connectionsjson-with-bicep-part-1-2mhi</guid>
      <description>&lt;p&gt;Yet another issue I found when dealing with Logic App in Azure. This time, I want to parameterise the connections.json with the values from appsettings. Specifically, it's the managedApiConnections section of connections.json as this requires a particularly new item: &lt;code&gt;connectionRuntimeUrl&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"managedApiConnections"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"azureblob_1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"api"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/xxxxxxxxxx/providers/Microsoft.Web/locations/xxxxxxxxxx/managedApis/azureblob"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"authentication"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ManagedServiceIdentity"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"connection"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/xxxxxxxxxx/resourceGroups/xxxxxxxxxx/providers/Microsoft.Web/connections/azureblob"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"connectionRuntimeUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://xxxxxxxxxx.azure-apihub.net/apim/azureblob/xxxxxxxxxx"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Looking around Microsoft's &lt;a href="https://docs.microsoft.com/en-us/azure/templates/microsoft.web/connections?tabs=bicep"&gt;documentation on Web Connections&lt;/a&gt;, there don't "seem" much useful info on the list of parameters that it requires to build the connections in bicep. However, if we go down further, there're quickstart templates that we can refer to for &lt;a href="https://github.com/Azure/azure-quickstart-templates/tree/master/demos/arm-template-retrieve-azure-storage-access-keys"&gt;storage&lt;/a&gt; or &lt;a href="https://github.com/Azure/azure-quickstart-templates/blob/master/demos/alert-to-queue-with-logic-app"&gt;service bus queue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As we'll be building in bicep, we start with decompiling (&lt;code&gt;az bicep decompile --file azuredeploy.json&lt;/code&gt;) the ARM template into bicep and try to analyse what's required.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource serviceBusConnectionName_resource 'Microsoft.Web/connections@2018-07-01-preview' = {
  location: location
  name: serviceBusConnectionName
  properties: {
    api: {
      id: subscriptionResourceId('Microsoft.Web/locations/managedApis', location, 'servicebus')
    }
    displayName: 'servicebus'
    parameterValues: {
      connectionString: serviceBusConnectionString
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of interest is the item under &lt;code&gt;parameterValues&lt;/code&gt; as it's not documented. With this, we can retrieve the service bus connection string and put it into the bicep script. Do note that the above bicep is only for service bus. We can use the other quickstart template for other resources such as azure blob which will show us a different set of required &lt;code&gt;parameterValues&lt;/code&gt; to build the bicep script.&lt;/p&gt;

&lt;p&gt;Once we've the above, the next step is then to update the Logic App (Standard) &lt;code&gt;connections.json&lt;/code&gt; to retrieve the necessary information from e.g. appsettings. This is another journey into the uncharted which I will cover in the next post.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>bicep</category>
      <category>logicapps</category>
    </item>
    <item>
      <title>Automating Azure APIM configuration based on Logic App (standard) workflows' callback URLs</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Wed, 20 Apr 2022 14:33:31 +0000</pubDate>
      <link>https://forem.com/leonards/automating-azure-apim-configuration-based-on-logic-app-standard-workflows-callback-urls-26fe</link>
      <guid>https://forem.com/leonards/automating-azure-apim-configuration-based-on-logic-app-standard-workflows-callback-urls-26fe</guid>
      <description>&lt;p&gt;Continuing from my research to &lt;a href="https://dev.to/leonards/retrieve-logic-app-standard-single-tenant-workflow-callback-url-using-azure-bicep-5c9j"&gt;retrieve Logic App (standard) workflow callback URL&lt;/a&gt;, my next step was to automatically configure the Azure API Management in bicep.&lt;/p&gt;

&lt;p&gt;My plan is to retrieve list of workflows for a particular Logic App (standard), and then iteratively configure APIM to add the backend endpoints. I had thought that it's an easy case, but it's not.&lt;/p&gt;

&lt;p&gt;The resulting json from listcallbackUrl() is as follows (sample from Microsoft website):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://prod-03.westus.logic.azure.com/workflows/d4690301f3b340de9330256bb2e83974/triggers/requestTrigger/paths/invoke?api-version=2016-06-01&amp;amp;se=2018-04-19T16%3A00%3A00.0000000Z&amp;amp;sp=%2Ftriggers%2FrequestTrigger%2Frun&amp;amp;sv=1.0&amp;amp;sig=JXbHjs3qzLPDyk-IM_VzsN-WL_mNql3v_uWbBbKgtVk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"basePath"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://prod-03.westus.logic.azure.com/workflows/d4690301f3b340de9330256bb2e83974"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"queries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"api-version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2016-06-01"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"se"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2018-04-19T16:00:00.0000000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"//*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sv"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"sig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"JXbHjs3qzLPDyk-IM_VzsN-WL_mNql3v_uWbBbKgtVk"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My requirements need me to populate APIM's set-backend-service and rewrite-uri. With the above json, a user-defined function is required. And alas, as of now it's &lt;a href="https://github.com/Azure/bicep/issues/2"&gt;not possible in bicep&lt;/a&gt; :(&lt;/p&gt;

&lt;p&gt;After further research and testing, in the end this is what I came up with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Call a new module from the main bicep file by passing an array of logic app
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module cbUrl 'module_cburl.bicep' = [for (item, i) in apiOperations: {
  name: 'url${i}'
  params: {
    logicAppId: resourceId(logicAppName)
    workflows: item
  }
}]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Create the module that just call listCallbackUrl() and provide the output with my custom format
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param logicAppId string
param workflows string

var url = listCallbackURL('${logicAppId}/hostruntime/runtime/webhooks/workflow/api/management/workflows/${workflows}/triggers/manual', '2022-03-01')
var apiVersion = url.queries['api-version']

output url object = {
  basePath: url.basePath
  queries: '?api-version=${uriComponent(apiVersion)}&amp;amp;amp;sv=${uriComponent(url.queries.sv)}&amp;amp;amp;sp=${uriComponent(url.queries.sp)}&amp;amp;amp;sig=${uriComponent(url.queries.sig)}'
}

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

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Use the array of result into API Management policy, iterating it with the same apiOperations variable.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource apiPolicies 'Microsoft.ApiManagement/service/apis/operations/policies@2021-08-01' = [for (item, i) in apiOperations: {
  name: '${apimSvcRef.name}/${apiName}/${item}/policy'
  properties: {
    value: '&amp;lt;policies&amp;gt;\r\n  &amp;lt;inbound&amp;gt;\r\n    &amp;lt;base /&amp;gt;\r\n    &amp;lt;set-backend-service base-url="${cbUrl[i].outputs.url.basePath}" /&amp;gt;\r\n    &amp;lt;rewrite-uri template="${cbUrl[i].outputs.url.queries}" /&amp;gt;\r\n  &amp;lt;/inbound&amp;gt;\r\n  &amp;lt;backend&amp;gt;\r\n    &amp;lt;base /&amp;gt;\r\n  &amp;lt;/backend&amp;gt;\r\n  &amp;lt;outbound&amp;gt;\r\n    &amp;lt;base /&amp;gt;\r\n  &amp;lt;/outbound&amp;gt;\r\n  &amp;lt;on-error&amp;gt;\r\n    &amp;lt;base /&amp;gt;\r\n  &amp;lt;/on-error&amp;gt;\r\n&amp;lt;/policies&amp;gt;'
    format: 'xml'
  }
}]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>azure</category>
      <category>bicep</category>
      <category>logicapps</category>
      <category>apim</category>
    </item>
    <item>
      <title>Retrieve Logic App (Standard / Single-tenant) workflow callback URL using Azure bicep</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Wed, 20 Apr 2022 14:02:11 +0000</pubDate>
      <link>https://forem.com/leonards/retrieve-logic-app-standard-single-tenant-workflow-callback-url-using-azure-bicep-5c9j</link>
      <guid>https://forem.com/leonards/retrieve-logic-app-standard-single-tenant-workflow-callback-url-using-azure-bicep-5c9j</guid>
      <description>&lt;p&gt;Recently I've been researching on Azure components, especially using Logic App (single-tenant) and its deployment automation using Azure bicep. One roadblock I faced was retrieving the callback URLs of the workflows inside the Logic App.&lt;/p&gt;

&lt;p&gt;It's pretty easy to retrieve the callback URL of a workflow of Logic App (multi-tenant), since practically they're the same thing. The code below retrieve the callback URL of a workflow:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;listCallbackURL('${logicAppWorkflow.id}/triggers/manual', '2017-07-01').value&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Logic App (single-tenant) on the other hand, is a different beast altogether. A single Logic App (single-tenant) can house many different workflows. I've been searching around in Microsoft's documentation, in forums to no avail. Finally I got the hint from stackoverflow post &lt;a href="https://stackoverflow.com/questions/69008987/not-able-to-retrieve-logic-app-standard-workflow-url-from-arm-template"&gt;here&lt;/a&gt; where user ibda provided the REST API sample below:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;az rest --method post --uri https://management.azure.com/subscriptions/$subscription/resourceGroups/$ResourceGroupName/providers/Microsoft.Web/sites/$LogicAppName/hostruntime/runtime/webhooks/workflow/api/management/workflows/$MyWorkflow/triggers/manual/listCallbackUrl?api-version=2018-11-01&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Essentially, with the above sample we can just call the function as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;listCallbackUrl('${logicAppStd.id}/hostruntime/runtime/webhooks/workflow/api/management/workflows/${workflowName}/triggers/manual', '2018-11-01')&lt;/code&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>bicep</category>
      <category>logicapps</category>
      <category>automation</category>
    </item>
    <item>
      <title>Building container image in AWS CodeBuild with buildah</title>
      <dc:creator>Leonard Soetedjo</dc:creator>
      <pubDate>Sat, 02 Jan 2021 09:20:40 +0000</pubDate>
      <link>https://forem.com/leonards/building-container-image-in-aws-codebuild-with-buildah-8gk</link>
      <guid>https://forem.com/leonards/building-container-image-in-aws-codebuild-with-buildah-8gk</guid>
      <description>&lt;p&gt;While I was trying out AWS CodeBuild, I realised that the available build images are only Amazon Linux 2 &amp;amp; Ubuntu 18.04. Being used to CentOS, I initially tested out using Amazon Linux 2.&lt;/p&gt;

&lt;p&gt;However, Amazon Linux 2 is based on RHEL7. I faced issues in building image using buildah in Amazon Linux 2. As such, I decided to take the challenge to use custom image based on &lt;code&gt;centos:latest&lt;/code&gt;, which buildah can be easily installed and configured.&lt;/p&gt;

&lt;p&gt;When using custom image, there are a couple of things that need to be done as these will not be available in the image:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;install aws cli&lt;/li&gt;
&lt;li&gt;install buildah&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  1. Installing AWS CLI v2
&lt;/h2&gt;

&lt;p&gt;As per AWS CLI's guide, we'll download &amp;amp; install the latest version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip
unzip -q awscliv2.zip
./aws/install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Installing buildah
&lt;/h2&gt;

&lt;p&gt;Installing buildah is simpler in CentOS8:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dnf install -y buildah fuse-overlayfs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;However, the build process was giving an error:&lt;br&gt;
&lt;code&gt;failed to mount overlay for metacopy check with "nodev,metacopy=on" options: invalid argument&lt;/code&gt;. Googling around, I found this issue &lt;/p&gt;
&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/containers/podman/issues/8118"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Error: failed to mount overlay for metacopy check with "nodev,metacopy=on" options: invalid argument
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#8118&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/boistordu"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xd-MkNqU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://avatars3.githubusercontent.com/u/9523075%3Fv%3D4" alt="boistordu avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/boistordu"&gt;boistordu&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/containers/podman/issues/8118"&gt;&lt;time&gt;Oct 23, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      
&lt;p&gt;&lt;strong&gt;Is this a BUG REPORT or FEATURE REQUEST? (leave only one on its own line)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;/kind bug&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional information you deem important (e.g. issue happens only occasionally):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Output of &lt;code&gt;podman version&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;podman version 2.1.1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Output of &lt;code&gt;podman info --debug&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: failed to mount overlay for metacopy check with "nodev,metacopy=on" options: invalid argument
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Package info (e.g. output of &lt;code&gt;rpm -q podman&lt;/code&gt; or &lt;code&gt;apt list podman&lt;/code&gt;):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(paste your output here)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Have you tested with the latest version of Podman and have you checked the Podman Troubleshooting Guide?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;this is last version on fedora repo&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Additional environment details (AWS, VirtualBox, physical, etc.):&lt;/strong&gt;
vps at provider of vps&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/containers/podman/issues/8118"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;. What needs to be done is to remove the &lt;code&gt;metacopy=on&lt;/code&gt; in &lt;code&gt;/etc/containers/storage.conf&lt;/code&gt;. Subsequently, the build is successful :)&lt;/p&gt;

&lt;p&gt;Below is a summary of my CodeBuild's buildspec.yml (configured for terraform):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 0.2

phases:
  install:
    commands:
      - dnf -y update

      - echo "Install aws cli v2"
      - dnf -y install unzip
      - curl https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip
      - unzip -q awscliv2.zip
      - ./aws/install
      - export PATH=/usr/local/bin:$PATH

      - echo "Install buildah"
      - dnf install -y podman buildah fuse-overlayfs
      - sed -i 's/^mountopt =.*/mountopt = "nodev"/g' /etc/containers/storage.conf
  pre_build:
    commands:
      - echo "Login to ECR"
      - REPO_URI=${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com
      - aws ecr get-login-password --region ${AWS_DEFAULT_REGION} | buildah login --username AWS --password-stdin ${REPO_URI}
  build:
    commands:
      - echo "Build started on `date`"
      - cd ${CODEBUILD_SRC_DIR}
      - cat /etc/os-release
      - sh build-container.sh ${IMAGE_NAME}
  post_build:
    commands:
      - echo "Build completed on `date`"
      - TAG=`date +%Y%m%d_%H%M%S`
      - echo "Pushing image to repository ${IMAGE_NAME}"
      - buildah push ${IMAGE_NAME} ${REPO_URI}/${IMAGE_NAME}:${TAG}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above, I'm able to build the container image using buildah and pushing it to my container repo.&lt;/p&gt;

</description>
      <category>buildah</category>
      <category>codebuild</category>
      <category>centos</category>
    </item>
  </channel>
</rss>
