HCLは、コマンドラインツールで使用するために、人間と機械に優しい構造化された構成言語を作成するためのツールキットです。一般的に有用であることを意図していますが、主にDevOpsツール、サーバーなどをターゲットにしています。
注:これはHCLのメジャーバージョン2であり、GO APIはメジャーバージョン1と互換性がありません。どちらのバージョンもGOモジュールプロジェクトで選択できます。 HCL 2は、GOモジュールを使用していないGOプロジェクトからインポートすることはできません。詳細については、バージョン選択ガイドを参照してください。
HCLには、人間のために読み書きを快適にすることを目的としたネイティブの構文と、マシンが生成して解析しやすいJSONベースのバリアントの両方があります。
HCLネイティブの構文は、Libucl、Nginx構成などに触発されています。
基本的なインライン計算を可能にする式構文と、呼び出しアプリケーションからのサポート、より動的な構成言語の変数の使用と関数が含まれます。
HCLは、呼び出しアプリケーションで使用して構成言語を構築するために使用できる一連のコンストラクトを提供します。アプリケーションは、どの属性名とネストされたブロックタイプが予想されるかを定義し、HCLは構成ファイルを解析し、予想される構造に適合することを確認し、アプリケーションがさらなる処理に使用できる高レベルのオブジェクトを返します。
package main
import (
"log"
"github.com/hashicorp/hcl/v2/hclsimple"
)
type Config struct {
IOMode string `hcl:"io_mode"`
Service ServiceConfig `hcl:"service,block"`
}
type ServiceConfig struct {
Protocol string `hcl:"protocol,label"`
Type string `hcl:"type,label"`
ListenAddr string `hcl:"listen_addr"`
Processes [] ProcessConfig `hcl:"process,block"`
}
type ProcessConfig struct {
Type string `hcl:"type,label"`
Command [] string `hcl:"command"`
}
func main () {
var config Config
err := hclsimple . DecodeFile ( "config.hcl" , nil , & config )
if err != nil {
log . Fatalf ( "Failed to load configuration: %s" , err )
}
log . Printf ( "Configuration is %#v" , config )
}
低レベルのAPIは、構成の解析、デコード、評価をより強化する必要があるアプリケーションで使用できます。詳細については、パッケージのドキュメントを参照してください。
HCLの新人はしばしば尋ねます:なぜJSON、YAMLなどではないのですか?
JSONとYAMLは、データ構造をシリアル化するための形式ですが、HCLは構造化された構成形式を構築するために特別に設計された構文とAPIです。
HCLは、JSONなどの一般的なシリアル化形式と、Rubyなどの完全なプログラミング言語を中心に構築された構成形式の間で妥協を試みます。 HCL構文は、人間によって簡単に読み書きされるように設計されており、宣言的なロジックがより複雑なアプリケーションでの使用を可能にすることができます。
HCLは、構造が呼び出しアプリケーションによって明確に定義されているキー価値のペアと階層ブロックを中心に構築された構成形式のベース構文として意図されており、この構成構造のこの定義により、呼び出しアプリケーション内のより良いエラーメッセージとより便利な定義が可能になります。 。
JSONは、異なるソフトウェア間の相互運用性のためのLingua Francaとして非常に便利であることを否定することはできません。このため、HCLは、ネイティブの構文または明確に定義された同等のJSON構造のいずれかから解析できる共通の構成モデルを定義します。これにより、JSONのネイティブ構文と機械で生成されたファイルのヒューマン著作権構成ファイルの混合として構成を提供できます。
HCLは、属性とブロックの2つの主要な概念を中心に構築されています。ネイティブの構文では、仮想アプリケーション用の構成ファイルは次のようになる場合があります。
io_mode = " async "
service "http" "web_proxy" {
listen_addr = " 127.0.0.1:8080 "
process "main" {
command = [ " /usr/local/bin/awesome-app " , " server " ]
}
process "mgmt" {
command = [ " /usr/local/bin/awesome-app " , " mgmt " ]
}
}
この構成に相当するJSONは次のとおりです。
{
"io_mode" : " async " ,
"service" : {
"http" : {
"web_proxy" : {
"listen_addr" : " 127.0.0.1:8080 " ,
"process" : {
"main" : {
"command" : [ " /usr/local/bin/awesome-app " , " server " ]
},
"mgmt" : {
"command" : [ " /usr/local/bin/awesome-app " , " mgmt " ]
},
}
}
}
}
}
どの構文が使用されているかに関係なく、呼び出しアプリケーション内のAPIは同じです。より高度なユースケースのために、低レベルの属性とブロックで直接動作するか、デコーダーパッケージのいずれかを使用してGO構造体または動的値構造のいずれかに宣言的に抽出することができます。
属性値は、式と文字通りの値だけでなく、
# Arithmetic with literals and application-provided variables
sum = 1 + addend
# String interpolation and templates
message = " Hello, ${ name } ! "
# Application-provided functions
shouty_message = upper (message)
JSON構文では式の直接的な使用は許可されていませんが、補間構文により、JSON文字列内の任意の式を使用できます。
{
"sum" : " ${1 + addend} " ,
"message" : " Hello, ${name}! " ,
"shouty_message" : " ${upper(message)} "
}
詳細については、詳細な仕様を参照してください。
HCLのバージョン2.0は、HCL 1.0の機能と補間言語HILの機能を組み合わせて、任意の表現をサポートする単一の構成言語を作成します。
この新しいバージョンには、まったく新しいパーサーとGo APIがあり、直接移行パスはありません。構文は似ていますが、実装は、元の実装で存在する「ラフなエッジ」を改善し、より堅牢なエラー処理を可能にするために、いくつかの非常に異なるアプローチを取ります。
Goのセマンティックインポートバージョンメカニズムを使用して、HCL 1とHCL 2の両方を同じプログラムにインポートすることができます。
import (
hcl1 "github.com/hashicorp/hcl"
hcl2 "github.com/hashicorp/hcl/v2"
)
HCLは、Vsevolod Stakhovに重度に触発されました。
HCLとHILは、ミッチェルハシモトによって書かれた各パーサーで、ハシコープテラフォームに由来します。
元のHCLパーサーは、Fatih ArslanによってPure Go(YACCから)に移植されました。新しいネイティブ構文パーサーの構造関連部分は、その作業に基づいて構築されています。
元のヒルパーサーは、マーティンアトキンスによって純粋なGo(YACCから)に移植されました。新しいネイティブ構文パーサーの式に関連する部分は、その作業に基づいて構築されています。
元のHCL言語とHIL言語をこの単一の新しい言語に統合したHCL 2は、ZCLのMartin Atkinsによる設計およびプロトタイピング作業に基づいています。