AWS Certified Developer Associateに合格した

Azureばかりのことを書いていますが、AWSも同時に勉強しています。というわけで、先日、AWS Certified Developer Associateを受験して合格しました。

f:id:miyohide:20220321182351p:plain

このエントリーでは合格するために行なった勉強などを記します。

準備期間

準備は概ね1ヶ月、仕事終わりに1時間ぐらい勉強用の資料をみたり問題を解いたりしていました。具体的な資料などは以下に記します。

予約

締め切りを定めないと勉強しないタチなので、まずは試験日を決めました。年度末のためなのかすぐさま席が埋まる感じだったので、自分の予定と相談しながら日付を決めました。

オンラインで自宅で受験することも可能みたいなのですが、自宅でオンライン試験の環境を満たすのは難しそうだったので試験会場に行って受験することにしました。

試験日を決めたらあとは黙々と勉強するだけです。勉強方法について以下に記します。

内容の確認

まずは、AWSのDeveloper Associateのページにて試験範囲のサービスなどを確認しました。

aws.amazon.com

たくさんのサービスがあるのでびっくりしますが、AWS上でシステムを構築する上で欠かせないものばかりなので致し方ありません。

勉強用資料

まずは、AWS サービス別資料のページで公開されているBlackBeltの資料に一通り目を通しました。

aws.amazon.com

これだけだと不安を覚えたので、「ポケットスタディ AWS認定デベロッパーアソシエイト」を買ってサービスを一通り学習。

この段階でサンプル問題を解いてみたところあまり点数がよくなかったので、Udemyの「Ultimate AWS Certified Developer Associate 2022 - NEW!」を買って動画を2回見ました。

www.udemy.com

英語ということで理解できるか不安でしたが、すでに上記の資料などで把握している項目も多く、画面の操作方法も合わせて動画で説明されていたので2回見ると理解が進みました。

自分は利用しませんでしたが、AWSのDeveloper Associateのページにて案内がある模擬試験が無料で利用できるのでこちらも利用すると良いかもしれません。利用方法は以下のページがわかりやすいと思います。

dev.classmethod.jp

試験当日

年度末のためなのか、ひっきりなしに受験者が会場に来ていました。いくつか書類を確認して、本人確認書類を提示(自分の場合、免許証とマイナンバーカードを使いました)して、荷物をロッカーに押し込んで受験。じっくりと問題を読んで早とちりしないように慎重に回答しました。

一通り問題を解き終わった段階で30分経過。時間には余裕があったので見直しをして納得した上で回答完了。画面上に「合格」という文字が見えた時にはホッとしました。

以下のページにあるように最終結果の通知は最大5営業日後に連絡が来ます。

aws.amazon.com

メールが届いたのを確認して、ようやく一安心です。

ReactとRailsで簡単な認証付きアプリを作る その1

はじめに

Azure Static Web Apps登場以降、細々と勉強しています。その中で、Azure Static Web Appsの認証と承認という以下の記事が気になりました。

docs.microsoft.com

ちょっとやってみようかなと思ったのですが、その前にReactでの認証機能ってどうやって実装するんだろうと思ってしまいました。そのため、まずはReactの理解を含めるために簡単な認証付きのアプリを作ってみることにしました。

やってみる

何かいいサンプルないかなと思って探してみたら、以下のQiitaの記事が良さそうだったのでまずはこの記事をベースに進めていくことにしました。

qiita.com

サクサクと進めていくことができたのですが、Reactの部分でTypeScriptのエラーなどが出てきてどうにもこうにも前に進みませんでした。

よくよく調べてみると、使われているライブラリのバージョンアップが数多くあり、その影響でうまく動かないことがわかりました。

とりあえず動かすには以下のライブラリを更新することで対応しました。

  • js-cookie^2.2.6に(作業時点では^3.0.1になっていた)
  • axios^0.21.1に(作業時点では^0.26.0になっていた)
  • react-router-dom^5.2.0に(作業時点では^6.2.1になっていた)
  • react-scripts4.0.3に(作業時点では5.0.0になっていた)
  • web-vitals^1.0.1に(作業時点では^2.1.4になっていた)

本当はバージョン変更に伴う仕様変更を調べて対応すべきなんでしょうが、まずは動くものを作るところから...

とりあえず動く版は以下のものです。

github.com

Azure Container AppsにVNet統合が来たので試してみたけどなんかうまく動かない

はじめに

2021年11月にAzure Container Appsというものがパブリックプレビューとして公開されました。パブリックプレビューなので、まだ色々と環境が整っていない感じがするのですが、試してみました。

前回までの記事は以下のものを参照してください。チュートリアルを実施して、自分で作成したコンテナアプリを動かし、リビジョンについて実践してみました。

今回は以下のアナウンスにあったVNet統合を試してみたけれどもうまく動かなかったという結果です。

VNet統合

2022年2月2日に以下のエントリーが投稿され、Azure Container AppsにVNet統合のアナウンスがされました。

techcommunity.microsoft.com

ちょっとやってみます。

上記のエントリーにあるように、ポータルからContainer Appsを作成するときにネットワークの設定ができるようになっていました。VNetはその場で作れるのですが、その際は以下のスクリーンショットのように今のところ「10.0.0.0/16」の固定値になります。

ポチポチと値を入力して、こんな感じに設定できました。

VNet統合において違うところはここぐらいかなと感じました。

アクセスしてみるが...

もちろんこれでインターネットからはアクセスできないです。

上記のエントリーにあるようにPrivate DNSを設定すればVNet上のVMからアクセスできるかなと考えたのですが、どうにもうまく動かず。あれぇ???

参考

うまく動かなかったので、色々と調べていたら既に試されていた方がいました。

kogelog.com

今度試すときは上記を参考に試そうかなと。

追記

続きを書きました。

miyohide.hatenablog.com

Gradle 7.4 + JUnit 5.8.1でUnitテストとは別にIntegrationTestを作る

小ネタ。JUnitにて./gradlew testで実行するテスト(Unitテスト)とは別に複数の要素が絡む総合テスト(Integration Test)を動かしたいことがあります。今回はその実装方法について。

結論

早速結論です。build.gradleに以下のように書けば良いです。

sourceSets {
    integrationTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/intTest/java')
        }
        resources.srcDir file('src/intTest/resources')
    }
}

configurations {
    integrationTestImplementation.extendsFrom testImplementation
    integrationTestRuntime.extendsFrom testRuntime
}

task integrationTest(type: Test) {
    useJUnitPlatform()
    testClassesDirs = sourceSets.integrationTest.output.classesDirs  // DirではなくDirsにする
    classpath = sourceSets.integrationTest.runtimeClasspath
    outputs.upToDateWhen { false }
}

あとはsrc/intTest/java以下にIntegration Test用のテストプログラムを書き、

./gradlew clean integrationTest

を実行すればOKです。

調査の流れ

実装するために調査したところ、以下のブログがヒットしました。

inspeerity.com

上記のブログはGroovyの例なのですが、JavaでもsourceSetsを変えれば良いかなと思って始めました。こんな感じに書きました。

sourceSets {
    integrationTest {
        java {
            compileClasspath += main.output + test.output
            runtimeClasspath += main.output + test.output
            srcDir file('src/intTest/java')
        }
        resources.srcDir file('src/intTest/resources')
    }
}

テスト用のクラスパスを通すために以下の記述を追加。

configurations {
    integrationTestImplementation.extendsFrom testImplementation
    integrationTestRuntime.extendsFrom testRuntime
}

動かしたときにパッケージorg.junit.jupiter.apiは存在しませんみたいなエラーメッセージが出たら、上記の設定を見直すか、build.gradledependenciesに以下の記述があることを確認します。

dependencies {
    // 他のものは省略
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}

最後にtaskの定義です。

task integrationTest(type: Test) {
    useJUnitPlatform()
    testClassesDirs = sourceSets.integrationTest.output.classesDirs  // DirではなくDirsにする
    classpath = sourceSets.integrationTest.runtimeClasspath
    outputs.upToDateWhen { false }
}

useJUnitPlatform()がないと./gradlew clean integrationTestを実行してもテストが実行されず、しばらくハマりました。

参考

理解を深めるための各種参考資料。

Azure Container Appsを試してみる(3)

はじめに

2021年11月にAzure Container Appsというものがパブリックプレビューとして公開されました。パブリックプレビューなので、まだ色々と環境が整っていない感じがするのですが、試してみました。

前回までの記事は以下のものを参照してください。チュートリアルを実施して、自分で作成したコンテナアプリを動かすことまでを実施しました。

今回は、リビジョンについて実施してみます。

リビジョンとは?

Azure Container Appsのポータルをみると「リビジョン管理」という項目が目につきました。

f:id:miyohide:20220206164805p:plain

ドキュメントは以下にあるのですが、あまりピンときませんでした。バージョン管理みたいなものと捉えたら良いのかな?

docs.microsoft.com

実際に実行してみることにしました。

最初のアプリをデプロイする

最初のアプリをデプロイします。以下のコマンドは環境変数RESOURCE_GROUPCONTAINERAPPS_ENVIRONMENTを設定しています。これら環境変数は、ドキュメントのチュートリアルにあるものをそのまま使っています。

docs.microsoft.com

az containerapp createコマンドでデプロイします。

az containerapp create \
  --name my-container-app \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --image イメージ名:v0.0.1 \
  --registry-login-server Azure Container Registryのログインサーバー名 \
  --registry-username Azure Container Registryのユーザー名 \
  --registry-password Azure Container Registryのパスワード \
  --environment-variables 環境変数名1=値1,環境変数名2=値2,環境変数名3=値3 \
  --target-port 8080 \
  --ingress 'external' \
  --query configuration.ingress.fqdn

イメージ名:v0.0.1みたいにlatestではなく、バージョン番号を指定しています。このイメージはこんな感じの画面です。

f:id:miyohide:20220206165956p:plain

次のバージョンのアプリをデプロイする

バージョンを変えたアプリをデプロイします。このバージョンはこんな感じの画面です。バージョン番号をつけました。

f:id:miyohide:20220206170221p:plain

デプロイは、az containerapp updateコマンドで行います。イメージ名のバージョン部分をv0.0.2にすることを忘れず、そのほかは同じ値で実行します。

az containerapp update \
  --name my-container-app \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --image イメージ名:v0.0.2 \
  --registry-login-server Azure Container Registryのログインサーバー名 \
  --registry-username Azure Container Registryのユーザー名 \
  --registry-password Azure Container Registryのパスワード \
  --environment-variables 環境変数名1=値1,環境変数名2=値2,環境変数名3=値3 \
  --target-port 8080 \
  --ingress 'external' \
  --query configuration.ingress.fqdn

ポータルのリビジョン管理の画面は2行に増えました。

f:id:miyohide:20220206170603p:plain

今回はトラフィックをv0.0.1とv0.0.2それぞれに分けるように50%、50%に設定しました。

これでブラウザをリロードするとv0.0.1とv0.0.2のどちらかにアクセスされます。試したところ、v0.0.1の次は必ずv0.0.2にアクセスされるわけではなく、v0.0.1→v0.0.1→v0.0.2という感じになることがありました。

あとがき

今回試したことは以下のドキュメントに書かれていました。ま、自分で試すことは大事だと思います。

docs.microsoft.com

IDEを使わずSpring Boot DevToolsのAutomatic Restartを実現する

今日は時間がなくて小ネタ。

Spring Bootにはspring-boot-devtoolsというものがあります。これをいれると./gradlew bootRunで起動中にソースコードを変更しても./gradlew bootRunを一度終了して再度起動するということをせずとも反映させることができます。これをAutomatic Restartといいます。

docs.spring.io

ここでは、以下の環境で試しました。

  • Spring Boot 2.6.3
  • Gradle 7.3.3

導入

build.gradledependenciesにて以下を追記するだけです。

    developmentOnly("org.springframework.boot:spring-boot-devtools")

EclipseとかのIDEとかを導入しているとこれだけでOKなようなのですが、IDEを使わずエディタだけで開発していた場合はこれだけではAutomatic Restartはうまく動きません。

実行

Automatic Restartをうまく動かすには、./gradlew bootRun以外に別のコンソールにて./gradlew -t classesを実行します。

ここでポイントは以下の二つです。

  • -tオプションを指定する
  • classesタスクを実行する

-tオプションは./gradlew -hを実行してみると以下のような説明です。

-t, --continuous                   Enables continuous build. Gradle does not exit and will re-execute tasks when task file inputs change.

-tオプションを指定した場合はタスクを終了してもプロンプトを返さず待機してファイルの変更を待ち受ける状態です。

classesタスクは以下に説明があります。

docs.gradle.org

あとはクラスパス内にあるJavaファイルやHTMLファイルを変更するとそれを検出して自動的にAutomatic Restartが動きます。 例えばPostsController.javaというプログラムを更新すると、./gradlew -t classesを実行している画面には以下のような表示が行われます。

BUILD SUCCESSFUL in 4s
2 actionable tasks: 1 executed, 1 up-to-date

Waiting for changes to input files of tasks... (ctrl-d to exit)
modified: /Users/hogehoge/work/app_modernization_example/webapp/src/main/java/com/example/webapp/PostsController.java
Change detected, executing build...

BUILD SUCCESSFUL in 486ms
2 actionable tasks: 1 executed, 1 up-to-date

Waiting for changes to input files of tasks... (ctrl-d to exit)

./gradlew bootRunを実行している画面はアプリケーションが再起動されていることが確認できます。

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.3)

2022-01-30 16:02:50.789  INFO 19683 --- [  restartedMain] com.example.webapp.WebappApplication     : Starting WebappApplication using Java 11.0.11 on hikari.local with PID 19683 (/Users/hogehoge/work/app_modernization_example/webapp/build/classes/java/main started by hogehoge in /Users/hogehoge/work/app_modernization_example/webapp)
2022-01-30 16:02:50.789  INFO 19683 --- [  restartedMain] com.example.webapp.WebappApplication     : No active profile set, falling back to default profiles: default
2022-01-30 16:02:50.899  INFO 19683 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2022-01-30 16:02:50.900  INFO 19683 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 0 ms. Found 0 JDBC repository interfaces.
2022-01-30 16:02:50.945  INFO 19683 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-01-30 16:02:50.946  INFO 19683 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-01-30 16:02:50.946  INFO 19683 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-30 16:02:50.953  INFO 19683 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-01-30 16:02:50.953  INFO 19683 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 162 ms
2022-01-30 16:02:51.001  INFO 19683 --- [  restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2022-01-30 16:02:51.078  INFO 19683 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Starting...
2022-01-30 16:02:51.091  INFO 19683 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Start completed.
2022-01-30 16:02:51.101  INFO 19683 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2022-01-30 16:02:51.106  INFO 19683 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-30 16:02:51.109  INFO 19683 --- [  restartedMain] com.example.webapp.WebappApplication     : Started WebappApplication in 0.34 seconds (JVM running for 35.92)
2022-01-30 16:02:51.110  INFO 19683 --- [  restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
2022-01-30 16:02:59.474  INFO 19683 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-01-30 16:02:59.475  INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-01-30 16:02:59.475  INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
aaa
2022-01-30 16:03:20.680  INFO 19683 --- [       Thread-7] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Shutdown initiated...
2022-01-30 16:03:20.684  INFO 19683 --- [       Thread-7] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Shutdown completed.

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.6.3)

2022-01-30 16:03:20.729  INFO 19683 --- [  restartedMain] com.example.webapp.WebappApplication     : Starting WebappApplication using Java 11.0.11 on hikari.local with PID 19683 (/Users/hogehoge/work/app_modernization_example/webapp/build/classes/java/main started by hogehoge in /Users/hogehoge/work/app_modernization_example/webapp)
2022-01-30 16:03:20.729  INFO 19683 --- [  restartedMain] com.example.webapp.WebappApplication     : No active profile set, falling back to default profiles: default
2022-01-30 16:03:20.814  INFO 19683 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2022-01-30 16:03:20.814  INFO 19683 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 0 ms. Found 0 JDBC repository interfaces.
2022-01-30 16:03:20.850  INFO 19683 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2022-01-30 16:03:20.851  INFO 19683 --- [  restartedMain] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2022-01-30 16:03:20.851  INFO 19683 --- [  restartedMain] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.56]
2022-01-30 16:03:20.858  INFO 19683 --- [  restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2022-01-30 16:03:20.858  INFO 19683 --- [  restartedMain] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 127 ms
2022-01-30 16:03:20.903  INFO 19683 --- [  restartedMain] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page template: index
2022-01-30 16:03:20.997  INFO 19683 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Starting...
2022-01-30 16:03:21.008  INFO 19683 --- [  restartedMain] com.zaxxer.hikari.HikariDataSource       : HikariPool-3 - Start completed.
2022-01-30 16:03:21.017  INFO 19683 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2022-01-30 16:03:21.020  INFO 19683 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2022-01-30 16:03:21.023  INFO 19683 --- [  restartedMain] com.example.webapp.WebappApplication     : Started WebappApplication in 0.309 seconds (JVM running for 65.834)
2022-01-30 16:03:21.024  INFO 19683 --- [  restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged
2022-01-30 16:03:24.452  INFO 19683 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-01-30 16:03:24.453  INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2022-01-30 16:03:24.453  INFO 19683 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
aaa1
<==========---> 80% EXECUTING [1m 18s]

自分が手元で試した感じ、ファイルを保存したらすぐさま変更が反映されるというわけではなく、数秒ぐらいの待ちが発生する感じがしましたが、いちいち自分で./gradlew bootRunを終了して再度実行する手間を考えると些細な待ち時間かなと思います。

Azure Container Appsを試してみる(2)

はじめに

2021年11月にAzure Container Appsというものがパブリックプレビューとして公開されました。パブリックプレビューなので、まだ色々と環境が整っていない感じがするのですが、試してみました。

前回はチュートリアルをそのまま実施してみたのですが、今回は自分が作成したコンテナイメージを動かすことをやってみました。

前回までの記事は以下を参照してください。

Azure Container Registryを作成する

自分が作成したコンテナイメージを保存するために、Azure Container Registryを作成します。管理者ユーザーを有効にしておき、作成したAzure Container Registryに自分が作成したコンテナイメージを登録しておきます。

f:id:miyohide:20220123144429j:plain

Azure Container Appsにデプロイする

Azure Portalからデプロイしようと思いましたが、2022年1月23日時点でAzure Portalからは環境変数の設定が見当たらなかったので、今回はAzure CLIを使います。

基本はクイックスタートのものを使います。

docs.microsoft.com

違うところはaz containerapp createコマンド。イメージ名や環境変数を設定しておきます。具体的には以下のコマンドを実行します。

az containerapp create \
  --name my-container-app \
  --resource-group $RESOURCE_GROUP \
  --environment $CONTAINERAPPS_ENVIRONMENT \
  --image イメージ名 \
  --registry-login-server 上で作成したAzure Container Registryのログインサーバー \
  --registry-username 上で作成したAzure Container Registryの管理者 \
  --registry-password 上で作成したAzure Container Registryのパスワード \
  --environment-variables 環境変数名=環境変数の値 \
  --target-port 3000 \
  --ingress 'external' \
  --query configuration.ingress.fqdn

今回は簡単なRailsアプリを動かそうとしたので、target-port3000に。ただ、ブラウザからはポート番号を指定せずにhttpsでアクセスすることになります。

f:id:miyohide:20220123145824p:plain

今日はここまで。