Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Parsing HCL/CUE / Fukuoka.go #21

Parsing HCL/CUE / Fukuoka.go #21

Ken’ichiro Oyama

March 11, 2025
Tweet

More Decks by Ken’ichiro Oyama

Other Decks in Technology

Transcript

  1. • HCL is a toolkit for creating structured configuration languages

    that are both human- and machine-friendly, for use with command-line tools. • Terraformの記述言語として有名 • HCL attempts to strike a compromise between generic serialization formats such as JSON and configuration formats built around full programming languages such as Ruby. ◦ HCLは、JSONのような汎用的なシリアライゼーション・フォーマットと、 Rubyのような完全なプログラミング言 語で構築されたコンフィギュレーション・フォーマットとの妥協点を見出そうとしている。 • HashiCorp Configuration Language ref: https://github.com/hashicorp/hcl HCL What is HCL/CUE 3
  2. • CUE is an open-source data validation language and inference

    engine with its roots in logic programming. • Types are values ◦ データ、スキーマ、検証、ポリシー制約を指定するための単一言語 ▪ (設定などの)構造データと、そのデータの構造を同時に定義することができる • Configure(設定)、Unify(統一)、Execute(実行) ref: https://cuelang.org/ CUE What is HCL/CUE 4
  3. • Tailor Platform is a backend platform that enables enterprises

    to create tailor-made business tools that perfectly match their unique requirements, amazingly fast. ◦ ローコードでヘッドレスな業務アプリケーションバックエンドを構築できるプラットフォーム • Tailor DB / Auth / Pipeline / StateFlow / Executor / Function などのサービスとそれぞれでトリガーされる Events を使用してスケーラブルなインフ ラも含めたアプリケーションを構築できる • 構成の全てをTerraform、もしくはCUEで の管理が可能 ref: https://docs.tailor.tech Tailor Platform 7
  4. • Tailor PlatformではロジックとしてJavaScriptやCELが記述でき、GraphQLで一連の操作を繋げた Query/Mutation(やそれに必要なDSL)を新たに定義することができる。 • terraform fmt や cue fmt

    はHCL/CUEシンタックスの範囲においては整形してくれるが、 ヒアドキュメントの中 の文字列は対象外。 • JavaScriptやGraphQLを外部ファイルにすることは可能だが、ヒアドキュメントで書く選択肢も持ちたい。 • HCL/CUEファイルシンタックス内のヒアドキュメントに対して、任意のフォーマッタ(例えば prettier)を適用したい。 1. HCL/CUEファイルシンタックス内の文字列それぞれにフォー マッタを適用したい 解決したかった課題 9
  5. • hclstr is a utility tool for string literals in

    HCL files. ◦ https://github.com/k1LoW/hclstr • cuestr is a utility tool for string literals in CUE files. ◦ https://github.com/k1LoW/cuestr • HCL/CUE内の文字列に対して任意のフォーマッタを適用しつつ HCL/CUEのフォーマットも実施するCLIツール 1. hclstr / cuestr Implementation 13
  6. • tbls driver for TailorDB schema definition ◦ https://github.com/k1LoW/tbls-driver-tailordb •

    Terraform/CUEで定義されたTailor Platformアプリケーション内のTailor DBの定義を元にスキーマ情報を作成し tblsに渡すExternal database driver。 ◦ External database driver is ... ▪ tbls-driver-foodb という実行バイナリをPATHに置いてくとtblsが foodb:// スキームを受け 取った時に tbls-driver-foodb にDSNを渡す。 ▪ External database driver は受け取ったDSNから標準出力経由で schema.json を返す。 ▪ schema.jsonを元にtblsは例えば doc コマンドでドキュメント生成をする。 2. tbls-driver-tailordb Implementation 14
  7. 16 1. HCL/CUEファイルシンタックス内の文字列それぞれにフォーマッタを適用したい 課題ごとのパースパッケージへの要求 1/2 • 「文字列それぞれ」 ◦ 構造は意識する必要がない。しかしどのフィールドの文字列なのかは知りたい。 •

    「フォーマッタを適用したい」 ◦ パースした結果を修正し、 再度HCL/CUEファイルとして書き出したい。 • 「文字列それぞれにフォーマッタを適用したい」 ◦ 変数展開や式評価の必要はないが フォーマッタが理解できるように整形する必要がある。
  8. 17 2. Tailor DBのデータベーススキーマドキュメントを生成したい 課題ごとのパースパッケージへの要求 2/2 • 「Tailor DBの定義を元に」 ◦

    構造化された意味のある情報として取得したい。 • 「スキーマ情報を作成」 ◦ HCL/CUEファイルを操作するわけではない。 Read Only。 • 「スキーマ情報を作成」 ◦ ワークスペース内の情報で 変数展開や式評価はできる限りする必要がある 。
  9. 19 1. HCL/CUEファイルシンタックス内の文字列それぞれにフォーマッタを適用したい 実装時のパースパッケージ利用 1/2 1. ASTを filepath.WalkDir のように走査する関数や、 Visitorパターンを実装しているパッケージや関数を探す。

    走査途中で書き換えが可能なものが望ましい。 2. 上記が難しければ他の方法を探す • HCL HCLを書き換えるパッケージとして github.com/hashicorp/hcl/v2/hclwrite があるのでこれを中心に実装 ◦ 再帰的に走査しながら書き換える関数を自作 ◦ github.com/hashicorp/hcl/v2/hclsyntax.Walk や github.com/hashicorp/hcl/v2/hclsyntax.VisitAll は今回は使用せず(hclwriteの検証をしていたらそのまま実装できた) • CUE cuelang.org/go/cue/ast func Walk(node Node, before func(Node) bool, after func(Node)) で走査しながら書き換える ◦ https://github.com/k1LoW/cuestr/blob/6d81945edf2dee6d73b4307b4adc77eb8fdd0619/fmt/f mt.go#L48L128
  10. 20 2. Tailor DBのデータベーススキーマドキュメントを生成したい 実装時のパースパッケージ利用 2/2 1. json.Unmarshal のような、構造体に変換してくれる関数を探す •

    HCL hcl.Body.PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics) で想定しているデータ構造 ( schema )と値を取得する ◦ https://github.com/k1LoW/tbls-driver-tailordb/blob/5d53f12cd944813ae3036a19650c68daacb 6150a/tailordb/tf/tf.go#L136L271 • CUE func (v cue.Value) Decode(x interface{}) error や func (v cue.Value) LookupPath(p cue.Path) cue.Value を駆使して想定しているデータ構造 ( x )と値を取得する ◦ https://github.com/k1LoW/tbls-driver-tailordb/blob/main/tailordb/cue/cue.go#L122L236
  11. • 正直置換しか思いつかなかった ◦ https://github.com/k1LoW/cuestr/blob/6d81945edf2dee6d73b4307b4adc77eb8fdd0619/fmt/f mt.go#L87L90 • それでも変数(Interpolation )はなんとか対応できたが、 ifやforが含まれる場合(Directives )は対応できていない

    ◦ ref: https://developer.hashicorp.com/terraform/language/expressions/strings • 何かアイデアがあれば是非 HCL/CUEの変数や式が埋め込まれているヒアドキュメントの フォーマット Appendix 24