1

I am writing a HCL-based configuration language where some types of blocks can reference other blocks using expressions, as follows:

source "my_source" {
  // some blocks and attributes...

  to = destination.my_kafka_topic
}

destination "kafka" "my_kafka_topic" {
  // some blocks and attributes...
}

destination "elasticsearch" "my_es_index" {
  // some blocks and attributes...
}

(The goal is the model the flow of events in a messaging system, and then materialize the actual system in terms of infrastructure.)

During parsing, I simply perform a partial decoding of the static attributes and blocks and ensure "to" hcl.Attributes can be interpreted as hcl.Traversals, but don't evaluate them (yet).

type Source struct {
    Name string // first HCL tag

    /* ... */

    To hcl.Traversal
}

type Destination struct {
    Type string // first HCL tag
    Name string // second HCL tag

    /* ... */
}

Later, referenceable blocks (e.g. destination in the example above) are associated with a certain Go type based on their Type label, and this Go type always implements an interface called Referenceable.

type Referenceable interface {
    AsReference() *Destination
}

type Destination struct {
    // fields that represent the destination in terms of address, protocol, etc.
}

At that stage, I know how to build a map of referenceables map[string]Referenceable where the key is <block_type>.<block_name> (e.g. "destination.my_kafka_topic"), but I am unsure how to leverage that in an hcl.EvalContext in order to evaluate the variables to Go Referenceables.

What I would like to know is: how to express a Go interface in the cty type system used by hcl.EvalContext? Is is even possible? If not, is it advised to inject instances of *Destination in the hcl.EvalContext instead?

Antoine Cotten
  • 2,673
  • 18
  • 37

0 Answers0