小ネタ:runnでローカルに立てたPostgreSQLサーバーに接続するテストを行う
yamlでテストシナリオを書いてそのまま実行までできるAPIテストツールの新星 “runn” を試してみた
で紹介したシナリオテストツール"runn"ですが、DBに対するテストも行えるようです。
今回はローカルに立てたPostgreSQLサーバーに接続しようとしてちょっと躓いたので、その対象方法を紹介します。
何がおきた?
公式の以下の箇所の記述を元に、ローカルに立てたPostgreSQLサーバーに接続しようとしました。
https://github.com/k1LoW/runn?tab=readme-ov-file#db-runner-query-a-database
書いたrunbookがこちらです。
desc: データベースを初期化する runners: db: postgres://user:password@localhost:5432/dbname steps: - desc: 接続確認 db: query: SELECT 1 dump: current.rows[0]
そして実行結果がこちらです。
$ runn run db-connect-fail.yaml --debug Run "接続確認" on "データベースを初期化する".steps[0] F 1) db-connect-fail.yaml bfcc572a0de6f7cbba77abdd77d99d73428aa5e1 Failure/Error: db query failed on "データベースを初期化する".steps[0]: pq: SSL is not enabled on the server Failure step (db-connect-fail.yaml): 5 - 6 desc: 接続確認 7 db: 8 query: SELECT 1 9 dump: current.rows[0] 1 scenario, 0 skipped, 1 failure
エラーの内容をよく見てみると、
pq: SSL is not enabled on the server
とあるので、SSLを使わないDB接続をする必要があるようです。
解決への道
問題を解決するため、まずはrunnのドキュメントを探してみましたが、それらしきものは見つかりませんでした。
となると、runnはOSSですので、実際にDB接続周りのコードを読むのが早そうです。早速見てみましょう。
まず、DB Runnerの定義はこちらのようです。
https://github.com/k1LoW/runn/blob/main/db.go#L40-L46
type dbRunner struct { name string dsn string client TxQuerier hostRules hostRules trace *bool }
DB接続には dsn
というフィールドが使われそうなことが見て取れます。
次に、このdsn
を使う箇所を探してみましょう。すると、DBRunner構造体を作成するタイミングで、 dburl.Parse(dsn)
という処理でパースが行われているようです。
https://github.com/k1LoW/runn/blob/main/db.go#L60-L69
func newDBRunner(name, dsn string) (*dbRunner, error) { _, err := dburl.Parse(dsn) if err != nil { return nil, err } return &dbRunner{ name: name, dsn: dsn, }, nil }
では、dburl
とは何なのか?と思ってコードを検索すると、 github.com/xo/dburl
というパッケージのようです。
https://github.com/k1LoW/runn/blob/main/db.go#L3-L23
import ( "context" "database/sql" "errors" "fmt" "reflect" "strconv" "strings" "sync/atomic" "unsafe" "github.com/araddon/dateparse" _ "github.com/go-sql-driver/mysql" "github.com/goccy/go-json" "github.com/golang-sql/sqlexp" "github.com/golang-sql/sqlexp/nest" _ "github.com/googleapis/go-sql-spanner" _ "github.com/lib/pq" "github.com/xo/dburl" "modernc.org/sqlite" )
GoのプログラムはGitHubリポジトリのパッケージを参照する文化があるので、パッケージ名を元にリポジトリを見てみましょう。
dburlリポジトリのREADMEを見ると、Quickstartにそのものズバリの記載がありました。
import ( "github.com/xo/dburl" ) u, err := dburl.Parse("postgresql://user:pass@localhost/mydatabase/?sslmode=disable") if err != nil { /* ... */ }
dsnの最後に?sslmode=disable
を追加すればいけそうです。
やってみた
ということで、runbookに反映してやってみましょう。
desc: データベースを初期化する runners: db: postgres://postgres:password@localhost:5433/pzx?sslmode=disable steps: - desc: 接続確認 db: query: SELECT 1 dump: current.rows[0]
実行結果がこちらです。
$ runn run db-connect-success.yaml --debug Run "接続確認" on "データベースを初期化する".steps[0] -----START QUERY----- SELECT 1 -----END QUERY----- -----START QUERY RESULT----- +----------+ | ?column? | +----------+ | 1 | +----------+ (1 row) -----END QUERY RESULT----- Run "dump" on "データベースを初期化する".steps[0] { "?column?": 1 } . 1 scenario, 0 skipped, 0 failures
無事、DB接続できて、SQLが実行できたようです。
まとめ
というわけで、「やってみた」ところ問題にぶつかったので、原因を探して対処してみました。 runnはOSSということで、なにか問題があったときに自分でコードを読みに行くことで対処できるのは、やっぱり良いですね。
今後もrunnを使いながら、なにか見つけたら順次ブログにしていきます。
余談:sslmodeの正体
https://github.com/xo/dburl?tab=readme-ov-file#database-schemes-aliases-and-drivers
を見ると、dburl
がPostgreSQLの接続に利用しているのは、github.com/lib/pg
というパッケージのようです。
このリポジトリ内を検索したところ、libpg
と同様にPostgreSQLの接続パラメータが指定できると記載がありました。
https://github.com/lib/pq/blob/3d613208bca2e74f2a20e04126ed30bcb5c4cc27/doc.go#L42-L59
For compatibility with libpq, the following special connection parameters are supported: * dbname - The name of the database to connect to * user - The user to sign in as * password - The user's password * host - The host to connect to. Values that start with / are for unix domain sockets. (default is localhost) * port - The port to bind to. (default is 5432) * sslmode - Whether or not to use SSL (default is require, this is not the default for libpq) * fallback_application_name - An application_name to fall back to if one isn't provided. * connect_timeout - Maximum wait for connection, in seconds. Zero or not specified means wait indefinitely. * sslcert - Cert file location. The file must contain PEM encoded data. * sslkey - Key file location. The file must contain PEM encoded data. * sslrootcert - The location of the root certificate file. The file must contain PEM encoded data.
これを受けて、libpq
のドキュメントを探したところ、指定できる値にちゃんと記載がありました。
表 31-1. SSLモードの説明 ー SSLサポート ー 第 31章libpq - C ライブラリ ー PostgreSQL 9.4.5文書