All Projects → hashicorp → hcl-lang

hashicorp / hcl-lang

Licence: MPL-2.0 license
Schema and decoder to be used as building blocks for an HCL2-based language server.

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to hcl-lang

schemawax
🧬 Tiny typed data decoder—get to the DNA of your data
Stars: ✭ 45 (+2.27%)
Mutual labels:  schema, decoder
jsonnet-language-server
A Language Server Protocol (LSP) server for Jsonnet (https://jsonnet.org)
Stars: ✭ 55 (+25%)
Mutual labels:  language-server
element-schema-form
A schema-based element-ui form component for Vue2.x.
Stars: ✭ 31 (-29.55%)
Mutual labels:  schema
terraform-aws-cloudtrail
Terraform module to provision an AWS CloudTrail and an encrypted S3 bucket with versioning to store CloudTrail logs
Stars: ✭ 78 (+77.27%)
Mutual labels:  hcl2
schema-builder
Laravel/Lumen schema builder & migration generator
Stars: ✭ 51 (+15.91%)
Mutual labels:  schema
Mail
RiiConnect24 Mail Scripts. OSS.
Stars: ✭ 11 (-75%)
Mutual labels:  schema
terraform-external-module-artifact
Terraform module to fetch any kind of artifacts using curl (binary and text okay)
Stars: ✭ 13 (-70.45%)
Mutual labels:  hcl2
storage
Mongoose-like schema validation, collections and documents on browser (client-side)
Stars: ✭ 17 (-61.36%)
Mutual labels:  schema
schema.tl
📜 Easy-to-use TL-Schema viewer
Stars: ✭ 55 (+25%)
Mutual labels:  schema
graphql-directive-sql
Unify your SQL schema and your GraphQL Schema. Use GraphQL SDL as the lingua franca to define your data requirements.
Stars: ✭ 28 (-36.36%)
Mutual labels:  schema
encoding-html
A golang library for decoding html into structs
Stars: ✭ 29 (-34.09%)
Mutual labels:  decoder
vscode-caddyfile-support
Rich Caddyfile support for Visual Studio Code
Stars: ✭ 30 (-31.82%)
Mutual labels:  language-server
querymen
Querystring parser middleware for MongoDB, Express and Nodejs (MEN)
Stars: ✭ 128 (+190.91%)
Mutual labels:  schema
modelsafe
A type-safe data modelling library for TypeScript
Stars: ✭ 13 (-70.45%)
Mutual labels:  schema
cassandra-migration
Apache Cassandra / DataStax Enterprise database migration (schema evolution) library
Stars: ✭ 51 (+15.91%)
Mutual labels:  schema
SICP
✨practice for SICP, the wizard book < Structure and Interpretation of Computer Programs >
Stars: ✭ 89 (+102.27%)
Mutual labels:  schema
vscode-tenkawa-php
Visual Studio Code extension integrating Tenkawa PHP language server.
Stars: ✭ 28 (-36.36%)
Mutual labels:  language-server
ffmpeg-h264-dec
H.264 decoder extracted from FFmpeg.
Stars: ✭ 81 (+84.09%)
Mutual labels:  decoder
stardog-language-servers
Language Servers for Stardog Languages
Stars: ✭ 19 (-56.82%)
Mutual labels:  language-server
fix-decoder
Unravels FIX messages into human readable tables
Stars: ✭ 71 (+61.36%)
Mutual labels:  decoder

hcl-lang Go Reference

This library provides basic building blocks for an HCL2-based language server in the form of a schema and a decoder.

Current Status

This project is in use by the Terraform Language Server and it is designed to be used by any HCL2 language server, but it's still in early stage of development.

For that reason the API is not considered stable yet and should not be relied upon.

Breaking changes may be introduced.

What is HCL?

See https://github.com/hashicorp/hcl

What is a Language Server?

See https://microsoft.github.io/language-server-protocol/

What is Schema?

Schema plays an important role in most HCL2 deployments as it describes what to expect in the configuration (e.g. attribute or block names, their types etc.), which in turn provides predictability, static early validation and more.

Other Schemas

There are other known HCL schema implementations, e.g.:

These each have slightly different valid reasons to exist and they will likely continue to exist - i.e. no schema on that list (nor the one contained in this library) is meant to replace another, or at least it wasn't designed with that intention.

However in the interest of compatibility and adoption it's expected that some conversion mechanisms from/to the above schemas will emerge.

Schema

The schema package provides a way of describing schema for an HCL2 language.

For example (simplified Terraform provider block):

import (
	"github.com/hashicorp/hcl-lang/lang"
	"github.com/hashicorp/hcl-lang/schema"
	"github.com/zclconf/go-cty/cty"
)

var providerBlockSchema = &schema.BlockSchema{
	Labels: []*schema.LabelSchema{
		{
			Name:        "name",
			Description: lang.PlainText("Provider Name"),
			IsDepKey:    true,
		},
	},
	Description: lang.PlainText("A provider block is used to specify a provider configuration. The body of the block (between " +
		"{ and }) contains configuration arguments for the provider itself. Most arguments in this section are " +
		"specified by the provider itself."),
	Body: &schema.BodySchema{
		Attributes: map[string]*schema.AttributeSchema{
			"alias": {
				ValueType:   cty.String,
				Description: lang.PlainText("Alias for using the same provider with different configurations for different resources"),
			},
		},
	},
}

Dependent Body Schema

In most known complex HCL2 deployments (e.g. in Terraform, Nomad, Waypoint), schemas of some block bodies are defined partially by its type.

e.g. resource in Terraform in itself brings count attribute.

resource "..." "..." {
  count = 2
  
}

Other attributes or blocks are then defined by the block's labels or attributes.

e.g. 1st label + (optional) provider attribute in Terraform's resource brings all other attributes (such as ami or instance_type).

resource "aws_instance" "ref_name" {
  provider = aws.west

  # dependent attributes
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
}

Such schema can be represented using the DependentBody field of BlockSchema, for example:

var resourceBlockSchema = &schema.BlockSchema{
	Labels: []*schema.LabelSchema{
		{
			Name:        "type",
			Description: lang.PlainText("Resource type"),
		},
		{Name: "name"},
	},
	Body: &schema.BodySchema{
		Attributes: map[string]*schema.AttributeSchema{
			"count":      {ValueType: cty.Number},
			// ...
		},
	},
	DependentBody: map[schema.SchemaKey]*schema.BodySchema{
		schema.NewSchemaKey(schema.DependencyKeys{
			Labels: []schema.LabelDependent{
				{Index: 0, Value: "aws_instance"},
			},
		}): {
			Attributes: map[string]*schema.AttributeSchema{
				"ami":           {ValueType: cty.String},
				"instance_type": {ValueType: cty.String},
				// ...
			},
		},
	},
}

Nested DependentBody

It is discouraged from declaring DependentBody as part of another ("parent") DependentBody due to complexity (reduced readability of code).

This complex scenario is however supported and is used e.g. in Terraform for terraform_remote_state data block, where config attribute is dependent on backend value, which itself is dependent on the value of the 1st block label.

data "terraform_remote_state" "name" {
  backend = "local"

  config = {
    workspace_dir = "value"
  }
}

Such nested bodies have to declare full schema key, including labels.

Populating Dependent Body Schemas

It is expected for DependentBody to be populated based on the needs and capabilities of a particular tool.

For example in Terraform, dependent schemas come from providers (plugins) and these can be obtained via terraform providers schema -json (Terraform CLI 0.12+). In the future these may also be made available in the Terraform Registry, or from the provider binaries (via gRPC protocol).

hcl-lang does not care how any part of the schema is obtained or where from.

It expects SetSchema to be called either with full schema (including fully populated DependentBody), or SetSchema to be called repeatedly as more schema is known. The functionality will adapt to the amount of schema provided (e.g. label completion isn't available without DependentBody).

This means that the same configuration may need to be parsed and some minimal form of schema used for the first time, before the full schema is assembled and passed to hcl-lang's decoder for the second decoding stage.

terraform-config-inspect and terraform-schema represent examples of how this is done in Terraform.

Decoder

The decoder package provides a decoder which can be utilized by a language server.

d, err := NewDecoder()
if err != nil {
	// ...
}
d.SetSchema(schema)

// for each (known) file (e.g. any *.tf file in Terraform)
f, pDiags := hclsyntax.ParseConfig(configBytes, "example.tf", hcl.InitialPos)
if len(pDiags) > 0 {
	// ...
}
err = d.LoadFile("example.tf", f)
if err != nil {
	// ...
}

See available methods in the documentation.

Experimental Status

By using the software in this repository (the "Software"), you acknowledge that: (1) the Software is still in development, may change, and has not been released as a commercial product by HashiCorp and is not currently supported in any way by HashiCorp; (2) the Software is provided on an "as-is" basis, and may include bugs, errors, or other issues; (3) the Software is NOT INTENDED FOR PRODUCTION USE, use of the Software may result in unexpected results, loss of data, or other unexpected results, and HashiCorp disclaims any and all liability resulting from use of the Software; and (4) HashiCorp reserves all rights to make all decisions about the features, functionality and commercial release (or non-release) of the Software, at any time and without any obligation or liability whatsoever.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].