decadence

個人のメモ帳

localstack を aws-sdk-java-v2 で利用する

AWSを活用しているときに、localやCIではAWSのmockとしてlocalstackを利用することがある。 特にS3 / Kinesis / SQS / ...のように複数のAWS Resourceを使う場合にはlocalstackはとても便利だ。 localstackはdocker imageも公式配布されているので本当に便利。

それとは別に、最近ではaws-sdk-javaはv2が主流となりつつある。 こちらはv1と比べてコード生成されたり、非同期APIが提供されたりしている。

aws-sdk-java-v2でlocalstackを利用する際には、以下の点に気をつける必要がある。

  • aws-sdk-java-v2はhttp2でつなぎに行こうとするが、localstackはhttp1.1しか喋れない
  • aws-sdk-java-v2はCBORでやり取りしようとするが、localstackはJSONしか処理出来ない
  • localstackも何も認証情報が取れない環境だとsdkが例外を吐いて通信できないので、どのような環境でも動かせるように、適当なaws key/secretを入れておく
    • もちろんAWS上の本番環境などではaccess key/secretなんかは使わずに、instance profileやexecution roleからassume roleでもして必要なresourceへアクセスされたい
  • USE_SSLssl接続にする際は、awscliにある --no-verify-ssl と同じようにflagを立ててスキップさせる
    • aws-sdk-java-v2ではnettyを利用しているため、他libraryとのnetty dependency hellによりsslがClassNotFoundで実行時エラーになりやすいので、極力localやCI環境でもlocalstackをssl接続にして検証をした方が良い
// disable CBOR
System.setProperty(SdkSystemSetting.CBOR_ENABLED.property(), "false")
// use http1.1 not http2
val sdkAsyncHttpClient = NettyNioAsyncHttpClient
  .builder()
  .protocol(Protocol.HTTP1_1)
  .build()
  // localstackでUSE_SSLしている際には、以下のように変更
  //  .buildWithDefaults(
  //    AttributeMap.builder().put(SdkHttpConfigurationOption.TRUST_ALL_CERTIFICATES, java.lang.Boolean.TRUE).build()
  //  )

// set static credentials
val credentialsProvider = StaticCredentialsProvider.create(
  AwsBasicCredentials.create("unused", "unused")
)
val client = SqsAsyncClient.builder()
  .region(Region.AP_NORTHEAST_1)
  .credentialsProvider(credentialsProvider)
  .endpointOverride(new URI(s"http://localhost:4576"))
  .httpClient(sdkAsyncHttpClient)
  .build()

client.listQueues(
  ListQueuesRequest
    .builder()
    .build()
)