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/fm t.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/5d53f12cd944813ae3036a19650c68daacb6 150a/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/fm t.go#L87-L90 • それでも変数(Interpolation )はなんとか対応できたが、ifやforが含まれる場合(Directives)は対応で きていない ◦

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