Skip to content

Reference<T>: Type safe "deferred" references #912

@HT154

Description

@HT154

One common pattern in infrastructure-as-code systems like Terraform and Pulumi is "references". A reference provides a way to refer to a resource (or a property thereof) that exists at a time after Pkl evaluation completes.

Example: The pulumi aws-yaml-static-website example creates a aws:s3:BucketV2 and creates a aws:s3:BucketPolicy that both directly references the bucket and a property of the bucket (its arn). In the case of the Pulumi YAML runtime, references are rendered as String sequences beginning with ${ and ending with }.

It would be useful for a Pkl module representing the aws:s3:BucketPolicy resource to define its bucket like so:

bucket: String | // accept a bucket name directly
  Reference<String> | // accept a reference to a string, possibly from another resource or function's output
  Reference<Resource> // accept a reference to a aws:s3:BucketV2 or another resource, using its ID (a String)

There should be an API within the standard library for representing and producing such references. How a reference is rendered or otherwise consumed would be module-dependent. At minimum, the Reference API should look something like this:

// members must be functions to avoid ambiguities between reading reference info and construction property "sub-references"
class Reference<T> {
  /// The Class that this underlying Reference points to.
  function getRootClass(): Class<T>

  /// The concrete value of the "root" of the reference.
  function getRootData(): Any

  /// The "path" of properties/keys referenced from the "root" value.
  function getPath(): List<PropertyReference|SubscriptReference>
}

class PropertyReference {
  property: String
}

class SubscriptReference {
  key: Any
}

function Reference<T>(root: T): Reference<T> = new {
  // clazz = root.getClass()
  // data = root
}

Reference should also exhibit covariance: given a class T and a subclass class U extends T, Reference<U> should be a subtype of Reference<T>.

It may also be beneficial to add syntax sugar for producing references, so these two expressions would be equivalent:

Reference(someValue).propA["key1"].propB[0]
&someValue.propA["key1"].propB[0]

This requires a SPICE to be written to iterate on the design.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status

    In progress

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions