全力で怠けたい

怠けるために全力を尽くしたいブログ。

Cloudflare Zero Trust のダッシュボードからトンネルを作成する方法。

Cloudflare Zero Trust のダッシュボードからトンネルを作成する方法を記載する。

前提条件として、以下は事前に設定済み。

Cloudflare Zero Trust のダッシュボードからトンネルを作成する方法だが、Set up a tunnel through the dashboard の手順どおりに作業すると、ものの1分くらいで終わる。 はまりポイントがまったくといっていいほどなく、書くことがまったくないくらい簡単。

Cloudflare のトンネルは CLI で何回か作成したことがあったけど、こんなに簡単だったかな……という印象がある。

Pixela の CLI ツール pa が v1.7.0 にバージョンアップしました。

Pixela の CLI ツール pa が v1.7.0 にバージョンアップしました。

v1.7.0 アップデート内容

API リクエストのリトライ回数を指定する -r, --retry オプションを追加

API リクエストのリトライ回数を指定する -r, --retry オプションを追加しました *1

Pixela v1.25.0 のリリースによって、一部のAPIにおいて 25%の割合でそのAPIに対するリクエストがリジェクトされる仕様が追加されました。

-r, --retry オプションは、API のリクエストがリジェクトされたとき、pa が自動的に API リクエストをリトライする回数を指定できるようにしています。 -r, --retry オプションのデフォルト値は 0、つまり1回もリトライしません。 -r, --retry オプションを指定しない場合は v1.6.0 以前と同じ挙動になります。

-r, --retry オプションを指定すると、API のリクエストがリジェクトされたときのリトライ処理を pa に任せることができ、コードの記述量を減らすことができます。

たとえば、pa graph get-all --retry 5 は、--retry オプションを指定しない以下のコードと同等の処理となります。

# API 呼び出しがリジェクトされた場合は5回までリトライする
for I in $(seq 1 5)
do
    RESULT=$(pa graph get-all 2>&1)
    # API のリクエストが成功
    if [ $? -eq 0 ]; then
        echo "${RESULT}"
        break
    fi

    # API のリクエストがリジェクト以外の理由で失敗
    if ! echo "${RESULT}" | grep "api call rejecte" > /dev/null
    then
        echo "${RESULT}"
        break
    fi

    # API のリクエストがリジェクトされた
    # echo "*** retry ***"
done

v1.7.0 へのアップグレード方法

Homebrew を使っている場合は以下のコマンドにてアップグレードできます。

$ brew update && brew upgrade pa

go install コマンドでアップグレードすることもできます。

$ go install github.com/ebc-2in2crc/pa/cmd/pa@latest

現場からは以上です。

*1:実験的な機能となります

Redash のユーザーパスワードを CLI で変更する方法。

はじめに

Redash は 公式の AMI を使って AWS 上に構築しているのでそれ前提で書く。

検証に使用した Redash のバージョンは 8.0.0。

Redash のユーザーパスワードを CLI で変更する方法

Redash を稼働させている EC2 にログインすることができれば、Redash の管理用スクリプトを使ってユーザーパスワードを変更できる。

Redash のユーザーパスワードを変更できるには、Redash を稼働させている EC2 に SSH ログイン後に以下のコマンドを実行する。以上。

$ CID=$(sudo docker container ls -q -f 'name=redash_server*')
$ sudo docker container exec ${CID} /bin/bash -c '/app/bin/run ./manage.py users password <user's email> <new password>'
User updated.

参考サイト

pixela4go が v1.6.0 にバージョンアップしました。

pixela4go が v1.6.0 にバージョンアップしました。

Pixela v1.25.0 に対応するバージョンアップとなります。

【追記】現在、内部実装を改良した v1.6.1 がリリースされています *1

v1.6.0 アップデート内容

Pixela の一部の API が 25% の割合でリクエストをリジェクトする仕様が追加された

Pixela v1.25.0 のリリースによって、一部のAPIにおいて 25%の割合でそのAPIに対するリクエストがリジェクトされる仕様が追加されました。

詳しくは 公式ページ を参照してください ← Pixela v1.25.1 にて、Pixela v1.25.1 (日本時間 2022年7月31日午前8時) よりも前に作成されたユーザー はリジェクトの対象外になる、ように仕様が変わっています

pixela4go での機能追加

pixela4go v1.6.0 は、API 呼び出しがリジェクトされたときに API 呼び出しを自動でリトライする機能を追加しています。

具体的には以下のコードを追加することにより、API 呼び出しがリジェクトされたときの自動リトライが有効になります。

// API 呼び出しが拒否されたときにリトライする場合、リトライ回数を指定します。
// pixela4go での自動リトライが必要なければ指定する必要はありません。
pixela.RetryCount = 10

pixela4go に自動リトライ機能を追加した理由

pixela4go は Pixela の「薄いライブラリ」を目指しており、エラーが発生したときのハンドリング *2 はライブラリの利用者側が行えるように (行うように)、という方針で実装しています。

このような方針があるので、Pixela v1.25.0 にて一部の API が 25% の割合でリクエストをリジェクトする仕様が追加されたときも、pixela4go は特になにか対応するなどのリアクションはしないつもりでした。 しかしながら、「エラーハンドリングは必要なのは分かっているけど、まずはもっと手軽に API サービスを使いたい、試してみたい」というようなニーズがあるかもしれない……とも思ったので、API リクエストがリジェクトされたときの自動リトライ機能を実装した次第です。

ちなみに、自動リトライ機能は実験的な機能の位置づけです。 今後、取り除かれるかもしれませんし、正式な機能としてリリースすることがあるかもしれません。

現場からは以上です。

*1:サービスの運営者様から「API 呼び出しがリジェクトされたかどうかはこーゆーやり方のほうでいいですよ!」と、まさかのアドバイス (ご指摘) をいただいたことへの対応になります

*2:リトライなど

CSV 内のカンマを除去するワンライナー3選 + おまけ2つ。

Twitter で「CSV 内の数値項目がカンマを含んでいるが、そのカンマを除去したい」というのを見かけたので、ワンライナーでやってみた。 あと、おまけとして普通にプログラムを書くやり方でもやってみた。

はじめに

個人的には、システム同士の間などでデータ連係をするとき「CSV でいいんじゃない、簡単だし」みたいな会話が聞こえてきたら、相当苦労しそうな予感がする。 実際、CSV を少しでも扱った経験があれば「相当面倒くさい」データ形式だということは一定の理解を得られると思うし、CSV を扱った経験がなくても CSV の国際標準を定める RFC 4180 をサーッと流し読みすると、結構いろいろなことを考慮しないといけなさそうだな、とピンとくると思う。

今回は「CSV 内の数値項目がカンマを含んでいるが *1 、そのカンマを除去したい」という問題をワンライナーで解決していく *2

処理する CSV

数値項目がカンマを含んでいる 2つの CSV ファイル、data.csv と new-lines-and-comma.csv を用意した。

2つの CSV ファイルとも1行目がヘッダー行になっていて、col2 がカンマを含む数値項目となっている。 また、new-lines-and-comma.csvcol2 はカンマだけでなく改行も含むというよく分からないデータにしてみた。

$  cat data.csv
col1,col2,col3
a,"1,2,3",b

$ cat new-lines-and-comma.csv
col1,col2,col3
"comma is ,","1,2,
3",100

ワンライナー3選

xsv コマンド + よく知られたコマンドの組み合わせ

xsv コマンドを使うと、CSV ファイルを分割したり結合したりといったことが簡単にできる。

xsv コマンドの table サブコマンドを使うと、CSV をスペース区切りのデータに変換できる。また。col2 のようにカンマを含む項目も正しく処理できる。

$ xsv table data.csv
col1  col2   col3
a     1,2,3  b

CSV をスペース区切りのデータに変換したら、よく使うコマンドを組み合わせてカンマを除去できる。

$ xsv table data.csv | \
    teip -f 2 -- tr -d ',' | \
    awk 'BEGIN{OFS=","}{print $1,$2,$3}'
col1,col2,col3
a,123,b

ただ、CSV ファイルが new-lines-and-comma.csv のようにデータ内に改行を含むときはうまく処理できない。

$  xsv table new-lines-and-comma.csv
col1        col2  col3
comma is ,  "1,2,
3"          100

$ xsv table new-lines-and-comma.csv | \
    teip -f 2 -- tr -d ',' | \
    awk 'BEGIN{OFS=","}{print $1,$2,$3}'
col1,col2,col3
comma,is,,
3",100,

q コマンドを使う

CSV や TSV に対して SQL クエリを実行できる q コマンドを使うと、CSV ファイル内のカンマを簡単に除去できる。

以下のように replace 関数でカンマを除去してしまえばよい。

$  q -H -O -d, 'select col1, replace(col2, ",", "") as col2, col3 from data.csv'
col1,col2,col3
a,123,b

また、CSV ファイルが new-lines-and-comma.csv のようにデータ内に改行を含む場合も、意図通りに処理できる。

$ q -H -O -d, 'select col1, replace(col2, ",", "") as col2, col3 from new-lines-and-comma.csv'
col1,col2,col3
"comma is ,","12
3",100

Rubycsv ライブラリを使う

Rubycsv ライブラリを使うと、CSV ファイル内のカンマを簡単に除去できる。

$ ruby -r csv -e 'CSV.read("data.csv").each{|row| row[1].gsub!(",", ""); puts row.to_csv}'
col1,col2,col3
a,123,b

また、CSV ファイルが new-lines-and-comma.csv のようにデータ内に改行を含む場合も、意図通りに処理できる。

$  ruby -r csv -e 'CSV.read("new-lines-and-comma.csv").each{|row| row[1].gsub!(",", ""); puts row.to_csv}'
col1,col2,col3
"comma is ,","12
3",100

おまけ2つ

汎用言語の csv 処理用のライブラリを使う

汎用言語の csv 処理用のライブラリを使う。

Rubycsv ライブラリを使うのとほぼ同じだが、Ruby 以外の汎用のプログラミング言語CSV を処理するライブラリを備えているので、そのライブラリを使えば CSV ファイル内のカンマを簡単に除去できる。

たとえば、Go なら以下のようなプログラムを書くと今回の目的が達成できる。

package main

import (
    "encoding/csv"
    "io"
    "log"
    "os"
    "strings"
)

func main() {
    r := csv.NewReader(os.Stdin)
    w := csv.NewWriter(os.Stdout)

    for {
        row, err := r.Read()
        if err == io.EOF {
            break
        }
        if err != nil {
            log.Fatalln(err)
        }
     
        row[1] = strings.ReplaceAll(row[1], ",", "")
        if err := w.Write(row); err != nil {
            log.Fatalln("error writing record to csv:", err)
        }
    }

    w.Flush()

    if err := w.Error(); err != nil {
        log.Fatalln(err)
    }
}

data.csv も new-lines-and-comma.csv も意図通りに処理できる。

$ go build -o main main.go

$ cat data.csv | ./main
col1,col2,col3
a,123,b

$ cat new-lines-and-comma.csv | ./main
col1,col2,col3
"comma is ,","12
3",100

一番確実な解決法

いろいろ書いたけど、「CSV 内の数値項目がカンマを含んでいるが、そのカンマを除去したい」という問題の一番簡単な解決法は、「CSV を出力するとき、数値項目はカンマを含めない」ことだと思う。

参考サイト

*1:CSV 内の数値項目がカンマを含んでいたら、それはもう文字列なのでは? という疑問は一旦置いておく

*2:実行速度も一旦置いておく

JSON, CSV, Excel, Parquet 等の様々なデータ形式に SQL クエリを実行できる dsq コマンドが便利。

JSON, CSV, Excel, Parquet 等の様々なデータ形式SQL クエリを実行できる dsq コマンドが便利なのでメモしておく。

はじめに

dsq コマンドは JSON, CSV, Excel, Parquet などの様々なデータ形式に対して SQL クエリを実行できるツール。

対応しているデータ形式

dsql は以下のように多くのデータ形式に対応している。

データ形式 ファイル拡張子 Mime タイプ
CSV csv text/csv
TSV tsv, tab text/tab-separated-values
JSON json application/json
Newline-delimited JSON ndjson, jsonl application/jsonlines
Concatenated JSON cjson application/jsonconcat
ORC orc orc
Parquet parquet parquet
Avro avro
YAML yaml, yaml application/yaml
Exel xlsx, xls application/vnd.ms-excel
ODS ods application/vnd.oasis.opendocument.spreadsheet
Apache Error Logs NA text/apache2error
Apache Access Logs NA text/apache2access
Nginx Access Logs NA text/nginxaccess

類似のツールとの比較

詳細は公式サイトを見てほしいが、q コマンドや textql コマンド等の類似ツールと比べると、対応しているフォーマットがあきらかに多い。

dsq は後発のツールということもあり、既存の類似ツールに対して以下のような優位性があるようだ。

バージョン

このエントリーで使っている dsq のバージョン。

$ dsq --version
dsq 0.21.0

インストール方法

Macbrew でインストールすると楽。

$ brew install dsq

Mac 以外は (releases)https://github.com/multiprocessio/dsq/releases からバイナリを取得し、パスが通っているディレクトリに配置する。 たとえば Linux はこんな感じ。

$ curl -LO https://github.com/multiprocessio/dsq/releases/download/0.21.0/dsq-linux-x64-0.21.0.zip
$ unzip dsq-linux-x64-0.21.0.zip
$ sudo mv dsq /usr/local/bin/dsq

最新版を使いたいときは go install でインストールする。

$ go install github.com/multiprocessio/dsq@latest

基本的な使い方

ファイルに対して SQL クエリを実行する

dsq <ファイル> <SQL クエリ> のように処理対象のファイルを指定して実行する。 SQL クエリの中の {} についてはあとで説明する。

$ cat employee.json | jq
[
  {
    "employee_id": 100,
    "department_id": 1,
    "name": "Alice"
  },
  {
    "employee_id": 200,
    "department_id": 1,
    "name": "Bob"
  },
  {
    "employee_id": 300,
    "department_id": 2,
    "name": "Carol"
  }
]

$ dsq employee.json "select * from {} where employee_id = 100"
[{"department_id":1,"employee_id":100,"name":"Alice"}]

標準入力に対して SQL クエリを実行する

dsq -s <ファイルタイプ> <SQL クエリ> のように実行すると、標準入力に対して SQL クエリを実行することができる。

$ cat employee.json | dsq -s json "select * from {} where employee_id = 100"
[{"department_id":1,"employee_id":100,"name":"Alice"}]

クエリ結果を整形する

dsq はデフォルトではクエリ結果の JSON は整形せずに出力する。

これは実行効率を重視しての挙動のようだが、もしクエリ結果を整形したいときは jq と組み合わせればよい。

$ cat employee.json | dsq -s json "select * from {} where employee_id = 100" | jq
[
  {
    "department_id": 1,
    "employee_id": 100,
    "name": "Alice"
  }
]

あるいは、dsq の -p, --pretty を指定するとクエリ結果をテーブル表示することもできる。

$ cat employee.json | dsq -s json --pretty "select * from {} where employee_id = 100"
+---------------+-------------+-------+
| department_id | employee_id | name  |
+---------------+-------------+-------+
|             1 |         100 | Alice |
+---------------+-------------+-------+
(1 row)

複数のファイルに対して SQL クエリを実行する

複数のファイルを JOIN する

dsq は複数のファイルに対して SQL クエリを実行し、JOIN できる。

$ cat department.json | jq
[
  {
    "department_id": 1,
    "name": "Sales department"
  },
  {
    "department_id": 2,
    "name": "Marketing department"
  }
]

$ dsq --pretty employee.json department.json \
    "select {0}.name as 'employee_name', {1}.name as 'department_name' from {0} join {1} on {1}.department_id = {0}.department_id"
+----------------------+---------------+
|   department_name    | employee_name |
+----------------------+---------------+
| Sales department     | Alice         |
| Sales department     | Bob           |
| Marketing department | Carol         |
+----------------------+---------------+
(3 rows)

SQL クエリからは {N} のようにしてテーブル (読み込み元のファイル) を指定できる。 N は 0 から始まり、dsq の引数に指定したファイルの順番に対応している。

N を省略すると {0} を指定したものとして処理される。 つまり、以下の SQL クエリは先ほどの SQL クエリと同じ意味になる。

$ dsq --pretty employee.json department.json \
    "select {}.name as 'employee_name', {1}.name as 'department_name' from {} join {1} on {1}.department_id = {}.department_id"
+----------------------+---------------+
|   department_name    | employee_name |
+----------------------+---------------+
| Sales department     | Alice         |
| Sales department     | Bob           |
| Marketing department | Carol         |
+----------------------+---------------+
(3 rows)

SQL クエリ内のテーブルにはエイリアスを付けることもできる。 エイリアスを使うと先ほどの SQL クエリは以下のように書くことができる。

$ dsq --pretty employee.json department.json \
    "select e.name as 'employee_name', d.name as 'department_name' from {0} as e join {1} as d on d.department_id = e.department_id"
+----------------------+---------------+
|   department_name    | employee_name |
+----------------------+---------------+
| Sales department     | Alice         |
| Sales department     | Bob           |
| Marketing department | Carol         |
+----------------------+---------------+
(3 rows)

データ形式が異なるファイルを JOIN する

dsq はデータ形式が異なるファイル同士も処理できる。

たとえば、以下の例では JSONCSV に対して SQL クエリを実行し、JOIN している。

$ cat department.csv
"department_id","name"
1,"Sales department"
2,"Marketing department"

$ dsq --pretty employee.json department.csv \
    "select {0}.name as 'employee_name', {1}.name as 'department_name' from {0} join {1} on {1}.department_id = {0}.department_id"
+----------------------+---------------+
|   department_name    | employee_name |
+----------------------+---------------+
| Sales department     | Alice         |
| Sales department     | Bob           |
| Marketing department | Carol         |
+----------------------+---------------+
(3 rows)

任意のデータ形式から JSON ヘの変換

dsq はデフォルトではクエリ結果を JSON で出力するので、任意のデータ形式から JSON ヘの変換フィルターとして使うことができる。

$ dsq department.csv "select * from {}"
[{"name":"Sales department","department_id":"1"},
{"department_id":"2","name":"Marketing department"}]

dsq は SQL クエリを省略すると select * from {} が指定されたものとして動作するので、先ほどの実行例は以下のように短くすることができる。

$ dsq department.csv
[{"department_id":"1","name":"Sales department"},
{"department_id":"2","name":"Marketing department"}]

オブジェクト内にネストしている配列に SQL クエリを実行する

SQL クエリを実行したいオブジェクトの配列がオブジェクト内にネストしている場合、{N, 'path'} または {N, "path"}のようにテーブルを指定する。

$ cat employee-2.json | jq
{
  "data": {
    "employees": [
      {"employee_id": 100, "department_id": 1, "name": "Alice"},
      {"employee_id": 200, "department_id": 1, "name": "Bob"},
      {"employee_id": 300, "department_id": 2, "name": "Carol"}
    ]
  }
}

$ dsq --pretty employee-2.json "select * from {0, 'data.employees'} where employee_id = 100"
+---------------+-------------+-------+
| department_id | employee_id | name  |
+---------------+-------------+-------+
|             1 |         100 | Alice |
+---------------+-------------+-------+
(1 row)

テーブルに {} を指定すると {0} を指定したものとして処理されるので、先ほどの SQL クエリは以下のように短くできる。

$ dsq --pretty employee-2.json "select * from {'data.employees'} where employee_id = 100"
+---------------+-------------+-------+
| department_id | employee_id | name  |
+---------------+-------------+-------+
|             1 |         100 | Alice |
+---------------+-------------+-------+
(1 row)

ネストしているオブジェクトから値を取得する

dsq がクエリできるのはスカラー値のみで、オブジェクト全体は取得できない。 したがって、下記のようなコマンドを実行すると「カラムがない」旨を示すメッセージが表示される。

$ cat employee-3.json
[
  {
    "employee_id": 100,
    "department_id": 1,
    "name": {"first": "Alice", "last": "Smith"}
  },
  {
    "employee_id": 200,
    "department_id": 1,
    "name": {"first": "Bob", "last": "Johnson"}
  },
  {
    "employee_id": 300,
    "department_id": 2,
    "name": {"first": "Carol", "last": "Williams"}
  }
]

$ dsq --pretty employee-3.json 'select name from {} where employee_id = 100'
no such column: name

以下のようにスカラー値へのパスを指定すると、オブジェクトのフィールドの値を取得できる。

$ dsq --pretty employee-3.json 'select "name.first", "name.last" from {} where employee_id = 100'
+------------+-----------+
| name.first | name.last |
+------------+-----------+
| Alice      | Smith     |
+------------+-----------+
(1 row)

ネストしている配列から値を取得する

dsq が内部で利用している SQLiteJSON 演算子 をサポートしており、下記のようにネストしている配列から任意の値を取得することができる (正確には、dsq が内部で利用している datastation が SQLite を利用している)

$ cat fields.json
[
  {"field1": [1]},
  {"field1": [2]},
]

$ dsq fields.json "SELECT field1->0 FROM {}" | jq
[
  {
    "field1->0": "1"
  },
  {
    "field1->0": "2"
  }
]

正規表現のサポート

SQL クエリ内で正規表現を使うことができる。

$ dsq --pretty employee.json 'select * from {} where name regexp "^[AB]"'
+---------------+-------------+-------+
| department_id | employee_id | name  |
+---------------+-------------+-------+
|             1 |         100 | Alice |
|             1 |         200 | Bob   |
+---------------+-------------+-------+
(2 rows)

その他

カラムの出力順

--pretty を指定する場合、カラムはアルファベット順に出力される。

$ dsq --pretty employee.json 'select name, department_id, employee_id from {} where employee_id = 100'
+---------------+-------------+-------+
| department_id | employee_id | name  |
+---------------+-------------+-------+
|             1 |         100 | Alice |
+---------------+-------------+-------+
(1 row)

--pretty を指定しない場合、カラムは select 句で指定した順に出力される。 カラムを順序付けして出力する場合は jq --sort-keys と併用するとよい。

$ dsq employee.json 'select department_id, name, employee_id from {} where employee_id = 100'
[{"department_id":1,"name":"Alice","employee_id":100}]

$ dsq employee.json 'select department_id, name, employee_id from {} where employee_id = 100' | jq --sort-keys
[
  {
    "department_id": 1,
    "employee_id": 100,
    "name": "Alice"
  }
]

スキーマの推測

--schema を指定するとファイルのスキーマを推測して出力する。

$ dsq --schema employee.json
{
  "kind": "array",
  "array": {
    "kind": "object",
    "object": {
      "department_id": {
        "kind": "scalar",
        "scalar": "number"
      },
      "name": {
        "kind": "scalar",
        "scalar": "string"
      },
      "employee_id": {
        "kind": "scalar",
        "scalar": "number"
      }
    }
  }
}

入力ファイルのキャッシュ

-C, --cache を指定すると入力ファイルをキャッシュするようになり、キャッシュ済みのファイルへの SQL クエリが大幅に高速化される。 -C, --cache を指定する代わりに環境変数DSQ_CACHE=true を設定しておくこともできる。

$ dsq some-large-file.json --cache 'SELECT COUNT(1) FROM {}'

$ export DSQ_CACHE=true
$ dsq some-large-file.json 'SELECT COUNT(1) FROM {}'

REPL

-i, --interactive を指定すると REPL が起動し、対話的に SQL クエリを実行できる。

$ dsq --interactive employee.json
dsq> select count(1) from {}
+----------+
| count(1) |
+----------+
|        3 |
+----------+
(1 row)

dsq> select * from {} where employee_id = 100;
+---------------+-------------+-------+
| department_id | employee_id | name  |
+---------------+-------------+-------+
|             1 |         100 | Alice |
+---------------+-------------+-------+
(1 row)

dsq> exit
bye

CSV と TSV ファイル内の数値の変換

CSV と TSV ファイル内のフィールドは、デフォルトではすべて文字列として扱われる。

したがって、下記の CSV のように score が実際は数値であっても、score でソートすると辞書順にソートされてしまう。

$ cat scores.csv
name,score
Fritz,90
Rainer,95
Fountainer,100

$ dsq scores.csv 'select score from {} order by score'
[{"score":"100"},
{"score":"90"},
{"score":"95"}]

-n, --convert-numbers を指定すると、数値 (整数と浮動小数点数) を自動検出して、文字列から数値に変換する。

$ dsq --convert-numbers scores.csv 'select score from {} order by score'
[{"score":90},
{"score":95},
{"score":100}]

-n, --convert-numbers を指定する代わりに環境変数DSQ_CONVERT_NUMBERS=true を設定しておくこともできる。

$ export DSQ_CONVERT_NUMBERS=true
$ dsq scores.csv 'select score from {} order by score'
[{"score":90},
{"score":95},
{"score":100}]

なお、数値 (整数と浮動小数点数) の自動検出 & 文字列から数値への変換を有効にすると、一部の最適化が無効になる。

参考サイト

AWS Elastic Beanstalk の環境変数を AWS CLI で設定する。

はじめに

AWS Elastic Beanstalk の環境変数AWS CLI で設定する方法のメモ。

AWS Elastic Beanstalk の環境変数はいろんな方法で設定できる

AWS Elastic Beanstalk の環境変数を設定する方法はいくつかある。

  • マネージメントコンソール
  • EB CLI
  • AWS CLI
  • ebextensions (option settings)

個人的には ebextensions が最推しで、次点で AWS CLI というところ。 (ただし、ebextensions で環境変数を管理している場合、環境変数は ebextensions だけで管理し、その他の方法では変更しないのが鉄則)

その他の2つについては、以下の理由によりほとんど使っていない。

  • マネージメントコンソールを開いての作業はしたくない
  • EB CLI は最初に init したり等の準備が必要で、意外と面倒くさい

個人的には ebextensions が最推しだが、すでにマネージメントコンソールで環境変数を設定する運用になっていたり、とりあえずサッと環境変数を設定して動作を見てみたい、というときには AWS CLI環境変数を設定することがある。

以下、AWS CLI での環境変数の設定方法を記載する。

AWS Elastic Beanstalk の環境変数AWS CLI で追加・変更する

AWS Elastic Beanstalk の環境変数AWS CLI で追加・変更するには update-environment コマンドを使う。

$ aws elasticbeanstalk update-environment \
    --region=<リージョン> \
    --application-name=<アプリ名> \
    --environment-name=<環境名> \
    --option-settings \
    "Namespace=aws:elasticbeanstalk:application:environment,OptionName=CLI_ENV_1,Value=CLI から設定した環境変数_1" \
    "Namespace=aws:elasticbeanstalk:application:environment,OptionName=CLI_ENV_2,Value=CLI から設定した環境変数_2"

--option-settings オプションは以下のように指定する。

項目
Namespace aws:elasticbeanstalk:application:environment
OptionName 環境変数の名前
Value 環境変数の値

describe-configuration-settings コマンドにて環境変数を表示すると、さきほど設定した環境変数がちゃんと反映していることを確認できる。

$ aws elasticbeanstalk describe-configuration-settings \
    --region=<リージョン> \
    --application-name=<アプリ名> \
    --environment-name=<環境名> \
    jq -r '.ConfigurationSettings[0].OptionSettings | map(select(.Namespace == "aws:elasticbeanstalk:application:environment")) | .[] | [.OptionName, .Value] | @csv'
"CLI_ENV_1","CLI から設定した環境変数_1"
"CLI_ENV_2","CLI から設定した環境変数_2"

値が空の環境変数を設定する

値が空の環境変数を設定するには、--option-settings オプションにて Value= のように指定する。

$ aws elasticbeanstalk update-environment \
    --region=<リージョン> \
    --application-name=<アプリ名> \
    --environment-name=<環境名> \
    "Namespace=aws:elasticbeanstalk:application:environment,OptionName=CLI_ENV_2,Value="

$  aws elasticbeanstalk describe-configuration-settings \
    --region=<リージョン> \
    --application-name=<アプリ名> \
    --environment-name=<環境名> \
    jq -r '.ConfigurationSettings[0].OptionSettings | map(select(.Namespace == "aws:elasticbeanstalk:application:environment")) | .[] | [.OptionName, .Value] | @csv'
"CLI_ENV_1","CLI から設定した環境変数_1"
"CLI_ENV_2",""

AWS Elastic Beanstalk の環境変数AWS CLI で削除する

AWS Elastic Beanstalk の環境変数AWS CLI で削除するには、 update-environment コマンドの --options-to-remove オプションを指定する。

--options-to-remove オプションは以下のように指定する。

項目
Namespace aws:elasticbeanstalk:application:environment
OptionName 環境変数の名前

環境変数を削除する例。 環境変数 CLI_ENV_2 が削除されていることを確認できる。

$ aws elasticbeanstalk update-environment \
    --region=<リージョン> \
    --application-name=<アプリ名> \
    --environment-name=<環境名> \
    --options-to-remove \
    "Namespace=aws:elasticbeanstalk:application:environment,OptionName=CLI_ENV_2"

$ aws elasticbeanstalk describe-configuration-settings \
    --region=<リージョン> \
    --application-name=<アプリ名> \
    --environment-name=<環境名> \
    jq -r '.ConfigurationSettings[0].OptionSettings | map(select(.Namespace == "aws:elasticbeanstalk:application:environment")) | .[] | [.OptionName, .Value] | @csv'
"CLI_ENV_1","CLI から設定した環境変数_1"

おまけ: AWS Elastic Beanstalk の環境への変更が完了するまで待ち合わせる

AWS Elastic Beanstalk の環境への変更が完了するまで待ち合わせるには environment-updated コマンドを使う。

$ aws elasticbeanstalk wait environment-updated \
    --region=<リージョン> \
    --application-name=<アプリ名> \
    --environment-name=<環境名>

describe-environments コマンドとシェルコマンドを組み合わせて environment-updated コマンドと同じことをできるが、environment-updated コマンドを使うほうが楽だろう。

参考サイト