hclpack

package
v0.0.0-...-fb75b32 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 2, 2019 License: MPL-2.0 Imports: 12 Imported by: 3

Documentation

Overview

Package hclpack provides a straightforward representation of HCL block/body structure that can be easily serialized and deserialized for compact transmission (e.g. over a network) without transmitting the full source code.

Expressions are retained in native syntax source form so that their evaluation can be delayed until a package structure is decoded by some other system that has enough information to populate the evaluation context.

Packed structures retain source location information but do not retain actual source code. To make sense of source locations returned in diagnostics and via other APIs the caller must somehow gain access to the original source code that the packed representation was built from, which is a problem that must be solved somehow by the calling application.

Example (MarshalJSON)
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"

	"github.com/hashicorp/hcl2/hcl"
	"github.com/hashicorp/hcl2/hclpack"
)

func main() {
	src := `
	service "example" {
	  priority = 2
	  platform {
		os   = "linux"
		arch = "amd64"
	  }
	  process "web" {
	    exec = ["./webapp"]
	  }
	  process "worker" {
	    exec = ["./worker"]
	  }
	}
	`

	body, diags := hclpack.PackNativeFile([]byte(src), "example.svc", hcl.Pos{Line: 1, Column: 1})
	if diags.HasErrors() {
		fmt.Fprintf(os.Stderr, "Failed to parse: %s", diags.Error())
		return
	}

	jb, err := body.MarshalJSON()
	if err != nil {
		fmt.Fprintf(os.Stderr, "Failed to marshal: %s", err)
		return
	}

	// Normally the compact form is best, but we'll indent just for the sake
	// of this example so the result is readable.
	var buf bytes.Buffer
	json.Indent(&buf, jb, "", " ")
	os.Stdout.Write(buf.Bytes())

}
Output:

{
 "r": {
  "b": [
   {
    "h": [
     "service",
     "example"
    ],
    "b": {
     "a": {
      "priority": {
       "s": "2",
       "r": "ChAKDA4QDhA"
      }
     },
     "b": [
      {
       "h": [
        "platform"
       ],
       "b": {
        "a": {
         "arch": {
          "s": "\"amd64\"",
          "r": "IiwiJCYsKCo"
         },
         "os": {
          "s": "\"linux\"",
          "r": "FiAWGBogHB4"
         }
        },
        "r": "Li4"
       },
       "r": "EhQSFA"
      },
      {
       "h": [
        "process",
        "web"
       ],
       "b": {
        "a": {
         "exec": {
          "s": "[\"./webapp\"]",
          "r": "OEA4OjxAPD4"
         }
        },
        "r": "QkI"
       },
       "r": "MDYwMjQ2"
      },
      {
       "h": [
        "process",
        "worker"
       ],
       "b": {
        "a": {
         "exec": {
          "s": "[\"./worker\"]",
          "r": "TFRMTlBUUFI"
         }
        },
        "r": "VlY"
       },
       "r": "REpERkhK"
      }
     ],
     "r": "WFg"
    },
    "r": "AggCBAYI"
   }
  ],
  "r": "Wlo"
 },
 "s": [
  "example.svc"
 ],
 "p": "BAQEAA4OAAICABISAggMABAQAAYGAAICAggIABAQAgYKAAQEAAoKAAICAAoKAAICAgYGAAgIAAYGAAICAAoKAAICAgoKAggIAA4OAAICAAoKAgwQAAgIAAYGAAICABYWAgoKAggIAA4OAAICABAQAgwQAAgIAAYGAAICABYWAgoKAgYGAgQE"
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Attribute

type Attribute struct {
	Expr Expression

	Range, NameRange hcl.Range
}

Attribute represents an attribute definition within a body.

type Block

type Block struct {
	Type   string
	Labels []string
	Body   Body

	DefRange, TypeRange hcl.Range
	LabelRanges         []hcl.Range
}

Block represents a nested block within a body.

type Body

type Body struct {
	Attributes  map[string]Attribute
	ChildBlocks []Block

	MissingItemRange_ hcl.Range
}

Body is an implementation of hcl.Body.

func PackNativeFile

func PackNativeFile(src []byte, filename string, start hcl.Pos) (*Body, hcl.Diagnostics)

PackNativeFile parses the given source code as HCL native syntax and packs it into a hclpack Body ready to be marshalled.

If the given source code contains syntax errors then error diagnostics will be returned. A non-nil body might still be returned in this case, which allows a cautious caller to still do certain analyses on the result.

func (*Body) Content

func (b *Body) Content(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Diagnostics)

Content is an implementation of the method of the same name on hcl.Body.

When Content is called directly on a hclpack.Body, all child block bodies are guaranteed to be of type *hclpack.Body, so callers can type-assert to obtain a child Body in order to serialize it separately if needed.

func (*Body) JustAttributes

func (b *Body) JustAttributes() (hcl.Attributes, hcl.Diagnostics)

JustAttributes is an implementation of the method of the same name on hcl.Body.

func (*Body) MarshalJSON

func (b *Body) MarshalJSON() ([]byte, error)

MarshalJSON is an implementation of Marshaler from encoding/json, allowing bodies to be included in other types that are JSON-marshalable.

The result of MarshalJSON is optimized for compactness rather than easy human consumption/editing. Use UnmarshalJSON to decode it.

func (*Body) MissingItemRange

func (b *Body) MissingItemRange() hcl.Range

MissingItemRange is an implementation of the method of the same name on hcl.Body.

func (*Body) PartialContent

func (b *Body) PartialContent(schema *hcl.BodySchema) (*hcl.BodyContent, hcl.Body, hcl.Diagnostics)

PartialContent is an implementation of the method of the same name on hcl.Body.

The returned "remain" body may share some backing objects with the receiver, so neither the receiver nor the returned remain body, or any descendent objects within them, may be mutated after this method is used.

When Content is called directly on a hclpack.Body, all child block bodies and the returned "remain" body are guaranteed to be of type *hclpack.Body, so callers can type-assert to obtain a child Body in order to serialize it separately if needed.

func (*Body) UnmarshalJSON

func (b *Body) UnmarshalJSON(data []byte) error

UnmarshalJSON is an implementation of Unmarshaler from encoding/json, allowing bodies to be included in other types that are JSON-unmarshalable.

type ExprSourceType

type ExprSourceType rune

ExprSourceType defines the syntax type used for an expression's source code, which is then used to select a suitable parser for it when evaluating.

const (
	// ExprNative indicates that an expression must be parsed as native
	// expression syntax, with hclsyntax.ParseExpression.
	ExprNative ExprSourceType = 'N'

	// ExprTemplate indicates that an expression must be parsed as native
	// template syntax, with hclsyntax.ParseTemplate.
	ExprTemplate ExprSourceType = 'T'

	// ExprLiteralJSON indicates that an expression must be parsed as JSON and
	// treated literally, using cty/json. This can be used when populating
	// literal attribute values from a non-HCL source.
	ExprLiteralJSON ExprSourceType = 'L'
)

func (ExprSourceType) String

func (i ExprSourceType) String() string

type Expression

type Expression struct {
	// Source is the raw source code of the expression, which should be parsed
	// as the syntax specified by SourceType.
	Source     []byte
	SourceType ExprSourceType

	// Range_ and StartRange_ describe the physical extents of the expression
	// in the original source code. SourceRange_ is its entire range while
	// StartRange is just the tokens that introduce the expression type. For
	// simple expression types, SourceRange and StartRange are identical.
	Range_, StartRange_ hcl.Range
}

Expression is an implementation of hcl.Expression in terms of some raw expression source code. The methods of this type will first parse the source code and then pass the call through to the real expression that is produced.

func (*Expression) Parse

func (e *Expression) Parse() (hcl.Expression, hcl.Diagnostics)

Parse attempts to parse the source code of the receiving expression using its indicated source type, returning the expression if possible and any diagnostics produced during parsing.

func (*Expression) Range

func (e *Expression) Range() hcl.Range

func (*Expression) StartRange

func (e *Expression) StartRange() hcl.Range

func (*Expression) UnwrapExpression

func (e *Expression) UnwrapExpression() hcl.Expression

UnwrapExpression parses and returns the underlying expression, if possible.

This is essentially the same as Parse but without the ability to return an error; it is here only to support the static analysis facilities in the main HCL package (ExprList, ExprMap, etc). If any error is encountered during parsing, the result is a static expression that always returns cty.DynamicVal.

This function does not impose any further conversions on the underlying expression, so the result may still not be suitable for the static analysis functions, depending on the source type of the expression and thus what type of physical expression it becomes after decoding.

func (*Expression) Value

func (e *Expression) Value(ctx *hcl.EvalContext) (cty.Value, hcl.Diagnostics)

Value implements the Value method of hcl.Expression but with the additional step of first parsing the expression source code. This implementation is unusual in that it can potentially return syntax errors, whereas other Value implementations usually work with already-parsed expressions.

func (*Expression) Variables

func (e *Expression) Variables() []hcl.Traversal

Variables implements the Variables method of hcl.Expression but with the additional step of first parsing the expression source code.

Since this method cannot return errors, it will return a nil slice if parsing fails, indicating that no variables are present. This is okay in practice because a subsequent call to Value would fail with syntax errors regardless of what variables are in the context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL