<?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>The Ops Community ⚙️: Leonardo Rodrigues de Oliveira</title>
    <description>The latest articles on The Ops Community ⚙️ by Leonardo Rodrigues de Oliveira (@oleonardorodrigues).</description>
    <link>https://community.ops.io/oleonardorodrigues</link>
    <image>
      <url>https://community.ops.io/images/S0sims9gl9zkHFvk_PFUNUC9B72MI0A3wY2-HZOzIBM/rs:fill:90:90/g:sm/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL3Vz/ZXIvcHJvZmlsZV9p/bWFnZS83MjgvNGMy/MGFiM2UtZjY1ZC00/MmY3LTk1NDktYTJl/M2FkYTQ0ZTIyLmpw/ZWc</url>
      <title>The Ops Community ⚙️: Leonardo Rodrigues de Oliveira</title>
      <link>https://community.ops.io/oleonardorodrigues</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://community.ops.io/feed/oleonardorodrigues"/>
    <language>en</language>
    <item>
      <title>A Quebra de Linha no Final dos Arquivos e sua Necessidade no Ambiente Linux</title>
      <dc:creator>Leonardo Rodrigues de Oliveira</dc:creator>
      <pubDate>Mon, 20 Feb 2023 14:15:26 +0000</pubDate>
      <link>https://community.ops.io/lontritech/a-quebra-de-linha-no-final-dos-arquivos-e-sua-necessidade-no-ambiente-linux-jd4</link>
      <guid>https://community.ops.io/lontritech/a-quebra-de-linha-no-final-dos-arquivos-e-sua-necessidade-no-ambiente-linux-jd4</guid>
      <description>&lt;p&gt;A quebra de linha no fim dos arquivos é um assunto pouco conhecido para muitos usuários de Linux, mas é essencial para o funcionamento adequado de muitas aplicações. A quebra de linha no final de cada linha de um arquivo é um padrão que indica ao sistema operacional como ler e interpretar o arquivo.&lt;/p&gt;

&lt;p&gt;Nos sistemas Unix e Linux, a quebra de linha é indicada pelo caractere LF (line feed), enquanto no Windows, é indicada pelos caracteres CR (carriage return) e LF. Isso significa que um arquivo criado no Windows com a quebra de linha adequada pode não funcionar corretamente em um ambiente Unix ou Linux, e vice-versa.&lt;/p&gt;

&lt;p&gt;Sem a quebra de linha no final de um arquivo, o sistema operacional não pode determinar onde uma linha termina e onde começa a próxima. Isso pode causar erros ao tentar ler ou executar o arquivo, e até mesmo corromper o arquivo completamente.&lt;/p&gt;

&lt;p&gt;Por isso, é importante garantir que todos os arquivos criados em um sistema Unix ou Linux tenham a quebra de linha adequada no final de cada linha. Isso pode ser feito facilmente usando editores de texto como o vi ou o nano, que inserem automaticamente a quebra de linha ao final de cada linha.&lt;/p&gt;

&lt;p&gt;Além disso, existem ferramentas de conversão de arquivos disponíveis que podem ser usadas para converter arquivos com quebras de linha incompatíveis em um formato que funcione em sistemas Unix e Linux.&lt;/p&gt;

&lt;p&gt;Em resumo, a quebra de linha no final dos arquivos é um padrão essencial que deve ser seguido para garantir que os arquivos funcionem corretamente em sistemas Unix e Linux. É importante lembrar de incluir a quebra de linha ao final de cada linha ao criar ou editar arquivos, e converter arquivos incompatíveis quando necessário. Dessa forma, podemos evitar problemas e garantir que nossos arquivos sejam lidos e executados corretamente.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>sysadmin</category>
    </item>
    <item>
      <title>We Need to Talk About AzureRM's Terraform Provider Limitations and Known Bugs</title>
      <dc:creator>Leonardo Rodrigues de Oliveira</dc:creator>
      <pubDate>Thu, 16 Feb 2023 10:44:14 +0000</pubDate>
      <link>https://community.ops.io/lontritech/we-need-to-talk-about-azurerms-azure-provider-limitations-and-known-bugs-5eeo</link>
      <guid>https://community.ops.io/lontritech/we-need-to-talk-about-azurerms-azure-provider-limitations-and-known-bugs-5eeo</guid>
      <description>&lt;p&gt;Terraform is an open-source infrastructure as code (IAC) tool that enables users to provision and manage cloud infrastructure resources across multiple providers, including Microsoft Azure. The Azure provider for Terraform, known as "azurerm," has become increasingly popular for managing Azure resources due to its ease of use and extensive feature set. However, like any software product, the azurerm provider has some known limitations and bugs that users should be aware of.&lt;/p&gt;

&lt;p&gt;One limitation of the azurerm provider is that it can be slow to apply changes to large or complex environments. This can be particularly noticeable when working with larger virtual networks or storage accounts. Some users have reported that applying changes to these resources can take several minutes or even hours, which can be frustrating when working on time-sensitive projects.&lt;/p&gt;

&lt;p&gt;Another known limitation of the azurerm provider is that it can be difficult to manage dependencies between resources. This can be especially problematic when working with complex infrastructure configurations that require resources to be created in a specific order. While Terraform does provide some tools to manage these dependencies, users may need to manually configure resource dependencies in some cases, which can be time-consuming and error-prone.&lt;/p&gt;

&lt;p&gt;In addition to these limitations, the azurerm provider also has some known bugs that can cause issues for users. For example, some users have reported issues with the provider's support for managing Azure AD groups and permissions. There have also been reports of intermittent issues with the provider's support for certain Azure resource types, such as load balancers and virtual networks.&lt;/p&gt;

&lt;p&gt;Despite these limitations and bugs, the azurerm provider for Terraform remains a powerful and flexible tool for managing Azure resources. To mitigate these issues, users can take steps such as optimizing their resource configurations for speed, carefully managing resource dependencies, and keeping an eye out for updates and bug fixes from the Terraform community. By doing so, users can continue to take advantage of the benefits of Terraform and the azurerm provider for managing their cloud infrastructure resources in Azure.&lt;/p&gt;




&lt;h2&gt;
  
  
  More Content
&lt;/h2&gt;

&lt;p&gt;If this article helped you or someone you know and you want to know more of these useful tools or tips for your IaC needs, follow me on &lt;a href="https://www.linkedin.com/in/lro/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://community.ops.io/oleonardorodrigues"&gt;here&lt;/a&gt; or on &lt;a href="https://github.com/OLeonardoRodrigues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and don't miss my updates!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>azure</category>
      <category>terraform</category>
      <category>cloudops</category>
    </item>
    <item>
      <title>Multi-Stage Dockerfiles, Why and How to Use Them</title>
      <dc:creator>Leonardo Rodrigues de Oliveira</dc:creator>
      <pubDate>Wed, 15 Feb 2023 03:20:35 +0000</pubDate>
      <link>https://community.ops.io/lontritech/multi-stage-dockerfiles-why-and-how-to-use-them-4bdl</link>
      <guid>https://community.ops.io/lontritech/multi-stage-dockerfiles-why-and-how-to-use-them-4bdl</guid>
      <description>&lt;p&gt;When building Docker images, it's often necessary to install build tools and dependencies to compile your application. However, these build tools and dependencies can take up a lot of space in your Docker image, which can make your image larger than necessary. To solve this problem, Docker introduced multi-stage builds.&lt;/p&gt;

&lt;p&gt;Multi-stage builds allow you to use multiple FROM statements in a single Dockerfile. Each FROM statement begins a new build stage, allowing you to build and package different parts of your application in separate stages. This can result in smaller and more efficient Docker images.&lt;/p&gt;

&lt;p&gt;Here's an example of a multi-stage Dockerfile for a Node.js application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Stage 1: Build the application
FROM node:14-alpine AS build

WORKDIR /app

COPY package.json package-lock.json ./
RUN npm install

COPY . .
RUN npm run build

# Stage 2: Serve the application
FROM node:14-alpine

WORKDIR /app

COPY --from=build /app/dist ./dist
COPY package.json package-lock.json ./
RUN npm install --production

CMD ["npm", "start"]

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

&lt;/div&gt;



&lt;p&gt;Let's go over what this Dockerfile is doing. In the first stage, we're using the node:14-alpine base image to build the application. We set the working directory to /app, copy the package.json and package-lock.json files, and run npm install. Then, we copy the rest of the application files and run npm run build. This will compile the application into the /app/dist directory.&lt;/p&gt;

&lt;p&gt;In the second stage, we're using the node:14-alpine base image again to serve the application. We set the working directory to /app, copy the compiled files from the previous stage using the --from flag, copy the package.json and package-lock.json files, and run npm install --production. Finally, we set the command to start the application using npm start.&lt;/p&gt;

&lt;p&gt;When building this Dockerfile, Docker will first build the first stage, then use the compiled files in the second stage. This allows us to keep the build tools and dependencies in the first stage, and only include the compiled files and runtime dependencies in the second stage. The resulting Docker image will be smaller and more efficient.&lt;/p&gt;

&lt;p&gt;To build this Dockerfile, run the following command in the same directory as the Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t my-node-app .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will build the Docker image and tag it with the name my-node-app. You can then run the Docker image using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -p 8080:8080 my-node-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start the Docker container and map port 8080 on the container to port 8080 on the host machine.&lt;/p&gt;

&lt;p&gt;That's it! You now know how to create a multi-stage Dockerfile to build and package your applications more efficiently.&lt;/p&gt;




&lt;h2&gt;
  
  
  More Content
&lt;/h2&gt;

&lt;p&gt;If this article helped you or someone you know and you want to know more of these useful tools or tips for your IaC needs, follow me on &lt;a href="https://www.linkedin.com/in/lro/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://community.ops.io/oleonardorodrigues"&gt;here&lt;/a&gt; or on &lt;a href="https://github.com/OLeonardoRodrigues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and don't miss my updates!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>cicd</category>
      <category>tutorials</category>
      <category>devops</category>
    </item>
    <item>
      <title>How I Keep my Dependencies Updated on GitHub</title>
      <dc:creator>Leonardo Rodrigues de Oliveira</dc:creator>
      <pubDate>Fri, 10 Feb 2023 03:11:22 +0000</pubDate>
      <link>https://community.ops.io/lontritech/how-i-keep-my-dependencies-updated-on-github-12bk</link>
      <guid>https://community.ops.io/lontritech/how-i-keep-my-dependencies-updated-on-github-12bk</guid>
      <description>&lt;p&gt;First I want to let you know I have a hard time keeping track of my projects dependencies, specially if it is something I don't update often, and it might be too late when I finally find out something I'm using is no longer supported, so I was glad to find out about GitHub's way of dealing with this.&lt;/p&gt;

&lt;p&gt;Sometime ago, I learned about a few ways to check for updates on your dependencies, and from time to time I would remember to check it and update my stuff, but it wasn't enough for me, and it got old fast, too manual, until...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/JGsYUCEwyo9wtmyd-AkRWrF9LFDx7jpmmFIBDZ0U9fU/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3dydG9k/dzJuNmU5Z2lrdnV4/eWMzLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/JGsYUCEwyo9wtmyd-AkRWrF9LFDx7jpmmFIBDZ0U9fU/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3dydG9k/dzJuNmU5Z2lrdnV4/eWMzLnBuZw" alt="Dependabot's Anouncement" width="800" height="487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And even if this is not exactly &lt;strong&gt;new&lt;/strong&gt; I don't think we use it enough!&lt;/p&gt;

&lt;p&gt;Dependabot checks for dependency updates for many different package systems, such as NPM, Terraform and even GitHub Actions! Besides the range of this tool it can also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open automatic Pull Requests with the updates; &lt;/li&gt;
&lt;li&gt;Ask for specific reviewers; &lt;/li&gt;
&lt;li&gt;Run as often as you want, daily, weekly, and so on;&lt;/li&gt;
&lt;li&gt;Tag the Pull Request it opens as you like; &lt;/li&gt;
&lt;li&gt;Be configured with a file inside the repository itself; &lt;/li&gt;
&lt;li&gt;Show you changelogs for every single update it finds; &lt;/li&gt;
&lt;li&gt;Check dependencies inside specific directories; &lt;/li&gt;
&lt;li&gt;Check dependencies for multiple technologies inside the same repository; &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setting up
&lt;/h2&gt;

&lt;p&gt;To configure Dependabot the way you want it to work inside your repositories all you have to do is add a file called &lt;code&gt;dependabot.yml&lt;/code&gt; inside the directory &lt;code&gt;.github&lt;/code&gt; on the root of your repository.&lt;/p&gt;

&lt;p&gt;A simple version of the file to keep track of your GitHub Actions dependencies with daily checks could look like this:&lt;br&gt;
&lt;/p&gt;

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

updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "daily"

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

&lt;/div&gt;



&lt;p&gt;And that's about it! It is already set and ready to start helping you.&lt;/p&gt;




&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;If you want to know more about the launching of this tool, check the original post by GitHub: &lt;br&gt;
&lt;a href="https://github.blog/2020-06-01-keep-all-your-packages-up-to-date-with-dependabot/" rel="noopener noreferrer"&gt;Dependabot's Announcement&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To learn about &lt;code&gt;dependabot.yml&lt;/code&gt; check the official syntax guide: &lt;br&gt;
&lt;a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file" rel="noopener noreferrer"&gt;dependabot.yml syntax&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also here's an example of mine on how &lt;code&gt;dependabot.yml&lt;/code&gt; looks like inside a repository: &lt;br&gt;
&lt;a href="https://github.com/OLeonardoRodrigues/terraform-azurerm-available-ips/blob/main/.github/dependabot.yml" rel="noopener noreferrer"&gt;dependabot.yml example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally there's also a list for supported package ecosystems: &lt;br&gt;
&lt;a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem" rel="noopener noreferrer"&gt;Packages Support&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  More Content
&lt;/h2&gt;

&lt;p&gt;If this article helped you or someone you know and you want to know more of these useful tools or tips for your IaC needs, follow me on &lt;a href="https://www.linkedin.com/in/lro/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://community.ops.io/oleonardorodrigues"&gt;here&lt;/a&gt; or on &lt;a href="https://github.com/OLeonardoRodrigues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and don't miss my updates!&lt;/p&gt;

</description>
      <category>dependabot</category>
      <category>automation</category>
      <category>github</category>
      <category>cicd</category>
    </item>
    <item>
      <title>How to Create Automatic Documentation for your Terraform Modules</title>
      <dc:creator>Leonardo Rodrigues de Oliveira</dc:creator>
      <pubDate>Thu, 09 Feb 2023 02:13:44 +0000</pubDate>
      <link>https://community.ops.io/lontritech/how-to-create-automatic-documentation-for-your-terraform-modules-da2</link>
      <guid>https://community.ops.io/lontritech/how-to-create-automatic-documentation-for-your-terraform-modules-da2</guid>
      <description>&lt;p&gt;When I first started writing my Terraform modules, inside organizations or on my own, I struggled with the idea of creating useful documentation for them, and specially looking at the official Terraform Registry it became obvious there should be a way of keeping my README files up to date and useful without a lot of pain, so I started looking for something to solve these issues.&lt;/p&gt;

&lt;p&gt;Eventually I found a tool called "terraform-docs", yeah, pretty straightforward! After testing it for a while it was basically the answer to all my prayers, just to name a few of this tool's capabilities: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;very simple configuration syntax; &lt;/li&gt;
&lt;li&gt;generates markdown valid output; &lt;/li&gt;
&lt;li&gt;replaces or appends to your existing README files; &lt;/li&gt;
&lt;li&gt;can mix the automatic stuff with your own content; &lt;/li&gt;
&lt;li&gt;the results are really useful and look good; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And besides those, when I got to it, there's a handy GitHub Action to make these updates &lt;strong&gt;fully automatic&lt;/strong&gt; even if you commit new stuff without updating the README file, the workflow runs and updates it for you!&lt;/p&gt;

&lt;p&gt;Here is the one example of the results: &lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/LontriTech" rel="noopener noreferrer"&gt;
        LontriTech
      &lt;/a&gt; / &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips" rel="noopener noreferrer"&gt;
        terraform-azurerm-available-ips
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Module responsible for getting available IPs inside a subnet.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Terraform Azure Module: Available IPs&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;Module responsible for getting available IPs inside a subnet.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Requirements&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#requirement_azurerm" rel="noopener noreferrer"&gt;azurerm&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;~&amp;gt; 3.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#requirement_null" rel="noopener noreferrer"&gt;null&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;~&amp;gt; 3.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Providers&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#provider_azurerm" rel="noopener noreferrer"&gt;azurerm&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;~&amp;gt; 3.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#provider_external" rel="noopener noreferrer"&gt;external&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#provider_null" rel="noopener noreferrer"&gt;null&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;~&amp;gt; 3.1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Resources&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource" rel="nofollow noopener noreferrer"&gt;null_resource.keepers&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;resource&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/client_config" rel="nofollow noopener noreferrer"&gt;azurerm_client_config.current&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;data source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/data-sources/subnet" rel="nofollow noopener noreferrer"&gt;azurerm_subnet.this&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;data source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/external/latest/docs/data-sources/external" rel="nofollow noopener noreferrer"&gt;external_external.available_ips&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;data source&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Inputs&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#input_resource_group" rel="noopener noreferrer"&gt;resource_group&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Subnet's resource group.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#input_subnet_name" rel="noopener noreferrer"&gt;subnet_name&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Subnet's name.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#input_vnet_name" rel="noopener noreferrer"&gt;vnet_name&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Subnet's virtual network name.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#input_keepers" rel="noopener noreferrer"&gt;keepers&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Keepers for this IP.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;list(string)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#input_subscription_id" rel="noopener noreferrer"&gt;subscription_id&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;Subnet's subscription ID.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;string&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Outputs&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#output_all" rel="noopener noreferrer"&gt;all&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;List all checked available IPs for the Subnet.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
 &lt;a href="https://github.com/LontriTech/terraform-azurerm-available-ips#output_one" rel="noopener noreferrer"&gt;one&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;List one checked available IP for the Subnet.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/LontriTech/terraform-azurerm-available-ips" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;





&lt;h2&gt;
  
  
  First: Do It Locally
&lt;/h2&gt;

&lt;p&gt;To achieve this I created a "default" configuration file for terraform-docs named &lt;code&gt;.terraform.docs.yml&lt;/code&gt; and it looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;formatter: "markdown"

recursive:
  enabled: true
  path: examples

output:
  file: "README.md"
  mode: replace

settings:
  color: false
  description: "true"
  hide-empty: true
  read-comments: true
  sensitive: true
  lockfile: true

sort:
  enabled: true
  by: required
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I downloaded the tool itself following these steps, found on the &lt;a href="https://terraform-docs.io/user-guide/installation/#pre-compiled-binary" rel="noopener noreferrer"&gt;official guide&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sSLo ./terraform-docs.tar.gz https://terraform-docs.io/dl/v0.16.0/terraform-docs-v0.16.0-$(uname)-amd64.tar.gz
tar -xzf terraform-docs.tar.gz
chmod +x terraform-docs
mv terraform-docs /some-dir-in-your-PATH/terraform-docs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the download all I had to do was run &lt;code&gt;terraform-docs .&lt;/code&gt; from my command line inside of the module's directory and it was done!&lt;/p&gt;




&lt;h2&gt;
  
  
  Now: Using GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Assuming you have the &lt;code&gt;.terraform-docs.yml&lt;/code&gt; file on your repository as shown above you just need to create a new workflow, with whatever name you want it to have, mine is just "Terraform Docs", and it should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Terraform Docs

on:
  push:
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: terraform-docs-gh-actions
        uses: terraform-docs/gh-actions@v1.0.0
        with:
          config-file: .terraform-docs.yml
          git-push: true
          git-push-sign-off: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, now you just have to wait for it to run, and you will be good to go!&lt;/p&gt;




&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;The configuration file used for terraform-docs is just an example, and even if it works for me, it may not work for you or your organization, so this is what you need to know to create your own: &lt;br&gt;
&lt;a href="https://terraform-docs.io/user-guide/configuration/" rel="noopener noreferrer"&gt;terraform-docs configuration guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, the installation process may not work in a non-linux environment, so if you are working on Mac or Windows, you will need to use a different approach like the ones listed here: &lt;br&gt;
&lt;a href="https://terraform-docs.io/user-guide/installation/" rel="noopener noreferrer"&gt;terraform-docs installation guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About GitHub Actions and Workflows, I assumed for this article you know the basics of it, but if you need help seting up your workflow, you should definitely check out this quickstart guide: &lt;br&gt;
&lt;a href="https://docs.github.com/en/actions/quickstart" rel="noopener noreferrer"&gt;GitHub Actions Quickstart&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are wondering what the official docs on Terraform's Registry look like, here is an example: &lt;br&gt;
&lt;a href="https://registry.terraform.io/modules/OLeonardoRodrigues/available-ips/azurerm/latest" rel="noopener noreferrer"&gt;Terraform Registry Example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, if you are wondering how to publish your Terraform Modules on the Official Registry, here's how you do it: &lt;br&gt;
&lt;a href="https://developer.hashicorp.com/terraform/registry/modules/publish" rel="noopener noreferrer"&gt;How to Publish a Terraform Module on the Official Registry&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  More Content
&lt;/h2&gt;

&lt;p&gt;If this article helped you or someone you know and you want to know more of these useful tools or tips for your IaC needs, follow me on &lt;a href="https://www.linkedin.com/in/lro/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;, &lt;a href="https://community.ops.io/oleonardorodrigues"&gt;here&lt;/a&gt; or on &lt;a href="https://github.com/OLeonardoRodrigues" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; and don't miss my updates!&lt;/p&gt;

</description>
      <category>terraform</category>
      <category>iac</category>
      <category>devops</category>
      <category>github</category>
    </item>
    <item>
      <title>Understanding Terraform's Core Workflow</title>
      <dc:creator>Leonardo Rodrigues de Oliveira</dc:creator>
      <pubDate>Wed, 01 Jun 2022 17:31:24 +0000</pubDate>
      <link>https://community.ops.io/lontritech/understanding-terraforms-core-workflow-5ck7</link>
      <guid>https://community.ops.io/lontritech/understanding-terraforms-core-workflow-5ck7</guid>
      <description>&lt;p&gt;Terraform is a growing tool created by HashiCorp to deploy cloud resources using the same syntax, making it easier to apply what you already know to new cloud providers.&lt;/p&gt;

&lt;p&gt;Enough about the reasons, let's get into how you can manage your cloud infrastructure using Terraform.&lt;/p&gt;

&lt;p&gt;Terraform uses a three step core workflow: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;init&lt;/li&gt;
&lt;li&gt;plan&lt;/li&gt;
&lt;li&gt;apply&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Init
&lt;/h2&gt;

&lt;p&gt;First of all, you'll need to write your Terraform configuration using valid cloud credentials, these can be your own or some service account with the necessary permissions.&lt;/p&gt;

&lt;p&gt;With your configuration ready you'll have to initialize your Terraform module using &lt;code&gt;terraform init&lt;/code&gt;, this will download any dependencies, such as providers and referenced modules, the init command also creates the &lt;code&gt;terraform.lock.hcl&lt;/code&gt; file, an automatically generated dependency lock file simmilar to &lt;code&gt;requirements.txt&lt;/code&gt; from Python.&lt;/p&gt;

&lt;p&gt;The last thing done during the module's initialization is configuring the backend, this is where Terraform will store its state file, the state file or TFState is responsible for holding everything Terraform needs to know about your infrastructure to be able to manage it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/J3D2NWRJM7usG-WOXIQOC3T_4KhjmWdgdnM2zsRWLws/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3pnaGFl/Y2pvazkxZncxbXEw/dnk2LnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/J3D2NWRJM7usG-WOXIQOC3T_4KhjmWdgdnM2zsRWLws/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3pnaGFl/Y2pvazkxZncxbXEw/dnk2LnBuZw" alt="Terraform Init - Execution" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Plan
&lt;/h2&gt;

&lt;p&gt;Planning your Terraform configuration works as a way of comparing three things, and it looks something like this diagram: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/0fn4dixUKaRhdzcByuylqG4JSAc60zdig-CYEyHM3KU/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL21lbzk5/dG91dnR5bGJ0dGJz/d2NkLmpwZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/0fn4dixUKaRhdzcByuylqG4JSAc60zdig-CYEyHM3KU/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL21lbzk5/dG91dnR5bGJ0dGJz/d2NkLmpwZw" alt="Terraform Plan - Diagram" width="641" height="671"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The items compared during a plan are: &lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform Configuration
&lt;/h3&gt;

&lt;p&gt;The configuration itself, what Terraform assumes is the desired state for the cloud resources you declared inside the module.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terraform State
&lt;/h3&gt;

&lt;p&gt;Everything mapped by Terraform from previous applies/updates, this is only used as a way of knowing what was done by Terraform and what was done by outside sources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Provider
&lt;/h3&gt;

&lt;p&gt;The cloud provider is the place where your actual infrastructure is running, by checking the provider's API, Terraform is able to tell the current status of things, any changes from what is registered in the state will make Terraform want to update things, always trying to match the desired state declared on your configuration.&lt;/p&gt;




&lt;p&gt;Terraform always needs to perform this step to plan what changes need to be done to the running infrastructure so it matches the desired state declared in the configuration.&lt;/p&gt;

&lt;p&gt;Using the &lt;code&gt;-o&lt;/code&gt; or &lt;code&gt;-output&lt;/code&gt; option on the CLI you're able to generate a plan file, this can be used when applying the planned changes to make sure only the planned/approved changes will take place.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://community.ops.io/images/ysPFLo2ttgLGig897FXGhESQYtLXDmaKSYxFa5qbZjg/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3RmZmM4/d2k3cGh4eWl2bzYz/eHgwLnBuZw" class="article-body-image-wrapper"&gt;&lt;img src="https://community.ops.io/images/ysPFLo2ttgLGig897FXGhESQYtLXDmaKSYxFa5qbZjg/rt:fit/w:800/g:sm/q:0/mb:500000/ar:1/aHR0cHM6Ly9jb21t/dW5pdHkub3BzLmlv/L3JlbW90ZWltYWdl/cy91cGxvYWRzL2Fy/dGljbGVzL3RmZmM4/d2k3cGh4eWl2bzYz/eHgwLnBuZw" alt="Terraform Plan - Execution" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply
&lt;/h2&gt;

&lt;p&gt;The final command of what is known as Terraform's Core Workflow is &lt;code&gt;apply&lt;/code&gt;, running this command starts the same way as running &lt;code&gt;plan&lt;/code&gt; if a plan file is not provided.&lt;/p&gt;

&lt;p&gt;After determining what changes should take place, Terraform will ask for the user's approval before applying any real changes/updates to the infrastructure, the &lt;code&gt;-auto-approve&lt;/code&gt; flag eliminates the need for the manual approval, &lt;strong&gt;but it's not a recommended practice, since it may even delete running infrastructure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At the bottom of the changes list, there's a summary telling the user how many of each operation will take place if the plan is actually approved and applied.&lt;/p&gt;

&lt;p&gt;The kinds of operation are: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add - New resources will be added to your infrastructure&lt;/li&gt;
&lt;li&gt;Change - Existing resources will be changed in your infrastructure&lt;/li&gt;
&lt;li&gt;Destroy - Existing resources will be deleted from your infrastructure&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The summary will look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan: 2 to add, 5 to change, 4 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In some cases destroying a resource might mean the resource is going to be replaced due to a breaking change. Terraform doesn't decide what is a breaking change, this is a responsability of the cloud provider and its API, since Terraform is not responsible for the resource's configuration and/or contents, it cannot guarantee if the replacements won't break dependencies and running applications.&lt;/p&gt;

&lt;p&gt;When approved, the changes will start to be applied.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Applying changes using Terraform may have destructive impacts to your infrastructure, so do it carefully, but it's predictable and repeatable, making it one of the safest way to manage a cloud environment, if you don't think so, just think about the mistakes you could have done by forgetting a route table or a single NSG rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.terraform.io/intro/core-workflow" rel="noopener noreferrer"&gt;Official Docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>iac</category>
      <category>cloudops</category>
    </item>
  </channel>
</rss>
