hcledit

repository·master·Indexed 20 days ago

https://github.com/minamijoyo/hcledit

A command-line tool for editing HCL2 (HashiCorp Configuration Language) files, designed for automation and refactoring. It provides a schemaless, token-based approach to manipulate attributes and blocks via dot-notation addresses without losing comments. Key features include attribute manipulation (set, get, mv, rm, replace, append), block management (new, rm, mv, list, append), body retrieval, and HCL formatting.

Tokens
3.6K
Snippets
27
Records
29
Agent score
67%

What's inside hcledit

  1. Overview of hcledit features

    master

    hcledit is a CLI-friendly, schemaless HCL2 editor designed for automation and refactoring (e.g., Terraform configurations).

    Key features:

    • Token-based editing: Updates HCL files without losing existing comments.
    • CLI-first: Reads from stdin and writes to stdout by default, making it easy to pipe commands.
    • Schemaless: Does not depend on a specific HCL application schema.
    • Operations: Supports attribute manipulation (append, get, mv, replace, rm, set), block manipulation (append, get, list, mv, new, rm), body retrieval, and formatting.
  2. Escape dots in HCL addresses

    master

    When an HCL label contains a literal dot (.), you must escape it with a backslash (\) in the command-line address to prevent the parser from treating it as a hierarchy separator.

    Example: If you have a resource named resource "foo.bar":

    cat tmp/attr.hcl | hcledit attribute get 'resource.foo\.bar.nested.attr2'
    cat tmp/attr.hcl | hcledit attribute get 'resource.foo\.bar.nested.attr2'
  3. Install hcledit

    master

    You can install hcledit using Homebrew, by downloading pre-compiled binaries, or by building from source.

    ### Homebrew (macOS)
    ```bash
    $ brew install minamijoyo/hcledit/hcledit

    Source (Go 1.26+)

    $ git clone https://github.com/minamijoyo/hcledit
    $ cd hcledit/
    $ make install
    $ hcledit version
  4. Format HCL files with fmt

    master

    The fmt command formats an HCL file to a canonical style.

    Global Flags:

    • -f, --file <string>: Path to input file (defaults to - for stdin).
    • -u, --update: Update the file in-place.

    Example:

    cat tmp/fmt.hcl | hcledit fmt
    cat tmp/fmt.hcl | hcledit fmt
  5. Use hcledit body commands

    master

    The body command is used to retrieve the contents of a block's body.

    Available Commands:

    • get: Returns the HCL content inside the specified block address.

    Global Flags:

    • -f, --file <string>: Path to input file (defaults to - for stdin).
    • -u, --update: Update the file in-place.

    Example:

    cat tmp/body.hcl | hcledit body get resource.foo.bar
    cat tmp/body.hcl | hcledit body get resource.foo.bar
  6. Use hcledit block commands

    master

    The block command allows you to manage HCL blocks (like resource or module blocks) using dot-notation addresses.

    Available Commands:

    • append: Append a new block to an existing block. Use --newline for spacing.
    • get: Retrieve the entire content of a block.
    • list: List available blocks at a specific address.
    • mv: Rename a block (changes its type and labels).
    • new: Create a new empty block at a specific address.
    • rm: Remove a block.

    Global Flags:

    • -f, --file <string>: Path to input file (defaults to - for stdin).
    • -u, --update: Update the file in-place.

    Example: Listing and Getting blocks

    # List blocks
    cat tmp/block.hcl | hcledit block list
    
    # Get a specific block
    cat tmp/block.hcl | hcledit block get resource.foo.bar
    cat tmp/block.hcl | hcledit block list
  7. Use hcledit attribute commands

    master

    The attribute command allows you to manipulate individual attributes within an HCL file using dot-notation addresses.

    Available Commands:

    • append: Add an attribute. Use --newline to ensure proper spacing.
    • get: Retrieve the value of an attribute.
    • mv: Rename an attribute key.
    • replace: Change both the name and the value of an attribute.
    • rm: Remove an attribute.
    • set: Set or update an attribute value.

    Global Flags:

    • -f, --file <string>: Path to input file (defaults to - for stdin).
    • -u, --update: Update the file in-place.

    Example: Setting and Moving an attribute

    # Set an attribute
    cat tmp/attr.hcl | hcledit attribute set resource.foo.bar.nested.attr2 '"val3"'
    
    # Move (rename) an attribute
    cat tmp/attr.hcl | hcledit attribute mv resource.foo.bar.nested.attr2 resource.foo.bar.nested.attr3
    cat tmp/attr.hcl | hcledit attribute set resource.foo.bar.nested.attr2 '"val3"'
  8. Edit HCL files using Client.Edit

    master

    The Edit method reads a HCL file and applies a provided Filter.

    • filename: The path to the HCL file. Use "-" to read from the client's InStream (stdin).
    • update:
      • If true, the filtered output is written directly back to the input file.
      • If false, the filtered output is written to the client's OutStream (stdout).
    • filter: An implementation of the Filter interface used to modify the HCL content.
    // Example: Apply a filter and write the result to stdout instead of overwriting the file
    err := client.Edit("config.hcl", false, myFilter)
    if err != nil {
    	// handle error
    }
    
    // Example: Apply a filter and overwrite the original file
    err = client.Edit("config.hcl", true, myFilter)
  9. Derive HCL content using Client.Derive

    master

    The Derive method reads a HCL file and applies a Sink to generate new content.

    • filename: The path to the HCL file. Use "-" to read from the client's InStream (stdin).
    • sink: An implementation of the Sink interface that defines how the HCL data is transformed or extracted.
    • Output: The result is always written to the client's OutStream (stdout).
    // Example: Derive new content from an existing file and write to stdout
    err := client.Derive("input.hcl", mySink)
    if err != nil {
    	// handle error
    }
  10. Initialize a new hcledit Client

    master

    To programmatically edit or derive HCL files, create a new Client using NewClient(o *Option). The Option struct allows you to configure the input, output, and error streams used by the client.

    Use InStream for stdin, OutStream for stdout, and ErrStream for stderr.

    import (
    	"os"
    	"github.com/minamijoyo/minamijoyo/hcledit/editor"
    )
    
    func main() {
    	opts := &editor.Option{
    		InStream:  os.Stdin,
    		OutStream: os.Stdout,
    		ErrStream: os.Stderr,
    	}
    
    	client := editor.NewClient(opts)
    	// Use client.Edit or client.Derive here
    }
  11. Configure fmt command options

    master

    The fmt command uses the following configuration keys (accessible via flags or environment variables) to control its behavior:

    KeyTypeDescription
    filestringThe path to the HCL file to be formatted.
    updatebooleanIf true, the file will be updated in place.

    Note: These keys are managed via viper and are typically passed as flags to the hcledit binary.

  12. Configure Client streams with Option

    master

    The Option struct defines the I/O behavior for the Client:

    FieldTypeDescription
    InStreamio.ReaderThe source for stdin operations (used when filename is "-").
    OutStreamio.WriterThe destination for stdout operations.
    ErrStreamio.WriterThe destination for error reporting.
    type Option struct {
    	InStream  io.Reader
    	OutStream io.Writer
    	ErrStream io.Writer
    }