Javascript で RDSの起動・停止を制御して節約する


# やったことまとめ

RDSの起動・停止するスクリプトを書いて、cronで営業時間の間だけ起動するように制御しています


## なぜやろうと思ったか？

開発環境を業務時間外の時間で稼働させるとお金がもったいない
reactを勉強しててjavascript が思ったより面白かったから何か作りたくなった

## やってみた感想

dash というスニペットツールで課金すると 公式ドキュメントが簡単に見れて文言で検索できたのがすごく便利でドキュメントを探す手間がかなり省けたので助かりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222463/f483b906-df11-2c2d-1c3b-e34c0ef317bf.png)

javascript の書き方を理解し切れていないけれど、今後 react を触る過程で慣れたいな、、


## 実装した内容
### 事前準備

※ RDSを制御可能な権限を持った iam の認証情報を使います




```~/.aws/credential
[プロファイル名]
aws_access_key_id = xxxxxx
aws_secret_access_key = xxxxxx
```

aws-sdk　と @slack/web-api をインストールする

```sh
$yarn add @slack/web-api @slack/events-api
$yarn add aws-sdk
```

### crontab サンプル

これを cron で起動時と終了時を指定して呼び出してます

```~/etc/crontab


PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
HOME=/root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name command to be executed

#開発環境のDBを平日（月 ~ 金の 8時 ~ 19時）稼働制御
## dev01-03(jty)
00 8 * * 1,2,3,4,5 root node <配置したディレクトリパス>/dev-rds-controler.js start <RDS識別子>
00 19 * * 1,2,3,4,5 root node <配置したディレクトリパス>/dev_rds_controler.js stop <RDS識別子>

```

### node での実装サンプル
```javascript

const AWS = require('aws-sdk');
const { WebClient } = require('@slack/web-api')

//#### Slack
const slackNotifiCation = async (message) => {
  const token = '<SlackのトークンID＞'
  const channel = '＜通知するチャンネル名＞'

  const client = new WebClient(token)
  const params = {
    channel: channel,
    text: message
  }
  const response = await client.chat.postMessage(params)
  //console.log(response)
}

const credentials = new AWS.SharedIniFileCredentials({profile: 'プロファイル名'});
AWS.config.credentials = credentials;

//利用する環境のリージョンを指定する
AWS.config.update({region: '<利用するリージョンを指定する>'}); // 東京とか→「ap-northeast-1」

// Create RDS object
const rds = new AWS.RDS({apiVersion: '2014-10-31'})


// RDS AZを停止する
const fetch_rds_az = {
  // RDSパラメータ定義
  params:{
    DBInstanceIdentifier: ''
  },
  dbInstanceParams:"",
  // RDS の情報を取得
  getRdsStatus: async function(){
    await rds.describeDBInstances(this.params).promise()
      .then(data => {
          this.dbInstanceParams = data.DBInstances[0]
        }
      ).catch(err => {
        console.log(err)
      })
  },
  fetchRdsParams: async function(){
    await this.getRdsStatus()
    await console.log(this.dbInstanceParams.DBInstanceStatus)
  },
  rdsController: async function(commandParam){
    await this.fetchRdsParams()
    switch (commandParam){
      case 'start':
        if(this.dbInstanceParams.DBInstanceStatus === 'available'){
          slackNotifiCation(`${this.dbInstanceParams.DBInstanceIdentifier}は起動中だよ！`)
          break
        }
        rds.startDBInstance(this.params).promise()
          .then(data => {
            slackNotifiCation(`${this.dbInstanceParams.DBInstanceIdentifier}を起動するよ！`)
          }).catch( err => {
            slackNotifiCation(`【test】起動処理中にエラー発生 message:${err}`)
            slackNotifiCation(`【test】起動処理中にエラー発生 message:${this.dbInstanceParams.DBInstanceStatus}`)
          }
        )
        break

      case 'stop':
        console.log('stop')
        if(this.dbInstanceParams.DBInstanceStatus === 'stopped'){
          slackNotifiCation(`${this.dbInstanceParams.DBInstanceIdentifier}は停止中だよ！`)
          break
        }
        rds.stopDBInstance(this.params).promise()
          .then(data => {
            slackNotifiCation(`${this.dbInstanceParams.DBInstanceIdentifier}を停止するよ！`)
          }).catch( err => {
            slackNotifiCation(`【test】停止処理中にエラー発生 message:${err}`)
            slackNotifiCation(`【test】停止処理中にエラー発生 message:${this.dbInstanceParams.DBInstanceStatus}`)
          }
        )
        break

      case 'watch': // RDS の AZ を監視するためのメソッド
        await this.getRdsStatus()
        const currentAz = this.dbInstanceParams.AvailabilityZone
        const rdsInstance = this.dbInstanceParams.DBInstanceIdentifier
        await slackNotifiCation(`【test】${rdsInstance} は ${currentAz}で稼働しています`)
        break


      default:
        console.log('arg params is Inappropriate ')
        slackNotifiCation(`残念でしたー、コマンド実行時の引数に誤りがあります${commandParam}`)
        break
    }
  }
}

//##>> コマンド引数を取得する( $node env-dev-rds-controller watch |start | stop)
const commandParam = process.argv[2].toString()

//##>> 起動、停止するDBのインスタンス情報を指定する
const targetRds = process.argv[3].toString()
fetch_rds_az.params.DBInstanceIdentifier = targetRds


//##>> 起動・停止するRDSの指定をオブジェクト内として実行
fetch_rds_az.rdsController(commandParam)



```