URLアクセスでEC2を起動/停止してその結果とIPアドレスをメール通知する

# 目的
主に Python の勉強用に、使いたい時にサッと使えるようにしたい

`ローカル PC に入れたらえーやんとか言わない`
`ChromeBook ってコマンド使えるんかいな？`

# やり方
API Gateway + Lambda + EC2 + SNS を組み合わせる (AWS を利用する)

# 構成概要
![Created using Draw.io](https://camo.qiitausercontent.com/4a9b362966a840e30aa571f479b6ae023a4d7e99/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3132393438382f61316661363135302d633761322d353539322d613735612d6166353238353136336661632e706e67)

Created using [Draw.io](https://draw.io/)

# 作っていく

## EC2 を作成
IP アドレス通知を自動化するのに起動スクリプトを利用するので、Linux (Amazon Linux) で作成

## SNS Topic を作成
通知先メールアドレスをサブスクライブしておく

## Lambda function を作成

### コードを記述

#### EC2 起動用 Lambda function コード

ランタイムは Python 2.7 を使用
(print 構文を直せば Python 3.6 でも使えると思う)

```
import boto3
 
def lambda_handler(event, context):
    client = boto3.client('ec2')
    response = client.start_instances(
        InstanceIds=[
            'i-051e83f1cd4171403',
        ]
    )
    print "Response: ", response
    
    sns = boto3.client('sns')
    res = sns.publish(
        TopicArn='arn:aws:sns:ap-northeast-1:012345678912:mySnsTopic',
        Subject='Started EC2ID:i-051e83f1cd4171403',
        Message='Started EC2ID:i-051e83f1cd4171403'
    )
```

> コード中のインスタンス ID やトピック名は、適宜自身のリソースのものに読み替える

#### EC2 停止用 Lambda function コード

ランタイムは Python 2.7 を使用
(print 構文を直せば Python 3.6 でも使えると思う)

```
import boto3
 
def lambda_handler(event, context):
    client = boto3.client('ec2')
    response = client.stop_instances(
        InstanceIds=[
            'i-051e83f1cd4171403',
        ]
    )
    print "Response: ", response
    
    sns = boto3.client('sns')
    res = sns.publish(
        TopicArn='arn:aws:sns:ap-northeast-1:012345678912:mySnsTopic',
        Subject='Stopped EC2ID:i-051e83f1cd4171403',
        Message='Stopped EC2ID:i-051e83f1cd4171403'
    )
```

> コード中のインスタンス ID やトピック名は、適宜自身のリソースのものに読み替える

### ロールを作成

Lambda 用のデフォルトロールに以下 Action を追加 (該当の Resource も追加しておく)

- ec2:StartInstances
- ec2:StopInstances
- sns:Publish

## API をデプロイ

※ロールの作成含め、API Gateway のチュートリアルが詳しい
> [AWS Lambda 関数の API GatewayAPI を作成する](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/integrating-api-with-aws-services-lambda.html)

1. EC2 起動用と停止用のリソースを作成
2. それぞれのリソースにGETメソッドを作成し、上記で作成した Lambda function と関連付ける
3. ステージを作成
4. すると、ステージ毎に下記のような URL が生成される
5. URL を叩くと EC2 が起動/停止する。また、その通知がメールで届く (通知内容は Lambda function で定義しておく)

https://aaaabbbbcccc.execute-api.ap-northeast-1.amazonaws.com/test/startec2
https://aaaabbbbcccc.execute-api.ap-northeast-1.amazonaws.com/test/stoptec2

> スマホのホーム画面にアイコンを置いておくと便利
> でも開いたタブは閉じておかないと、次回ブラウザ起動時に開いてしまう恐れあり
> 2017/10/2 以降に起動する EC2 は秒課金 (最低 60 秒) なのであまり心配ない (メールも届く)

## IP アドレスを通知

EC2 Public IPv4 アドレスは、Linux の起動スクリプトで通知

[ec2-user@ec2]$ sudo vi /etc/init.d/snspublish

```
#!/bin/bash
#
# chkconfig: 3 99 99
# description:

start() {
        su -l ec2-user -c "sh /home/ec2-user/snspublish.sh"
}

# See how we were called.
case "$1" in
  start)
        start
        ;;
  *)
        echo $"Usage: $0 {start}"
        exit 2
esac
```

[ec2-user@ec2]$ vi snspublish.sh

```
#!/bin/sh
publicipv4=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`
topic_arn="arn:aws:sns:ap-northeast-1:012345678912:mySnsTopic"
aws sns publish --topic-arn $topic_arn --message $publicipv4 --subject "Started EC2 IPv4 Address"
```

> EC2 (Linux) が起動すると、本文に IP アドレスが書かれたメールが届く

[ec2-user@ec2]$ sudo chkconfig --add snspublish

> ※スクリプト中で aws コマンドで AWS リソースにアクセスするので、
> 「aws configure」をするか、EC2 をロール付きで再作成する必要あり

# 想定される課金内容

|サービス|無料利用枠|コメント|
|--------|-----|-------|
|API Gateway|100 万件/月の API 呼び出しの受信|≒実質無料|
|Lambda|100 万件/月のリクエストおよび 320 万秒/月(128 MB)のコンピューティング|≒実質無料|
|SNS|100 万件/月のリクエストおよび 1000 件/月の E メール配信|≒実質無料|