Setting State for types.Map

Going through the tutorial for creating a custom provider using the beta Terraform Provider Framework but don’t see an example of how to handle setting types.Map values returned from APIs.

For example, an API returns a map called config that looks like:

{
  "config": {
    "item1": "value1",
    "item2": "value2",
  }
}

I can set this as types.Map in my struct but when I get the data from the api client, it is as a map[string]string value type. I tried using something like types.Map{Value: data.Config} where data.Config is the map[string]string returned from the API, but this does not work because it is not of the proper type. Any assistance or examples of how to handle these would be helpful – still navigating a lot of go and TF provider creation so there could be something I’m completely missing. Thanks.

Have you checked out the hashicups-pf provider?

This blob shows how to populate API data into some of the framework types.

If you’re using a types.Map, you do pretty much the same thing, but need to spell out the type of the elements within the map:

thing := types.Map{
    ElemType: types.StringType,
    Elems: map[string]attr.Value{
			"foo": types.String{Value: "this_is_foo"},
			"bar": types.String{Value: "this_is_bar"},
		},
}

types.Object are one step more complicated because rather than the simple ElemType field, you need to specify a map which details, by name, the type of each attribute within the object.

Hi @gstotts :wave:

There are a few options for accomplishing this which we can certainly walk through if you’d like, but I wanted to specifically call out that terraform-plugin-framework version 0.15.0 released today now offers a new way that might suit this use case well: types package - github.com/hashicorp/terraform-plugin-framework/types - Go Packages

For example, I think you should be able to accomplish what you’d like via:

// This should accept the map[string]string from data.Config and create
// a known `types.Map` value with the map contents.
configMap, diags := types.MapValueFrom(StringType, data.Config)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
  return
}

// configMap can now safely go where the `types.Map` is expected

It would be awesome if you could give that a shot and let us know how that goes.

2 Likes

Thank you. I had to modify to types.MapValueFrom(ctx, types.StringType, data.Config) as it was asking for context as well. Is that expected?

Also, in updating the provider framework to version 0.15.0, I see a new error elsewhere. My read function was taking in and using some values that were set in the config but now I can’t use the .Value as I was before… the error states that .Value is deprecated and I need to use a ValueString method to retrieve instead. Do you have an example of the ValueString method use? Tried a few things but wasn’t what I initially expected. Thank you!

NVM… figured that out as well.