<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="https://perrotta.dev/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Aws on ¬ just serendipity 🍀</title>
    <link>https://perrotta.dev/</link>
    <description>Recent content in Aws on ¬ just serendipity 🍀</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <managingEditor>serendipity@perrotta.dev (Thiago Perrotta)</managingEditor>
    <webMaster>serendipity@perrotta.dev (Thiago Perrotta)</webMaster>
    <copyright>© 2013 - 2026 Thiago Perrotta ·
  a fork of [hugo ʕ•ᴥ•ʔ bear](https://github.com/janraasch/hugo-bearblog/)
</copyright>
    <lastBuildDate>Thu, 26 Mar 2026 18:46:44 +0100</lastBuildDate>
    <atom:link href="https://perrotta.dev/tags/aws/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Terraformer
      </title>
      <link>https://perrotta.dev/2025/11/terraformer/</link>
      <pubDate>Wed, 19 Nov 2025 10:22:18 -0300</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <category>terraform</category>
      <guid>https://perrotta.dev/2025/11/terraformer/</guid>
      <description>&lt;p&gt;♠ &lt;a href=&#34;https://github.com/GoogleCloudPlatform/terraformer&#34;&gt;terraformer&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;CLI tool to generate terraform files from existing infrastructure (reverse&#xA;Terraform). Infrastructure to Code&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;In other words: &amp;ldquo;reverse terraform&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;I was quite excited to add this project to my tool belt, as it can save a lot of&#xA;time with scaffolding and &lt;code&gt;terraform import&lt;/code&gt; commands.&lt;/p&gt;&#xA;&lt;p&gt;Then &lt;a href=&#34;https://www.claude.com/product/claude-code&#34;&gt;Claude Code&lt;/a&gt;, once again,&#xA;surprised me.&lt;/p&gt;&#xA;&lt;p&gt;It turns out there&amp;rsquo;s absolutely no need to adopt &lt;code&gt;terraformer&lt;/code&gt; if you have a&#xA;superb agent available and a few cents/dollars to spare.&lt;/p&gt;&#xA;&lt;p&gt;Claude can figure out which CLI arguments to pass to &lt;code&gt;aws&lt;/code&gt;, &lt;code&gt;az&lt;/code&gt;, etc. to list&#xA;all relevant cloud resources. Then it can generate / scaffold a basic set of&#xA;Terraform files to manage them&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;https://perrotta.dev/2025/11/terraformer/#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. And then it can craft an one-off shell or&#xA;python script to import them all in terraform.&lt;/p&gt;&#xA;&lt;p&gt;Easy. Quick. Painless.&lt;/p&gt;&#xA;&lt;p&gt;The interesting part is that I had initially asked Claude to explicitly use&#xA;&lt;em&gt;terraformer&lt;/em&gt; to do so, but it turned out to be more complicated / less&#xA;efficient than having the agent perform the task &lt;em&gt;directly&lt;/em&gt;.&lt;/p&gt;&#xA;&lt;p&gt;I am sorry if you were expecting a &lt;code&gt;terraformer&lt;/code&gt; tutorial.&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;You&amp;rsquo;ll need to refactor these later for maintainability.&amp;#160;&lt;a href=&#34;https://perrotta.dev/2025/11/terraformer/#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: Terraformer&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/terraform/&#34;&gt;#terraform&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>New script: AWS China MFA login
      </title>
      <link>https://perrotta.dev/2025/10/new-script-aws-china-mfa-login/</link>
      <pubDate>Sat, 04 Oct 2025 11:34:58 +0200</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <category>security</category>
      <guid>https://perrotta.dev/2025/10/new-script-aws-china-mfa-login/</guid>
      <description>&lt;p&gt;♠ &lt;a href=&#34;https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/&#34;&gt;Previously&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://github.com/thiagowfx/pancake/tree/5c4122f7ee0dd7917b3f21054a8e7d6b7101687a/aws_china_mfa&#34;&gt;aws_china_mfa&lt;/a&gt;:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;A script to authenticate to AWS China using MFA and export temporary session credentials.&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;p&gt;The idea is simple. To log into AWS, we need the following environment variables&#xA;to be defined:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;export AWS_PROFILE=&amp;#39;china&amp;#39;&#xA;export AWS_ACCESS_KEY_ID=&amp;#39;AKIAWHEATLICIOUSPANCAK&amp;#39;&#xA;export AWS_SECRET_ACCESS_KEY=&amp;#39;wSyrupyDeliciousSecretKeyForBreakfastDelight42&amp;#39;&#xA;export AWS_SESSION_TOKEN=&amp;#39;FwoGZXIvYXdzEBaaDCakesYrUpSWeetToKenArEDelIcIoUs...&amp;#39;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;code&gt;AWS_PROFILE&lt;/code&gt; is static and can be hard-coded. It&amp;rsquo;s also possible to supply it&#xA;to the &lt;code&gt;aws&lt;/code&gt; CLI via &lt;code&gt;--profile&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;The other three are fetched upon a successful authentication against AWS, using&#xA;MFA (multi-factor authentication) with an OTP.&lt;/p&gt;&#xA;&lt;p&gt;The usage experience of the script is like this:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;% ./aws_china_mfa.sh&#xA;Note: Script is being executed. To apply credentials, run:&#xA;  eval &amp;#34;$(./aws_china_mfa.sh china)&amp;#34;&#xA;&#xA;Using AWS profile: china&#xA;Enter the MFA token code for your AWS China account: 123456&#xA;Retrieving MFA device ARN...&#xA;Requesting session token...&#xA;&#xA;  export AWS_PROFILE=&amp;#39;china&amp;#39;&#xA;  export AWS_ACCESS_KEY_ID=&amp;#39;AKIAWHEATLICIOUSPANCAK&amp;#39;&#xA;  export AWS_SECRET_ACCESS_KEY=&amp;#39;wSyrupyDeliciousSecretKeyForBreakfastDelight42&amp;#39;&#xA;  export AWS_SESSION_TOKEN=&amp;#39;FwoGZXIvYXdzEBaaDCakesYrUpSWeetToKenArEDelIcIoUs...&amp;#39;&#xA;&#xA;✓ Successfully authenticated to AWS China&#xA;&#xA;Copy and paste the export commands above to apply credentials.&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The script prompts the user for an OTP; that&amp;rsquo;s the only input.&lt;/p&gt;&#xA;&lt;p&gt;There are three ways to execute it:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;source it: the variables are then exported directly&lt;/li&gt;&#xA;&lt;li&gt;eval it: ditto&lt;/li&gt;&#xA;&lt;li&gt;execute it: in this mode it&amp;rsquo;s not possible to export the variables. Instead,&#xA;they are simply printed to stdout, and there&amp;rsquo;s a message instructing the user&#xA;to manually copy and paste the exports&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Later on I added integration with 1Password, via &lt;code&gt;--op-account&lt;/code&gt; and &lt;code&gt;--op-item&lt;/code&gt;,&#xA;so that the OTP can be retrieved directly from it, without any user intervention&#xA;or interruption – besides using biometrics (touch ID) to confirm the&#xA;operation.&lt;/p&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: New script: AWS China MFA login&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/security/&#34;&gt;#security&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Terraform: rename resources
      </title>
      <link>https://perrotta.dev/2025/03/terraform-rename-resources/</link>
      <pubDate>Wed, 19 Mar 2025 11:40:43 +0100</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <category>terraform</category>
      <guid>https://perrotta.dev/2025/03/terraform-rename-resources/</guid>
      <description>&lt;p&gt;♠ Sometimes I need to make a simple refactoring rename change to a terraform&#xA;resource that has already been applied. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;aws_api_gateway_request_validator&amp;#34; &amp;#34;delete&amp;#34; {&#xA;  name                        = &amp;#34;Validate body, query string parameters, and headers&amp;#34;&#xA;  rest_api_id                 = aws_api_gateway_rest_api.this.id&#xA;  validate_request_body       = true&#xA;  validate_request_parameters = true&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;to&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;resource &amp;#34;aws_api_gateway_request_validator&amp;#34; &amp;#34;this&amp;#34; {&#xA;  name                        = &amp;#34;Validate body, query string parameters, and headers&amp;#34;&#xA;  rest_api_id                 = aws_api_gateway_rest_api.this.id&#xA;  validate_request_body       = true&#xA;  validate_request_parameters = true&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;The simplest way to do so is to &lt;code&gt;terraform apply&lt;/code&gt;. However, that incurs&#xA;destruction + re-creation of the resource, which would incur downtime in case&#xA;it&amp;rsquo;s already deployed in prod.&lt;/p&gt;&#xA;&lt;p&gt;The best way is &lt;code&gt;% terraform state mv aws_api_gateway_request_validator.{delete,this}&lt;/code&gt;. In-place move, simple and&#xA;easy.&lt;/p&gt;&#xA;&lt;p&gt;When doing it at scale, running multiple &lt;code&gt;terraform state mv&lt;/code&gt; commands could be&#xA;cumbersome.&lt;/p&gt;&#xA;&lt;p&gt;There&amp;rsquo;s a second way, using the&#xA;&lt;a href=&#34;https://developer.hashicorp.com/terraform/language/moved&#34;&gt;&lt;code&gt;moved&lt;/code&gt;&lt;/a&gt; block in HCL:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;moved {&#xA;    from = aws_api_gateway_request_validator.delete&#xA;    to = aws_api_gateway_request_validator.this&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;terraform&lt;/code&gt; docs call this operation &amp;ldquo;move&amp;rdquo;, instead of &amp;ldquo;rename&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: Terraform: rename resources&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/terraform/&#34;&gt;#terraform&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>★ skopeo: operate container images and registries
      </title>
      <link>https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/</link>
      <pubDate>Tue, 17 Dec 2024 17:49:31 -0300</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>bestof</category>
      <category>dev</category>
      <category>docker</category>
      <category>kubernetes</category>
      <guid>https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/</guid>
      <description>&lt;p&gt;♠ When working with &lt;code&gt;docker&lt;/code&gt; and private image registries, a common workflow is to copy images from one private registry in the cloud to another. This can be done with &lt;a href=&#34;https://github.com/containers/skopeo/&#34;&gt;&lt;code&gt;skopeo&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;This post includes some common recipes for it.&lt;/p&gt;&#xA;&lt;h2 id=&#34;usage-1-default--root-to-staging&#34;&gt;&#xA;  Usage 1) Default / Root to Staging&#xA;  &lt;a class=&#34;heading-anchor&#34; href=&#34;https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/#usage-1-default--root-to-staging&#34; aria-label=&#34;Link to this section&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;From the default / root account registry to the staging registry:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;skopeo sync \&#xA;  --src-creds &amp;#34;AWS:$(aws ecr get-login-password --region {region} --profile default)&amp;#34; \&#xA;  --dest-creds &amp;#34;AWS:$(aws ecr get-login-password --region {region} --profile staging)&amp;#34; \&#xA;  --override-os linux --override-arch amd64 \&#xA;  --src docker --dest docker \&#xA;  {account_id_root}.dkr.ecr.{region}.amazonaws.com/{org}/{repository}:{tag} \&#xA;  {account_id_staging}.dkr.ecr.{region}.amazonaws.com/{org}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Example values&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;repository: &lt;code&gt;argocd-gitops-tools&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;tag (version): &lt;code&gt;1.0.1&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;region: &lt;code&gt;us-east-1&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;usage-2-public-to-mfa&#34;&gt;&#xA;  Usage 2) Public to MFA&#xA;  &lt;a class=&#34;heading-anchor&#34; href=&#34;https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/#usage-2-public-to-mfa&#34; aria-label=&#34;Link to this section&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;From a public registry to a private registry that uses MFA (multi-factor authentication).&lt;/p&gt;&#xA;&lt;p&gt;First, it&amp;rsquo;s necessary to get MFA credentials. Source the script below&#xA;(&lt;code&gt;china.mfa.sh&lt;/code&gt;):&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;#!/usr/bin/env bash&#xA;# shellcheck disable=SC2155&#xA;&#xA;export AWS_PROFILE=china&#xA;&#xA;echo -n &amp;#34;Enter the MFA token code for your AWS China account: &amp;#34; &amp;amp;&amp;amp; read -r token&#xA;&#xA;mfa_arn=&amp;#34;$(aws iam --profile &amp;#34;$AWS_PROFILE&amp;#34; get-user --output text --query User.Arn | sed &amp;#39;s/:user\//:mfa\//&amp;#39;)&amp;#34;&#xA;credentials=&amp;#34;$(aws --profile &amp;#34;$AWS_PROFILE&amp;#34; sts get-session-token --serial-number &amp;#34;$mfa_arn&amp;#34; --token-code &amp;#34;$token&amp;#34; --duration-seconds 86400)&amp;#34;&#xA;&#xA;echo &amp;#34;Got credentials: $credentials&amp;#34;&#xA;&#xA;export AWS_ACCESS_KEY_ID=$(echo &amp;#34;$credentials&amp;#34; | jq -r &amp;#39;.Credentials.AccessKeyId&amp;#39;)&#xA;export AWS_SECRET_ACCESS_KEY=$(echo &amp;#34;$credentials&amp;#34; | jq -r &amp;#39;.Credentials.SecretAccessKey&amp;#39;)&#xA;export AWS_SESSION_TOKEN=$(echo &amp;#34;$credentials&amp;#34; | jq -r &amp;#39;.Credentials.SessionToken&amp;#39;)&#xA;&#xA;[[ -n &amp;#34;$AWS_SESSION_TOKEN&amp;#34; ] &amp;amp;&amp;amp; echo &amp;#34;Success!&amp;#34;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: It is necessary to do &lt;code&gt;source china-mfa.sh&lt;/code&gt;. Doing &lt;code&gt;./china-mfa.sh&lt;/code&gt;&#xA;will &lt;strong&gt;not&lt;/strong&gt; work.&lt;/p&gt;&#xA;&lt;p&gt;Then we can proceed with the image sync:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;skopeo sync \&#xA;  --dest-creds &amp;#34;AWS:$(aws ecr get-login-password --region cn-north-1)&amp;#34; \&#xA;  --override-os linux --override-arch amd64 \&#xA;  --src docker \&#xA;  --dest docker \&#xA;  quay.io/argoproj/argocd:v2.12.6 \&#xA;  {account_id_mfa}.dkr.ecr.cn-north-1.amazonaws.com.cn/quay.io/argoproj&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Notes:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;A public registry does not need authentication, hence there&amp;rsquo;s no &lt;code&gt;--src-creds&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;--dest-creds&lt;/code&gt; does not specify a &lt;code&gt;--profile&lt;/code&gt;. Likewise, no &lt;code&gt;AWS_PROFILE&lt;/code&gt; env var should be defined.&lt;/li&gt;&#xA;&lt;li&gt;In this example, China (&lt;code&gt;cn-north-1&lt;/code&gt;) is an AWS account with MFA enabled.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;h2 id=&#34;potpourri&#34;&gt;&#xA;  Potpourri&#xA;  &lt;a class=&#34;heading-anchor&#34; href=&#34;https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/#potpourri&#34; aria-label=&#34;Link to this section&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;It&amp;rsquo;s possible to pass &lt;code&gt;--scoped&lt;/code&gt; to prefix images at destination using the&#xA;full source image path as scope.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;To sync multiple image architectures, pass &lt;code&gt;-a&lt;/code&gt; or &lt;code&gt;--all&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;If syncing from/to Azure (ACR), use &lt;code&gt;az acr login&lt;/code&gt;. Find the &lt;code&gt;username&lt;/code&gt; in the&#xA;Azure portal. For example:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;az acr login -n {container registry name} --expose-token | jq -r &amp;#39;.accessToken&amp;#39; | skopeo login {registry} --password-stdin --username {username}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;image = registry (includes the org name) + repository + tag&amp;#160;&lt;a href=&#34;https://perrotta.dev/2024/12/skopeo-operate-container-images-and-registries/#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: skopeo: operate container images and registries&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/bestof/&#34;&gt;#bestof&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/docker/&#34;&gt;#docker&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/kubernetes/&#34;&gt;#kubernetes&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Docker build: ignore cache
      </title>
      <link>https://perrotta.dev/2024/12/docker-build-ignore-cache/</link>
      <pubDate>Tue, 10 Dec 2024 19:45:42 -0300</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <category>docker</category>
      <guid>https://perrotta.dev/2024/12/docker-build-ignore-cache/</guid>
      <description>&lt;p&gt;♠ To build a docker image completely from scratch, without reusing cache layers on&#xA;your system:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;docker build --no-cache -f Dockerfile . -t {image name}:{image tag} --platform&#xA;linux/amd64&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Pass an explicit platform in case e.g. you&amp;rsquo;re building on a Mac M1 (arm64)&#xA;with the intent of running it on Linux in the cloud (amd64 typically).&lt;/li&gt;&#xA;&lt;li&gt;The docker image full specification is: image =&#xA;&lt;code&gt;{registry}/{repository}:{tag}&lt;/code&gt;. For example, the registry could be an AWS ECR&#xA;URL, whereas the repository is something like &amp;ldquo;bitnami/sealed-secrets&amp;rdquo;, and&#xA;the tag typically follows semantic versioning.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: Docker build: ignore cache&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/docker/&#34;&gt;#docker&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Check if docker image exists in registry
      </title>
      <link>https://perrotta.dev/2024/10/check-if-docker-image-exists-in-registry/</link>
      <pubDate>Fri, 25 Oct 2024 14:11:14 +0200</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <category>docker</category>
      <guid>https://perrotta.dev/2024/10/check-if-docker-image-exists-in-registry/</guid>
      <description>&lt;p&gt;♠ Given a docker registry, image and tag, run the following command:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;% docker manifest inspect 9876543210.foo.ecr.us-east-1.amazonaws.com/org/image:123456789&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If it does not exist, you&amp;rsquo;ll see:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plaintext&#34;&gt;no such manifest: 9876543210.foo.ecr.us-east-1.amazonaws.com/org/image:123456789&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Ensure you are authenticated and/or connected to the VPN in case of a private registry.&lt;/p&gt;&#xA;&lt;p&gt;When using ECR (AWS&amp;rsquo;s registry), you can authenticate this way:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;% which docker_login&#xA;docker_login () {&#xA;&#x9;aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 9876543210.foo.ecr.us-east-1.amazonaws.com&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: Check if docker image exists in registry&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/docker/&#34;&gt;#docker&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>★ prodaccess
      </title>
      <link>https://perrotta.dev/2024/10/prodaccess/</link>
      <pubDate>Fri, 18 Oct 2024 14:57:27 +0200</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>bestof</category>
      <category>dev</category>
      <guid>https://perrotta.dev/2024/10/prodaccess/</guid>
      <description>&lt;p&gt;♠ At Google we had a &lt;code&gt;prodaccess&lt;/code&gt; command used to log in and authenticate in all&#xA;sorts of internal corp systems&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;https://perrotta.dev/2024/10/prodaccess/#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; for 20 hours. It became a daily ritual to run&#xA;&lt;code&gt;prodaccess&lt;/code&gt; first thing in the morning when logging in upon unlocking our&#xA;physical workstations&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;https://perrotta.dev/2024/10/prodaccess/#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;&#xA;&lt;p&gt;During the pandemic, when heavily using our virtual workstations (dubbed&#xA;&lt;em&gt;cloudtops&lt;/em&gt;, think of an EC2 instance or a VPS) it was common to hook&#xA;&lt;code&gt;prodaccess&lt;/code&gt; into &lt;code&gt;ssh&lt;/code&gt;. There was a &lt;code&gt;prodcertstatus&lt;/code&gt; command that would tell&#xA;you when &lt;code&gt;prodaccess&lt;/code&gt; would expire. A common pattern was to modify your &lt;code&gt;ssh&lt;/code&gt;&#xA;startup command to automatically run &lt;code&gt;prodaccess&lt;/code&gt; whenever &lt;code&gt;prodcertstatus&lt;/code&gt;&#xA;indicated that access would expire within 2-4 hours, depending on the user&amp;rsquo;s&#xA;preference.&lt;/p&gt;&#xA;&lt;p&gt;Given my trained muscle memory, I wanted to continue to use this alias even in&#xA;environments other than Google:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;[...]&#xA;prodaccess() {&#xA;&#x9;echo &amp;#34;--&amp;gt; VPN&amp;#34;&#xA;&#x9;vpn_login&#xA;&#xA;&#x9;echo &amp;#34;--&amp;gt; Teleport&amp;#34;&#xA;&#x9;teleport_login&#xA;&#xA;&#x9;echo &amp;#34;--&amp;gt; AWS&amp;#34;&#xA;&#x9;aws_login&#xA;&#xA;    echo &amp;#34;--&amp;gt; Azure&amp;#34;&#xA;    azure_login&#xA;&#xA;&#x9;case &amp;#34;$1&amp;#34; in&#xA;&#x9;&#x9;-u|--update)&#xA;&#x9;&#x9;&#x9;echo &amp;#34;--&amp;gt; mr&amp;#34;&#xA;&#x9;&#x9;&#x9;# Update all well-known corp repositories&#xA;&#x9;&#x9;&#x9;(cd ~/Corp &amp;amp;&amp;amp; mr update &amp;amp;&amp;amp; mr run git world)&#xA;&#xA;&#x9;&#x9;&#x9;# Package manager upgrade&#xA;&#x9;&#x9;&#x9;echo &amp;#34;--&amp;gt; sd-world&amp;#34;&#xA;&#x9;&#x9;&#x9;sd-world&#xA;&#xA;&#x9;&#x9;&#x9;shift&#xA;&#x9;&#x9;&#x9;;;&#xA;&#xA;&#x9;&#x9;-a|--all)&#xA;&#x9;&#x9;&#x9;echo &amp;#34;--&amp;gt; Atlas Mongo&amp;#34;&#xA;&#x9;&#x9;&#x9;atlas_login&#xA;&#xA;&#x9;&#x9;&#x9;shift&#xA;&#x9;&#x9;&#x9;;;&#xA;&#x9;esac&#xA;}&#xA;[...]&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Notes:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;mr&lt;/code&gt; is &lt;a href=&#34;https://myrepos.branchable.com/&#34;&gt;https://myrepos.branchable.com/&lt;/a&gt; (&amp;ldquo;a tool to manage all your version&#xA;control repositories&amp;rdquo;)&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;https://perrotta.dev/2024/10/prodaccess/#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;sd-world&lt;/code&gt; was introduced in a &lt;a href=&#34;https://perrotta.dev/2024/01/sd-world-perform-a-full-system-upgrade/&#34;&gt;previous post&lt;/a&gt;: it performs a full system upgrade&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;--all&lt;/code&gt; holds services I only need / use from time to time.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;shift&lt;/code&gt; is not really needed, but IMHO it&amp;rsquo;s a good practice (and another&#xA;ingrained habit of mine), especially when inside &lt;code&gt;for&lt;/code&gt; loops&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;git world&lt;/code&gt; is an alias in my &lt;code&gt;~/.gitconfig&lt;/code&gt; that runs &lt;code&gt;git fetch --all &amp;amp;&amp;amp; git remote prune origin&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Every morning I invoke &lt;code&gt;prodaccess -u&lt;/code&gt; when starting my work day. A few password&#xA;prompts and touch IDs later and I do not need to worry about logging in anymore&#xA;during the middle of the day, which reduces overall context switching and&#xA;stress.&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;Until someone in CorpEng decided it was a good idea to&#xA;&lt;a href=&#34;https://killedbygoogle.com/&#34;&gt;deprecate&lt;/a&gt; it in favour of a new &lt;code&gt;gcert&lt;/code&gt;&#xA;command, destroying many SWE-years of developed muscle memory.&amp;#160;&lt;a href=&#34;https://perrotta.dev/2024/10/prodaccess/#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:2&#34;&gt;&#xA;&lt;p&gt;Ah, the &lt;em&gt;good ol&amp;rsquo; times&lt;/em&gt;.&amp;#160;&lt;a href=&#34;https://perrotta.dev/2024/10/prodaccess/#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;li id=&#34;fn:3&#34;&gt;&#xA;&lt;p&gt;I should write a post about it sometime.&amp;#160;&lt;a href=&#34;https://perrotta.dev/2024/10/prodaccess/#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: prodaccess&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/bestof/&#34;&gt;#bestof&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>AWS S3: search by suffix
      </title>
      <link>https://perrotta.dev/2024/09/aws-s3-search-by-suffix/</link>
      <pubDate>Thu, 05 Sep 2024 17:09:38 +0200</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <guid>https://perrotta.dev/2024/09/aws-s3-search-by-suffix/</guid>
      <description>&lt;p&gt;♠ Given an AWS S3 bucket, how to recursively list all objects within it that match&#xA;a given suffix?&lt;/p&gt;&#xA;&lt;p&gt;The following example searches for all objects that end with &lt;code&gt;thiagowfx&lt;/code&gt;.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;aws s3 rm --profile {aws_profile} s3://example.com/my/path/ --recursive --dryrun --exclude &amp;#39;*&amp;#39; --include &amp;#34;*thiagowfx&amp;#34;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;This is a hack with a dry-run deletion operation.&lt;/p&gt;&#xA;&lt;p&gt;Alternatively, use &lt;code&gt;aws s3 ls&lt;/code&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;https://perrotta.dev/2024/09/aws-s3-search-by-suffix/#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; plus &lt;code&gt;grep&lt;/code&gt; / &lt;code&gt;awk&lt;/code&gt; / &lt;code&gt;sed&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-bash&#34;&gt;aws s3 ls --profile {aws_profile} s3://example.com/my/path | awk -F &amp;#39; &amp;#39; &amp;#39;{print $4}&amp;#39; | grep &amp;#39;thiagowfx$&amp;#39;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Why would you use &lt;code&gt;rm&lt;/code&gt; in lieu of &lt;code&gt;ls&lt;/code&gt;? Mostly because of the built-in&#xA;&lt;code&gt;--include&lt;/code&gt; / &lt;code&gt;--exclude&lt;/code&gt; options. If you happen to have millions of objects in&#xA;your S3 bucket, then you do not need to list them all.&lt;/p&gt;&#xA;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;&#xA;&lt;hr&gt;&#xA;&lt;ol&gt;&#xA;&lt;li id=&#34;fn:1&#34;&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html&#34;&gt;https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html&lt;/a&gt;&amp;#160;&lt;a href=&#34;https://perrotta.dev/2024/09/aws-s3-search-by-suffix/#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/div&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: AWS S3: search by suffix&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Terraform: AWS deployment to random availability zones
      </title>
      <link>https://perrotta.dev/2024/05/terraform-aws-deployment-to-random-availability-zones/</link>
      <pubDate>Tue, 21 May 2024 14:31:03 +0200</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <category>terraform</category>
      <guid>https://perrotta.dev/2024/05/terraform-aws-deployment-to-random-availability-zones/</guid>
      <description>&lt;p&gt;♠ A common scenario: there&amp;rsquo;s a new deployment you would like to roll out to AWS.&#xA;Let&amp;rsquo;s say you pick &amp;ldquo;us-east-1&amp;rdquo; as your cloud region. There are multiple&#xA;availability zones within it:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;us-east-1a&lt;/li&gt;&#xA;&lt;li&gt;us-east-1b&lt;/li&gt;&#xA;&lt;li&gt;us-east-1c&lt;/li&gt;&#xA;&lt;li&gt;us-east-1d&lt;/li&gt;&#xA;&lt;li&gt;us-east-1e&lt;/li&gt;&#xA;&lt;li&gt;us-east-1f&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Suppose you want to pick two of them for your service/app, and you don&amp;rsquo;t&#xA;particularly care about which one. How to proceed?&lt;/p&gt;&#xA;&lt;h2 id=&#34;option-1-hard-coding&#34;&gt;&#xA;  Option #1: Hard-coding&#xA;  &lt;a class=&#34;heading-anchor&#34; href=&#34;https://perrotta.dev/2024/05/terraform-aws-deployment-to-random-availability-zones/#option-1-hard-coding&#34; aria-label=&#34;Link to this section&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Pick two arbitrary zones and hard-code them.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;variable &amp;#34;availability_zones&amp;#34; {&#xA;  type    = list(string)&#xA;  default = [&amp;#34;us-east-1a&amp;#34;, &amp;#34;us-east-1b&amp;#34;]&#xA;}&#xA;&#xA;resource &amp;#34;aws_subnet&amp;#34; &amp;#34;private&amp;#34; {&#xA;  vpc_id            = aws_vpc.chartmuseum.id&#xA;  cidr_block        = element(var.private_subnets, count.index)&#xA;  availability_zone = element(var.availability_zones, count.index)&#xA;  count             = length(var.private_subnets)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;strong&gt;Caveat&lt;/strong&gt;: &lt;a href=&#34;https://www.goodreads.com/book/show/10639.The_Paradox_of_Choice&#34;&gt;The paradox of&#xA;choice&lt;/a&gt;,&#xA;unnecessary decision fatigue.&lt;/p&gt;&#xA;&lt;h2 id=&#34;option-2-pick-the-first-two&#34;&gt;&#xA;  Option #2: Pick the first two&#xA;  &lt;a class=&#34;heading-anchor&#34; href=&#34;https://perrotta.dev/2024/05/terraform-aws-deployment-to-random-availability-zones/#option-2-pick-the-first-two&#34; aria-label=&#34;Link to this section&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Use the AWS data source to dynamically find all zones, and pick the first two.&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;data &amp;#34;aws_availability_zones&amp;#34; &amp;#34;available&amp;#34; {&#xA;  state = &amp;#34;available&amp;#34;&#xA;}&#xA;&#xA;resource &amp;#34;aws_subnet&amp;#34; &amp;#34;private&amp;#34; {&#xA;  vpc_id            = aws_vpc.chartmuseum.id&#xA;  cidr_block        = element(var.private_subnets, count.index)&#xA;  availability_zone = element(data.aws_availability_zones.available.names, count.index)&#xA;  count             = length(var.private_subnets)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;Note that &lt;code&gt;terraform plan&lt;/code&gt; should display the full zone list.&lt;/p&gt;&#xA;&lt;p&gt;&lt;strong&gt;Caveat&lt;/strong&gt;: Heavily biased towards the first two zones.&lt;/p&gt;&#xA;&lt;h2 id=&#34;option-3-random-shuffling&#34;&gt;&#xA;  Option #3: Random shuffling&#xA;  &lt;a class=&#34;heading-anchor&#34; href=&#34;https://perrotta.dev/2024/05/terraform-aws-deployment-to-random-availability-zones/#option-3-random-shuffling&#34; aria-label=&#34;Link to this section&#34;&gt;#&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;p&gt;Pick two zones at random!&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-terraform&#34;&gt;data &amp;#34;aws_availability_zones&amp;#34; &amp;#34;available&amp;#34; {&#xA;  state = &amp;#34;available&amp;#34;&#xA;}&#xA;&#xA;resource &amp;#34;random_shuffle&amp;#34; &amp;#34;aws_availability_zone_names&amp;#34; {&#xA;  input        = data.aws_availability_zones.available.names&#xA;  result_count = 2&#xA;}&#xA;&#xA;resource &amp;#34;aws_subnet&amp;#34; &amp;#34;private&amp;#34; {&#xA;  vpc_id            = aws_vpc.chartmuseum.id&#xA;  cidr_block        = element(var.private_subnets, count.index)&#xA;  availability_zone = element(random_shuffle.aws_availability_zone_names.result, count.index)&#xA;  count             = length(var.private_subnets)&#xA;}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;strong&gt;Winner&lt;/strong&gt;: In my opinion, this is the most elegant approach.&lt;/p&gt;&#xA;&lt;p&gt;&lt;code&gt;random_shuffle&lt;/code&gt; will output the selected regions upon running &lt;code&gt;terraform apply&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: Terraform: AWS deployment to random availability zones&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/terraform/&#34;&gt;#terraform&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>Adding a healthcheck to chartmuseum in AWS Fargate
      </title>
      <link>https://perrotta.dev/2024/05/adding-a-healthcheck-to-chartmuseum-in-aws-fargate/</link>
      <pubDate>Fri, 17 May 2024 11:15:09 +0200</pubDate><author>serendipity@perrotta.dev (Thiago Perrotta)</author>
      <category>aws</category>
      <category>dev</category>
      <category>docker</category>
      <category>kubernetes</category>
      <guid>https://perrotta.dev/2024/05/adding-a-healthcheck-to-chartmuseum-in-aws-fargate/</guid>
      <description>&lt;p&gt;♠ Assume that you have a &lt;a href=&#34;https://chartmuseum.com/&#34;&gt;Chartmuseum&lt;/a&gt; container running&#xA;in &lt;a href=&#34;https://aws.amazon.com/fargate/&#34;&gt;AWS Fargate&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;p&gt;Chartmuseum is a repository for helm charts. AWS Fargate is an Amazon service to&#xA;run containers (&amp;ldquo;serverless&amp;rdquo;), being part of ECS (Elastic Container Service).&lt;/p&gt;&#xA;&lt;p&gt;Problem statement: Add a container &lt;em&gt;healthcheck&lt;/em&gt; to the chartmuseum task&#xA;definition associated with the container.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html&#34;&gt;official&#xA;docs&lt;/a&gt;&#xA;suggest using &lt;code&gt;curl&lt;/code&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plaintext&#34;&gt;[&amp;#34;CMD-SHELL&amp;#34;, &amp;#34;curl -f http://localhost/ || exit 1&amp;#34;]&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;For Chartmuseum specifically we&amp;rsquo;re interested in its &lt;code&gt;/health&lt;/code&gt; endpoint, as per&#xA;&lt;a href=&#34;https://github.com/helm/chartmuseum/issues/28&#34;&gt;this reference&lt;/a&gt;:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plaintext&#34;&gt;[&amp;#34;CMD-SHELL&amp;#34;, &amp;#34;curl -f http://localhost/health || exit 1&amp;#34;]&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;But we&amp;rsquo;re using port 8080:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plaintext&#34;&gt;[&amp;#34;CMD-SHELL&amp;#34;, &amp;#34;curl -f http://localhost:8080/health || exit 1&amp;#34;]&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;If you use this healthcheck for the official chartmuseum image&#xA;(&lt;code&gt;ghcr.io/helm/chartmuseum&lt;/code&gt;) it will fail, because the Alpine Linux environment&#xA;it uses does not contain &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;&#xA;&lt;p&gt;A straightforward fix is to use &lt;code&gt;wget&lt;/code&gt; instead:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-plaintext&#34;&gt;[&amp;#34;CMD-SHELL&amp;#34;, &amp;#34;wget -q --spider http://localhost:8080/health || exit 1&amp;#34;]&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;&lt;code&gt;--spider&lt;/code&gt; is needed because we do not want to download anything, &lt;code&gt;-q&lt;/code&gt; is&#xA;optional and short for &amp;ldquo;quiet&amp;rdquo;.&lt;/p&gt;&#xA;&lt;p&gt;The &lt;code&gt;/health&lt;/code&gt; endpoint merely returns a simple JSON:&lt;/p&gt;&#xA;&#xA;&lt;pre&gt;&lt;code class=&#34;language-json&#34;&gt;{&amp;#34;healthy&amp;#34;:true}&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;p&gt;References: &lt;a href=&#34;https://stackoverflow.com/questions/47722898/how-can-i-make-a-docker-healthcheck-with-wget-instead-of-curl&#34;&gt;https://stackoverflow.com/questions/47722898/how-can-i-make-a-docker-healthcheck-with-wget-instead-of-curl&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;— § —&lt;/p&gt;&lt;p&gt;Reply via &lt;a href=&#34;mailto:serendipity@perrotta.dev?subject=Reply to: Adding a healthcheck to chartmuseum in AWS Fargate&#34;&gt;email&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&#34;https://perrotta.dev/tags/aws/&#34;&gt;#aws&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/dev/&#34;&gt;#dev&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/docker/&#34;&gt;#docker&lt;/a&gt; &lt;a href=&#34;https://perrotta.dev/tags/kubernetes/&#34;&gt;#kubernetes&lt;/a&gt;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
