Kengo's blog

Technical articles about original projects, JVM, Static Analysis and TypeScript.

2024年の振り返りと2025年の抱負

2024年終わりました。仕事の面では医療系スタートアップに転職してから3年目に突入、より混沌としてきています。子供も心身ともに大きくなってきていて、自らの加齢を感じることも増えてきました。人生ですね。

さて今年のトピックはだいたいこんなところ↓だと思うので、掘り下げていきます。

  1. 情報処理安全確保支援士試験に合格した
  2. 勤め先でDevelocityを導入した
  3. 技術書典に合同誌を出した
  4. OSS活動を休止した

情報処理安全確保支援士試験に合格した

こちらは独立した記事を書いたのでそちらを参照ください。昨年の医療情報技師に続けての資格取得でしたが、転職前は資格試験から距離をとっていたこともあり、とても新鮮な体験でした。

来年は新たな受験ではなく、資格を仕事に活かす方向でのキャッチアップと発信を心がけていきたいと考えています。

勤め先でDevelocityを導入した

私の勤め先である株式会社ヘンリーはサーバサイドKotlinを推しており、もちろんサービスの開発でも活用しています。この夏に私もモノレポ化について発信していました。

Kotlinプロジェクトのモノレポ化には大きな恩恵がある一方で、増えるコードやテストケースのコンパイルならびにテスト実行をどう高パフォーマンスに行うかという壁があります。この解決にはGitHub Actions workflowの最適化も有効ですが、勤め先ではそれにあわせてGradle社が展開するオンプレサービスであるDevelocityの導入と運用を手がけました。実際有効なので、今後もサーバサイドKotlinを盛り上げる一環に情報を発信していきます。

技術書典で合同誌を出した

前述のDevelocityをはじめとした各種工夫を盛り込んだ本を勤め先の有志で作成し、技術書典に出しました。Re:VIEWでの執筆は初体験でしたが、なかなか好評だったようで良かったです。

GitbookやSphinx、zennなどとはまた違った書き味で面白く、また書いてみたいと思っています。

OSS活動を休止した

ちょこちょこGradleプラグインや自作RDBMSを書き溜めたり、仕事で使っているツールの不具合修正のためのPRを送ったりはしているのですが、実質的にOSS活動は止まってました。

狙ってそうしたというよりは、他にやりたいことがあるので結果的にそうなったという感じで、まぁそういうこともあるのかなという所です。来年もおそらくこの状況が続くと思われます。

2025年の抱負

まだ決めきれてないですが、来年はこんな感じにしようと思っています:

  1. 技術書典に個人で出展する
  2. マネジメントスキルの棚卸し

技術書典の出典には、既刊のMaven本にあわせてGradle本を書き下ろしたいと考えています。Gradleの本って、商業でも同人でもほぼないんですよね。Gradle 9対応で出せれば唯一無二の日本語本ということになりそうです。ただ1人で書ける量には限度があるため、全ての概念を1から教える初心者本ではなく触ったことのある人がステップアップするための本に特化するつもりです。

 

マネジメントについては今年もProduct Managementの真似事はやっていたものの、意図的に距離をとっていました。ICとしての勘や実績、自信が欲しかったのもありますが、何よりもPeople Managementで燃え尽きてしまったのでやりたくなかったんですよね。

People Managementは正直今でもやりたくないですが、充分に休息は取れたのでそろそろ今できることの再確認と古びたスキルの手入れをする時期かなと思っています。Project ManagementやProduct Managementを中心に据えつつ、必要なことをやっていきます。

来年もよろしくお願いいたします

今年は14記事と、昨年の20記事よりは少なくなりました。年間を通じて時間を作ることが難しく、なかなかタフな1年でした。来年もこのへんはあまり変わらない気はしますが、ちょいちょい書いていければと思います。引き続きよろしくお願いいたします。

Testcontainersで単体テスト実行時に必要なデータベースを自動的に用意する

この記事は Kotlin Advent Calendar 2024 10日目の記事です。前回はtsukakeiさんのExposedでStatementInterceptorを使ってSQL文実行前後に処理を差し挟むでした。

先日出した合同誌でも触れましたが、Testcontainersを使うと単体テスト実行時に必要なデータベースを自動的に用意することができます。TestcontainersといえばSelenide (Selenium)でもお世話になりましたが、ブラウザだけではなくデータベースも対応しているんですね。

合同誌掲載ケースではDevelocityのTest Distributionで遠隔テストを実行するのに利用しましたが、手元やGitHub Actionsなどでテストをするにも便利なので紹介します。なお掲載コードはKoinとKotest、Postgresを前提としています。

Testcontainersがなぜ便利なのか

Testcontainersはテストに利用するための外部プロセスをお手軽に利用するためのライブラリです。たとえば従来だとPostgresに依存したテストを実行するには実行環境にPostgresをインストールすること(GitHub Actionsなら services を使ってPostgresを起動する、など)が必要でしたが、ポート番号を環境変数で受け渡すとか、データベース側がちゃんと起動したか確認するとかの手間があり不便です。Testcontainersを使うことでプログラムからデータベースを起動できるので諸々をテストコードとして管理できるようになり、メンテナンス可能性が上がります。

TestcontainersをKotestで使う

公式のQuickStartにはKotestに特化したものがないので説明します。前提としてデータベースに接続するための接続プールをKoinで初期化しているものとします:

// src/main/kotlin/com/example/DatabaseModule.kt
@Module
@ComponentScan
class DatabaseModule {
  @Single
  fun createDatasource(): HikariDataSource { ... }
}

テスト実行時はこれを上書きして利用することにします。java-test-fixtures プラグインを使えばテストコードではないけどテストから利用するコードをテストコードから分離して管理できますので、これを利用すると良いでしょう。

// build.gradle.kts
plugins {
  `java-test-fixtures`
  ...
}

dependencies {
  testFixturesImplementation("org.testcontainers:postgresql:1.20.4")
  ...
}

TestFixtureとテストコードは次のようになります:

// src/testFixtures/kotlin/com/example/DatabaseModuleForTest.kt
fun createTestcontainerModule() = module {
  single<HikariDataSource> {
    // TODO: ここにTestcontainers利用コードを書く
  }
}
// src/test/kotlin/com/example/MyTest.kt
class MyTest : DescribeSpec({
  beforeSpec {
    startKoin {
      modules(DatabaseModule.module + createTestcontainerModule())
    }
  }
  afterSpec {
    stopKoin()
  }
  // TODO: ここにデータベースに依存したテストを書く
})

Postgres公式イメージを使う

Testcontainersの使い方のひとつとして、Postgres公式イメージを使ってデータベースを起動できます。スキーマがなにもない状態で起動しますから、ExposedのSchemaUtilsあたりで初期化する必要はあります。

fun createTestcontainerModule() = module {
  single<HikariDataSource> {
    val container = PostgreSQLContainer("postgres:17-alpine").apply {
      withLogConsumer(Slf4jLogConsumer(logger))
      start()
    }
    val config = HikariConfig().apply {
      jdbcUrl = container.jdbcUrl
      username = container.username
      password = container.password
      driverClassName = container.driverClassName

      // TODO: 他の設定をする

      validate()
    }

    return HikariDataSource(config)
  }
}

なお Slf4jLogConsumer はTestcontainersのログをSLF4Jのロガーに渡すための設定です。SLF4Jを利用していない場合は他の LogConsumer を使うことになるでしょう。

独自のコンテナを使う

すでにコンテナレジストリにある独自のコンテナを使うこともできます。Postgres互換のイメージであることを明示するために asCompatibleSubstituteFor("postgres") の実行が必要です。

fun createTestcontainerModule() = module {
  single<HikariDataSource> {
    val imageName = DockerImageName.parse(IMAGE_NAME).asCompatibleSubstituteFor("postgres")
    val container = PostgreSQLContainer(imageName).apply {
      ...
      start()
    }
    ...
  }
}

コンテナのライフサイクルを考える

PostgreSQLContainerAutoCloseable インタフェースを実装しています。つまりコンテナのライフサイクルをプログラムから管理する必要があります。KotestはJUnit5の基盤で動いているので、Testcontainers組み込みのJUnit4対応は期待できません。オフィシャルサイトを参考に、自分で管理を考える必要があります。

ところでテストコードで Koin を使う場合、すでに KoinApplication のライフサイクルを管理しているはずです。Specごとに KoinApplication を作るとか、テストケースごとに KoinApplication を作るとかの方法がありますが、コンテナのライフサイクルもこれと同じにできるなら、Koin moduleが閉じられたタイミングでコンテナを止めるようにするのがシンプルでしょう。

fun createTestcontainerModule() = module {
  single<PostgreSQLContainer> {
    ...
  } onClose {
    it.close()
  }
  ...
}

またKoinApplication とコンテナのライフサイクルをあわせてしまうとテストの実行パフォーマンスに影響がある場合は、コンテナをSingletonとして扱うことになります。この場合はコンテナの停止はTestcontainersに任せられるので、明示的に close() を呼ぶ必要はありません。

まとめ

Testcontainersを使うとデータベースに依存したテストケースをより簡単に実行できます。ちょっと前だとH2 Databaseなどのオンメモリデータベースを使っていましたが、Testcontainersだと本番環境と同じRDBMSを使えるのでより安心ですね。Postgresに依存するコードをテストする際にお試しください!

2024年に読んでよかった本

医療関係

「看護覚え書」ナイチンゲールが書いた本ということで、初心を理解するのに良いかなと思って購入しました。超人ナイチンゲール (シリーズ ケアをひらく)と合わせて、現代看護の成り立ちみたいなものに触れる良い機会になりました。システム実装やドメイン理解の役に立ったかというとNOですが、看護と聞いて自分が連想するものがとても狭いのだということはよく理解できました。

エンジニアリング

「情報セキュリティの敗北史」セキュリティがとても人間のウェットな部分をクローズアップするテーマなんだということを再認識した本です。マイクロソフト社のかつての過ちとか、様々な立場の人間が利益を最大化するために行動した結果として脆弱性が”活用”されているとか、ぱっと見たときに良さそうな選択肢(例えばバグバウンティ)が一歩引いてみるとそうでもないとか。

自分は性善説や理想論で動きがちな人間なので、改めて情報セキュリティめんどくせぇ奥が深いなぁと思いました。今後もちょくちょく振り返って手に取る本になりそうです。

「本質から考え行動する科学技術者倫理」 この春に放送大学の講義を受講しまして、残念ながら単位取得までは行かなかったんですが、この科学技術者倫理について学ぶ良い機会となりました。倫理というと高校の授業でやるやつですが、自分の高校の教師は歳を食ってある程度フラットに物事が見られるようになった今の自分から見ても疑いなくひどかったので、倫理についてはエッセンスも何もキャッチアップできていなかったんですよね。

失敗学の繋がりで回転ドアの話とかチャレンジャー号事件の話とかは知っていたのですが、AI技術の進展を踏まえた議論などは初めて見たので、きちんと学び直したいなと思い放送大学の講義資料とは別にこの教科書を購入しました。スタートアップで社会課題の解決にもがいていると前人未踏の問題領域に踏み込むことは多く、多かれ少なかれ倫理的判断が求められるシーンはきっとあると思うので、情報システムで社会に切り込むスタートアップに在籍しているタイミングでこの本に出会えて良かったと思います。

「一級建築士矩子と考える危ないデザイン」は単行本を購読しているマンガ「一級建築士矩子の設計思考」のスピンオフ?と言いますか、マンガのキャラクタを拝借して危ないデザインを紹介するというものです。元のマンガを購読していなくても楽しめますし、建築関係なくユーザインタフェースの設計・開発をするITエンジニアには広くおすすめです。

個人的には自分の母校のデザインがかなり危なかったのだなぁということに気づき、ちょっと怖くなりました。1階の庇に柵がついてないのに2階から乗ることができたんですよね。当時はそういうものだろうと思っていましたが、改めて考えると悪いデザインだったと思います。日頃の周囲を見る目が変わる1冊でした。

その他

建築好きなのでちょくちょく間取りや設計、建築についての本や雑誌を買っているのですが、今年は商店建築に加えてこちらの「お宿図鑑」を買いました。スケッチがとても美しく細かくて、自分が現地に赴いても発見できないだろうなと確信できる内容盛りだくさんでした。

掲載されているお宿はおおむね子連れで行ける宿というか、いずれ親と行きたい宿という風情ですね。この本を読んで、家族でゆっくりとした時間を楽しめる未来がより楽しみになりました。

Kotlinからお手製Javaライブラリを呼んでる人のためのJSpecify入門

これはKotlin Advent Calendar 20242日目の記事です。前日は id:take7010 さんの「KotlinとOpenAI APIで領収書の情報を抽出する」でした。

先日Kotlin愛好会オンラインでJSpecify入門について話しました。JSpecifyについては3年前のJJUG CCCでも話しましたが、この夏にv1.0.0が出たので改めて知っていただければと思っています。

speakerdeck.com

JSpecifyの何が嬉しいか

Kotlinの世界に閉じた実装を行っていると、JSpecifyのアノテーションを使う機会はほぼないはずです。JSpecifyが嬉しいのはKotlinからJavaを呼ぶ場合です。 Javaライブラリ側の引数や戻り値をJSpecifyアノテーションで修飾しておくと、null-safetyなKotlinの引数や戻り値と同じように扱えます。 今まではKotlinコンパイラが警告を吐くだけでしたが、Kotlin 2.1.0からエラーとして扱われるようになりました。

どこから始めればいいか

nullableな戻り値を @Nullable で修飾するところから始めましょう。ランタイムの NullPointerException を防ぐために最も重要なアノテーションだと思います。

次点が List<T> のようなGenericsだと思いますが、このへんはけっこう複雑なのでドキュメントに目を通しておきましょう。

なおすべてのnullableな型を修飾したと言えるようになったら、パッケージを @NullMarked で修飾しておけば「 @Nullable が無いところは全てnot-null」だということをコンパイラに伝えられます。 nullableな値を持ち回らないようなコードを書いている場合は便利かもしれません。

Java と Kotlin を安全に橋渡ししよう

Kotlinの強みのひとつとして「Javaの資産を活用できる」のが挙げられますが、そのためにはJavaになくてKotlinにある機能をどう扱うかを検討しなければなりません。 null安全はそのうちのひとつですが、JSpecifyのv1.0.0リリースによってある程度標準的な解決策が用意されたと言ってよいでしょう。 KotlinをJavaで書かれたライブラリやフレームワークと組み合わせて使っている方は、ぜひ試してみてください。

Kotlin Advent Calendar 2024の明日の記事は、 id:tsukakei1012 さんの「Exposedについて①」の予定です。

情報処理安全確保支援士になりました

今月より晴れて、情報処理安全確保支援士(登録番号028693)を名乗れるようになりました。昨年取った医療情報技師と合わせて、医療情報システムの情報処理安全についてのプロフェッショナルであることをある程度の説得力を持って説明できるようになったと考えています。

とはいえ資格をとったら急に仕事ができるようになるかというとンなわけないので、より複雑な課題解決ができるように継続して学んでいきます。とりあえず今日は、なぜセキュリティなのかと、今後の抱負をここにまとめておこうと考えた次第です。

なぜ今セキュリティなのか

私はいままでCDワークフロー改善であるとか、ログ管理含めた保守性であるとか、エンタープライズアプリケーションの性能改善であるとか、どちらかと言えばシステム実装に寄った非機能要件を多く見てきました。

一応OSSライセンスの管理やビルドスクリプト改善から発展して、OSS脆弱性への対応も経験してはいるのですが、セキュリティについてはそこまで専門でやってこなかったというのが正直なところです。

 

セキュリティについて学ぶ起点となったのは2021年末、Log4Shellの対応です。GitHubで突如公開されたコミットをもとに修正内容の把握や自社サービスへの影響などを短期間に特定して全社的になんとかする体験をし、セキュリティが「OSSエンジニアとしての経験とベストプラクティスを現場の運用に落とし込むという自身の関心領域とが交差する場」でもあるのだという発見に繋がりました。

そして転職後、医療情報システムの安全管理に関するガイドラインについて学んだり、サイバーセキュリティが医療機関等の管理者に対する義務化されたりして、自然とセキュリティについて学ぶ時間が増えたというのが「なぜセキュリティなのか」への回答というところです。端的に言うと医療業界的にニーズが高いのと、自分のWILLやCANとマッチしたというところですね。

情報処理安全確保の第一歩は相互理解

情報処理安全確保支援士の資格試験では、自分が支援士だと仮定したうえでどう考えて行動すべきかを問う設問が出ます。そしてその場には必ず複数の関係者が出てきます。そもそも情報処理安全確保「支援士」ですから、組織に対して支援を提供してゴールを目指す立ち位置=実行者ではなくハブであり、経営者や情報システム担当に対する助言者だということなのだと私は理解しました。

同様に医療情報技師も関係者との交流を指す「3C」を重視しています

他職種との意思疎通を図るためのコミュニケーション(Communication)、他職種と協力して対応するコラボレーション(Collaboration)、部門間や職種間の調整を行うコーディネーション(Coordination)の3つの能力を必要な資質としています

医療機関で働く医療情報技師は自らの管理下にない部門システムや保守用ネットワークを業務の前提とすることも多く、事業者を含む他職種との協業が絶対必要です。だからこそより安全で患者様や職員のためになるシステム運用を実現するために、協調や調整が重要なのだと私は理解しました。

異なる資格が同様に他者とのコミュニケーションを通じての実行にピンを留めているのは面白いですね。それだけ業務遂行に必要な能力だと考えられているわけで、重要性もまた理解できます。

不安に名前をつけるのが情報処理安全確保支援の初手

さてセキュリティに明るくない方とのコミュニケーションにおいて、その出発点は多くの場合「よく知らないけど、これをしたい」「あれってセキュリティに問題あるって本当?」といった漠然とした不安であることが多いと感じます。そしてわかりやすく一網打尽にできそうな、たとえば閉域網のような選択肢が支持されます。情報技術は目に見えないものを扱うので、気持ちは理解できます。

ここで求められる3Cはその不安を具体的に表すことだと思っています。どのようなゴールを望んでいるのか、どんなリスクがあると考えているのか、保守にどれだけの手間をかけられるのかなど、いろんな視点からあるべき姿を探ります。その結果として不安に名前がつき、この不安にはこう対処する、この不安は当面どうしようもないので受け入れる、という議論ができるようになります。

もちろん相手にはよるものの、多くの場合はこうしたコミュニケーションを通じて不安や心配をリスクマネジメントという経営的な営みに近づけること、なんとなくや人から聞いたからではなくて戦略的に決定を下せるようにすること、その決定に大きな穴が無いようにすることが支援士かつ医療情報技師としてできる貢献なのかなぁ、みたいな。

まとめ

情報処理安全確保支援士になりました。いろんな立場の方との相互理解に努め、ヒアリングを通じて不安に名前をつけ、合理的かつ利便性の高い情報処理安全確保の支援をしていきたいと思います。

そのためには今までやってきたマネジメントやコーチングといった経験が活きるでしょうし、自分のWILLであるベストプラクティスを現場に落とし込むことも役立つはずです。情報セキュリティの知識を常にアップデートしつつ、課題解決に貢献できるエキスパートとして成長していきます。

Gradle用のGitHub Actions勘どころ(2024年夏)

前回に引き続き以下略。

jarファイルのビルドはコンテナの外で行う

ビルドをコンテナの中で行う場合、工夫がなければ毎回はじめからコンテナのビルドが走ります。これはパフォーマンス上好ましくないので、GitHub Actionsのキャッシュ用APIだとかRepository Cacheだとかを使ってビルド性能の改善を図れます:

docs.docker.com

ただGradleプロジェクトの場合はGradle自身が常に同じビルド結果を生成するように動作してくれますので(JVM toolchainとかreproducible buildsとかの話ね)、jarファイルのビルドはコンテナの外でやって Dockerfile では COPY するだけでも良さそうです。この場合は actions/setup-java のキャッシュ機構やRemote Gradle Build Cacheなどを簡単に使えます。

pushとpull_requestで別のワークフローを使う

PR向けのGitHub Actions workflow runが走っているタイミングでPRをマージすると、push時に走るはずのGitHub Actions workflow runが実行されない!という問題があります。ワークフローを分けることで回避できるため push.ymlpull_request.yml とを別に定義してreusable workflowをコールする方法を採ると良さそうです。

# .github/workflows/push.yml
on:
  push:
    branches:
      - main
jobs:
  build:
    uses: ./.github/workflows/reusable-build.yml
    secrets: inherit
  deploy:
    uses: ./.github/workflows/reusable-deploy.yml
    secrets: inherit
    with:
      environment: production
# .github/workflows/reusable-deploy.yml
name: Deploy
run-name: Deploy ${{ github.sha }} to ${{ inputs.environments }}
on:
  workflow_call:
    inputs:
      environment: ...

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ inputs.environment }}
    permissions: ...
    steps: ...

プロジェクトを増減させやすいtfactionプロジェクトを書きたい

私はTerraformを使うときにtfactionを利用しています。tfactionはGitHub ActionsとS3やGCSのような永続層だけでTerraformをいい感じに管理できるのでオススメです。

suzuki-shunsuke.github.io

ところでプロジェクトの増減はTerraformの難しいところだと思っていて、OIDCで認証するサービスアカウントの作り方とか権限の設定とか、新規に作成したプロジェクトの初期化や設定がなかなかTerraform単体では完結できなかったりします。手順書を作っておいて全部手動でやるのもいいのですが、できるだけTerraformで記述する方法を考えてみました。

前提となるプロジェクト構成

以下、特に断りのない場合、Google Cloudを前提としています。

プロジェクトは環境(staging, productionなど)ごとに1つ作成します。例外としてArtifact RegistryやCloud DNSを管理する共有プロジェクト(shared)がひとつあります。これはstagingやproductionのサービスアカウントがsharedのArtifact Registryに対して読み書きする権限が必要ということで、権限管理のキモのひとつです。

flowchart TD
  staging --> shared
  production --> shared
  shared

GitHub ActionsからのログインにはOIDCを利用します。これはWIP(Workflow Identity Pool)が早い段階で必要になることを意味しています。ブランチ戦略に従ってWIP Providerのattribute conditionを設定する必要があるので、たとえばproductionにはmainブランチからしかデプロイしない、といったルールは先に決めておきます。

プロジェクトの作成フローを定めておく

プロジェクト作成の大まかなフローは次のようになります。moduleはこれらの複数のステップに跨ることがないように作成しておくと良さそうです:

  • プロジェクト作成(scaffold workdir
  • 課金の有効化(手動)
  • 各種サービスの有効化(google_project_service
  • terraform plan用サービスアカウント, terraform apply用サービスアカウント, WIPなど作成(モジュール)
  • terraform plan用サービスアカウントとterraform apply用サービスアカウントがGCSバケットにアクセスできるようにする(同上)
  • terraform plan用サービスアカウントとterraform apply用サービスアカウントの切り替え(workdirのtfaction.yaml更新)

ここまではプロジェクトの作成や他のプロジェクトに属するサービスアカウントの作成ができる、強めの権限を持つサービスアカウントを使います。ここからは他のプロジェクトには影響できないサービスアカウントだけで済むはずです。以下のような手順になります:

  • firebaseプロジェクトの作成(手動)
  • サービスアカウントの作成と権限設定(他プロジェクトにあるArtifact Registryなどを含む)
  • リソースの作成
  • notification channelの作成(手動)

サービスアカウントの作成とリソースの作成は同じmoduleでやって大丈夫ですが、他プロジェクトにあるリソースのIAM設定を考えると分けておいても良さそうです。Cloud RunがArtifact Registryに接続できなくてterraform applyに失敗した、とかはよくやります。

workdirの作り方

workdirは少なくとも3種類を持つようにします。これはわかりやすさはもちろん、 terraform apply 等を実行するサービスアカウントの権限を単純にするためにも有効です:

  • プロジェクトやフォルダを作成・管理するworkdir
    • google_folder
    • google_project
    • google_app_engine_application
    • google_project_service
  • 共有プロジェクト内のリソースを管理するworkdir
    • google_artifact_registry_repository
    • google_storage_bucket
    • google_dns_managed_zone
  • 各プロジェクト内のリソースを管理するworkdir

プロジェクトやフォルダを作成・管理するworkdirは main.tf 内に直接処理を書きますが、他のworkdirは適宜moduleに処理を委譲するような書き方が良さそうです。共有プロジェクト内のリソースを管理するworkdirでは、接続を許可するプロジェクトのIDを locals.tf に定義して使うようにすると、プロジェクト増減時の手順が簡素化されます。

moduleの作り方

「各プロジェクト内のリソースを管理するworkdir」の処理はmoduleとして実装しておくことで、workdirに似たような処理を書いて回る手間がなくなります。tfaction 1.3.0からローカルモジュールの扱いがより便利になったので、ローカルモジュールを使う上でのハードルも下がってます。

suzuki-shunsuke.github.io

「各プロジェクト内のリソースを管理するworkdir」が使うモジュールは先ほど整理した作成フローをもとに、以下の種類に分けられます:

  • 各種サービスの有効化(プロジェクトを作成して課金を有効にした後で行う)
  • terraform-plan用サービスアカウント, terraform-apply用サービスアカウント, WIPなど作成(これは他のworkdirでも使える)
  • リソースの作成

ひとつのモジュールが複数のステップを担っても問題ありませんが、前提ステップが終わるまで後続ステップを進めないことを確実にできるように、リソース間依存やvariableを使う必要はありそうです。

まとめ

サービス運用中はこういった観点を意識できてなかったりして、いざ環境を増やすぞというときに苦労するということが自分は多かったので、しばらく今回まとめたmoduleやworkdirの書き方を意識してみます。