<?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: Cody Antonio Gagnon</title>
    <description>The latest articles on Forem by Cody Antonio Gagnon (@codycodes).</description>
    <link>https://forem.com/codycodes</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%2F351249%2F4fa48ca0-9374-4438-bdc4-a4c8f4b2b416.png</url>
      <title>Forem: Cody Antonio Gagnon</title>
      <link>https://forem.com/codycodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/codycodes"/>
    <language>en</language>
    <item>
      <title>Sharing gh cli aliases between Windows &amp; WSL ⚡</title>
      <dc:creator>Cody Antonio Gagnon</dc:creator>
      <pubDate>Tue, 03 Sep 2024 17:35:47 +0000</pubDate>
      <link>https://forem.com/codycodes/sharing-gh-cli-aliases-between-windows-and-wsl-19p9</link>
      <guid>https://forem.com/codycodes/sharing-gh-cli-aliases-between-windows-and-wsl-19p9</guid>
      <description>&lt;p&gt;Aliases are a fantastic way to shave seconds off of repetitively typed commands. In this post we'll explore how to share &lt;code&gt;gh&lt;/code&gt; cli aliases between Windows and WSL!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1rh90xwed985a0bdfd4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1rh90xwed985a0bdfd4.png" alt="borrow your laptop" width="334" height="493"&gt;&lt;/a&gt;&lt;/p&gt;
Source: https://xkcd.com/1806



&lt;h3&gt;
  
  
  ✔️ Pre-reqs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;gh&lt;/code&gt; cli installed on:

&lt;ul&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;li&gt;WSL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  📃 Setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Create the shared gh aliases file
&lt;/h4&gt;

&lt;p&gt;Under Windows using &lt;code&gt;cmd.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Using Windows %USERPROFILE%
cd %USERPROFILE%
mkdir config
notepad.exe %USERPROFILE%\config\shared-gh-aliases.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using a yaml file to store &lt;code&gt;gh&lt;/code&gt; aliases, use the &lt;a href="https://cli.github.com/manual/gh_alias_import" rel="noopener noreferrer"&gt;format described in cli man pages&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name_of_alias&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actual_command&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# shared-gh-aliases.yaml&lt;/span&gt;
&lt;span class="na"&gt;prc&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pr create&lt;/span&gt;
&lt;span class="na"&gt;prv&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pr view&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configure Windows and WSL to use the shared aliases file
&lt;/h4&gt;

&lt;p&gt;As the &lt;code&gt;gh&lt;/code&gt; cli does not include an exposed store for aliases, we instead rely on running shell commands that import all the aliases into the session per-windows/WSL.&lt;/p&gt;

&lt;p&gt;In PowerShell, edit your profile (I like to use &lt;code&gt;CurrentUserAllHosts&lt;/code&gt; and YMMV):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;notepad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$profile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CurrentUserAllHosts&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Append the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;gh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:/Users/YOUR_USER/config/shared-gh-aliases.yml"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--clobber&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# add '&amp;gt; $null' to suppress output&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use the &lt;code&gt;--clobber&lt;/code&gt; option to indicate we are OK with updating/potentially clobbering our aliases when this command runs as we intend to source our aliases from the file&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;code&gt;gh alias list&lt;/code&gt; to review existing aliases on both platforms before potentially clobbering&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Restart your terminal and confirm that your &lt;code&gt;gh&lt;/code&gt; aliases loaded!&lt;/p&gt;

&lt;p&gt;Heading over to WSL Ubuntu:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wslpath &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"C:/Users/YOUR_USER/config/shared-gh-aliases.yml"&lt;/span&gt; &lt;span class="c"&gt;# copy this for next step&lt;/span&gt;
notepad.exe ~/.bashrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And append the following,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh &lt;span class="nb"&gt;alias &lt;/span&gt;import &lt;span class="s2"&gt;"/mnt/c/Users/YOUR_USER/config/shared-gh-aliases.yml"&lt;/span&gt; &lt;span class="nt"&gt;--clobber&lt;/span&gt;
&lt;span class="c"&gt;# add '&amp;gt;/dev/null' to suppress output&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💥 Your &lt;code&gt;gh&lt;/code&gt; aliases should now work in WSL &amp;amp; Windows! 🎸&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>linux</category>
      <category>gh</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Sharing Git Aliases between Windows &amp; WSL</title>
      <dc:creator>Cody Antonio Gagnon</dc:creator>
      <pubDate>Fri, 23 Aug 2024 16:15:29 +0000</pubDate>
      <link>https://forem.com/codycodes/sharing-git-aliases-between-wsl-windows-198a</link>
      <guid>https://forem.com/codycodes/sharing-git-aliases-between-wsl-windows-198a</guid>
      <description>&lt;p&gt;Git aliases are a fantastic way to perform repetitive commands with less keystrokes. In this tutorial you'll learn how to easily share these aliases made on Windows with your WSL instance and vice-versa!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9xjzgr7o1pc3pwpw3ek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9xjzgr7o1pc3pwpw3ek.png" alt="git comic" width="330" height="478"&gt;&lt;/a&gt;&lt;/p&gt;
Source: https://xkcd.com/1597/



&lt;h3&gt;
  
  
  ✔️ Pre-reqs
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;git installed on:

&lt;ul&gt;
&lt;li&gt;Windows (git-bash is fine)&lt;/li&gt;
&lt;li&gt;WSL&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Some helpful git aliases&lt;/li&gt;

&lt;li&gt;Five or so minutes&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  📃 Setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Create the shared git aliases file
&lt;/h4&gt;

&lt;p&gt;Under Windows using &lt;code&gt;cmd.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Using %USERPROFILE%/config/shared-git-aliases
cd %USERPROFILE%
mkdir config
notepad.exe %USERPROFILE%\config\shared-git-aliases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside of the shared-git-aliases file, add a single line &lt;code&gt;[alias]&lt;/code&gt; and below add aliases accordingly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[alias]&lt;/span&gt;
&lt;span class="py"&gt;s&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;status&lt;/span&gt;
&lt;span class="py"&gt;sw&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;switch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Configure Windows and WSL to use the shared aliases file
&lt;/h4&gt;

&lt;p&gt;Copy the full path of your shared-git-aliases file and open git config using &lt;code&gt;cmd.exe&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--edit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE: any aliases defined here will only exist on Windows. You must move the aliases to the included file to enable access in WSL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Add the following, replacing the path with your shared-git-aliases file. We can avoid escaping the path by using forward slashes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[include]&lt;/span&gt;
      &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;C:/Users/YOUR-USER/config/shared-git-aliases&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copy the path here and open a WSL terminal. Convert the Windows path to be accessible via WSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wslpath &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"C:/Users/YOUR_USER/config/shared-git-aliases"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Almost there! Now edit gitconfig on WSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--edit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="nn"&gt;[include]&lt;/span&gt;
      &lt;span class="py"&gt;path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;/mnt/c/Users/YOUR_USER/config/shared-git-aliases&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file, and voila! Your aliases should be working.&lt;/p&gt;

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

</description>
      <category>tutorial</category>
      <category>git</category>
      <category>productivity</category>
      <category>linux</category>
    </item>
    <item>
      <title>Terraform Associate: Top 5 Learnings</title>
      <dc:creator>Cody Antonio Gagnon</dc:creator>
      <pubDate>Sat, 13 Apr 2024 00:57:14 +0000</pubDate>
      <link>https://forem.com/codycodes/terraform-associate-top-5-learnings-iao</link>
      <guid>https://forem.com/codycodes/terraform-associate-top-5-learnings-iao</guid>
      <description>&lt;p&gt;Unlock the power of Terraform for your career, project, or any opportunity with these essential tips and tricks from my Terraform Associate exam journey!&lt;/p&gt;

&lt;h3&gt;
  
  
  Overview:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;🔦 Essential Commands&lt;/li&gt;
&lt;li&gt;⌨️ Command line options for days&lt;/li&gt;
&lt;li&gt;🧮 Functions, functions, and more functions!&lt;/li&gt;
&lt;li&gt;🌟 Splatting it up&lt;/li&gt;
&lt;li&gt;🧠 Getting into the &lt;code&gt;terraform state&lt;/code&gt; of mind&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  1. 🔦 Essential Commands
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;terraform validate&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Validates the syntax of terraform files statically (before running a plan)&lt;/li&gt;
&lt;li&gt;Helps (quickly!) uncover any potential issues with syntax (e.g. typos, undeclared variables, etc.)&lt;/li&gt;
&lt;li&gt;Does not determine issues that may occur at plan or apply time (e.g. circular resource dependencies in which resources depend on each other for creation, API considerations for deployment on a given cloud provider, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: ensure when running this command that you're inside the directory containing your Terraform files!! This command will output "Success!" even when no Terraform files exist in the current directory 🥲&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;terraform fmt&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Ensures consistency and adherence to HashiCorp's canonical file formatting standards by automatically formatting your Terraform files&lt;/li&gt;
&lt;li&gt;Using the &lt;code&gt;-recursive&lt;/code&gt; flag will format all the Terraform files under the current directory and its subdirectories options &lt;/li&gt;
&lt;li&gt;While you'll need to know this command for the exam, this functionality is built into &lt;a href="https://marketplace.visualstudio.com/items?itemName=HashiCorp.terraform" rel="noopener noreferrer"&gt;HashiCorp's extension for VS Code&lt;/a&gt; and can automatically format your Terraform configuration on save!&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;terraform console&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Think of this as a playground for testing out expressions. You can take the current Terraform state you have and interact with its values.&lt;/li&gt;
&lt;li&gt;You can use variables in the current Terraform workspace as its input as well as other state that's been applied - this makes it super easy to evaluate expressions to see if they'll get the job done (all without needing to apply a plan!)&lt;/li&gt;
&lt;li&gt;Additionally, if no default values exist for input variables, they can be initialized using &lt;code&gt;-var 'name_of_defined_variable=value_of_defined_variable'&lt;/code&gt; on the command line or using either &lt;code&gt;*.auto.tfvars&lt;/code&gt; or &lt;code&gt;terraform.tfvars&lt;/code&gt; files when running &lt;code&gt;terraform console&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. ⌨️ Command line options for days
&lt;/h3&gt;

&lt;p&gt;Learning terraform's command line options can save you time, helping you get the most out of the tools at your disposal! Some of my favorites include:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;terraform apply -auto-approve&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;skip the plan, just apply (exercising caution where necessary) &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;terraform apply -destroy&lt;/code&gt; or shall I say &lt;code&gt;terraform destroy&lt;/code&gt;?
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;did you know &lt;code&gt;terraform destroy&lt;/code&gt; &lt;a href="https://developer.hashicorp.com/terraform/cli/commands/destroy#usage" rel="noopener noreferrer"&gt;is actually just an alias&lt;/a&gt; for &lt;code&gt;terraform apply -destroy&lt;/code&gt;? I didn't either!&lt;/li&gt;
&lt;li&gt;you can also use &lt;code&gt;-auto-approve&lt;/code&gt; here but &lt;a href="https://www.reddit.com/r/ProgrammerHumor/comments/rjx1y5/i_hope_you_know_what_youre_doing/" rel="noopener noreferrer"&gt;"I sure hope you know what you're doing"&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;terraform apply -replace&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Super helpful command to indicate to Terraform that a resource needs to be marked for replacement&lt;/li&gt;
&lt;li&gt;Example could include a database that didn't get provisioned correctly when Terraform thinks it was. Just replace it!&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;terraform apply -refresh=false&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Instead of refreshing state during the apply stage, Terraform will accept whatever it has as its plan, reducing the time it would otherwise take to refresh resources.&lt;/li&gt;
&lt;li&gt;This can cause issues if the current state does not match the target environment, it's important to ensure that state is reconciled before using this option!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. 🧮 Functions, functions, and more functions!
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wphlm24i2fbek9vz5v0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wphlm24i2fbek9vz5v0.png" alt="Functions functions functions meme" width="600" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  String Functions
&lt;/h4&gt;

&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/format" rel="noopener noreferrer"&gt;format&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;This interesting command can come in handy when you want to output a variable in a specific way. For instance, I may have a variable &lt;code&gt;pi&lt;/code&gt; with a value of 3.14159265358979323846264338... well using the format command I can truncate, approximate, and manipulate the value for display in other ways:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"big_ol_pi"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A big 'ol pi 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14159265358979323846264338&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This 🥧 is approximated to %.2f"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;big_ol_pi&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"This 🥧 is approximated to 3.14"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/trimprefix" rel="noopener noreferrer"&gt;trimprefix&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;Super simple command that allows you remove part of the beginning of a string. Say we have the following variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"string_of_pi"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A string of 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🥧3.14159265358979323846264338🥧"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;trimprefix&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string_of_pi&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"3.14159265358979323846264338🥧"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/trimsuffix" rel="noopener noreferrer"&gt;trimsuffix&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;Same as &lt;code&gt;trimprefix&lt;/code&gt;, but at the end rather than the beginning!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"string_of_pi"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A string of 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🥧3.14159265358979323846264338🥧"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;trimsuffix&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string_of_pi&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"🥧3.14159265358979323846264338"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/replace" rel="noopener noreferrer"&gt;replace&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;Allows you to transform your pie into cake, or rather, takes an input string and substitutes the value(s) you specify with another value!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"string_of_pi"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A string of 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🥧3.14159265358979323846264338🥧"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;string_of_pi&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"🍰"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"🍰3.14159265358979323846264338🍰"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Collection Functions
&lt;/h4&gt;

&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/keys" rel="noopener noreferrer"&gt;keys&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;Helps get the keys of a map. Can really be useful in a cinch - notice the keys are &lt;a href="https://developer.hashicorp.com/terraform/language/functions/keys" rel="noopener noreferrer"&gt;&lt;em&gt;sorted in lexicographical order&lt;/em&gt;&lt;/a&gt;, which is probably different than the order they're created in!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"map_of_pies"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lotsa pi 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"3.141592653589793238462643384"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"the number pi"&lt;/span&gt;
    &lt;span class="s2"&gt;"'3.14'"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"literal approximation of the number pi"&lt;/span&gt;
    &lt;span class="s2"&gt;"🥧"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"emoji pie"&lt;/span&gt;
    &lt;span class="s2"&gt;"🍰"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"not a pie"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map_of_pies&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;tolist&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"'3.14'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"3.141592653589793238462643384"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍰"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/lookup" rel="noopener noreferrer"&gt;lookup&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;Great little function that can help return a single value based on the input. What differentiates this from a typical map index (using &lt;code&gt;var.map_of_pies["🍰"]&lt;/code&gt; syntax) is that it can fall back to a default value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"map_of_pies"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lotsa pi 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"3.141592653589793238462643384"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"the number pi"&lt;/span&gt;
    &lt;span class="s2"&gt;"'3.14'"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"literal approximation of the number pi"&lt;/span&gt;
    &lt;span class="s2"&gt;"🥧"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"emoji pie"&lt;/span&gt;
    &lt;span class="s2"&gt;"🍰"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"not a pie"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lookup&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map_of_pies&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"👾"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="s2"&gt;"🥧"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a key isn't present inside of &lt;code&gt;var.map_of_pies&lt;/code&gt;, we elect to always return a pie emoji!&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0f1oba56ubqw4p6xohy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0f1oba56ubqw4p6xohy.png" alt="OMG Pie meme" width="386" height="390"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;I like that default value more, tastes better&lt;/em&gt;&lt;/p&gt;
&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/concat" rel="noopener noreferrer"&gt;concat&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;Simply take two lists and make them one!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"list_of_pies"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"more 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"'3.14'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"3.141592653589793238462643384"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"list_of_cakes"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"definitely not 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"🎂"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"🍰"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"🍥"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list_of_pies&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list_of_cakes&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list_of_pies&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list_of_cakes&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;tolist&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"'3.14'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"3.141592653589793238462643384"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🎂"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍰"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍥"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, we can also take other functions that return a list and use them here as well!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"map_of_pies"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lotsa pi 🥧"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"3.141592653589793238462643384"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"the number pi"&lt;/span&gt;
    &lt;span class="s2"&gt;"'3.14'"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"literal approximation of the number pi"&lt;/span&gt;
    &lt;span class="s2"&gt;"🥧"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"emoji pie"&lt;/span&gt;
    &lt;span class="s2"&gt;"🍰"&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"not a pie"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;keys&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map_of_pies&lt;/span&gt;&lt;span class="err"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map_of_pies&lt;/span&gt;&lt;span class="err"&gt;))&lt;/span&gt;
&lt;span class="nx"&gt;tolist&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"'3.14'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"3.141592653589793238462643384"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍰"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🥧"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"literal approximation of the number pi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"the number pi"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"not a pie"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"emoji pie"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  &lt;a href="https://developer.hashicorp.com/terraform/language/functions/formatlist" rel="noopener noreferrer"&gt;formatlist&lt;/a&gt;
&lt;/h5&gt;

&lt;p&gt;Just like with the &lt;code&gt;format&lt;/code&gt; command, &lt;code&gt;formatlist&lt;/code&gt; can apply its specification to a whole list of strings!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"list_of_shadys"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"All the shadys"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="s2"&gt;"who"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"what"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;"chka chka slim-shady!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;formatlist&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"hi my name is %s"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list_of_shadys&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;tolist&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"hi my name is who"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"hi my name is what"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"hi my name is chka chka slim-shady!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. 🌟 Splatting it up
&lt;/h3&gt;

&lt;p&gt;Have you ever woken up and just thought: wow, splats are great? Me neither, but someday I might, because it turns out these expressions can really improve readability and make it easier to wrap your head around some loops in Terraform!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So, what is a splat expression really?&lt;/em&gt;&lt;br&gt;
A splat is really just a shorthand for "all the things in this list."&lt;br&gt;
It's a syntatical sugar that you can use to convert all types of &lt;code&gt;for&lt;/code&gt; expressions for in Terraform to even simpler splat expressions! &lt;/p&gt;

&lt;p&gt;Here's an example of converting a variable to a splat&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"desserts"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A list of favorite desserts"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🍰"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Cheesecake"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🍪"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Chocolate Chip Cookie"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🍦"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Ice Cream"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🍩"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Donut"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"🧁"&lt;/span&gt;
      &lt;span class="nx"&gt;name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Cupcake"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# running this in terraform console&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;dessert&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desserts&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dessert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emoji&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"🍰"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍪"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍦"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍩"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🧁"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="c1"&gt;# is equivalent to&lt;/span&gt;
&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;desserts&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emoji&lt;/span&gt;
&lt;span class="nx"&gt;tolist&lt;/span&gt;&lt;span class="err"&gt;(&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="s2"&gt;"🍰"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍪"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍦"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🍩"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"🧁"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see in the above, our &lt;code&gt;for&lt;/code&gt; expression, while totally readable, is less concise. You know the saying though: "once you understand splat you'll never want to go back!"&lt;/p&gt;

&lt;p&gt;Now, splats are great for replacing &lt;code&gt;for&lt;/code&gt; expressions on lists, but they can also be used for conditional inputs on dynamic blocks. While we have focused on Terraform being able to get all elements from a list, we haven't discussed the special behavior splat expressions exhibit when applied to a &lt;strong&gt;single&lt;/strong&gt; (non-collection) value. Say we have the following resource definition fo an &lt;code&gt;azurerm_key_vault&lt;/code&gt;, which utilizes a dynamic block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_key_vault"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"examplekeyvault"&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;tenant_id&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_client_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tenant_id&lt;/span&gt;
  &lt;span class="nx"&gt;sku_name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"standard"&lt;/span&gt;

  &lt;span class="nx"&gt;dynamic&lt;/span&gt; &lt;span class="s2"&gt;"contact"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;for_each&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key_vault_contact&lt;/span&gt;&lt;span class="p"&gt;[*]&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we look into our variable definition, we have what looks like only a single object, that can have its variable by default initialized to a default value of &lt;code&gt;null&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"key_vault_contact"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will plan just fine. Buy why, you may ask?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41cfuh6p8tpq177arlvl.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F41cfuh6p8tpq177arlvl.gif" alt="Why meme" width="498" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The splat operator can actually do more than just handle lists. It can also take a single value, such as an object or a map, and convert it behind the scenes to a list of a single object! If the value the object is &lt;code&gt;null&lt;/code&gt;, Terraform will take and convert it into an empty list. This makes it possible to &lt;code&gt;for_each&lt;/code&gt; over more complex data types in Terraform!&lt;/p&gt;

&lt;p&gt;Curious to splat it up even more? I recommend checking &lt;a href="https://developer.hashicorp.com/terraform/language/expressions/splat" rel="noopener noreferrer"&gt;Terraform Docs&lt;/a&gt;!&lt;/p&gt;

&lt;h3&gt;
  
  
  5. 🧠 Getting into the &lt;code&gt;terraform state&lt;/code&gt; of mind
&lt;/h3&gt;

&lt;p&gt;Last but not least, where would we be without out our beloved &lt;code&gt;terraform state&lt;/code&gt; command? While there is also now a &lt;a href="https://developer.hashicorp.com/terraform/language/modules/develop/refactoring" rel="noopener noreferrer"&gt;&lt;code&gt;moved&lt;/code&gt; block&lt;/a&gt;, making some state transitions even more reliable/repeatable through GitOps, for the purpose of the Terraform associate exam here are three use cases of the imperative: a still valuable command to know for your state needs!&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Change the name of a resource/module
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;terraform state mv my_provider.pie my_provider.cake&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple, on the tin changing of a resource's name.&lt;/li&gt;
&lt;li&gt;Additionally, we can provide &lt;code&gt;-dry-run&lt;/code&gt; as an option to view what changes would be performed before doing so.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Move a resource into a module
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;terraform state mv my_provider.pie module.pie_soft.pie&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This can be super helpful if you are testing out the changes to a given resource, get it how you'd like it, and then want to bring those changes into a module.&lt;/li&gt;
&lt;li&gt;Or if you simply didn't have the module before to bring the changes into, this can be a lifesaver!&lt;/li&gt;
&lt;li&gt;Additionally, you can choose to rename the resource as you wish to fit the module's naming conventions&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Move a module into another module
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;terraform state mv module.pie_soft.pie module.cake_soft.pie&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finally, last, but certainly not least, we have the ability to move an entire module into another module!&lt;/li&gt;
&lt;li&gt;If we are at this point, we may be using the imperative command to move modules between two completely different terraform projects.

&lt;ul&gt;
&lt;li&gt;For this we can use the options &lt;code&gt;-state=../my_dir/a -state-out=../my_dir/b&lt;/code&gt;, meaning that we can tell Terraform to take existing module state from other projects and bring it into our current project accordingly!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Those are my five learning takeaways from studying and taking the Terraform Associate exam!&lt;br&gt;
I'm hopeful this post will serve as a valuable resource throughout your Terraform journey.&lt;/p&gt;

&lt;p&gt;Please feel free to comment with your experience, suggestions, and anything else you'd be curious to learn or share!&lt;/p&gt;

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

&lt;p&gt;-- 🗺️ 🧠 🤩 Happy Terraforming&lt;/p&gt;




&lt;p&gt;I'd also like to shout out to a few awesome resources that helped me study along the way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free: &lt;a href="https://www.youtube.com/watch?v=SPcwo0Gq9T8" rel="noopener noreferrer"&gt;HashiCorp Terraform Associate Certification Course (003) - Pass the Exam!&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Paid: &lt;a href="https://www.udemy.com/course/terraform-associate-practice-exam/" rel="noopener noreferrer"&gt;HashiCorp Certified: Terraform Associate Practice Exam 2024&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>terraform</category>
      <category>certification</category>
      <category>learning</category>
      <category>devops</category>
    </item>
    <item>
      <title>Terraforming with a Twist: Go with the (azapi) Flow</title>
      <dc:creator>Cody Antonio Gagnon</dc:creator>
      <pubDate>Sun, 18 Feb 2024 19:25:30 +0000</pubDate>
      <link>https://forem.com/codycodes/terraforming-with-a-twist-go-with-the-flow-in-azapi-configuring-classic-sql-vulnerability-assessments-on-azure-in-2024-33j1</link>
      <guid>https://forem.com/codycodes/terraforming-with-a-twist-go-with-the-flow-in-azapi-configuring-classic-sql-vulnerability-assessments-on-azure-in-2024-33j1</guid>
      <description>&lt;p&gt;Sometimes we find ourselves with new default resource configurations which are incompatible with previously deployed infrastructure. These configurations may not even exist inside of a given Terraform provider.&lt;/p&gt;

&lt;p&gt;In this post we go over one such example I'd discovered, how I worked around the issue, and some takeaways I learned through the experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚨 Hello Error
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi24nbrkx5h2s4jfsh0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxi24nbrkx5h2s4jfsh0u.png" alt="HTTP 409 meme"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;credit, original link: &lt;a href="https://http.cat/status/409" rel="noopener noreferrer"&gt;https://http.cat/status/409&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Recently, while repurposing some code to enable vulnerability assessments on Azure SQL databases, I came across the following error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Status=409 Code="VulnerabilityAssessmentStoragelessIsEnabled" Message="Vulnerability Assessment is enabled on this server or one of its underlying databases with an incompatible version. Additional troubleshooting can be found at &lt;a href="https://aka.ms/SQLVAStoragelessDocumentation" rel="noopener noreferrer"&gt;https://aka.ms/SQLVAStoragelessDocumentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I didn't understand at the time that this actually had little to do with the resource I was trying to provision (&lt;code&gt;azurerm_mssql_server_vulnerability_assessment&lt;/code&gt;) and more to do with how Azure now auto-enables a new type of vulnerability assessments on newly provisioned MSSQL servers.&lt;br&gt;
 &lt;/p&gt;

&lt;h2&gt;
  
  
  🔍 Sleuthing for a Fix
&lt;/h2&gt;

&lt;p&gt;Upon initial search for the usual suspects (Stack Overflow, GitHub, cloud/provider documentation), I didn't come across others running into this particular error. Luckily, all was not lost. With the link from the error itself(&lt;a href="https://aka.ms/SQLVAStoragelessDocumentation" rel="noopener noreferrer"&gt;https://aka.ms/SQLVAStoragelessDocumentation&lt;/a&gt;) I was able to educate myself on exactly what was happening.&lt;/p&gt;

&lt;p&gt;This configuration was new to me, so I first needed to learn what the difference between the "express" configuration in comparison to the "classic" configuration. This was provided on the error's link &lt;a href="https://learn.microsoft.com/en-us/azure/defender-for-cloud/sql-azure-vulnerability-assessment-overview#whats-the-difference-between-the-express-and-classic-configuration" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After some digging from the resources provided, I learned a crucial piece of info from the &lt;a href="https://learn.microsoft.com/en-us/azure/defender-for-cloud/faq-defender-for-databases#can-i-choose-which-experience-is-the-default-" rel="noopener noreferrer"&gt;common questions&lt;/a&gt; doc:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Q: Can I choose which experience is the default?&lt;br&gt;
A: No. Express configuration is the default for every new supported Azure SQL database.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Learning that this was auto-configured by default, the next step is to determine how to work through configuring this in Terraform, which led me to &lt;a href="https://github.com/hashicorp/terraform-provider-azurerm/issues/19971" rel="noopener noreferrer"&gt;this&lt;/a&gt; GitHub issue (which essentially is simply a request for getting the express configuration of SQL &lt;br&gt;
server vulnerability assessments supported in the &lt;code&gt;azurerm&lt;/code&gt; provider.)&lt;/p&gt;

&lt;p&gt;So this presented a dead end... or did it? ...&lt;/p&gt;

&lt;h2&gt;
  
  
  🚦 Decision Point - Classic, or Express?
&lt;/h2&gt;

&lt;p&gt;I now needed to make a decision as to which type of Azure SQL Vulnerability Assessment to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Either the new "express" configuration (which was created outside of Terraform automatically by Azure and does not currently [as of 2/16/2024] have support directly in the &lt;code&gt;azurerm&lt;/code&gt; provider)&lt;/li&gt;
&lt;li&gt;Or somehow disable the "express" configuration (which was causing the original error) and then continue to provision the "classic" configuration &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I decided that using the classic configuration (at least for now) would provide the easiest configuration for our customer. The tradeoffs we made were negligible in this case, since:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Classic version has an internal scheduler for sending emails automatically, meaning we would not need to &lt;a href="https://learn.microsoft.com/en-us/azure/defender-for-cloud/faq-defender-for-databases#is-there-a-way-with-express-configuration-to-get-the-weekly-email-report-that-is-provided-in-the-classic-configuration-" rel="noopener noreferrer"&gt;stand up a separate Logic Apps&lt;/a&gt; to get this functionality.&lt;/li&gt;
&lt;li&gt;Requires a storage account dependency, and this is a simple resource to provision.&lt;/li&gt;
&lt;li&gt;Other minor changes, like what the policy could apply to (Database granularity), or what the scans export format could be (classic can export to Excel).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can read more about the differences between express and classic configuration &lt;a href="https://learn.microsoft.com/en-us/azure/defender-for-cloud/sql-azure-vulnerability-assessment-overview#whats-the-difference-between-the-express-and-classic-configuration" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Idea &amp;amp; Testing - Introducing &lt;code&gt;azapi&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;With the decision made to use classic configuration, the main question was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we disable the express configuration if it's not available in the &lt;code&gt;azurerm&lt;/code&gt; provider?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Luckily, the &lt;a href="https://github.com/hashicorp/terraform-provider-azurerm/issues/19971" rel="noopener noreferrer"&gt;GitHub issue&lt;/a&gt; from sleuthing provided a very useful bit of code that shows it's possible to configure "express" mode simply from an ARM/Bicep template!&lt;/p&gt;

&lt;p&gt;But wait, that's not Terraform!&lt;/p&gt;

&lt;p&gt;Well, what if I told you that actually, there's a much simpler way to write ARM or Bicep code directly from your Terraform?&lt;/p&gt;

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

&lt;p&gt;The &lt;code&gt;azapi&lt;/code&gt; provider is pretty cool and easy to get started with. Here are some of my favorite ways it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Can re-use the same provider credentials as used in azurerm (but doesn't have to). Theoretically, if you have Terraform setup with azurerm, it should just work out of the box with azapi!&lt;/li&gt;
&lt;li&gt;Acts as almost a shim to ARM or Bicep templates - you only need to specify the body which, thanks to &lt;a href="https://developer.hashicorp.com/terraform/language/functions/jsonencode" rel="noopener noreferrer"&gt;&lt;code&gt;jsonencode()&lt;/code&gt;&lt;/a&gt; can also be done in HCL 🤓. Of course, you can also just use something like a &lt;a href="https://developer.hashicorp.com/terraform/language/expressions/strings#heredoc-strings" rel="noopener noreferrer"&gt;heredoc&lt;/a&gt; to write actual JSON from the ARM template here too.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For more info on the &lt;code&gt;azapi&lt;/code&gt; provider, check out the official docs &lt;a href="https://learn.microsoft.com/en-us/azure/developer/terraform/overview-azapi-provider" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Final Implementation
&lt;/h2&gt;

&lt;p&gt;You can find a full Terraform deployment &lt;a href="https://github.com/codycodes/blog-resources/blob/main/terraform/mssql-vulnerability-assessments-classic-azapi/main.tf" rel="noopener noreferrer"&gt;here&lt;/a&gt;, with an abridged (sql-only) subset below:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# ---------&lt;/span&gt;
&lt;span class="c1"&gt;# SQL&lt;/span&gt;
&lt;span class="c1"&gt;# ---------&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_mssql_server"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mysqlserver${random_id.sql_server.hex}"&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt;                      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"12.0"&lt;/span&gt;
  &lt;span class="nx"&gt;administrator_login&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"4dm1n157r470r"&lt;/span&gt;
  &lt;span class="nx"&gt;administrator_login_password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"4-v3ry-53cr37-p455w0rd"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_mssql_server_security_alert_policy"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;server_name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_mssql_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Enabled"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Use a descriptive name for the terraform resource so it is easy to infer from the plan&lt;/span&gt;
&lt;span class="c1"&gt;# and continued management of said resource&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azapi_update_resource"&lt;/span&gt; &lt;span class="s2"&gt;"disable_sql_vulnerability_assessments_express_configuration"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Microsoft.Sql/servers/sqlVulnerabilityAssessments@2022-05-01-preview"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt;
  &lt;span class="nx"&gt;parent_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_mssql_server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jsonencode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;properties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Disabled"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_mssql_server_vulnerability_assessment"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;server_security_alert_policy_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_mssql_server_security_alert_policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;storage_container_path&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${azurerm_storage_account.example.primary_blob_endpoint}${azurerm_storage_container.example.name}/"&lt;/span&gt;
  &lt;span class="nx"&gt;storage_account_access_key&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_storage_account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary_access_key&lt;/span&gt;

  &lt;span class="nx"&gt;recurring_scans&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;enabled&lt;/span&gt;                   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;email_subscription_admins&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="nx"&gt;emails&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="s2"&gt;"email@example1.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s2"&gt;"email@example2.com"&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;# Ensure that express configuration is disabled before we provision classic&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;azapi_update_resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disable_sql_vulnerability_assessments_express_configuration&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;A nice graph of all the resources to be provisioned can be found below&lt;br&gt;
(this was generated using &lt;code&gt;terraform graph | dot -Tpng -o graph.png&lt;/code&gt; after installing &lt;code&gt;graphviz&lt;/code&gt; on macOS)&lt;/p&gt;

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

&lt;h2&gt;
  
  
  🔑 Main Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔄 Change is inevitable

&lt;ul&gt;
&lt;li&gt;🔧🚫 Provisioning code that used to work may become incompatible due to updated external API changes.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;🤖 &lt;code&gt;azapi&lt;/code&gt; makes sense to use when external API changes remain to be implemented officially

&lt;ul&gt;
&lt;li&gt;🔍🔄 &lt;code&gt;azurerm&lt;/code&gt;'s status of the resource/config in question's implementation due to the changes are important to consider first.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;🛑 The best way to use &lt;code&gt;azapi&lt;/code&gt; is not to use it at all

&lt;ul&gt;
&lt;li&gt;🔄➡️ When &lt;code&gt;azurerm&lt;/code&gt; is updated with the changes that were implemented in &lt;code&gt;azapi&lt;/code&gt;, it's best to migrate resources to &lt;code&gt;azurerm&lt;/code&gt; as it more tightly integrates with Terraform to enable features like intellisense (autocomplete and syntax validation).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  🎁 Wrapping Up
&lt;/h2&gt;

&lt;p&gt;I'm hopeful this was a helpful blog post on your cloud journey ☁&lt;/p&gt;

&lt;p&gt;How have you used &lt;code&gt;azapi&lt;/code&gt; in your past Terraform deployments? Any comments or clarifications I could use to improve this post? Please feel free to reach out in the comments section below.&lt;/p&gt;

&lt;p&gt;All code in the post can be found here &lt;a href="https://github.com/codycodes/blog-resources" rel="noopener noreferrer"&gt;https://github.com/codycodes/blog-resources&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks, and happy automating ✨&lt;br&gt;
-codycodes&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>azure</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Creating a png of Your Memoji Contact Photo (the easy way)</title>
      <dc:creator>Cody Antonio Gagnon</dc:creator>
      <pubDate>Sat, 24 Apr 2021 16:05:08 +0000</pubDate>
      <link>https://forem.com/codycodes/creating-a-png-of-your-memoji-contact-photo-the-easy-way-26id</link>
      <guid>https://forem.com/codycodes/creating-a-png-of-your-memoji-contact-photo-the-easy-way-26id</guid>
      <description>&lt;p&gt;If you, like me, are one of the many people who adore the ability to generate a slick memoji profile picture with a nice pastel background, and then have the novel idea that you'd like to use that picture outside of your iMessage, read on!&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;will&lt;/em&gt; need a mac to use this workflow! We will use the built-in tool Preview to do our modifications, but you can use many other services to accomplish the same thing.&lt;/p&gt;

&lt;p&gt;Easy as 1-2-3!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create your memoji profile picture (either on macOS or iOS). While creating your profile picture, take a screenshot after you choose a background (e.g. this stage:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmg7f1udaylonzrum2mec.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmg7f1udaylonzrum2mec.PNG" alt="Alt Text" width="800" height="1731"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you're on an iPhone/iPad, send that over to your Mac. Now on your Mac, open that screenshot in Preview where we will crop it to a square. Click the icon highlighted to use the rectangular crop tool, and proceed to crop a square around your profile picture by pressing ⌘ + K.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;if you don't see the toolbar you can click "Help" in the menubar and type "mark" and then select the "Show Markup Toolbar" option.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddibajp5m9ofhhrtry0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fddibajp5m9ofhhrtry0s.png" alt="Screenshot_2021-04-24 08.45.28_bLKPbj" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Now we can use the magic tool which apparently is called "instant alpha". This is a nice little hidden tool inside Preview that allows you to select the perimeter of a matching color up to that color's boundary, and then delete that to make said area transparent. Here's where you can find it:
&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnhjkci91tbry6e151as1.png" alt="Screenshot_2021-04-24 08.48.17_7mQHsD" width="800" height="533"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All you need to do is click inside the boundary. Depending on your crop you may need to do it four times, but I just needed to do it once:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frlmp45rbp4e6solow06e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frlmp45rbp4e6solow06e.png" alt="Screenshot_2021-04-24 08.54.28_NtQdTG" width="800" height="509"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Press delete to remove those colored pixels and voilá! We now have a beautiful seemingly circular memoji profile picture we can use wherever we please! Make sure to save it in a good location and start sharing this workflow with your friends 😉.&lt;/p&gt;

&lt;p&gt;End result:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ivc0k6p93ace33vvka0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ivc0k6p93ace33vvka0.png" alt="memoji profile picture" width="484" height="481"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;quick note about this guide: I think the ability to export the profile picture should be built into the creation of said picture, and in the future, it may be! If it is now different than when I wrote this post, please let me know and I will update it :)&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>productivity</category>
      <category>macos</category>
      <category>ios</category>
    </item>
    <item>
      <title>FaceSpace - A web app that helps you become more mindful of face touching.</title>
      <dc:creator>Cody Antonio Gagnon</dc:creator>
      <pubDate>Thu, 21 May 2020 05:06:05 +0000</pubDate>
      <link>https://forem.com/codycodes/facespace-a-web-app-that-helps-you-become-more-mindful-of-face-touching-596l</link>
      <guid>https://forem.com/codycodes/facespace-a-web-app-that-helps-you-become-more-mindful-of-face-touching-596l</guid>
      <description>&lt;h2&gt;
  
  
  Inspiration
&lt;/h2&gt;

&lt;p&gt;One of our team members, Steven, stumbled upon on this article from &lt;a href="https://www.geekwire.com/2020/response-coronavirus-seattle-team-creates-smartband-vibrates-touch-face/" rel="noopener noreferrer"&gt;GeekWire&lt;/a&gt;. Inspired by the simplicity, positive response, and demand for such a product, we thought about being able to create a similar detection mechanism using off-the-shelf technologies over spring break. We shared this information with our teacher Sidhant to validate the idea, and word got out to our other teachers and heads of our university program. Next thing we are hosting a Hackathon with our fellow cohort of students in the &lt;a href="http://gixnetwork.org" rel="noopener noreferrer"&gt;Global Innovation Exchange&lt;/a&gt; program at the University of Washington.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ppu0tled0mivl1djruj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6ppu0tled0mivl1djruj.png" alt="FaceSpace in Action" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We created &lt;a href="https://facespace.app" rel="noopener noreferrer"&gt;https://facespace.app&lt;/a&gt;, which helps you protect yourself by bringing mindfulness to when you touch your face while working. We accomplish this by running machine learning models for the hand and face all in your browser. We take your privacy very seriously and want you to know that none of your hand or face data ever leaves your browser. These models run completely locally within your browser window. All code is open source and can be viewed on &lt;a href="https://github.com/Global-Innovation-Exchange/FaceSpace" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Just click start and FaceSpace will begin loading Machine Learning models into your browser. This can take some time so please hang tight and be patient while it loads. You will be asked to accept camera access and notification access. These are used to correctly determine when you touch your face and notify you when this happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Please note that this is an imperfect solution which does not distinguish between other behaviors that occur around your face, such as drinking or touching glasses. It does its best to determine what a hand is and what a face is and when they intersect.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How we built it
&lt;/h2&gt;

&lt;p&gt;During our first meeting, a team member spoke of an idea of using the webcam to detect face touching. We thought that it was a great idea. The first MVP was created using the handtrack.js and face-api.js libraries. We then moved to using some of the latest models which have come from Google, handpose and facemesh. All of our work thus far has been built upon existing tensorflow.js libraries. Using git we practiced branching and merging methodologies and communicated several times as a team to merge code seamlessly. We tracked our progress over time and delegated tasks using Trello. Features were discussed and we decided to implement the ones that we thought would drive the most impact for those using our application. We focused heavily on the user experience in ensuring that our application made it clear what it can and can't do, as well as addressing privacy concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges we ran into
&lt;/h2&gt;

&lt;p&gt;Given the short period of time over spring break we believe we implemented the key capability: for our application to notify users when they're touching their face. Getting to this point would prove to be difficult though. In the beginning we'd used handtrack and face-api, and, while face-api worked great, handtrack was just not able to reliably track hands in the image. It was crucial that we got to this point though because we'd then learn in another meeting that Google had just made new models for face tracking and hand tracking; these models are much more reliable and can brought our vision to reality. Getting these models to work in conjunction with each other would prove to be the biggest challenge we'd faced, as there are even some issues with the handpose model which we could not change upstream given the time frame we're working in. We persisted and worked around these issues, allowing us to  deliver a delightful user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accomplishments that we're proud of
&lt;/h2&gt;

&lt;p&gt;As students of University of Washington's Global Innovation Exchange, we're proud that we are able to bring innovation to help in these unprecedented times. The best situation is the one where we bring awareness to a user so they become aware of touching their face and can stop when they otherwise wouldn't have been. We knew that when developing this application and it got to the point where it would detect us touching our faces when we weren't aware of doing so, that we're so proud it actually worked!&lt;/p&gt;

&lt;h2&gt;
  
  
  What we learned
&lt;/h2&gt;

&lt;p&gt;Due to our strict timeline to develop this application, we spent the majority of our days coding and meeting. Throughout this process we learned a lot about implementing new technologies. Multiple team members have never worked in the industry as software developers and needed to use technologies like GIT. We wanted to ensure that each team member could contribute to our project, which in itself was a challenge. Others hadn't done web development and needed to learn the responsive framework Bootstrap. We had some members working on design and others taking that design and turning it into code. We also ran a short survey to test our application and gained a lot of valuable insight from our users which we took to quickly improve our application. There was so much we learned in the short time that we developed this application that it was like being part of a startup. It was super fun and we can't wait to learn more on other projects inside and outside of our program!&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next for FaceSpace
&lt;/h2&gt;

&lt;p&gt;We want to continue improving our application. There are many features which we didn't end up implementing but could really make a difference in our users' lives. We have a heat map feature which we've since developed after spring break which can help users visually see where they touch their face throughout the day. This is something that would simply not be possible without using some way to track hand and face separately and be able to pinpoint their individual landmarks. We also added audio, cookies to persist user settings, and overhauled the UI to be more aesthetically pleasing. We are hoping to continue working on this app in the future!&lt;/p&gt;

&lt;p&gt;Developed at&lt;br&gt;
Global Innovation Exchange in University of Washington&lt;/p&gt;

&lt;p&gt;by&lt;br&gt;
Steven Guh, Cody Gagnon, Ken Christofferson, Robin Yang, Ke Wang, Wenbo Zhong, Justice (Yi) Zheng, Xuyu Chen, and Hao Liu&lt;/p&gt;

&lt;p&gt;with the help of&lt;br&gt;
Sidhant Gupta, John Raiti, Yuntao Wang, and Shwetak Patel&lt;/p&gt;

</description>
      <category>octograd2020</category>
    </item>
  </channel>
</rss>
