前提
- CodeDeploy側でApplication, DeploymentGroup, AutoScalingなどなどの設定が終わっていること
- Lambdaの設定は基本的には http://aws.typepad.com/sajp/2015/04/automatically-deploy-from-amazon-s3-using-aws-codedeploy.html と同じ(現在は不要になっていると思われる手順もある)
手順
-
Lambda側
基本的にはAWSブログと同じなので差分だけ- 必要なRoleはExecution Roleだけ
- Lambdaの設定は少し画面が変わっている
- Lambda関数の設定
- Select blueprintはSkip
- Name, Descriptionは適当に。RuntimeはNode.js
- CodeはAWSブログからコピー。必要に応じて修正する
- Handlerはデフォルトのindex.handler
- Roleは先ほど作ったRoleを設定
- Event Sourceの設定
- event sourceタブを選択
- Event source typeをS3にして、Bucketを選ぶ
- Event typeはObject Created
ここまでで、aws deploy pushすると勝手にデプロイしてくれるようになっているはず。
-
sbt側
今回はsbtのタスクとして作成。- project/plugins.sbtに以下を追加
libraryDependencies += "com.amazonaws" % "aws-java-sdk" % "1.10.20" libraryDependencies += "com.amazonaws" % "aws-java-sdk-s3" % "1.10.20"
- build.sbtにタスクキーの設定を行う(SettingKeyは必要に応じて)
lazy val bucketName = settingKey[String]("S3 Bucket Name") lazy val key = settingKey[String]("S3 Key Name") lazy val appName = settingKey[String]("CodeDeploy Application Name") lazy val dirName = settingKey[String]("Source directory name") lazy val push = taskKey[Unit]("push zip to S3 for CodeDeploy") bucketName := <Bucket Name> key := <S3 Key Name> appName := <Application Name> dirName := <デプロイするアプリケーションがあるディレクトリ> lazy val push = taskKey[Unit]("push zip to S3 for CodeDeploy") push := { DeployPush.push(dirName.value, bucketName.value, key.value, appName.value) }
- project/DeployPush.scalaにコードを設定
import com.amazonaws.regions._ import com.amazonaws.services.codedeploy.AmazonCodeDeployClient import com.amazonaws.services.codedeploy.model._ import com.amazonaws.services.s3.AmazonS3Client import com.amazonaws.services.s3.model.{PutObjectRequest, PutObjectResult} import sbt._ object DeployPush { def push(dir: String, bucketName: String, key: String, appName: String): Unit = { val s3Client: AmazonS3Client = new AmazonS3Client() s3Client.setRegion(Region.getRegion(Regions.AP_NORTHEAST_1)) val depClient: AmazonCodeDeployClient = new AmazonCodeDeployClient() verifySetting(depClient, appName) val zipFile: File = java.io.File.createTempFile(appName + "-", ".zip") IO.zip(sbt.Path.allSubpaths(new File(dir)), zipFile) val key: String = zipFile.getName val req: PutObjectRequest = new PutObjectRequest(bucketName, key, zipFile) println("put Object to S3 : " + zipFile.getName) val res: PutObjectResult = s3Client.putObject(req) val s3Loc: S3Location = new S3Location(). withBucket(bucketName). withKey(key). withBundleType(BundleType.Zip). withETag(res.getETag) println("Location: " + s3Loc.getKey) println("Version: " + s3Loc.getVersion) println("ETag: " + s3Loc.getETag) val revLoc: RevisionLocation = new RevisionLocation(). withRevisionType(RevisionLocationType.S3). withS3Location(s3Loc) val revReq: RegisterApplicationRevisionRequest = new RegisterApplicationRevisionRequest(). withApplicationName(appName). withRevision(revLoc) depClient.registerApplicationRevision(revReq) } private def verifySetting(depClient: AmazonCodeDeployClient, appName: String) { val applications: ListApplicationsResult = depClient.listApplications if (!applications.getApplications.contains(appName)) { println("applicationName(" + appName + ") not found") throw new Exception() } } }
デプロイ手順
- sbt clean assembly
-
こんな感じのディレクトリ階層を用意しておく(build.sbtでassemblyJarNameを設定して、該当ディレクトリに作成するようにすると少し幸せ)
├── appspec.yml ├── content │ └── hogehoge.jar └── scripts ├── start_server.sh └── stop_server.sh
sbt push
これでLambdaが気がついてデプロイされる
きになるところ
- SettingKeyを"appName in Push"とかにしたかったんだけど、どうやって設定するのかよくわからない