Convert Figma logo to code with AI

hashicorp logohcl

HCL is the HashiCorp configuration language.

5,227
590
5,227
214

Top Related Projects

26,777

Go configuration with fangs

6,829

YAML support for the Go language.

4,531

TOML parser for Golang with reflection.

1,697

Go library for the TOML file format

A Go port of Ruby's dotenv library (Loads environment variables from .env files)

Golang library for managing configuration data from environment variables

Quick Overview

HCL (HashiCorp Configuration Language) is a structured configuration language developed by HashiCorp. It is designed to be both human-readable and machine-friendly, making it ideal for use in configuration files and data serialization. HCL is used extensively in HashiCorp products like Terraform and Consul.

Pros

  • Easy to read and write, with a syntax similar to JSON but more human-friendly
  • Supports comments, making it easier to document configuration files
  • Offers advanced features like interpolation, variables, and functions
  • Can be used as a general-purpose configuration language outside of HashiCorp products

Cons

  • Less widely adopted compared to formats like JSON or YAML
  • May require additional parsing libraries in some programming languages
  • Learning curve for users unfamiliar with HCL syntax
  • Limited built-in data types compared to some other configuration languages

Code Examples

  1. Basic structure and variable usage:
variable "region" {
  default = "us-west-2"
}

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  region        = var.region
}
  1. List and map usage:
variable "availability_zones" {
  type    = list(string)
  default = ["us-west-2a", "us-west-2b", "us-west-2c"]
}

variable "tags" {
  type = map(string)
  default = {
    Environment = "Production"
    Project     = "MyApp"
  }
}
  1. Conditional expressions:
resource "aws_instance" "example" {
  instance_type = var.environment == "production" ? "t2.medium" : "t2.micro"
  
  tags = {
    Name = var.name != "" ? var.name : "default-instance"
  }
}

Getting Started

To use HCL in your project, you can start by creating a file with a .hcl extension. Here's a simple example:

# my_config.hcl

app_name = "MyApp"

server {
  host = "localhost"
  port = 8080
}

database {
  url      = "postgres://user:password@localhost:5432/mydb"
  max_conn = 100
}

To parse this HCL file in Go, you can use the official HCL library:

package main

import (
    "fmt"
    "github.com/hashicorp/hcl/v2/hclsimple"
)

type Config struct {
    AppName  string `hcl:"app_name"`
    Server   Server `hcl:"server,block"`
    Database Database `hcl:"database,block"`
}

type Server struct {
    Host string `hcl:"host"`
    Port int    `hcl:"port"`
}

type Database struct {
    URL     string `hcl:"url"`
    MaxConn int    `hcl:"max_conn"`
}

func main() {
    var config Config
    err := hclsimple.DecodeFile("my_config.hcl", nil, &config)
    if err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", config)
}

This example demonstrates how to define a configuration structure and parse an HCL file into it using the hclsimple package.

Competitor Comparisons

26,777

Go configuration with fangs

Pros of Viper

  • Supports multiple configuration formats (JSON, TOML, YAML, HCL, etc.)
  • Provides live watching and automatic reloading of configuration files
  • Offers environment variable binding and command-line flag integration

Cons of Viper

  • More complex setup and usage compared to HCL's simplicity
  • Potential performance overhead due to its extensive feature set
  • May be overkill for projects with simple configuration needs

Code Comparison

HCL:

resource "aws_instance" "example" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

Viper:

viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
err := viper.ReadInConfig()
instanceType := viper.GetString("instance_type")

Summary

HCL is a dedicated configuration language with a focus on simplicity and readability, making it ideal for infrastructure-as-code scenarios. Viper, on the other hand, is a more comprehensive configuration solution for Go applications, offering flexibility and advanced features at the cost of increased complexity. The choice between the two depends on the specific needs of your project and the desired balance between simplicity and feature richness.

6,829

YAML support for the Go language.

Pros of yaml

  • Widely adopted and supported across multiple programming languages
  • Simple and human-readable syntax, especially for complex nested structures
  • Extensive documentation and community support

Cons of yaml

  • Less expressive than HCL for configuration-specific use cases
  • Potential security risks due to arbitrary code execution in some implementations
  • Stricter indentation rules can lead to formatting errors

Code Comparison

yaml:

server:
  host: localhost
  port: 8080
  database:
    name: mydb
    user: admin

HCL:

server {
  host = "localhost"
  port = 8080
  database {
    name = "mydb"
    user = "admin"
  }
}

Key Differences

  • Syntax: yaml uses indentation and colons, while HCL uses braces and equals signs
  • Typing: yaml has implicit typing, whereas HCL requires explicit type declarations for certain values
  • Use case: yaml is a general-purpose data serialization format, while HCL is specifically designed for configuration files

Conclusion

Both yaml and HCL have their strengths and are suitable for different scenarios. yaml excels in general data serialization and cross-language compatibility, while HCL offers a more tailored experience for configuration management, particularly in HashiCorp's ecosystem.

4,531

TOML parser for Golang with reflection.

Pros of TOML

  • Simpler syntax, easier to read and write for non-programmers
  • Widely adopted standard with implementations in many languages
  • Better support for complex data structures like arrays of tables

Cons of TOML

  • Less flexible for configuration-as-code scenarios
  • Limited support for dynamic expressions or interpolation
  • May require more verbose syntax for deeply nested structures

Code Comparison

TOML:

[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true

HCL:

database {
  server = "192.168.1.1"
  ports = [8001, 8001, 8002]
  connection_max = 5000
  enabled = true
}

Both HCL and TOML are configuration languages, but they serve different purposes. TOML is designed for simplicity and readability, making it ideal for configuration files that need to be edited by humans. It's widely adopted and has a standardized specification.

HCL, on the other hand, is more powerful and flexible, designed specifically for infrastructure-as-code scenarios. It supports features like dynamic expressions and interpolation, which are crucial for complex configuration management tasks.

While TOML excels in straightforward configuration scenarios, HCL shines in more complex, programmatic environments where configuration and code intersect. The choice between them depends on the specific needs of the project and the target audience for the configuration files.

1,697

Go library for the TOML file format

Pros of go-toml

  • Simpler syntax and easier to read for basic configurations
  • Better support for TOML specification compliance
  • Faster parsing and encoding performance for TOML files

Cons of go-toml

  • Less flexible for complex configurations
  • Limited support for custom data types and structures
  • Fewer advanced features compared to HCL's rich functionality

Code Comparison

go-toml:

[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true

HCL:

database {
  server = "192.168.1.1"
  ports = [8001, 8001, 8002]
  connection_max = 5000
  enabled = true
}

Summary

go-toml is ideal for simpler configurations and strict TOML compliance, while HCL offers more flexibility and advanced features for complex configurations. go-toml excels in performance and readability for basic use cases, but HCL provides more powerful tools for sophisticated configuration needs. The choice between the two depends on the specific requirements of the project and the desired balance between simplicity and flexibility.

A Go port of Ruby's dotenv library (Loads environment variables from .env files)

Pros of godotenv

  • Simpler and more lightweight, focusing solely on environment variable management
  • Easy to use with minimal setup required
  • Follows the widely-used .env file format, making it familiar to developers from various backgrounds

Cons of godotenv

  • Limited functionality compared to HCL's more comprehensive configuration capabilities
  • Less suitable for complex configuration scenarios or hierarchical data structures
  • Lacks advanced features like variable interpolation and multi-file support

Code Comparison

godotenv:

import "github.com/joho/godotenv"

err := godotenv.Load()
if err != nil {
    log.Fatal("Error loading .env file")
}

HCL:

import "github.com/hashicorp/hcl/v2/hclsimple"

type Config struct {
    Name    string `hcl:"name"`
    Version string `hcl:"version"`
}

var config Config
err := hclsimple.DecodeFile("config.hcl", nil, &config)
if err != nil {
    log.Fatalf("Failed to load configuration: %s", err)
}

godotenv is ideal for simple environment variable management, while HCL offers a more powerful and flexible configuration solution for complex applications. godotenv is easier to set up and use, but HCL provides advanced features like variable interpolation and structured data representation. Choose godotenv for straightforward environment variable handling, and HCL for more sophisticated configuration needs in larger projects.

Golang library for managing configuration data from environment variables

Pros of envconfig

  • Simpler and more lightweight, focusing solely on environment variable configuration
  • Easier to use for basic configuration needs, with less setup required
  • Directly maps environment variables to struct fields, reducing boilerplate code

Cons of envconfig

  • Less flexible for complex configuration scenarios
  • Limited to environment variables, lacking support for other configuration sources
  • Fewer advanced features compared to HCL (e.g., no interpolation or functions)

Code Comparison

envconfig:

type Config struct {
    Host string `envconfig:"HOST"`
    Port int    `envconfig:"PORT"`
}

var c Config
err := envconfig.Process("myapp", &c)

HCL:

config {
    host = "localhost"
    port = 8080
}
type Config struct {
    Host string `hcl:"host"`
    Port int    `hcl:"port"`
}

var c Config
err := hcl.Decode(&c, hclBytes)

Summary

envconfig is a simpler solution for environment variable-based configuration, while HCL offers a more comprehensive and flexible configuration language. envconfig is ideal for projects with straightforward configuration needs, whereas HCL is better suited for complex configurations and supports multiple data sources.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

HCL

HCL is a toolkit for creating structured configuration languages that are both human- and machine-friendly, for use with command-line tools. Although intended to be generally useful, it is primarily targeted towards devops tools, servers, etc.

NOTE: This is major version 2 of HCL, whose Go API is incompatible with major version 1. Both versions are available for selection in Go Modules projects. HCL 2 cannot be imported from Go projects that are not using Go Modules. For more information, see our version selection guide.

HCL has both a native syntax, intended to be pleasant to read and write for humans, and a JSON-based variant that is easier for machines to generate and parse.

The HCL native syntax is inspired by libucl, nginx configuration, and others.

It includes an expression syntax that allows basic inline computation and, with support from the calling application, use of variables and functions for more dynamic configuration languages.

HCL provides a set of constructs that can be used by a calling application to construct a configuration language. The application defines which attribute names and nested block types are expected, and HCL parses the configuration file, verifies that it conforms to the expected structure, and returns high-level objects that the application can use for further processing.

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)
}

A lower-level API is available for applications that need more control over the parsing, decoding, and evaluation of configuration. For more information, see the package documentation.

Why?

Newcomers to HCL often ask: why not JSON, YAML, etc?

Whereas JSON and YAML are formats for serializing data structures, HCL is a syntax and API specifically designed for building structured configuration formats.

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 syntax is designed to be easily read and written by humans, and allows declarative logic to permit its use in more complex applications.

HCL is intended as a base syntax for configuration formats built around key-value pairs and hierarchical blocks whose structure is well-defined by the calling application, and this definition of the configuration structure allows for better error messages and more convenient definition within the calling application.

It can't be denied that JSON is very convenient as a lingua franca for interoperability between different pieces of software. Because of this, HCL defines a common configuration model that can be parsed from either its native syntax or from a well-defined equivalent JSON structure. This allows configuration to be provided as a mixture of human-authored configuration files in the native syntax and machine-generated files in JSON.

Information Model and Syntax

HCL is built around two primary concepts: attributes and blocks. In native syntax, a configuration file for a hypothetical application might look something like this:

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"]
  }
}

The JSON equivalent of this configuration is the following:

{
  "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"]
          },
        }
      }
    }
  }
}

Regardless of which syntax is used, the API within the calling application is the same. It can either work directly with the low-level attributes and blocks, for more advanced use-cases, or it can use one of the decoder packages to declaratively extract into either Go structs or dynamic value structures.

Attribute values can be expressions as well as just literal values:

# Arithmetic with literals and application-provided variables
sum = 1 + addend

# String interpolation and templates
message = "Hello, ${name}!"

# Application-provided functions
shouty_message = upper(message)

Although JSON syntax doesn't permit direct use of expressions, the interpolation syntax allows use of arbitrary expressions within JSON strings:

{
  "sum": "${1 + addend}",
  "message": "Hello, ${name}!",
  "shouty_message": "${upper(message)}"
}

For more information, see the detailed specifications:

Changes in 2.0

Version 2.0 of HCL combines the features of HCL 1.0 with those of the interpolation language HIL to produce a single configuration language that supports arbitrary expressions.

This new version has a completely new parser and Go API, with no direct migration path. Although the syntax is similar, the implementation takes some very different approaches to improve on some "rough edges" that existed with the original implementation and to allow for more robust error handling.

It's possible to import both HCL 1 and HCL 2 into the same program using Go's semantic import versioning mechanism:

import (
    hcl1 "github.com/hashicorp/hcl"
    hcl2 "github.com/hashicorp/hcl/v2"
)

Acknowledgements

HCL was heavily inspired by libucl, by Vsevolod Stakhov.

HCL and HIL originate in HashiCorp Terraform, with the original parsers for each written by Mitchell Hashimoto.

The original HCL parser was ported to pure Go (from yacc) by Fatih Arslan. The structure-related portions of the new native syntax parser build on that work.

The original HIL parser was ported to pure Go (from yacc) by Martin Atkins. The expression-related portions of the new native syntax parser build on that work.

HCL 2, which merged the original HCL and HIL languages into this single new language, builds on design and prototyping work by Martin Atkins in zcl.