EdgeWorkers CLI を使う

Akamai EdgeWorkers CLI を紹介します。

::: note warn
本記事では EdgeWorkers のコードやアカマイのプロパティ設定については触れません。
:::

# Akamai EdgeWorkers とは
超分散された Akamai CDN のエッジプラットフォーム上でサーバーレスコンピューティング機能を提供するのが EdgeWorkers です。EdgeWorkers を利用すると、Web アプリケーション、API、IoT のトラフィックに対してエッジ上でカスタムロジックを起動することができます。EdgeWorkers のコンセプトやユースケースについては、[Qiita X Akamai Meetup](https://www.youtube.com/watch?v=iPxhuyecYik) を参照ください。

https://www.youtube.com/watch?v=iPxhuyecYik

# Akamai CLI とは
Akamai コマンドライン インターフェース (Akamai CLI) は、Windows、 macOS、 Linux などのコマンドラインから直接 Akamai のプラットフォームと製品を管理できる拡張可能なツールキットです。DevOps パイプラインに統合したり、EdgeWorkers のようなサーバレスの開発時にコマンドラインで作業を完結することができます。Akamai CLI はパージのような機能や EdgeWorkers のような製品毎に CLI が用意されています。それぞれの CLI を使うためには、最初に Akamai CLI をインストールする必要があります。以下は、macOS の例です。

```
brew install akamai
````
:::note warn
Homebrew は事前にインストールしてください。
:::

Windows, Linux を使う場合は、次の記事を参考にインストールを完成させてください。

https://qiita.com/kabe-akam/items/cb08ebc2ad03b6ff3c58

Docker を利用して Akamai CLI を利用することもできます。

https://qiita.com/110hideki/items/58428a14974fd8003d7a

# Akamai EdgeWorkers のインストール

```
sudo akamai install edgeworkers
```
実行したときの出力例です。
```console
% sudo akamai install edgeworkers

Attempting to fetch command from https://github.com/akamai/cli-edgeworkers.git... ... [OK]
Installing... ... [OK]

Installed Commands:

  config
    Manage configuration
  edgekv (aliases: ekv, edgekv, edgeworkers/edgekv)
    Manage Akamai EdgeKV database.
  edgeworkers (aliases: ew, edgeworkers, edgeworkers/edgeworkers)
    Manage Akamai EdgeWorkers code bundles.
  help
    Displays help information
  install (alias: get)
    Fetch and install packages from a Git repository
  list
    By default, displays installed commands. Optionally, can display package commands from Git repositories
  pipeline (aliases: pl, pd, proddeploy, property-manager/pipeline)
    Akamai Pipeline for DevOps
  property-manager (aliases: pm, snippets, property-manager/property-manager)
    Property Manager CLI for DevOps
  sandbox (alias: sandbox/sandbox)
    Manage Akamai Sandbox environments.
  search
    Search for packages in the official Akamai CLI package repository
  terraform (alias: terraform/terraform)
    Administer and Manage Akamai Terraform configurations
  uninstall
    Uninstall package containing <command>
  update
    Update one or more commands. If no command is specified, all commands are updated
  upgrade
    Upgrade Akamai CLI to the latest version

See "akamai help [command]" for details.
```
インストールに成功したら、バージョンを確認します。
```
akamai edgeworkers --version
```
本記事で紹介するバージョンは 1.6.2 になります。
```
 % akamai edgeworkers --version
1.6.2
```

# Akamai EdgeWorkers コマンド
引数なしで実行するとコマンドとオプションの一覧が表示されます。
```
akamai edgeworkers
```
次のように ``edgeworkers`` の代わりに ``ew``も使えます。edgeworker なのか edgeworkers なのか迷うときがあるので、``ew`` を使うのが個人的な好みです。なお、製品名には EdgeWorkers と ``s`` が付きますが、個別のコードを指すときは ``edgeworker`` と単数名詞として扱われることが多いです。英語がネイティブでない人には分かりにくいですね。
```
akamai ew
```

オプションの情報です。
```bash
Options:
  -V, --version
  	output the version number
  --debug
  	Show debug information.
  --edgerc <path>
  	Use edgerc file for authentication.
  --section <name>
  	Use this section in edgerc file that contains the credential set.
  --json [path]
  	Write command output to JSON file at given path, otherwise written to CLI cache directory
  --jsonout
  	Write command output as JSON to stdout
  --accountkey <account-id>
  	internal parameter
  --ideExtension <ideExtensionTYpe>
  	extension parameter
  --timeout <timeout>
  	Use this for custom timeout
  -h, --help
  	display help for command
```

コマンドの例です。
```shell-session
Commands:
  help [command]
  	Displays help information for the given command
  list-groups|lg [group-identifier]
  	View a list of groups and the associated permission capabilities
  list-ids|li [options] [edgeworker-identifier]
  	List EdgeWorker ids currently registered
  register|create-id [options] <group-identifier> <edgeworker-name>
  	Register a new EdgeWorker ID to reference in Property Manager behavior
  list-contracts|li-contracts
  	View the list of contracts associated with an account
  list-properties|lp [options] <edgeworkerId>
  	View the list of properties associated with an EdgeWorker ID
  list-restiers|li-restiers [options]
  	View the list of resource tiers available for a specified contract
  list-limits|li-limits
  	List the various limits EdgeWorkers imposes on the number of activations, EdgeWorkers IDs, and versions you can deploy
  show-restier <edgeworkerId>
  	View the resource tier associated with an EdgeWorker ID
  update-id|ui [options] <edgeworker-identifier> <group-identifier> <edgeworker-name>
  	Update an existing EdgeWorker Identifier's Luna ACG or Name attributes
  delete-id [options] <edgeworker-identifier>
  	Permanently delete an existing EdgeWorker ID
  list-versions|lv <edgeworker-identifier> [version-identifier]
  	List Version information of a given EdgeWorker ID
  upload|create-version [options] <edgeworker-identifier>
  	Creates a new version of a given EdgeWorker ID which includes the code bundle
  delete-version [options] <edgeworker-identifier> <version-identifier>
  	Permanently delete an existing version of a given EdgeWorker ID
  download|download-version [options] <edgeworker-identifier> <version-identifier>
  	Download the code bundle of an EdgeWorker version
  status|list-activations [options] <edgeworker-identifier>
  	List Activation status of a given EdgeWorker ID
  activate|av <edgeworker-identifier> <network> <version-identifier>
  	Activate a Version for a given EdgeWorker ID on an Akamai Network
  clone [options] <edgeworker-identifier> <resourceTierId>
  	Clone the given EdgeWorker ID on an Akamai network
  deactivate|deact <edgeworker-identifier> <network> <version-identifier>
  	De-activate a version for a given EdgeWorker ID on an Akamai Network
  validate|vv <bundlePath>
  	Validates a code bundle version without uploading the code bundle
  generate-secret|secret
  	Generates a random secret key that can be used in the variable PMUSER_EW_DEBUG_KEY in their property
  create-auth-token|auth [options] <hostName>
  	Generates an authentication token that can be used to get detailed EdgeWorker debug response headers
  get
  	Get an EdgeWorkers report or get available report types.
```

# EdgeWorker ID の取得準備 (create-id)

``create-id`` コマンドを使います。
```
akamai ew create-id --help
```
ヘルプの出力です。
```console
% akamai ew create-id --help
Usage: akamai-edgeworkers register|create-id [options] <group-identifier> <edgeworker-name>

Register a new EdgeWorker id to reference in Property Manager behavior.

Options:
  -restier, --resourceTierId <resourceTierId>  New resource Tier id to associate with Edgeworker
  -h, --help                                   display help for command
```
``group-identifier`` が必須となっています。次にこのグループ ID を取得します。

# グループ ID の取得 (list-groups | lg)
``lg`` コマンドを使います。
```
akamai ew lg
```
出力結果です。
```console
% akamai ew lg
---------------------------------------------------------------------
--- User has the following Permission Group access for group: any ---
---------------------------------------------------------------------
groupId  groupName         capabilities                                                  
-------  ----------------  --------------------------------------------------------------
214362   Edge Compute CoE  VIEW,EDIT,VIEW_VERSION,CREATE_VERSION,VIEW_ACTIVATION,ACTIVATE
```
``214362`` がグループ ID となります。

# (オプション)コントラクト ID の取得 (list-contracts)
このあと ``create-id`` コマンドを実行するときに、コントラクト ID が正しいかを促されますので、コントラクト ID を確認します。
```
akamai ew list-contracts
```
``list-contracts`` コマンドの結果です。
```console
% akamai ew list-contracts
----------------------------------------------------------
--- List of contract id's associated with this account ---
----------------------------------------------------------
ContractIds
-----------
W-DUMMY_   
```
``W-DUMMY_`` がコントラクトIDとなります。

# EdgeWorker ID の取得 (create-id)
EdgeWorker ID を取得する準備が完了したので、実行します。

```
akamai ew create-id [グループ ID] [EdgeWorker 名]
```
今回 Hello World のサンプルを動作させます。``EdgeWorker 名``は任意の文字列を定義できます。分かりやすい名称を付けてください。
```console
% akamai ew create-id 214362 ew-hello-world

[1] W-DUMMY_
[0] CANCEL

Please select from the above contract ids [1/0]: 1
You have selected W-DUMMY_
```
グループ ID が一つしかない場合は、``1`` を選択します。複数選択されている場合は、適切なグループを選択します。

その後、EdgeWorkers の契約のリソース層（ティア）を選択します。``200`` もしくは ``100`` の層があります。今回は ``200`` の契約しかないケースです。
```console
Resource Tiers
1. Resource Tier 200 Dynamic Compute

Maximum CPU time during initialization: 60 ms
Maximum wall time during initialization: 500 ms
Maximum memory usage per event handler: 2.5 MB
Maximum CPU time per event handler: 20 ms
Maximum wall time per event handler: 5.5 s
Maximum number of HTTP sub-requests allowed from a parent request: 4
Maximum number of HTTP sub-requests allowed in parallel per request: 4
Maximum wall time per HTTP sub-request: 5.5 s
Maximum response size per HTTP sub-request: 5 MB
Maximum memory usage for responseProvider: 4 MB
Maximum CPU time for responseProvider: 200 ms
Maximum wall time for responseProvider: 8 s
Maximum number of HTTP sub-requests allowed for responseProvider: 50
Maximum number of HTTP sub-requests allowed in parallel for responseProvider: 5
Maximum wall time for HTTP sub-requests during the execution of the responseProvider event handler: 8 s
Maximum response size for HTTP sub-requests during the execution of the responseProvider event handler: 5 MB

[1] 200
[0] CANCEL

Please select from the above resource tier ids [1/0]: 1
```
``1`` を入力し ``[1]200`` を選択したら、次のような表示がされます。
```console
------------------------------------------
--- Created new EdgeWorker Identifier: ---
------------------------------------------
edgeWorkerId  name               groupId  resourceTierId
------------  -----------------  -------  --------------
43796         ew-hello-world     214362   200   
```

# EdgeWorker ID のリスト表示 (list-ids)

先程登録した EdgeWorker ID が存在することを ls コマンドで確認します。
```
akamai ew li [EdgeWorker ID]
```
コマンドの出力例です。
```console
% akamai ew li 43796 
INFO: Since EdgeWorker Id (43796) was provided, ignoring unnecessary Group Id, group: undefined...
--------------------------------------------------------------------------------------------------------------
--- The following EdgeWorker Ids are currently registered for account: B-W-XXXXXX, group: any, ewId: 43796 ---
--------------------------------------------------------------------------------------------------------------
edgeWorkerId  name               groupId  resourceTierId
------------  -----------------  -------  --------------
43796         ew-hello-world     214362   200 
```

# EdgeWorkers バンドルファイルの作成
:::note warn
既に EdgeWorkers のコードがある前提で説明します。
:::
EdgeWorkers のコードである ``main.js`` と EdgeWorker ID のバージョンなどが記載されている ``bundle.json`` ファイルが既にあるという前提で、この２つのファイルを ``helloworld.tgz`` という名前の圧縮 Tar 形式ファイルのフォーマットで作成します。作成したファイルを EdgeWorkers バンドルファイルと呼びます。コマンドの説明によっては、tarball ファイルと呼ぶこともあります。
```shell-session
% tar cvzf helloworld.tgz main.js bundle.json 
main.js
bundle.json
```

例で使用しているサンプルコードは GitHub から取得できます。

https://github.com/akamai/edgeworkers-examples/tree/master/edgecompute/examples/getting-started/hello-world%20(EW)

# EdgeWorkers バンドルファイルのアップロード (upload)
``upload`` コマンドの文法を確認します。
```
akamai ew upload --help
```
``upload`` コマンドのヘルプの結果です。
```console
% akamai ew upload --help
Usage: akamai-edgeworkers upload|create-version [options] <edgeworker-identifier>

Creates a new version of a given EdgeWorker Id which includes the code bundle.

Options:
  --bundle <bundlePath>         Path to bundle file in tgz format
  --codeDir <workingDirectory>  Working directory that includes main.js and bundle.json files
  -h, --help                    display help for command
```

バンドルファイルをアップロードするときのコマンドは次のようになります。
```
akamai ew upload --bundle [EdgeWorkers バンドルファイル] [EdgeWorker ID]
```
アップロードしたときの例です。
```console
% akamai ew upload --bundle helloworld.tgz 43796
-----------------------------------------------------
--- New version uploaded for EdgeWorker Id: 43796 ---
-----------------------------------------------------
edgeWorkerId  version  checksum                                                          createdBy   createdTime         
------------  -------  ----------------------------------------------------------------  ----------  --------------------
43796         0.2      479ff08b4249a62a5606aa855ec5b9faa2a23406f44c078d8d7a298657df6d9a  computesme  2022-04-06T15:29:13Z
```
Version が ``0.2`` と表示されています。これは、EdgeWorkers バンドルファイルに含まれている ``bundle.json`` の中に記載されているバージョンとなります。bundle.json の中身は以下のようになります。
```json
{
    "edgeworker-version": "0.2",
    "description" : "Hello World Example"
}
```

# EdgeWorker ID のステータス確認 (status)
``status`` コマンドで、EdgeWorker ID のステータスを確認します。
```
akamai ew status [EdgeWorker ID]
```
EdgeWorker ID ``43796`` のステータスを確認する例です。
```console
% akamai ew status 43796
INFO: There are currently no Activations for ewId: 43796, version: any, activationId: any
```
アクティベーションされたバンドルファイルがないと何も表示されません。

# EdgeWorker ID のアクティベーション (activate)
``activate`` コマンドで、Akamai ネットワーク上で有効化するためにアクティベーションを行います。
```
akamai ew activate [EdgeWorker ID] [Akamai Network] [EdgeWorker ID のバージョン]
```
Akamai Network は ``production`` もしくは ``staging`` を使います。以下はコマンドの出力例です。
```console
% akamai ew activate 43796 staging 0.2
-------------------------------------------------------------------------------------------------
--- New Activation record created for EdgeWorker Id: 43796, version: 0.2, on network: STAGING ---
-------------------------------------------------------------------------------------------------
edgeWorkerId  version  activationId  status     network  createdBy   createdTime         
------------  -------  ------------  ---------  -------  ----------  --------------------
43796         0.2      1             PRESUBMIT  STAGING  computesme  2022-04-06T15:35:21Z
```
アクティベーションが完了するまで ``status`` コマンドで確認します。
```console
% akamai ew status 43796 
----------------------------------------------------------------------------------------------------------------------------------
--- The following EdgeWorker Activations currently exist for account: B-W-XXXXXX, ewId: 43796, version: any, activationId: any ---
----------------------------------------------------------------------------------------------------------------------------------
edgeWorkerId  version  activationId  status    network  createdBy   createdTime         
------------  -------  ------------  --------  -------  ----------  --------------------
43796         0.2      1             COMPLETE  STAGING  computesme  2022-04-06T15:35:21Z
```
status が ``COMPLETE`` になっていることを確認します。

# EdgeWorkers の動作確認
最後に curl で動作確認します。以下はコマンドの例です。

```html
% curl --insecure https://myhost.edgekey-staging.net/ew/hello-world

<html><body><h1>Hello World From Akamai EdgeWorkers</h1></body></html>
```
上記は、EdgeWorkers バンドルファイルに含まれた ``main.js`` が実行された例です。``main.js`` は次のコードです。
```javascript
(c) Copyright 2020 Akamai Technologies, Inc. Licensed under Apache 2 license.

Version: 0.2
Purpose:  Modify an HTML streamed response by adding a script before the closing head tag.
Repo: https://github.com/akamai/edgeworkers-examples/tree/master/hello-world
*/

// Import logging module
import { logger } from 'log'

export function onClientRequest(request) {
    // Outputs a message to the X-Akamai-EdgeWorker-onClientRequest-Log header.
    logger.log("Responding with hello world from the path: %s", request.path)
    request.respondWith(
        200, {},
        '<html><body><h1>Hello World From Akamai EdgeWorkers</h1></body></html>')
}

export function onClientResponse(request, response) {
    // Outputs a message to the X-Akamai-EdgeWorker-onClientResponse-Log header.
    logger.log("Adding a header in ClientResponse")

    response.setHeader('X-Hello-World', 'From Akamai EdgeWorkers')
}
```
Akamai の配信設定の ``/ew/hello-world`` のパスで EdgeWorker ID ``43796`` が起動されるように設定された例となります。


# まとめ
EdgeWorkers を使って開発するには、何度もトライ＆エラーをするかと思います。その場合、UI を利用するよりも CLI を利用すると便利です。是非ご活用ください。