Parsing YAML for Computed Field

One of the resources of my custom provider will represent a YAML file and I would like to present the content as a computed field of type map(any). I think this will be nicer than requiring the end user to use yamldecode many times to extract values. I see that internally Terraform uses the zclconf/go-cty-yaml to implement yamldecode and this looks like exactly what I need. However, I’m not sure what to pass as the second parameter to Standard.Unmarshal. Should it be cty.Map(cty.DynamicPseudoType) or something else?

I’ve looked around but I can’t find where in the Terraform codebase the invocation of the YAMLDecodeFunc occurs. Clearly terraform is able to decode arbitrary YAML into Terraform data types using this same code.

Hi! Are you using the Terraform Plugin SDK, or are you interacting directly with the Terraform protocol?

I’m using the SDK for my provider plugin. The YAML handling code is in separate repositories from the Terraform CLI code.

Edit: I guess you already knew that.

Can you tell me a little more about the strategy you’re employing, or how you’re going about getting access to the YAML contents and how you intend to represent that content from your provider? The SDK, at this time, doesn’t have any way that I know of to expose a schema using cty types, so I’m having a little trouble following what you’re doing.

Of course.

The resource represents YAML files held in a separate system, so the resource simply reaches out to that system and pulls the contents into memory. The files describe a YAML object at the top level and the values of this object’s keys are to be fed into other resources.

So, I want to have a field in this resource to expose this YAML object as Terraform map. In other words:

Schema: map[string]*schema.Schema{
// ...
    "field": {
        Type: schema.TypeMap,
        Elem: &schema.Schema{
            Type: schema.TypeString,
        },
        Computed: true,
    },
// ...
}

In this case my_resource.instance.field is a map(string) with the keys and values from the YAML that was loaded from the external file specified.

I understand that cty types are not the same as the schema types. However, Terraform itself is able to take any arbitrary YAML and reify it into the equivalent Terraform types. I want to take advantage of that to avoid manually parsing YAML and building the map. I was hoping to understand how terraform itself accomplishes this transformation and do the same.

So I believe the distinction between Terraform and the SDK here that’s important is that Terraform gets to use cty types, and the SDK has to use what helper/schema.Schema supports. This is relevant because Terraform can use the cty.DynamicPseudoType, which the code you link to uses, but the helper/schema.Schema type has no concept for that. You’re defining, in your example, a map[string]string, essentially. The YAMLDecodeFunc you link to is returning what is essentially an interface{}.

If you’re just asking how to use go-cty-yaml to parse YAML into a cty.Map, that’s not super SDK related (…yet) but this demo seems to work for me. You’re basically going to be parsing raw bytes into a cty type, then converting that type into an SDK type manually (there’s no functionality for that at the moment), then the SDK will convert that type back into a cty type for Terraform, which Terraform will then use. I’m not super clear on what the benefit of using cty for the first step is, then, but I suppose some YAML parser would need to be used.

Thank you for the example, that’s helpful to illustrate the point.

The is no inherent benefit to using cty, it is simply the wrapper around the YAML parser that Terraform already uses. So, rather than dragging in my own and using it to grovel in the YAML I was hoping to re-use what was already available.

It seems that there is no good way for provider implementers to take advantage of that nifty machinery available to Terraform which is too bad. It would be nice if the SDK used the same type model as Terraform does.

Agreed, it would be, and that’s the plan for the future. Unfortunately, Terraform’s type system changed when we already had a lot of providers built using the SDK, so changing the SDK’s type system is prohibitively expensive. We’re making progress in bringing the two into alignment, it’s just a lengthy process because we need to be sensitive to the amount of existing code depending on the SDK.