AWS CLIを使って特定のタグを持つEC2にアクセス

# はじめに
* ケチなので、EC2を使い終わるたびにインスタンスを停止しておきたい。が、マネジメントコンソールから毎回ポチポチするのは面倒。
* AWS EC2 は、停止→再起動するとグローバルIP(とFQDN)が変動する仕様のため、次回接続時にいちいちマクロを書き換えるのも面倒。

ということで、AWS CLIを使って、以下をできるようにしたい。windows環境のためpowershellでの実行を前提とする。
* EC2 インスタンスの一覧取得・起動・停止
* 特定のタグ(`my-ec2`)を持つEC2にアクセス


# AWS CLIの導入

以下の記事を参照。
https://udemy.benesse.co.jp/development/system/aws-cli.html



# EC2 インスタンスの一覧取得・起動・停止

### 一覧取得

* aws cliでEC2インスタンスの一覧を取得し、jqで`InstanceID`, `PublicDnsName`, `State`, `Tags`の情報のみ抜き出す。
* 【注】powershellでjqを利用する場合、`"`にエスケープ(`\"`)をつけておかないとjqのコンパイルが通らないことに注意。
    * https://blog.jhashimoto.net/entry/2018/02/07/155716

```powershell:describe-instances.ps1
aws ec2 describe-instances  |  jq '.Reservations[].Instances[] | {InstanceId:.InstanceId, PublicDnsName:.PublicDnsName, State:.State.Name, Tags:.Tags[]|select (.Key == \"Name\")|.Value}' -C
```

```powershell
PS > describe-instances.ps1
{
  "InstanceId": "i-070cf1a9d8241xxxx",
  "PublicDnsName": "ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com",
  "State": "running",
  "Tags": "my-ec2"
}
{
  "InstanceId": "i-08fb1aa857e70xxxx",
  "PublicDnsName": "",
  "State": "terminated",
  "Tags": "test-tobedestracted"
}
```

### 起動

* ~~コマンドが覚えられないため~~自分用に以下ラッパーを作成。
* インスタンスIDを指定して起動。
* すでにマネジメントコンソールで一度作成済みのインスタンスを想定。


```powershell:start-instance.ps1
$instance_id = $Args[0]
aws ec2 start-instances --instance-ids $instance_id
```


```powershell
PS > .\start-instance.ps1 i-070cf1a9d8241xxxx
i-070cf1a9d824128ab
{
    "StartingInstances": [
        {
            "CurrentState": {
                "Code": 0,
                "Name": "pending"
            },
            "InstanceId": "i-070cf1a9d8241xxxx",
            "PreviousState": {
                "Code": 80,
                "Name": "stopped"
            }
        }
    ]
}

```

### 停止

```powershell:stop-instance.ps1
$instance_id = $Args[0]
aws ec2 stop-instances --instance-ids $instance_id
```

```powershell
PS > .\stop-instance.ps1 i-070cf1a9d8241xxxx 
{                                                                     {
    "StoppingInstances": [
        {
            "CurrentState": {
                "Code": 64,
                "Name": "stopping"
            },
            "InstanceId": "i-070cf1a9d8241xxxx",
            "PreviousState": {
                "Code": 16,
                "Name": "running"
            }
        }
    ]
}
```


# 特定のタグを持つEC2にアクセス
* 本題。
* 特定のタグ(→`my-ec2`)を持つEC2にアクセスする。

```powershell:ssh-ec2.ps1
# 各EC2の情報を取得。aws cliでEC2インスタンスの一覧を取得し、jqで`InstanceID`, `PublicDnsName`, `State`, `Tags`の情報のみ抜き出す。
$ec2_status= aws ec2 describe-instances  |  jq '[.Reservations[].Instances[] | {InstanceId:.InstanceId, PublicDnsName:.PublicDnsName, State:.State.Name, Tags:.Tags[]|select (.Key == \"Name\")|.Value}]'

# 各EC2の状態を画面にも表示
echo $ec2_status | jq '.' -C

# EC2の数を数える
$existing_instances_count = $($ec2_status | jq '[.[]| select(.State == \"running\" )] | length')

# 普段1インスタンスしか利用していないため、念のためそうでない場合は通知
If($existing_instances_count -eq 0){
    echo "no running instance exists"
    return 0
} elseif ($existing_instances_count -ge 2){
    $output = $existing_instances_count + " running instances exist... is it ok?"
    echo $output
}

# my-ec2のタグを持つEC2の`PublicDNSName`を取得。(一つしか存在しない前提)
$PublicDnsName = $($ec2_status | jq -r '.[] | select(.Tags == \"my-ec2\") | .PublicDnsName')

$output = "connect to " + $PublicDnsName 
echo $output
Read-Host "Press Enter to continue..."

# my-ec2のタグを持つEC2にsshで接続
ssh ec2-user@$PublicDnsName -i "key.pem"
```


# おわりに
時々runningのインスタンスがいないかチェックして、通知できると捗りそうだが、そのぐらいの機能はAWSの機能としてありそう・・・