<?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>DEV Community: Takashi Narikawa</title>
    <description>The latest articles on DEV Community by Takashi Narikawa (@fukubaka0825).</description>
    <link>https://dev.to/fukubaka0825</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%2F128752%2F96a3a46d-2401-4046-bf79-6afc8f8bc116.jpg</url>
      <title>DEV Community: Takashi Narikawa</title>
      <link>https://dev.to/fukubaka0825</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fukubaka0825"/>
    <language>en</language>
    <item>
      <title>My Python Project Development Guide ver.202412</title>
      <dc:creator>Takashi Narikawa</dc:creator>
      <pubDate>Sun, 14 May 2023 11:17:52 +0000</pubDate>
      <link>https://dev.to/fukubaka0825/my-python-project-development-guide-ver202305-2ge5</link>
      <guid>https://dev.to/fukubaka0825/my-python-project-development-guide-ver202305-2ge5</guid>
      <description>&lt;h1&gt;
  
  
  What is this
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The guide to set up a Python project for production deployment. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This guide assumes you are using &lt;a href="https://github.com/astral-sh/uv" rel="noopener noreferrer"&gt;uv&lt;/a&gt; for package management and adheres to the rules specified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;By following this guide, you can set up a Python project for production deployment using uv as the package manager, enforce code quality with linters and formatters, automate checks with GitHub Actions, configure your IDE to maintain consistency, and write comprehensive unit tests to ensure the project's reliability throughout the development process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We recommend using Python version 3.10 or higher for your project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The majority of this document was created using ChatGPT-4.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sample Project&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fukubaka0825/my-python-guide" rel="noopener noreferrer"&gt;https://github.com/fukubaka0825/my-python-guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Steps
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Project Setup/ Set up Local Environment with uv
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create a project directory and navigate to it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;project_path&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;project_path&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;uv allows you to manage local Python versions without the need for pyenv. It uses a .python-version file for project-specific Python version management.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv python &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;python_version&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Replace ${python_version} with the desired version, e.g., 3.10.2. This command will create a .python-version file in the project directory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ensure that all team members use the same Python version specified in the .python-version file.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Copy the provided file to the project directory and install dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy pyproject.yml example and arrange by yourself&lt;/li&gt;
&lt;li&gt;For the local environment, use uv to create a .venv virtual environment in the project root. &lt;/li&gt;
&lt;li&gt;Execute the following commands to set up the virtual environment and install the required packages
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv venv
uv &lt;span class="nb"&gt;sync&lt;/span&gt;
&lt;span class="c"&gt;# Run command in the created environment.&lt;/span&gt;
uv run &amp;lt;YOUR_COMMAND&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  In the pyproject.toml file, we configure various modules for linting, formatting, and task running. Here's an explanation of these modules:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Taskipy&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Taskipy is a task runner that allows you to automate various tasks in your Python project. In this project, we use Taskipy to define and run tasks such as formatting, linting, and testing. The tasks are configured in the pyproject.toml file under [tool.taskipy.tasks].&lt;/p&gt;

&lt;p&gt;For more information about Taskipy, check out the official documentation:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Linters and Formatters&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This project uses several linters and formatters to maintain code quality and consistency:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Black&lt;/strong&gt;: A code formatter that automatically formats your code according to the PEP 8 style guide. The configuration is set in the pyproject.toml file under [tool.black].&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ruff&lt;/strong&gt;: A linter that checks your code for style guide violations, potential bugs, and other issues.   This covers so many rules inluding flake8’s one and isort’s one. The configuration is set in the pyproject.toml file under [tool.ruff]. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mypy&lt;/strong&gt;: A static type checker that helps catch potential bugs and ensures that your code is type-safe. The configuration is set in the pyproject.toml file under [tool.mypy].&lt;/p&gt;

&lt;p&gt;These linters and formatters are integrated into the project's tasks and the IDE settings, ensuring a consistent code style across the entire project.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Create Directory Structure
&lt;/h2&gt;

&lt;p&gt;Create the necessary directories and files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;assets　# you can write main codes &lt;span class="k"&gt;in &lt;/span&gt;this directory
&lt;span class="nb"&gt;mkdir &lt;/span&gt;tests &lt;span class="c"&gt;# you can write test codes in this directory&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Write Sufficient Unit Tests with pytest
&lt;/h2&gt;

&lt;p&gt;Ensure that you write comprehensive unit tests using pytest for all critical components of your project. Adequate test coverage helps maintain code quality and reduces the likelihood of introducing bugs during development or refactoring.&lt;/p&gt;

&lt;p&gt;To write a unit test, create a unit test, create a new file in the tests directory with a name that follows the pattern test_*.py.&lt;/p&gt;

&lt;p&gt;Within the test file, import the necessary modules and define test functions that follow the pattern def test_*():.&lt;/p&gt;

&lt;p&gt;Use pytest's built-in assert statement to compare expected and actual values.&lt;/p&gt;

&lt;p&gt;To run tests, execute the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run task &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure that all tests pass before committing changes and creating a pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Configure IDE Settings
&lt;/h2&gt;

&lt;p&gt;Reflect the contents of the provided pyproject.toml file in the settings file related to your IDE.&lt;/p&gt;

&lt;p&gt;For example, if you are using VSCode, add the following settings to .vscode/settings.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"python.formatting.provider"&lt;/span&gt;: &lt;span class="s2"&gt;"black"&lt;/span&gt;,
  &lt;span class="s2"&gt;"python.formatting.blackArgs"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"--line-length"&lt;/span&gt;, &lt;span class="s2"&gt;"102"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
  &lt;span class="s2"&gt;"python.linting.flake8Enabled"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
  &lt;span class="s2"&gt;"python.linting.mypyEnabled"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
  &lt;span class="s2"&gt;"python.sortImports.args"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"--profile=black"&lt;/span&gt;, &lt;span class="s2"&gt;"--line-length=102"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;,
  &lt;span class="s2"&gt;"editor.codeActionsOnSave"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"source.organizeImports"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
    &lt;span class="s2"&gt;"source.fixAll"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;With these settings, VSCode will automatically format and lint code using Black, Flake8, Mypy, and isort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you use IntelliJ/Pycharm, Please use File Watcher function for auto-running uv run task fmt_lint&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbzp1bikhj9er6jf4i17p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbzp1bikhj9er6jf4i17p.png" alt="Image description" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Set up CI(Auto lint/test) with GitHub Actions
&lt;/h2&gt;

&lt;p&gt;Create the .github/workflows directory in the project root:&lt;/p&gt;

&lt;p&gt;mkdir -p .github/workflows&lt;/p&gt;

&lt;p&gt;Create a test_and_lint.yml file and add the following content:&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&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python lint and test&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_PROJECT/**.py"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tests/**.py"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.github/workflows/test_and_lint.yml"&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;lint_and_test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lint and Test&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;fail-fast&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.11"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.10"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.9"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Python ${{ matrix.python-version }}&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-python@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;python-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.python-version }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install uv&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;astral-sh/setup-uv@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;enable-cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;uv sync&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Python Test&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;uv run task test&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Python Lint&lt;/span&gt;
        &lt;span class="na"&gt;continue-on-error&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;uv run task lint&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;sample&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fukubaka0825/my-python-guide/blob/main/.github/workflows/docker-build-push-xxxxxxxxxx.yml" rel="noopener noreferrer"&gt;https://github.com/fukubaka0825/my-python-guide/blob/main/.github/workflows/docker-build-push-xxxxxxxxxx.yml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;This configuration will automatically run uv run task fmt_lint and uv run task test on pushes and pull requests to the main branch.&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Set up Stage/Prod Environment with Dockerfile
&lt;/h2&gt;

&lt;p&gt;For the stage/prod environment, use a Dockerfile to build the execution environment. First, export the project's dependencies to a requirements.txt file using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--no-dev&lt;/span&gt; &lt;span class="nt"&gt;--no-hashes&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; requirements-txt &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the Dockerfile, use pip install to install the dependencies from the requirements.txt file. Ensure that the specified Python version in the Dockerfile is the same as the one used in the local environment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sample Dockerfile

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fukubaka0825/my-python-guide/blob/main/Dockerfile" rel="noopener noreferrer"&gt;https://github.com/fukubaka0825/my-python-guide/blob/main/Dockerfile&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;By following these rules, you can ensure a consistent development environment for all team members and maintain a clean separation between local and stage/prod environments.&lt;/p&gt;

&lt;p&gt;Additionally, it is recommended to integrate the configuration of this process into the GitHub Actions YAML for the next 7 Continuous Deployment (CD) steps, as it eliminates the need to work locally.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Set up CD(Atuo build Dockerfile) with Github Actions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;sample

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/fukubaka0825/my-python-guide/blob/main/.github/workflows/test-and-lint-xxxxxxx.yml" rel="noopener noreferrer"&gt;https://github.com/fukubaka0825/my-python-guide/blob/main/.github/workflows/test-and-lint-xxxxxxx.yml&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Appendix
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://zenn.dev/turing_motors/articles/594fbef42a36ee" rel="noopener noreferrer"&gt;uvだけでPythonプロジェクトを管理する&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://future-architect.github.io/articles/20210611a/" rel="noopener noreferrer"&gt;サーバーアプリ開発環境(Python／FastAPI) | フューチャー技術ブログ&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://zenn.dev/tanny/articles/cdb555d6124a2a" rel="noopener noreferrer"&gt;Pythonのリンター・フォーマッターをしっかりと理解する（Flake8, Black, isort, mypy）&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://zenn.dev/horitaka/articles/4fc4a5c19bee22" rel="noopener noreferrer"&gt;【PyCharm】ファイル保存時にlinterとformatterが自動実行されるように設定する&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://zenn.dev/jdbtisk/articles/e6ed54b38b6a45" rel="noopener noreferrer"&gt;オレオレ Python 開発環境&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>Why are we organizing a tech conference called SRE NEXT 2022?</title>
      <dc:creator>Takashi Narikawa</dc:creator>
      <pubDate>Sun, 27 Feb 2022 13:23:36 +0000</pubDate>
      <link>https://dev.to/fukubaka0825/why-are-we-organizing-a-tech-conference-called-sre-next-2022-22ed</link>
      <guid>https://dev.to/fukubaka0825/why-are-we-organizing-a-tech-conference-called-sre-next-2022-22ed</guid>
      <description>&lt;p&gt;Japanese Edition: &lt;br&gt;
&lt;a href="https://blog.sre-next.dev/entry/2022/02/06/190047" rel="noopener noreferrer"&gt;https://blog.sre-next.dev/entry/2022/02/06/190047&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, I'm &lt;a href="https://twitter.com/wapper0825" rel="noopener noreferrer"&gt;nari/wapper&lt;/a&gt;, the organizer of SRE NEXT 2022.&lt;/p&gt;

&lt;p&gt;The other day, the &lt;a href="https://twitter.com/srenext" rel="noopener noreferrer"&gt;SRE NEXT official Twitter account&lt;/a&gt; announced that SRE NEXT 2022 will be held online on May 14 and 15, and the &lt;a href="https://sre-next.dev/2022/" rel="noopener noreferrer"&gt;official website&lt;/a&gt; has also been published!&lt;/p&gt;

&lt;p&gt;In this post, I will explain why we are holding SRE NEXT 2022 online and what kind of conference we want to hold. &lt;/p&gt;

&lt;h2&gt;
  
  
  What is SRE NEXT?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SRE NEXT is a conference for engineers who are deeply interested in reliability practices, and is run and organized by the members of &lt;a href="https://sre-lounge.connpass.com/" rel="noopener noreferrer"&gt;SRE Lounge&lt;/a&gt;, another community-based SRE study group. This community is organized with mainly Japanese.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first SRE NEXT 2020 was held in January 2020 in Tokyo, and the second is scheduled to be held this year in 2022. It is a conference for anyone interested in getting reliability with users, not just those working with SRE role. SRE is an idea and a practice, and there are many companies that have achieved this without having it as a role.&lt;/p&gt;

&lt;p&gt;The tickets of the first conference were sold out and more than 50 recap articles were wrote and published after the event.&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%2Fben0l1r3ssg6nirclonk.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%2Fben0l1r3ssg6nirclonk.png" alt="Quoted from 2022 official site"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we hold SRE NEXT 2022
&lt;/h2&gt;

&lt;p&gt;With the last SRE NEXT 2020, we believe that I was able to gather cases of SRE practices in the web domain of certain size companies and spread them throughout Japan.&lt;br&gt;
In the years since then, the number of topics and events related to SRE has been increasing, and the focus of attention has been growing up day by day. In particular, I've heard a lot about SLI/SLO design and operation for general availability in web applications.&lt;br&gt;
In order to accelerate this trend and to play a role in spreading SRE practices to a wider range of people and domains, we decided to hold SRE NEXT 2022 with the theme &lt;strong&gt;"SRE DIVERSITY"&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, in terms of variety of scales/phases, I had the impression that many of the presenters and participants of SRE NEXT 2020 were engaged in in-house products of a certain big scale. I think it will be more interesting if we can hear about SRE practices at more different scales and forms. Also, the fact that the best way of SRE practices is different depending on the phase of the product has been discussed in various places, and is even mentioned and cited in "Team Topology".&lt;br&gt;
Also, in terms of variety of domains/areas, We want to adopt proposals and sessions in more diverse areas like &lt;a href="https://www.usenix.org/conference/srecon19americas/presentation/thomson" rel="noopener noreferrer"&gt;"Jim Thomson and David Laing of Pivotal at SREcon19, Extending the Error Budget Model to Security and Feature Freshness"&lt;/a&gt; and the story of SRE practices and social movements in &lt;a href="https://www.oreilly.co.jp/books/9784873119618/" rel="noopener noreferrer"&gt;Seeking SRE&lt;/a&gt; and&lt;br&gt;
sessions related to AIOps, which is listed as a major monitoring component in catchpoint's &lt;a href="https://pages.catchpoint.com/2021-sre-report" rel="noopener noreferrer"&gt;SRE 2021 Report&lt;/a&gt;, and so on. I think it would be good to have more discussions on wide range of areas.&lt;/p&gt;

&lt;p&gt;With these in mind, &lt;strong&gt;we decided to hold SRE NEXT 2022 in order to provide an opportunity for the spread of more diverse SRE practices by gathering SRE practices in a wide range of industries, domains, and phases, from startups to large corporations, especially in Japan.&lt;/strong&gt;&lt;br&gt;
SRE book co-author Naill Murphy's keynote at SRECon21, &lt;a href="https://www.youtube.com/watch?v=7Ktzu0%20qvS6c" rel="noopener noreferrer"&gt;"Don't Follow Leaders or "All Models Are Wrong (and So Am I)"&lt;/a&gt;, he said that the absolute influence of SRE books has led to a cessation of thinking and a lack of innovation, and that what is important is to evolve these models with the times.&lt;br&gt;
I believe that the trial and error of gaining reliability with a wider variety of users will provide participants with a lot of insights and learning, and give them a chance to think over  their SRE practices and think about the &lt;strong&gt;"NEXT of SRE "&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of conference we want to hold
&lt;/h2&gt;

&lt;p&gt;The last event was well attended by mainly SREs.&lt;br&gt;
But, As for 2022 event, I would like to invite people not only from SREs but also from those who are struggling to achieve reliability in their daily lives.&lt;br&gt;
Also, as with the SRE Lounge, we would like to provide a place for interactive discussions, so we are working on providing a reception and an online venue.&lt;br&gt;
In addition, since this event will be held online, it will be a unique opportunity for those who were unable to attend last time to participate and interact with us.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our goal is to create an event that will help to democratize and generalize the idea and practice of SRE, so that it is not just for people with limited responsibilities and areas, but can be talked about in a variety of areas.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;In addition to providing a lineup of attractive sessions, we are also considering and working on various events, receptions, online venues, and other contents on the same day. ), so please follow us on &lt;a href="https://twitter.com/srenext" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and stay tuned for more information.&lt;br&gt;
As in the previous event, we are looking forward to working with the participants and sponsors to make the event even better, and we look forward to your continued support of SRE NEXT.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/forms/d/e/1FAIpQLSfg_G2hK0zQXJSVIPW90Naqd0DfJyfM2KKM7aqD--at4iVioQ/viewform" rel="noopener noreferrer"&gt;Here is Session Proposal Form for English speaking folks&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sre</category>
      <category>security</category>
      <category>corporate</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Introducing Conftest and setting up CI with Github Actions to automate reviewing of Terraform code</title>
      <dc:creator>Takashi Narikawa</dc:creator>
      <pubDate>Tue, 28 Dec 2021 12:48:27 +0000</pubDate>
      <link>https://dev.to/fukubaka0825/introducing-conftest-and-setting-up-ci-with-github-actions-to-automate-reviewing-of-terraform-code-4dfn</link>
      <guid>https://dev.to/fukubaka0825/introducing-conftest-and-setting-up-ci-with-github-actions-to-automate-reviewing-of-terraform-code-4dfn</guid>
      <description>&lt;p&gt;&lt;a href="https://fukubaka0825.hatenablog.com/entry/2021/12/25/175431" rel="noopener noreferrer"&gt;日本語版はこちら&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Hi, I’m &lt;a href="https://twitter.com/wapper0825" rel="noopener noreferrer"&gt;nari/wapper&lt;/a&gt; from SRE team at eureka, Match Group.👋&lt;/p&gt;

&lt;p&gt;In our SRE Team, we are planning to set &lt;code&gt;micro-services ready&lt;/code&gt; as one of the major keywords for next year ro prevent ourselves from becoming a bottleneck. (We are not going to rebuild our system as micro-services, though).&lt;/p&gt;

&lt;p&gt;With that, as well as the Production Readiness check, I've started to try to use &lt;code&gt;Policy as Code&lt;/code&gt; with Conftest, which is an important piece to promote transferability/Self Service, and I'll write about it as a memorandum.&lt;/p&gt;

&lt;p&gt;In this article, I'll show you how to write a policy for resource tag rules (AWS reousrce) in Terraform with Rego, write tests for the policy itself, and set up the CI for its automatic execution using Github Actions.&lt;br&gt;
(There is a lot of talk about writing Conftest (Rego), but not much has been written about setting up CI, and there were some points where I got stuck, so my main motivation for writing this article is to leave a reminder so that people who are about to try it don't get stuck.)&lt;/p&gt;

&lt;h1&gt;
  
  
  Target readers
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;People who have been curious about Policy as Code but needed a reason to start.&lt;/li&gt;
&lt;li&gt;People who want to know concrete examples of how to set up Github Actions CI of Conftest.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What is OPA/Rego/Conftest???
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;OPA (Open Policy Agent) is an OSS general-purpose policy engine, which is currently a Graduation project of CNCF. OPA writes policies in a policy description language called Rego. OPA evaluates the policy according to the policy written in Rego and structured data such as JSON (base document), and returns the result in the same way as structured data such as JSON (virtual document).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It just graduated from CNCF this year (2021): [&lt;a href="https://www.infoq.com/news/2021/02/opa-cncf-graduation/:title" rel="noopener noreferrer"&gt;https://www.infoq.com/news/2021/02/opa-cncf-graduation/:title&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;Source code: [&lt;a href="https://github.com/open-policy-agent/opa:title" rel="noopener noreferrer"&gt;https://github.com/open-policy-agent/opa:title&lt;/a&gt;]&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Conftest is a tool that supports various types of file-formats such as YAML, JSON, HCL, Dockerfile, etc. based on the policy written in OPA's Rego, and can be tested easily from the command line.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conftest was originally a third party tool using OPA's Rego, and now it seems to be a widely used CLI tool officially under the umbrella of the OPA community! &lt;/li&gt;
&lt;li&gt;Source code: [&lt;a href="https://github.com/open-policy-agent/conftest:title" rel="noopener noreferrer"&gt;https://github.com/open-policy-agent/conftest:title&lt;/a&gt;]&lt;/li&gt;
&lt;li&gt;This time, we will adopt this tool because it is supposed to be used in CI.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Write policy rules in Rego and set up CI with Github Actions
&lt;/h1&gt;

&lt;p&gt;All sample code can be found here: &lt;a href="https://github.com/fukubaka0825/terraform-conftest-with-acitions-ci-sample" rel="noopener noreferrer"&gt;https://github.com/fukubaka0825/terraform-conftest-with-acitions-ci-sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, I'd like to write a policy rule to make sure that a resource created by terraform has a minimum tag (name/owner/description) and that the importance of the data (high/middle/low) is set to the tag named data when it is a data store resource. We will use the result of the terraform plan converted to json as the input value so that we can test it with the policy rule in Rego we are about to write, and also test the policy rule itself. (The sample we are going to describe assumes the use of AWS)&lt;/p&gt;

&lt;h2&gt;
  
  
  0.Prerequisites
&lt;/h2&gt;

&lt;h2&gt;
  
  
  0.1.Set up Conftest (OPA/Rego)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If you are a Mac OS user, you can easily install it with brew. Users of other OS can also install it by referring to the README.&lt;/li&gt;
&lt;/ul&gt;

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

brew &lt;span class="nb"&gt;install &lt;/span&gt;conftest

&lt;span class="c"&gt;# also install OPA&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;opa


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;As for the editor plugin, you can use &lt;a href="https://plugins.jetbrains.com/plugin/14865-open-policy-agent" rel="noopener noreferrer"&gt;opa plugin&lt;/a&gt; for IntelliJ or &lt;a href="https://marketplace.visualstudio.com/items?itemName=tsandall.opa" rel="noopener noreferrer"&gt;opa plugin&lt;/a&gt; if you are IntelliJ/VSCode user.

&lt;ul&gt;
&lt;li&gt;I'm not sure but other editors may have them too, so try to find them and add them.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  0.2.Structure of Terraform Plan results
&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%2F7i0n6a0ffs1eut1xlufi.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%2F7i0n6a0ffs1eut1xlufi.png" alt="Structure of Terraform Plan results"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this structure, we will write a logic in Rego to check the content of this data as input.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Try to write Terrafom resource tag rules in Conftest/Rego
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;First, we will write the entry point in main.rego.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;span class="c1"&gt;# policy/main.rego&lt;/span&gt;


&lt;span class="ow"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="err"&gt;❶&lt;/span&gt;

&lt;span class="ow"&gt;import&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags_validation&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="err"&gt;❷&lt;/span&gt;

&lt;span class="c1"&gt;#####################################&lt;/span&gt;
&lt;span class="c1"&gt;# Policy as Code Rules&lt;/span&gt;
&lt;span class="c1"&gt;#####################################&lt;/span&gt;
&lt;span class="n"&gt;deny_tags_contain_minimum_set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Only target resources that have been changed/added.&lt;/span&gt;
    &lt;span class="n"&gt;changeset&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;resources_not_no_op_action&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="err"&gt;❸&lt;/span&gt;

    &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;tags_validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contain_proper_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Invalid tags (missing minimum required tags: name,owner,description) for the following resource: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="err"&gt;❹&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;deny_data_store_data_tag_is_proper&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Only target resources that have been changed/added.&lt;/span&gt;
    &lt;span class="n"&gt;changeset&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;resources_not_no_op_action&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="c1"&gt;# Only when resource_type is a data source/store type that can contain sensitive information&lt;/span&gt;
    &lt;span class="n"&gt;tags_validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_data_tag_required_target_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;tags_validation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;not_has_proper_data_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"data tag needs to be set to one of [low,high,middle] resource: %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;#####################################&lt;/span&gt;
&lt;span class="c1"&gt;# Utils&lt;/span&gt;
&lt;span class="c1"&gt;#####################################&lt;/span&gt;

&lt;span class="n"&gt;resources_not_no_op_action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resource_changes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"no-op"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="err"&gt;❺&lt;/span&gt;

&lt;span class="n"&gt;resources_with_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;type&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;❶ policy always requires a package clause. You can use any package name to divide the namespace.&lt;/p&gt;

&lt;p&gt;❷ You can use the import clause to import a different namespace and use the resources in that namespace. This time, you can write your own logic in the tags_validation namespace and use it in main.&lt;/p&gt;

&lt;p&gt;❸ Here, narrow down the resources to those whose action is not "no-op", and iterate through those resources (expression: [_]) to check for resources that violate the policy. This will ensure that only resources that are newly modified/added are targeted. In addition, since this operation is basically used in all policy rules, we have made it a common function and cut it out.&lt;/p&gt;

&lt;p&gt;❹ Multiple evaluation expressions can be written in the same rule, and since they are evaluated in AND fashion, only when all of them are true, deny/violation is judged, and error messages are registered in the error message array for each of these policy rules and output at test execution time.&lt;/p&gt;

&lt;p&gt;❺ In Rego, the familiar Python notation for inclusion can be used. The syntax is [ | ], and only the resources that match the rule are returned.&lt;/p&gt;

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


&lt;span class="c1"&gt;# policy/tags.rego&lt;/span&gt;

&lt;span class="ow"&gt;package&lt;/span&gt; &lt;span class="n"&gt;tags_validation&lt;/span&gt;

&lt;span class="n"&gt;minimum_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;contain_proper_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Subtract the key list of the given tags from the minimum tag list, and if there is no more left, you have the minimum tag.&lt;/span&gt;
    &lt;span class="n"&gt;keys&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="n"&gt;leftover&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;minimum_tags&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;keys&lt;/span&gt;
    &lt;span class="n"&gt;leftover&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;not_has_proper_data_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;❶&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"low"&lt;/span&gt;  
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"middle"&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"high"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;is_data_tag_required_target_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;❷&lt;/span&gt;
    &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"aws_dynamodb_table"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;is_data_tag_required_target_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"aws_s3_bucket"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;




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

&lt;/div&gt;

&lt;p&gt;❶ The evaluation expression within the same rule will be evaluated as &lt;code&gt;AND&lt;/code&gt;, so it will return true if it is neither "low", "middle", nor "high".&lt;/p&gt;

&lt;p&gt;❷ If you want to write &lt;code&gt;OR&lt;/code&gt; logic, you can do so by writing multiple processes with the same name, such as &lt;code&gt;is_data_tag_required_target_resource&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Write tests for the rule itself written in Rego with Conftest and try to run it.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;First, we will write a test for main.rego. As in Go, we will name it ${test_target_file_name}_test.rego.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;span class="c1"&gt;# policy/main_test.rego&lt;/span&gt;

&lt;span class="ow"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="c1"&gt;#####################################&lt;/span&gt;
&lt;span class="c1"&gt;# Tests of Policy as Code Rules&lt;/span&gt;
&lt;span class="c1"&gt;#####################################&lt;/span&gt;

&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="n"&gt;test_tags_contain_minimum_set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;                    &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&gt;❶&lt;/span&gt;
      &lt;span class="n"&gt;resource_changes&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;case&lt;/span&gt; &lt;span class="n"&gt;normal&lt;/span&gt;
          &lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;
          &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;aws_security_group_rule&lt;/span&gt;
          &lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
              &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;
            &lt;span class="n"&gt;after&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
              &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;hoge&lt;/span&gt;
                &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;piyo&lt;/span&gt;
                &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;
    &lt;span class="err"&gt;`&lt;/span&gt;

    &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unmarshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;deny_tags_contain_minimum_set&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;with&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="ow"&gt;as&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&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;❶ The input for the test is written in json in the official documentation, but json is hard to maintain, so it is better to manage the description in yaml and convert it to json for use.&lt;/p&gt;

&lt;p&gt;❷ The test for the rule can be written like this. If you don't need to check the message content of the array, you can just check whether the error message array is empty or not.&lt;/p&gt;

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

&lt;span class="c1"&gt;# tag_rest.rego&lt;/span&gt;

&lt;span class="ow"&gt;package&lt;/span&gt; &lt;span class="n"&gt;tags_validation&lt;/span&gt;

&lt;span class="n"&gt;test_contain_proper_keys&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"owner"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"hoge"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"description"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"normal test"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;contain_proper_keys&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="err"&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;❶ The function used in the main rule is unit tested in this way, and is considered to be passed if it returns true&lt;/p&gt;

&lt;h2&gt;
  
  
  3.Set CI to run Conftest with Github Action
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1.Set up CI for fmt/verify of the policy rule itself written in Conftest/Rego.
&lt;/h3&gt;

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

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conftest-fmt-and-verify-all&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;policy/**'&lt;/span&gt;
&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;CONFTEST_VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.28.3&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;terraform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fmt-all&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install conftest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;wget -O - 'https://github.com/open-policy-agent/conftest/releases/download/v${{ env.CONFTEST_VERSION }}/conftest_${{ env.CONFTEST_VERSION }}_Linux_x86_64.tar.gz' | tar zxvf -&lt;/span&gt;
          &lt;span class="s"&gt;./conftest --version&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conftest fmt&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;git add . &amp;amp;&amp;amp; ./conftest fmt ./ &amp;amp;&amp;amp; git diff --exit-code ./.    // ❶&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conftest verify&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;./conftest verify ./   // ❷&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;❶ We don't have a flag like terraform's validation yet, so I write codes make it that the test will fail if there is a difference in the result of &lt;code&gt;conftest fmt&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;❷ Here, we run the test for the policy rule written in Rego that we wrote earlier.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2.Setting up CI to test Terraform plan results with Conftest test
&lt;/h3&gt;

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

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tf-plan-apply&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;TF_VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
  &lt;span class="na"&gt;CONFTEST_VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.28.3&lt;/span&gt;
  &lt;span class="na"&gt;WORKING_DIR&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;terraform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-eureka-pairs-etc-s3&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install conftest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;wget -O - 'https://github.com/open-policy-agent/conftest/releases/download/v${{ env.CONFTEST_VERSION }}/conftest_${{ env.CONFTEST_VERSION }}_Linux_x86_64.tar.gz' | tar zxvf -&lt;/span&gt;
          &lt;span class="s"&gt;./conftest --version //❶&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Terraform&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hashicorp/setup-terraform@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;terraform_wrapper&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="s"&gt; //❷&lt;/span&gt;
          &lt;span class="na"&gt;terraform_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.TF_VERSION }}&lt;/span&gt;
          &lt;span class="na"&gt;cli_config_credentials_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.YOUR_CRED_NAME}}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Init ${{ env.WORKING_DIR }}&lt;/span&gt;
        &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.WORKING_DIR }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform init&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Terraform Plan ${{ env.WORKING_DIR }}&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'pull_request'&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
        &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.WORKING_DIR }}&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;plan&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform plan -out=tfplan -no-color -lock=false -parallelism=50&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Convert terraform plan result to json formmat&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'pull_request'&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;convert&lt;/span&gt;
        &lt;span class="na"&gt;working-directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.WORKING_DIR }}&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;terraform show -json tfplan &amp;gt; tfplan.json&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conftest test&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'pull_request'&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;conftest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./conftest test --no-color ${{ env.WORKING_DIR }}/tfplan.json //❸&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;❶ I've been using &lt;code&gt;wget&lt;/code&gt; to install conftest since I couldn't find any properly maintained Actions.&lt;/p&gt;

&lt;p&gt;❷ If you are using the official &lt;code&gt;hashicorp/setup-terraform&lt;/code&gt;, be aware that this value is set to &lt;code&gt;true&lt;/code&gt; by default and the plan results cannot be shown in the appropriate json, so you need to set it to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;❸ Now we will test the terraform plan results using the policy rule we just wrote. By default, it refers to &lt;code&gt;policy/&lt;/code&gt; when reading the policies to be used. If you want to refer to a different directory, you can set it by passing &lt;code&gt;-p&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;My honest impression after playing around with Conftest/OPA/Rego is that I would like to have a schema for data definitions because I am a type enthusiast, and the logic evaluation is quite strong and expressive, so if I don't try to write it in a simple and understandable way, it will soon become impossible for the team to maintain it.&lt;/p&gt;

&lt;p&gt;Also, It makes me comfy that I can easily write tests for Policy as Code itself. I can change, add, and refactor Rego code with confidence.&lt;/p&gt;

&lt;p&gt;Also, I feel that each company is still searching for a strategy for directory structure of OPA/Rego, so I'd like to try and find a good place to put it.&lt;/p&gt;

&lt;h1&gt;
  
  
  References
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://adventar.org/calendars/6601" rel="noopener noreferrer"&gt;OPA / Rego Advent Calendar 2021&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://speakerdeck.com/ryokbt/terraformfalserebiyuwoconftestdezi-dong-hua-suru" rel="noopener noreferrer"&gt;TerraformのレビューをConftestで自動化する&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.openpolicyagent.org/docs/v0.13.5/language-cheatsheet/" rel="noopener noreferrer"&gt;OPA language-cheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/open-policy-agent/conftest" rel="noopener noreferrer"&gt;conftest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://play.openpolicyagent.org/p/mm5faX5bz8" rel="noopener noreferrer"&gt;OPA/Rego playground&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://speakerdeck.com/korosuke613/testing-terraform-plan-with-conftest" rel="noopener noreferrer"&gt;terraform plan 結果の検証を自動化するぞ！ with Conftest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Blokje5/validating-terraform-with-conftest" rel="noopener noreferrer"&gt;validating-terraform-with-conftest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://speakerdeck.com/ryokbt/conftest-false-tips" rel="noopener noreferrer"&gt;Terraform x OPA/Conftest の tips&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/suzuki-shunsuke/9372337aa62a6f8394bb136582ec068e" rel="noopener noreferrer"&gt;Quipper における Rego の活用事例&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://engineering.mercari.com/blog/entry/20210804-opa-rego/" rel="noopener noreferrer"&gt;Open Policy Agent Rego Knowledge Sharing Meetupを開催しました #opa_rego&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://engineering.mercari.com/blog/entry/introduce_conftest/" rel="noopener noreferrer"&gt;Conftestを用いたCIでのポリシーチェックの紹介&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://logmi.jp/tech/articles/323647" rel="noopener noreferrer"&gt;メルペイのエンジニアが考えるOpen Policy AgentとSpinnakerで実現するマイクロサービスの安全な継続的デリバリー&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opa</category>
      <category>rego</category>
      <category>conftest</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Manage EKS aws-auth configmap with terraform</title>
      <dc:creator>Takashi Narikawa</dc:creator>
      <pubDate>Sat, 25 Dec 2021 14:54:50 +0000</pubDate>
      <link>https://dev.to/fukubaka0825/manage-eks-aws-auth-configmap-with-terraform-4ndp</link>
      <guid>https://dev.to/fukubaka0825/manage-eks-aws-auth-configmap-with-terraform-4ndp</guid>
      <description>&lt;h1&gt;
  
  
  ⚠️Caution
&lt;/h1&gt;

&lt;p&gt;Recently, managing EKS authentication via the API is preferred over using the aws-auth ConfigMap. Set authentication_mode to 'API' in the access configuration of the aws_eks_cluster resource, and streamline authentication management in Terraform by linking IAM roles with aws_eks_access_entry and aws_eks_access_policy_association.&lt;/p&gt;

&lt;p&gt;REF&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/setting-up-access-entries.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/setting-up-access-entries.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_entry" rel="noopener noreferrer"&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_entry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_policy_association" rel="noopener noreferrer"&gt;https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_access_policy_association&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&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;"aws_eks_cluster"&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;"example-cluster"&lt;/span&gt;
  &lt;span class="p"&gt;....&lt;/span&gt;
  &lt;span class="nx"&gt;access_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;authentication_mode&lt;/span&gt;                         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"API"&lt;/span&gt;
    &lt;span class="nx"&gt;bootstrap_cluster_creator_admin_permissions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&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;"aws_eks_access_entry"&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;cluster_name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_eks_cluster&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;principal_arn&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&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;arn&lt;/span&gt;
  &lt;span class="nx"&gt;kubernetes_groups&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"group-1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"group-2"&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;"STANDARD"&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;"aws_eks_access_policy_association"&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;cluster_name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_eks_cluster&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;policy_arn&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"arn:aws:eks::aws:cluster-access-policy/AmazonEKSViewPolicy"&lt;/span&gt;
  &lt;span class="nx"&gt;principal_arn&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_user&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;arn&lt;/span&gt;

  &lt;span class="nx"&gt;access_scope&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;"namespace"&lt;/span&gt;
    &lt;span class="nx"&gt;namespaces&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"example-namespace"&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;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi, everyone.&lt;br&gt;
I would like to leave a memorandum about how to manage Kubernetes's configmap AWS auto-generated with terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Trouble
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;If we want to add iam user/role for eks cluster operation, we need to fix auto-generated aws-auth configmap(namespace:kube-system)&lt;/li&gt;
&lt;li&gt;If we follow the official manual: &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html&lt;/a&gt;), we should manage it with kubernetes manifest yml, but we want to manage it with terraform.

&lt;ul&gt;
&lt;li&gt;Because at first we can access our eks cluster only with IAM user/role used when creating cluster(with ~/.kube/config as below) and our cluster generated role is terraform user/role&lt;/li&gt;
&lt;li&gt;Therefore, We want to add user/role to aws-auth configmap with terraform user/role and manage aws-auth configmap with terraform.&lt;/li&gt;
&lt;li&gt;Caution: According to &lt;a href="https://aws.github.io/aws-eks-best-practices/security/docs/iam/#create-the-cluster-with-a-dedicated-iam-role" rel="noopener noreferrer"&gt;EKS Best Practices Guides - Security&lt;/a&gt;, we should create the cluster with a dedicated IAM role
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ~/.kube/config&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:eks:ap-northeast-1:9999999999:cluster/eks-example&lt;/span&gt;
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client.authentication.k8s.io/v1alpha1&lt;/span&gt;
      &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--region&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ap-northeast-1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;eks&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;get-token&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--cluster-name&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;eks-example&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;
      &lt;span class="na"&gt;provideClusterInfo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to resolve the trouble
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Add terraform aws-auth configmap resouece and Use &lt;code&gt;terraform import&lt;/code&gt; command
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1.0 Prepare terraform kubernetes provider
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"kubernetes"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;host&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;aws_eks_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;
  &lt;span class="nx"&gt;cluster_ca_certificate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;base64decode&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;aws_eks_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;certificate_authority&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;token&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;aws_eks_cluster_auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Caution: we should set host/token/cluster_ca_certificate to operate kubernetes cluster with tf-provider.

&lt;ul&gt;
&lt;li&gt;REF: &lt;a href="https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest" rel="noopener noreferrer"&gt;https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h4&gt;
  
  
  1.1 Prapare aws-auth configmap tf resource for importing
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# aws-auth.tf&lt;/span&gt;
&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"kubernetes_config_map"&lt;/span&gt; &lt;span class="s2"&gt;"aws-auth"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"mapRoles"&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="nx"&gt;metadata&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;""&lt;/span&gt;
    &lt;span class="nx"&gt;namespace&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  1.2 Execute &lt;code&gt;terraoform import&lt;/code&gt; cmd
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform import kubernetes_config_map.aws-auth kube-system/aws-auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  1.3 terraform plan and remove diff from real resource state to resource config
&lt;/h4&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;"kubernetes_config_map"&lt;/span&gt; &lt;span class="s2"&gt;"aws-auth"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"mapRoles"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOT&lt;/span&gt;&lt;span class="sh"&gt;
- rolearn: arn:aws:iam::99999999999:role/hoge-role
  username: system:node:{{EC2PrivateDNSName}}
  groups:
    - system:bootstrappers
    - system:nodes
      # Therefore, before you specify rolearn, remove the path. For example, change arn:aws:iam::&amp;lt;123456789012&amp;gt;:role/&amp;lt;team&amp;gt;/&amp;lt;developers&amp;gt;/&amp;lt;eks-admin&amp;gt; to arn:aws:iam::&amp;lt;123456789012&amp;gt;:role/&amp;lt;eks-admin&amp;gt;. FYI:https://docs.aws.amazon.com/eks/latest/userguide/troubleshooting_iam.html#security-iam-troubleshoot-ConfigMap
&lt;/span&gt;&lt;span class="no"&gt;EOT
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;metadata&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;"aws-auth"&lt;/span&gt;
    &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kube-system"&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;h3&gt;
  
  
  2. Fix aws-auth configmap resource we imported and add iam user/role
&lt;/h3&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;"kubernetes_config_map"&lt;/span&gt; &lt;span class="s2"&gt;"aws-auth"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"mapRoles"&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOT&lt;/span&gt;&lt;span class="sh"&gt;
- rolearn: arn:aws:iam::99999999999:role/hoge-role
  username: system:node:{{EC2PrivateDNSName}}
  groups:
    - system:bootstrappers
    - system:nodes
      # Therefore, before you specify rolearn, remove the path. For example, change arn:aws:iam::&amp;lt;123456789012&amp;gt;:role/&amp;lt;team&amp;gt;/&amp;lt;developers&amp;gt;/&amp;lt;eks-admin&amp;gt; to arn:aws:iam::&amp;lt;123456789012&amp;gt;:role/&amp;lt;eks-admin&amp;gt;. FYI:https://docs.aws.amazon.com/eks/latest/userguide/troubleshooting_iam.html#security-iam-troubleshoot-ConfigMap
# Add as below 
- rolearn: hoge
  username: hoge
  groups: # REF: https://kubernetes.io/ja/docs/reference/access-authn-authz/rbac/
    - hoge
&lt;/span&gt;&lt;span class="no"&gt;EOT
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;metadata&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;"aws-auth"&lt;/span&gt;
    &lt;span class="nx"&gt;namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kube-system"&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;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/ja/docs/reference/access-authn-authz/rbac/" rel="noopener noreferrer"&gt;https://kubernetes.io/ja/docs/reference/access-authn-authz/rbac/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest" rel="noopener noreferrer"&gt;https://registry.terraform.io/modules/terraform-aws-modules/eks/aws/latest&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>eks</category>
      <category>aws</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
