地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

mysqld_exporterはmy.cnfに$が入っていると変数展開しようとする

github.com

タイトルが全て

[client]
user="test"
password="aaa$bbb"

って感じで設定してある状態でmysqld_exporterを起動しようとするとパスワードが正しいとしても接続エラーとなる。回避策としてはMYSQLD_EXPORTER_PASSWORDを使うことで正しく動くようになる。

なんでこんな動きなの?

mysqld_exporterが使っているiniのパーサの設定がそうなっているため。これは無効にするオプションとかもmysqld_exporterでは現状提供されていないので$のような文字を使う場合は先ほど挙げた環境変数設定の一択となる。my.cnfを置くみたいなのって結構使う気がするんだけどこれで良いのか?と思った。ファイルシステムにファイルを置くみたいなのよりも環境変数で全部やりましょうという時代なのだろうか

github.com

issueを漁ったけど困ってそうな人は見つけられなかった。DSNでの設定も昔からあるっぽいのでmy.cnfでやる人は少数派なのかもしれない。

この処理はどこでやってるの?

github.com

ValueMapperが設定されている場合はの部分に一致する。そこで変数展開が行われる。

func (k *Key) transformValue(val string) string {
    if k.s.f.ValueMapper != nil {
        val = k.s.f.ValueMapper(val) // os.ExpandEnvが指定されているのでパスワードに$が入っていると展開しようとする
    }

    // Fail-fast if no indicate char found for recursive value
    if !strings.Contains(val, "%") {
        return val
    }
    for i := 0; i < depthValues; i++ {
        vr := varPattern.FindString(val)
        if len(vr) == 0 {
            break
        }

        // Take off leading '%(' and trailing ')s'.
        noption := vr[2 : len(vr)-2]

        // Search in the same section.
        // If not found or found the key itself, then search again in default section.
        nk, err := k.s.GetKey(noption)
        if err != nil || k == nk {
            nk, _ = k.s.f.Section("").GetKey(noption)
            if nk == nil {
                // Stop when no results found in the default section,
                // and returns the value as-is.
                break
            }
        }

        // Substitute by new value and take off leading '%(' and trailing ')s'.
        val = strings.Replace(val, vr, nk.value, -1)
    }
    return val
}