IBM Cloud Functions の Action/Trigger/Rule を yaml ファイル一発でデプロイする


# はじめに

> ※ 一応「[IBM Cloud Schematics (Terraform) で External Resource を使って CIS Whitelisted IP を Security Group に適用](https://qiita.com/khayama/items/788fa9802cb3cef9fb53) 」の続きです。

公式ドキュメントの「[Deploying entities with a manifest file](https://cloud.ibm.com/docs/openwhisk?topic=cloud-functions-deploy)」の内容です。
IBM Cloud Functions を yaml でテンプレート化しておくと、こんなにいいことがあります。

- CI/CD しやすい
- Function のポータビリティがあがる
- `ibmcloud fn deploy` の一発で構成できる

# 構成イメージ図

今回は Functions で 1 時間ごとに IBM Cloud Schematics (Terraform) Apply をキックする機能を実装します。

![Kobito.dYFVqC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/2e7b6ea0-2a3e-ff5a-bf5e-cb9d11741a99.png "Kobito.dYFVqC.png")


# 事前準備

## IBM Cloud Schematics ワークスペース作成
「[IBM Cloud Schematics (Terraform) で External Resource を使って CIS Whitelisted IP を Security Group に適用](https://qiita.com/khayama/items/788fa9802cb3cef9fb53) 」を参考にして、 IBM Cloud Schematics の Workspace を準備します。



## GitHub からダウンロード
GitHub にあるファイルをダウンロードします。

```
git clone https://github.com/khayama/fn-schematics-apply.git
cd fn-schematics-apply
```

今回の Functions デプロイ用 yaml では以下のように定義しています。
`khayama/ibmcloud-cli` の Docker イメージを 1 時間ごとに起動し、`ibmcloud terraform apply` を実行する Function です。
Functions 実行パラメータは、環境変数の値を取得して埋め込む形で定義しています。

```yaml:schematics-apply-everyhour.yml
packages:
  schematics_package:
    version: 1.0
    license: Apache-2.0
    actions:
      schematics-apply:
        version: 1.0
        description: schematics apply with IBMCLOUD_API_KEY, WORKSPACE_ID
        docker: khayama/ibmcloud-cli
        function: schematics-apply.sh
        inputs:
          IBMCLOUD_API_KEY: $IBMCLOUD_API_KEY
          WORKSPACE_ID: $WORKSPACE_ID

    triggers:
      everyhour:
        feed: /whisk.system/alarms/alarm
        inputs:
          cron: "0 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23 * * *"

    rules:
      schematics-apply-everyhour:
        description: Action is triggered every hour
        action: schematics-apply
        trigger: everyhour
```

>- [openwhisk-wskdeploy/spec_actions.md at master · apache/openwhisk-wskdeploy](https://github.com/apache/openwhisk-wskdeploy/blob/master/specification/html/spec_actions.md#actions)
>- [openwhisk-wskdeploy/spec_trigger.md at master · apache/openwhisk-wskdeploy](https://github.com/apache/openwhisk-wskdeploy/blob/master/specification/html/spec_trigger.md)
>- [openwhisk-wskdeploy/spec_rule.md at master · apache/openwhisk-wskdeploy](https://github.com/apache/openwhisk-wskdeploy/blob/master/specification/html/spec_rule.md)
>- [openwhisk/actions-docker.md at master · apache/openwhisk](https://github.com/apache/openwhisk/blob/master/docs/actions-docker.md)

## `ibmcloud` コマンド準備
コマンドで使う変数を定義します。

```
export REGION="jp-tok"
export RESOURCE_GROUP="Default"
export WORKSPACE_NAME="khayama-classic-sg-allow-cis"
```

`ibmcloud` コマンドでログインし、プラグインをインストールします。

```
ibmcloud login
ibmcloud login -a cloud.ibm.com 
ibmcloud target -r $REGION -g $RESOURCE_GROUP 
ibmcloud plugin install cloud-functions
ibmcloud plugin install schematics
```

# Functions デプロイ

## Functions namespace 作成
`namespace` を作成してプロパティをセットします。

```
ibmcloud fn namespace create khayama-functions
ibmcloud fn namespace target khayama-functions
```

## Functions 用 API Key 発行・取得
Functions 用に API Key を発行し、 `json` ファイルとして保存します。
API Key は環境変数に定義し、Functions 実行用パラメータで使えるようにします。

```
ibmcloud iam api-key-create khayama-fn -d "for cloud functions access" --file khayama-fn-api-key.json
export IBMCLOUD_API_KEY=`cat khayama-fn-api-key.json |  jq -r '.apikey'`
```

続いて、IBM Cloud Schematics ワークスペース ID も環境変数に定義し、Functions 実行用パラメータで使えるようにします。

```
export WORKSPACE_ID=`ibmcloud terraform workspace list --json | jq -r .workspaces | jq -r '.[] | select (.name=="'$WORKSPACE_NAME'") | .id'`
```

## yaml ファイルを指定してデプロイ
これで Functions の Action/Trigger/Rule を一発でデプロイできます。

```
ibmcloud fn deploy --manifest schematics-apply-everyhour.yml
--> Success: Deployment completed successfully.
```

作成されたかどうかの確認するコマンドです。

```
ibmcloud fn package list
ibmcloud fn action list
ibmcloud fn trigger list
ibmcloud fn rule list
```

作成した Functions を実行し結果を確認します。

```
ibmcloud fn action invoke schematics_package/schematics-apply --result
{
    "message": "Applied, Your Activity ID is 6bc7d63f5794bf71f1106e9896b75aed."
}

```

また、しばらく待つと、1時間ごとに実行されていることが確認できました。

![Kobito.WGLDy2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/30133eec-48f3-a917-58d7-9b80429076b4.png "Kobito.WGLDy2.png")

![Kobito.0FPfyj.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/9415d447-1f99-e3ce-6ba2-1b3d46d2fb60.png "Kobito.0FPfyj.png")

作成した Functions の Action/Trigger/Rule を一発で削除するには、こちらのコマンドを実行します。

```
ibmcloud fn undeploy --manifest schematics-apply-everyhour.yml
--> Success: Undeployment completed successfully.
```

# さいごに
これで `https://api.cis.cloud.ibm.com/v1/ips` にある IP アドレス情報に更新があっても、1時間以内に Security Group に適用される仕組みがつくれました。
クラウドを使っていると IP アドレスが変わることがあるので、このような仕組みを使ってメンテナンスフリーで自動適用されるとかなり楽になると思います。

# 参考リンク

- [jqを活用してAPIレスポンス等から欲しい情報だけを抽出する【中級編】 ｜ Developers.IO](https://dev.classmethod.jp/tool/road-to-jq-master-apprentice/)
- [Whisk Deploy — Alarm Trigger - Apache OpenWhisk - Medium](https://medium.com/openwhisk/whisk-deploy-alarm-trigger-6c0984b06745)