「COBOLをAWS上のマイクロサービスとして使ってみる」の環境構築

# 開発環境構築

今回チームOSSコンソーシアムで作成したものはすべて以下のイメージにまとめています。
こちらからインスタンスを起動してください。
AMI：`ami-0c23b781d007d2085`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/0e6207da-eb8e-fed0-d8f4-84ac39c30194.png)

## 内容物

インスタンスを立ち上げると、カレントディレクトリに以下の成果物が配置してあります。
※lambda上でいろいろなライブラリを動かすため、かなり多くのファイルを含んでいます。
　これらの理由、設置方法などについては別の機会で説明しますので、本稿では省略します。

### 演算処理プログラム生成.xlsm

これは以下パスにあります。

```
/home/ec2-user/sample/演算処理プログラム生成.xlsm
```

今回のサンプルで作成するファイルレイアウトおよび集計処理が記述済みになっていますので、参考にしてください。
また、残念ながらxlsxマクロのためLinux上では動作しませんので、ローカルにダウンロードしてご利用ください。

### perl版lambdaコード

これはEXCELtoTSV変換プログラムを実行するlambdaコード群になります。

以下フォルダに含まれています。

```
/home/ec2-user/perl
```

主な内容は以下になります。

- bootstrap
    - lambdaで最初に呼ばれるスクリプトです。リクエストを受け取ります。

- run_perl.sh
    - 実際にperlプログラムを呼び出すスクリプトです。bootstrapから呼ばれます。

- xlsx2text.pl
    - EXCELtoTSV変換プログラムの本体です。

### cobol版lambdaコード

これはCOBOLの集計プログラムを実行するlambdaコード群になります。

以下フォルダに含まれています。

```
/home/ec2-user/cobol
```

主な内容は以下になります。

- bootstrap
    - lambdaで最初に呼ばれるスクリプトです。リクエストを受け取ります。

- run_cobol.sh
    - 実際にCOBOLプログラムを呼び出すスクリプトです。bootstrapから呼ばれます。

- TEST001.cbl
    - 演算処理プログラム生成によって作成されたCOBOLプログラムソースです。

- compile.TEST001.sh
    - TEST001をコンパイルするためのスクリプトです。

- TEST001.so
    - コンパイルされたCOBOLプログラムの実行ファイルです。

### 動作確認用サンプル

実際に動作確認をするための、xlsxファイルとs3操作用のスクリプトです
以下フォルダに含まれています。

```
/home/ec2-user/sample
```

- upload-s3.sh
    - S3のinputフォルダにファイルをアップロードするスクリプトです。アップロードするxlsxファイル名を引数に与えてください。

- list-s3.sh
    - S3のファイルをすべて表示するスクリプトです。

- download-s3.sh
    - S3のoutputフォルダに生成されたファイルをダウンロードするスクリプトです。アップロードしたxlsxファイル名を引数に与えてください。

- koukin_sample.xlsx
    - 東京都公金管理局の公金支出情報（一般会計・特別会計）を一部抜粋したファイルです。

# AWS側構築

続いてAWS上の各種サービスの設定を行っていきます。

## S3にバケットを作成

ファイルトリガー的に使うので、S3にバケットを作ります。
バケット名は適当につけてください。
パーミッションの設定とかは標準のままでOKです。
今回は`n-isaka.cobolhack01`としてます。
※バケット名はリージョンで一意になるので、自分のIDとか適宜利用してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/5c1383a8-9ae9-ceda-acd8-07d8c123cc7c.png)

## lambda関数を作る

中身は置いておいてとりあえずLambda関数だけ作っておきます。
関数は以下２つ作ります

- cobolhack-perl
    - EXCELからTSVに変換するperlを実行するための関数
- cobolhack-cobol
    - COBOL実行用の関数

### perl側

* 一から作成
* 関数名：`cobolhack-perl`
* ランタイム：ユーザー独自のブートストラップを提供する
* アクセス制限はデフォルトのまま

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/91f5d5e8-398b-3efd-8ab8-2e76a3f517de.png)

まっさらな状態のlambda関数が出来上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/31d7ee3c-28aa-3692-8dde-a1b596832608.png)

ページ下部に移動し、ロールの表示からロールの権限の修正を行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/ea916164-7950-4604-81f5-52671478eabd.png)

ポリシーをアタッチを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/703a4b51-230a-3028-6823-7ef9001a3faf.png)

AWSが提供しているポリシーから、S3全操作の許可を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/f32bb8e4-2571-e713-6bd9-cb093c5408bc.png)

以上でポリシーの修正は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/f9e793d7-bbe9-64ce-eaa7-e4228001b117.png)

トリガーを追加していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/87fe9e00-3d90-e97b-481d-1eba41a6192b.png)

`input`フォルダに`***.xlsx`がアップロードされたら動き出すように、以下の設定を行います。

* バケット：n-isaka.cobolhack01 (自分で作成したバケットを選択します)
* すべてのオブジェクト作成イベント
* プレフィックス：`input/`
* サフィックス：`.xlsx`
* トリガーの有効化：有効

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/6eda5419-7864-1395-cd7a-
a9586d3ec7cb.png)

再びページ下部の基本設定を修正します。
xlsxの処理は多少時間がかかるため、タイムアウト時間を延ばします。
また、xlsx処理用のモジュールでメモリを必要とするため、そちらも増やします。

* メモリ：512
* タイムアウト：5分

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/cc6f6c19-29be-a5b9-ca7f-960d5564fc0a.png)

perl版のlambda構築は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/a60ea909-80b9-c7c8-02d7-49f402b129fc.png)

### COBOL版

基本的にはperl版と同様に作成します。
S3へのアクセス権限も、perl版と同様に付与します。
※lambdaで別のロールを使いまわすと、ログが正常にできなくなる恐れがあります。
　知識のある方以外は、COBOL版で新規にロールを作るようにしましょう。

トリガーの設定を行っていきます。
先ほどのperl関数で`convert`フォルダに`***.tsv`が作成されたら実行されるよう、以下のようなトリガーを設定します。

* バケット：n-isaka.cobolhack01
* すべてのオブジェクト作成イベント
* プレフィックス：`convert/`
* サフィックス：`.tsv`
* トリガーの有効化：有効

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/b124e10f-0fb5-02b9-04e9-4b951bbbb627.png)

基本設定も同様に変更していきます。
こちらはメモリを増やさなくてもサンプルの動作は可能です。

* メモリ：128
* タイムアウト：5分

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/0316cb05-46a0-7b03-2671-7bea3ed08f80.png)


## アクセス用のキーを作る

全部ブラウザのGUIから作業するのは非常に面倒なため、コマンドラインからいろいろやるために、Identity and Access Management (IAM)でキーを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/cb9dbd0e-52ab-381e-7788-f685dd068db7.png)

# インスタンス上での操作

ここからは、AMIから起動したインスタンスにログインして作業を行います。

## awsのCLIを設定する

ログイン後、`aws configure`で設定します。
Access KeyとSecret Keyは先ほど作成したものを入力します。
また、regionは`ap-northeast-1`(東京)を指定します。

```
[ec2-user@ip-172-31-41-54 ~]$ aws configure
AWS Access Key ID [None]: ****
AWS Secret Access Key [None]: **** 
Default region name [None]: ap-northeast-1
Default output format [None]: 
```

## スクリプトの修正

以下のスクリプトのbucket名の部分を、自分で作成したものに変更します。
これらはAWSCLIからS3へのファイルアップロードや、lambdaへの関数登録を行うスクリプトです。

```
~/mkfunction-cobol.sh
~/mkfunction-perl.sh
~/sample/upload-s3.sh 
~/sample/upload-s3.sh 
~/sample/upload-s3.sh 
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/f784658b-95cc-3a05-bdb0-b5dbf16de502.png)

## スクリプトでlambdaへのコード登録

以下２つのスクリプトを実行することで、それぞれperlとCOBOLのlambda関数にコードを登録します。
COBOLプログラムはサンプルとして生成した`TEST001.cbl`が登録されます。


```
[ec2-user@ip-172-31-41-54 ~]$ ./mkfunction-perl.sh 
[ec2-user@ip-172-31-41-54 ~]$ ./mkfunction-cobol.sh 
```

エラーなく終われば、関数にコードが登録されています。

※作成時と違い、大きなコードを登録したため、インライン編集が使用不可になっていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/8c4757b6-1c56-d366-84bc-c8077d2cae40.png)

## 動かしてみる

sampleフォルダにS3操作用のスクリプトと、サンプルのTEST001で集計するxlsxファイルが配置してあります。
※元データでは処理に時間がかかるため、修正対象のxlsxのデータは生データではなく、1000行程度に減らしています。

```
[ec2-user@ip-172-31-41-54 ~]$ cd sample/
[ec2-user@ip-172-31-41-54 sample]$ ./upload-s3.sh koukin_sample.xlsx 
{
    "ETag": "\"1197656ab4046b6e9cd5a74b8a325757\""
}
```

しばらく待つと、S3にファイルが生成されていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/c93e3e0b-780b-d92a-1517-face5e568345.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/f801ae37-61a0-b0e5-eec9-f2039bca37a6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/25e9cb41-e48a-f510-30cb-0544976e4c14.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/9f220f7c-d2b2-54d5-1b21-c090a27d1175.png)

AWSCLI上からでは、インスタンス上で以下のように確認できます。

```
[ec2-user@ip-172-31-41-54 sample]$ ./list-s3.sh 
{
    "Contents": [
--- 中略 ---
        {
            "LastModified": "2020-03-13T07:24:05.000Z", 
            "ETag": "\"26a07151da703fdd80ab9d2c4593d1f3\"", 
            "StorageClass": "STANDARD", 
            "Key": "output/koukin_sample.xlsx.tsv.json", 
            "Owner": {
                "DisplayName": "n-isaka", 
                "ID": "6f0961303db4b7797faa7ef4c9b3110c0ac647fa4a6c80e251ecb8a9824f22b8"
            }, 
            "Size": 191
        }
    ]
}
```

## 結果を見てみる

集計結果のJSONは以下のようになっています。

```json:koukin_sample.xlsx.tsv.json
[{"トナー":24603,"旅費":16045227,"灯油":0,"キーボード":0,"オリンピック":0,"公園":0,"タクシー":3684483,"奨励金":0,"手当":0,"観光":0,"補助金":269126906,"報償":4389835,"漁業":0,"働き方改革":0}] 
```

```json:koukin_sample.xlsx.tsv.json(成形)
[
	{
		"トナー": 24603,
		"旅費": 16045227,
		"灯油": 0,
		"キーボード": 0,
		"オリンピック": 0,
		"公園": 0,
		"タクシー": 3684483,
		"奨励金": 0,
		"手当": 0,
		"観光": 0,
		"補助金": 269126906,
		"報償": 4389835,
		"漁業": 0,
		"働き方改革": 0
	}
]
```

モニタリング画面では成功が増えていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/9b53dabe-d32a-134f-1c61-192e99b14808.png)

ログでも実行が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439579/8099bcf0-aec0-e172-6f48に-4c2accceafc7.png)

AWSCLIで、結果をダウンロードして表示すると、以下のように確認できます。

```
[ec2-user@ip-172-31-41-54 sample]$ ./download-s3.sh koukin_sample.xlsx 
{
    "AcceptRanges": "bytes", 
    "ContentType": "binary/octet-stream", 
    "LastModified": "Fri, 13 Mar 2020 07:24:05 GMT", 
    "ContentLength": 191, 
    "ETag": "\"26a07151da703fdd80ab9d2c4593d1f3\"", 
    "Metadata": {}
}
[ec2-user@ip-172-31-41-54 sample]$ ls
download-s3.sh  koukin_sample.xlsx  koukin_sample.xlsx.tsv.json  list-s3.sh  upload-s3.sh  演算処理プログラム生成.xlsm
[ec2-user@ip-172-31-41-54 sample]$ jq < koukin_sample.xlsx.tsv.json 
[
  {
    "�g�i�[": 24603,
    "����": 0,
    "�L�[�{�[�h": 0,
    "�I�����s�b�N": 0,
    "�^�N�V�[": 3684483,
    "�����": 0,
    "�蓖": 0,
    "�ό�": 0,
    "�⏕��": 269126906,
    "��": 4389835,
    "���������v": 0
  }
]
```

※ファイルはSJISのため、残念ながら文字化けします。
　Linux上でSJISを扱いたい場合は別途設定を行う必要がありますが、ここでは省略します。

# なかでやっていること

lamdba上の処理の流れは以下のようになっています。

`bootstrap`から`run_perl.sh`、`run_cobol.sh`がよばれる
↓
jqを使ってリクエストのJSONからファイル名を取得
↓
awsのCLIを利用し、s3からファイルを取得
↓
perlまたはCOBOLが実行される
↓
出来上がったファイルをawsのCLIでs3にアップ


# 終わり

以上が、成果物を実行する環境構築になります。