ASK CLI で東京リージョンにデプロイする

## はじめに

現状の ask-cli(1.4.5) で skill を作成し、デプロイするとus-east-1(バージニア北部)にデプロイされてしまう。

公式のフォーラムを見る限り、デプロイ先に複数リージョンを指定することはできそうだが、

**東京リージョンのみ**

にデプロイはできなそう(できなかった)。

- [ask-cli does not deploy to eu-west-1 or other regions as the default us-east-1](https://forums.developer.amazon.com/questions/173679/ask-cli-does-not-deploy-to-eu-west-1-or-other-regi.html)

コードをざっと見たところ数箇所変更すれば、デフォルトのデプロイ先を変更できそうだったため、公式でサポートされるまでの暫定対応としてコードに変更を加えて東京リージョンをデフォルトのデプロイ先に変更する。

- 環境
  - OS: macOS High Sierra
  - node: v10.9.0
  - ask-cli: 1.4.5
  

## ソース変更

ask コマンドの元になっている js ファイルに変更を加える。

```
$ which ask
~/.nodebrew/current/bin/ask
;; ask はシンボリックリンク -> ~/.nodebrew/node/v10.9.0/lib/node_modules/ask-cli/bin/ask.js
```

変更箇所は`REGION_MAPPING.NA`(us-east-1)に設定されている以下の４箇所。


```
$ cd ~/.nodebrew/node/v10.9.0/lib/node_modules/ask-cli/
$ ask-cli ag REGION_MAPPING.NA
lib/utils/init-aws.js
68: let regionCode = CONSTANT.REGION_MAPPING[region] || CONSTANT.REGION_MAPPING.NA;

lib/utils/lambda-operation/lambda-endpoint-utility.js
62: awsRegion: CONSTANTS.REGION_MAPPING[region] || CONSTANTS.REGION_MAPPING.NA,
83: awsRegion: CONSTANTS.REGION_MAPPING[region] || CONSTANTS.REGION_MAPPING.NA,
96: awsRegion: CONSTANTS.REGION_MAPPING[region] || CONSTANTS.REGION_MAPPING.NA,
```

上記のコードで`CONSTANTS.REGION_MAPPING.NA`(us-east-1), を `CONSTANTS.REGION_MAPPING.FE`(ap-northeast-1) に変更することでデフォルトのデプロイ先を東京リージョンに変更することができる。

## コード調査

コードを調査したときの流れも載せておく。

```
$ which ask 
$ ~/.nodebrew/current/bin/ask
; ask はシンボリックリンク -> ~/.nodebrew/node/v10.9.0/lib/node_modules/ask-cli/bin/ask.js
```

`ask.js` のコードを調べる

```ask.js
require('../lib/deploy/deploy').createCommand(commander);
```

を発見 -> `deploy.js` をコードを調べる

```deploy.js
const deployLambda = require('./deploy-lambda');
```

を発見 -> `deploy-lambda.js` のコードを調べる

```deploy-lambda.js
lambdaEndpointUtil.separateLambdaCreateUpdate(skillInfo.skillName, skillInfo.endpointsInfo, './', profile, (err, lambdaList) => {
  ...
  createLambda.createLambda(skillId, skillInfo.skillName, createLambdaList, awsProfile, 
  (createdLambdaMetaDataList) => { 
  ...
```

で lambda 関数の作成を行っている

`lambda-endpoint-utility.js` の `separateLambdaCreateUpdate` 関数のコードを調べる

```lambda-endpoint-utility.js
lambdaList.createLambdaList.push({
  arn: '',
  functionName: `ask-${domain}-${skillName}-${profile}-${_getRandomInt(100000)}`,
  awsRegion: CONSTANTS.REGION_MAPPING[region] || CONSTANTS.REGION_MAPPING.NA,
  alexaUsage: [`${domain}/${region}`],
  sourceDir: sourceDir,
  customName: false
});
```

`ask deploy --target "lambda"`を実行して確認したところ、`region=default`が値として入ってくるため、`CONSTANTS.REGION_MAPPING[region]`は`undefined`になる。そのため、`CONSTANTS.REGION_MAPPING.NA`によりリージョンが決定している模様。

```constants.js
module.exports.REGION_MAPPING = {
    'NA' : 'us-east-1',
    'EU' : 'eu-west-1',
    'IN' : 'eu-west-1',
    'FE' : 'ap-northeast-1'
};
```

`CONSTANTS.REGION_MAPPING.NA`を他にも使っている場所がないか調べる。

```
$ ask-cli ag REGION_MAPPING.NA
lib/utils/init-aws.js
68: let regionCode = CONSTANT.REGION_MAPPING[region] || CONSTANT.REGION_MAPPING.NA;

lib/utils/lambda-operation/lambda-endpoint-utility.js
62: awsRegion: CONSTANTS.REGION_MAPPING[region] || CONSTANTS.REGION_MAPPING.NA,
83: awsRegion: CONSTANTS.REGION_MAPPING[region] || CONSTANTS.REGION_MAPPING.NA,
96: awsRegion: CONSTANTS.REGION_MAPPING[region] || CONSTANTS.REGION_MAPPING.NA,
```

`lambda-endpoint-utility.js`の該当箇所は lambda 関数の作成、更新時に対象となるリージョンを指定している。

`init-aws.js` の該当箇所は `skill.json` をパースするタイミングで、Lambda 関数の ARN を調べるのに利用している。

```
init-aws.js: resolveRegionCodeFromRegion(region)
  retrieve-lambda.js: retrieveLambdaFunction(functionName, region, awsProfile, callback)
    skill-schema-pocessor.js: generateSubmittingReadyManifest(mergedManifest, profile, callback)
      skill-schema-pocessor.js: parseSkill(projectConfigFile, skillFile, profile, callback)
        deploy.js: parseSkill(projectConfigFile, skillFile, profile, (preprocessedSkillSchema, skillInfo, skillId)
```

`ask deploy --target "lambda"`で確認したところ、何れの箇所でも `region=default` が値として入ってくるため、`CONSTANTS.REGION_MAPPING.NA` によりリージョンが決定している。

`CONSTANTS.REGION_MAPPING.NA`(us-east-1), を `CONSTANTS.REGION_MAPPING.FE`(ap-northeast-1)に変更すれば良さそう。([ソース変更](https://qiita.com/snufkon/items/a9db3d001f7df3797952#%E3%82%BD%E3%83%BC%E3%82%B9%E5%A4%89%E6%9B%B4)を参照)




## 動作確認

実際に東京リージョンがデプロイ対象になるか確認しておく。


**スキル & Lambda 関数作成**

```
$ ask new --skill-name "helloworld"
$ cd helloworld
$ ask deploy

-------------------- Create Skill Project --------------------
Profile for the deployment: [default]
Skill Id: amzn1.ask.skill.xxxxxxxxxxxxxxxx
Skill deployment finished.
Model deployment finished.
Lambda deployment finished.
Lambda function(s) created:
  [Lambda ARN] arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:ask-custom-helloworld-default
Your skill is now deployed and enabled in the development stage.
Try invoking the skill by saying “Alexa, open {your_skill_invocation_name}” or simulate an invocation via the `ask simulate` command.
```

- Lambda ARN が ap-northeast-1 となっていることを確認。
- AWS マネジメントコンソールの東京リージョンに ask-custom-helloworld-default 関数が作成されていることを確認。
- Alexa Skills Kit developer console に helloworld スキルが作成されていることを確認。


**Lambda 関数更新**

```
$ ask deploy --target "lambda"

Lambda deployment finished.
Lambda function(s) updated:
  [Lambda ARN] arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:ask-custom-helloworld-default
```

- Lambda ARN が ap-northeast-1 となっていることを確認。


## おわりに

いまのところ、特に問題も発生していないので大丈夫そう。
ただし、ご利用は計画的に。