AWS CDKでMavenではなくGradleを使用する

こんにちは。 エキサイト株式会社で内定者アルバイトをしている平石です。

今回は、AWS CDKをGradleで使用できるようにしていきたいと思います。

前の記事

tech.excite.co.jp

AWS CDKとMaven & Gradle

AWS CDKのコードをJavaで作成するにあたって、

cdk init app --language java

で自動生成されるプロジェクトはビルドツールにMavenを使用しています。
しかし、既存のプロジェクトで使用しているなどの理由でGradleを使用したい場合も十分にあると思います。

今回は、AWS CDKにおいてGradleを使って開発できるようにするための方法を紹介します。

この記事を執筆するにあたって以下のブログ記事を参考にしました。

Setting up the AWS CDK with Java & Gradle

実際にGradleで作成してみる

CDKのセットアップ

CDKのインストールや開発の流れについては以下で解説していますので、この記事では以下の内容を前提として進めていきます。(AWS CDKがインストールされ、bootstrapや各種設定が済んでいる状態、cdk initはしていなくて良い)

tech.excite.co.jp

CDKプロジェクトのテンプレートを作成してくれるcdk initは空のディレクトリでしか実行することができません。
そこで、下記の「gradleの準備」から「サブモジュールの作成」までを先に実行し、別のディレクトリ等で一度cdk initしたもののうち必要なファイルやディレクトリを移してくるか、cdk initを実行したディレクトリでMaven関連のファイルやディレクトリを削除することになるかと思います。
どちらでも問題ありませんので、ご自身の好みや開発プロジェクトでの方針等で決定してください。

gradleの準備

まずは、Gradleプロジェクトを初期化します。
今回は、cdk-gradleというプロジェクト名にします。

mkdir cdk-gradle
cd cdk-gradle
gradle init

type of projectbasicで問題ありません。build script DSLGroovyを選択してください。

build.gradleの編集

まずは、どのGradleのバージョンを使用するかを定義します。

build.gradleに以下を追加してください。(Gradleのバージョンはご自身が使用するものに変更してください)

wrapper {
    gradleVersion = "7.5"
    distributionType = Wrapper.DistributionType.ALL
}

以下のコマンドを実行すると、指定したバージョンのGradleがインストールされます。

./gradlew wrapper

Gradleのバージョンを確認しましょう。

./gradlew --version
------------------------------------------------------------
Gradle 7.5
------------------------------------------------------------

Build time:   2022-07-14 12:48:15 UTC
Revision:     c7db7b958189ad2b0c1472b6fe663e6d654a5103

Kotlin:       1.6.21
Groovy:       3.0.10
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.1 (Amazon.com Inc. 17.0.1+12-LTS)
OS:           Mac OS X 12.5 aarch64

また、依存関係をMaven Centralから取得するように設定します。
build.gradleに以下を追加してください。

plugins {
    id 'java-library'
}

group 'org.sample.group'
version = "0.1.0-SNAPSHOT"

wrapper {
    gradleVersion = "7.5"
    distributionType = Wrapper.DistributionType.ALL
}

allprojects {
    repositories {
        mavenCentral()
    }
    group = rootProject.group
    version = rootProject.version
}

ここで、グループとプロジェクトとこのプロジェクト内のすべてのサブモジュールのバージョンを設定しています。
グループについては定義変更してください。

このトップレベルのプロジェクトのbuild.gradleはもうこれ以上編集しません。
もちろん、トップレベルのプロジェクトで開発をしても動作上は問題ないのですが、モジュールに分割したくなった時のためにサブモジュールで開発をしていきます。

サブモジュールの作成

settings.gradleに以下のように記述します。

rootProject.name = 'cdk-gradle'

include("cdkcode")

cdk-gradleプロジェクトにcdkcodeというサブモジュールが存在することを表しています。

では、実際にサブモジュールを作成します。

mkdir cdkcode
cd cdkcode

このディレクトリにもbuild.gradleファイルが必要です。
当然、自動では作成されませんので、手動で作成してください。

touch build.gradle

では、サブモジュールのbuild.gradleファイルを編集していきましょう。

plugins {
    id 'java'
    id 'java-library'
    id 'application'
    id 'com.github.johnrengelman.shadow' version '7.1.2'

}

def CDK_VERSION = "2.46.0"
def CONSTRUCT_VERSION = "10.1.131"

dependencies {
    implementation "software.amazon.awscdk:aws-cdk-lib:${CDK_VERSION}"
    implementation "software.constructs:constructs:${CONSTRUCT_VERSION}"

    implementation 'org.slf4j:slf4j-simple:2.0.3'
    implementation 'io.github.origin-energy:java-snapshot-testing-junit5:3.3.2'

    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.1'
}

application {
    mainClassName = 'org.sample.group.cdkcode.CdkGradleApp'
}

AWS CDKとConstructsのバージョンは適宜変更してください。

バージョンは以下で確認できます。

実行可能なjarファイルを生成するためのapplicationプラグイン、実行可能jarファイルには必要な依存関係が全て含ませるため(fat jar)のshadowプラグインを宣言しています。

なお、fat jarの作成自体はSpring Boot等他のプラグインを使用しても問題ありません。

CDKアプリケーションの開発

CDKアプリケーションのコード自体は、Mavenを使用するときと変わりませんので、ご自身の必要なリソースを定義してください。
ここでは、設定項目が少なく作成が容易な、IAMユーザを作成するコード例を示します。

package org.sample.group.cdkcode;

import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.iam.User;
import software.constructs.Construct;

import java.util.List;

public class CdkGradleStack extends Stack {
    public CdkGradleStack(final Construct scope, final String id) {
        this(scope, id, null);

    }

    public CdkGradleStack2(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        User user = User.Builder.create(this, "GradleUser")
                .userName("elaina")
                .build();
    }
}

なお、パッケージをサブモジュールのbuild.gradlemainClassNameで指定したパッケージと一致させることを忘れないようにしましょう。

コードを記述できたなら、以下のコマンドを実行してビルドし、実行可能jarファイルを作成しましょう。

./gradlew shadowJar

当然、shadow以外を使用する場合にはそれぞれの方法でjarファイルを作成してください。

cdk.jsonの編集

cdk initを実行すると自動生成されるcdk.jsonは以下のようになっているかと思います。

{
  "app": "mvn -e -q compile exec:java",
  "watch": {
    "include": [
      "**"
    ],
    "exclude": [
      "README.md",
      "cdk*.json",
      "target",
      "pom.xml",
      "src/test"
    ]
  },
  "context": {
      略
    ]
  }
}

このcdk.jsonではcdkコマンドで使われるオプションのデフォルト値を設定することもできます。

例えば、CDKのコードからCloudFormationのテンプレートを作成するcdk synthコマンドではアプリケーションまたはクラウドアセンブリディレクトリを実行するためのコマンドラインである--app(または-a)オプションが必須となっています。
しかし、コマンド実行時にはこのオプションを指定しなくても問題なく実行されます。
なぜかというと、cdk.jsonの設定のappがデフォルト値として使用されるからです。

では、このファイルを編集してcdk synthcdk deployで使用されるオプションのデフォルト値を変更しましょう。

とはいえ、変更箇所は"app"のみです。ここを以下のように変更します。

"app": "java -jar <jarファイル>"

<jarファイル>の部分には作成したjarファイルのパスを記述してください。

補足

なお、"app"の部分に"./gradlew shadowJar && java -jar <jarファイル>"と記述すれば、コードの変更後にビルドコマンドを手動で実行する必要がなくなります。

出力先の変更

cdk synthcdk deployを実行するとCloudFormationのテンプレートを出力します。この出力先を変更したい場合もあるでしょう。
この場合には、--outputまたは-oオプションで指定することになりますが、いちいち指定するのは面倒ですよね。

こういう時には、どうすれば良いのでしょうか?
そう、cdk.jsonに記述すれば良いのでしたね!

cdk.jsonに以下のような設定を追加してください。(なお、"out"は自動生成時にはありませんので、手動で追加してください。)

"out": "cdkcode/build/cdk.out"

この例では、cdkcode/build/cdk.outというファイルに出力します。

合成、デプロイの確認

ここまで、設定できればあとはいつものように

cdk synth
cdk deploy

を実行することができます。

それでは

cdk deploy

を実行してみましょう。

cdk-gradle % cdk deploy

BUILD SUCCESSFUL in 639ms
2 actionable tasks: 2 up-to-date


✨  Synthesis time: 3.9s

CdkGradleStack: building assets...

[0%] start: Building xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxx-ap-northeast-1
[100%] success: Built xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxx-ap-northeast-1

CdkGradleStack: assets built

CdkGradleStack: deploying...
[0%] start: Publishing xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxx-ap-northeast-1
[100%] success: Published xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx:xxxxxxxxxxxx-ap-northeast-1
CdkGradleStack: creating CloudFormation changeset...

 ✅  <span style="color: #00cc00">CdkGradleStack</span>

✨  Deployment time: 59.61s

Stack ARN:
arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/CdkGradleStack/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

✨  Total time: 63.5s

エラーなく成功すればOKです。

念の為、マネジメントコンソール上で確認してみますと、

問題なくユーザが作成されているようです。

このあとは、Mavenを使用していたときと同様の手順でAWSのリソースを作成、管理することができるようになります。

終わりに

今回は、AWS CDKにおいてビルドツールにMavenではなくGradleを使う方法についてご紹介しました。

では、また次の記事で。

参考文献