AWS Lambda で Javaを使う ー実装編 - EC2を止める/立ち上げる

##やりたいこと
Lambdaで実行するJavaでEC2を起動・停止する
(↓をJavaで書いてみて、ちょっとだけカスタマイズする。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/)

##AWS Lambda で Javaを使う　目次
・[Eclipse準備編](https://qiita.com/t_ookubo/items/a71a9bd05282bf20e023)
・登録実行編（いつか）
・[実装編 - EC2を止める/立ち上げる](https://qiita.com/t_ookubo/items/3b12bd985a65a73b4c59)
・[実装編 - CloudWatchの引数を確認する](https://qiita.com/t_ookubo/items/18d47265d39bba4364b8)
・[実装編Tips - ReagionとInstanceIDからInstance名を取得する](https://qiita.com/t_ookubo/items/619d8029546447e61391)

## とりあえずクラス作成
前回Eclipseでサンプルクラスを作成できるようにしたので、
それを使って、入力タイプ「Custom」のLambdaプロジェクトを作る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559813/eb8e09b1-5ac5-5d43-68eb-4c694cff8ea3.png)

でできるのが、こちら

```java:LambdaFunctionHandler.java
	package com.amazonaws.lambda.demo;

	import com.amazonaws.services.lambda.runtime.Context;
	import com.amazonaws.services.lambda.runtime.RequestHandler;

	public class LambdaFunctionHandler implements RequestHandler<Object, String> {

	    @Override
	    public String handleRequest(Object input, Context context) {
	        context.getLogger().log("Input: " + input);

	        // TODO: implement your handler
	        return "Hello from Lambda!";
	    }
	}
```

handleRequestメソッドが作られるので、Lambdaで実行したい内容をゴリゴリ書いていく。
handlerの説明は下記を参照
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/java-handler.html
引数ではjsonを受け取ることができる。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/java-handler-pojo.html

##EC2をごにょごにょする
###EC2オブジェクトを作成する

```java
// EC2オブジェクトを作成
AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard().withRegion("us-east-1").build();
```

これで、引数のリージョンにあるEC2を操作できるようになる。
リージョンコードはここを参照
https://docs.aws.amazon.com/ja_jp/general/latest/gr/rande.html
今回は使わないが、Regionsという名前でEnumも準備されているので、下のクラスも使える。
com.amazonaws.regions.Regions

###インスタンスを起動する

```java
// 引数のリストに格納されたインスタンスIDを起動
StartInstancesResult ret = ec2.startInstances(new StartInstancesRequest(instanceIdList));
```

これで、Listの中にあるインスタンスIDを起動できる。

###インスタンスを停止する

```java
// 引数のリストに格納されたインスタンスIDを停止
StopInstancesResult ret = ec2.stopInstances(new StopInstancesRequest(instanceIdList));
```

起動と同じで、List<String>のインスタンスIDを停止できる。
起動、停止両方の戻り値で、AmazonWebServiceResultを継承している、ので下の様にできる。

```java
AmazonWebServiceResult<?> ret 
```


##出来上がったのがこちら
引数を↓のようにして、複数のリージョン、インスタンスに対して操作をできるようにする。

```json
{"targets":[
    {
         "action":"start"
        ,"targetReagion":"us-east-1"
        ,"targetInstances":"x-xxxxxxxxxxxxx"
    }
    ,{
         "action":"stop"
        ,"targetReagion":"ap-northeast-1"
        ,"targetInstances":"y-yyyyyyyyyyy"
    }
]}
```
この引数の例だとバージニア北部のx-xxxxxxxxxxxxxというインスタンスを起動して、
東京のy-yyyyyyyyyyyインスタンスを停止する。

```java:ActionEC2Instances 
package com.amazonaws.lambda.demo;

import java.util.ArrayList;
import java.util.List;

import com.amazonaws.AmazonWebServiceResult;
import com.amazonaws.services.ec2.AmazonEC2;
import com.amazonaws.services.ec2.AmazonEC2ClientBuilder;
import com.amazonaws.services.ec2.model.StartInstancesRequest;
import com.amazonaws.services.ec2.model.StopInstancesRequest;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

import com.amazonaws.lambda.demo.ActionEC2Instances.Input;
import com.amazonaws.lambda.demo.ActionEC2Instances.Output;

public class ActionEC2Instances implements RequestHandler<Input, Output> {

	@Override
	public Output handleRequest(Input input, Context context) {
		context.getLogger().log("Input : " + input);
		Output output = new Output();

		for (Target action : input.targets) {
			output.result.add(doAction(action));
		}

		return output;
	}

	private String doAction(Target target) {
		AmazonEC2 ec2 = AmazonEC2ClientBuilder.standard().withRegion(target.targetReagion).build();
		List<String> instances = target.targetInstances;

		AmazonWebServiceResult<?> ret = null;
		if ("start".equals(target.action)) {
			ret = ec2.startInstances(new StartInstancesRequest(instances));

		} else if ("stop".equals(target.action)) {
			ret = ec2.stopInstances(new StopInstancesRequest(instances));

		} else {
			return "Unexpected Action";

		}
		return ret.toString();
	}

	public static class Input {
		public List<Target> targets;

		@Override
		public String toString() {
			StringBuffer sbf = new StringBuffer();
			for (Target target : targets) {
				sbf.append(target);
			}
			return sbf.toString();
		}
	}

	public static class Target {

		private String action;
		private String targetReagion;
		private List<String> targetInstances;

		public String getAction() {
			return action;
		}

		public void setAction(String action) {
			this.action = action;
		}

		public String getTargetReagion() {
			return targetReagion;
		}

		public void setTargetReagion(String targetReagion) {
			this.targetReagion = targetReagion;
		}

		public List<String> getTargetInstances() {
			return targetInstances;
		}

		public void setTargetInstances(List<String> targetInstances) {
			this.targetInstances = targetInstances;
		}

		@Override
		public String toString() {
			StringBuffer sbf = new StringBuffer();
			sbf.append("{action :").append(action).append(" targetReagion :").append(targetReagion)
					.append(" targetInstances :").append(targetInstances).append("}");

			return sbf.toString();
		}

	}

	public static class Output {
		public List<String> result = new ArrayList<String>();
	}
}

```

追加したpom

```
<dependency>
	<groupId>com.amazonaws</groupId>
	<artifactId>aws-java-sdk-core</artifactId>
	<version>1.11.719</version>
</dependency>
<dependency>
	<groupId>com.amazonaws</groupId>
	<artifactId>aws-lambda-java-events</artifactId>
	<version>1.3.0</version>
</dependency>
<dependency>
	<groupId>com.amazonaws</groupId>
	<artifactId>aws-lambda-java-core</artifactId>
	<version>1.1.0</version>
</dependency>
<dependency>
	<groupId>com.amazonaws</groupId>
	<artifactId>aws-java-sdk-ec2</artifactId>
	<version>1.11.602</version>
	<scope>compile</scope>
</dependency>
```