如何为映射的映射值创建自定义 Terraform 数据源提供程序模式?

huangapple go评论81阅读模式
英文:

How to create a custom terraform datasource provider schema for a map of maps values?

问题

我有一个返回类型为map[string]map[string]string的golang函数。

例如:

map[foo:map[name:abc env:dev id:465 project:e-1] boo:map[name:def env:prd id:82 project:e-1] doo:map[name:ght env:stg id:353 project:e-3]]

我为它创建了以下模式...

func dataSourceAccountHelper() *schema.Resource {
	return &schema.Resource{
		Read: accountHelperRead,

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

				Computed: true,
			},

			"id": &schema.Schema{
				Computed: true,
				Type:     schema.TypeString,
			},
		},
	}
}

并且创建了一个传递角色值到模式的创建方法

func rolesRead(d *schema.ResourceData, m interface{}) error {
	filteredRoles := filterAccounts("john") // 返回`map[string]map[string]string`

	if err := d.Set("account_map", filteredRoles); err != nil {
		return err
	}

	d.SetId("-")

	return nil
}

但是Terraform的输出是一个空映射,我该如何修复它,请帮忙 如何为映射的映射值创建自定义 Terraform 数据源提供程序模式?

Outputs:

output = {
  "roles" = tomap(null) /* of map of string */
  "id" = tostring(null)
}

期望的输出如下

Outputs:

output = {
  "roles" = { 
    foo = {name = "abc" env = "dev" id = 465 project = "e-1"}
    boo = {name = "def" env = "prd" id = 82 project = "e-1"}       
  },
  "id" = "-"
}
英文:

I have a golang function that returns roles of type map[string]map[string]string

eg:

    map[foo:map[name:abc env:dev id:465 project:e-1] boo:map[name:def env:prd id:82 project:e-1] :doo[name:ght env:stg id:353 project:e-3]]

and I created a schema for it like the following...

func dataSourceAccountHelper() *schema.Resource {
	return &schema.Resource{
		Read: accountHelperRead,

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

				Computed: true,
			},

			"id": &schema.Schema{
				Computed: true,
				Type:     schema.TypeString,
			},
		},
	}
}

And the create method to pass the role values to the schema

func rolesRead(d *schema.ResourceData, m interface{}) error {
	filteredRoles := filterAccounts("john") // returns `map[string]map[string]string`



	if err := d.Set("account_map", filteredRoles); err != nil {
		return err
	}

	//accountMaps := make(map[string]interface{})

	d.SetId("-")

	return nil
}

but the Terraform output is an empty map, how do I fix it please help 如何为映射的映射值创建自定义 Terraform 数据源提供程序模式?

Outputs:

output = {
  "roles" = tomap(null) /* of map of string */
  "id" = tostring(null)
}

expecting output like

Outputs:

output = {
  "roles" = { foo    = {name = "abc" env = "dev" id= 465 project = "e-1"}
              boo    = {name = "efg" env = "prd" id= 82 project = "e-2"}       
            },
  "id" = "-"
}

答案1

得分: 0

你在这里尝试做的事情是不可能的,因为你正在使用的是旧版的 Terraform SDK。Maps 只能包含原始类型:TypeStringTypeIntTypeBool

要创建这种结构,你需要迁移到新的框架,该框架适用于现代 Terraform 的类型系统,而不是(对于 SDKv2)经典 Terraform v0.11 及更早版本的类型系统。

在 Terraform 插件框架中,与你在问题中尝试描述的结构相对应的是 MapNestedAttribute,以下是你在问题中展示的模式结构的描述:

schema.MapNestedAttribute{
    NestedObject: schema.NestedAttributeObject{
        Attributes: map[string]schema.Attribute{
            "name": schema.StringAttribute{
                // ...
            },
            "env": schema.StringAttribute{
                // ...
            },
            "id": schema.NumberAttribute{
                // ...
            },
            "project": schema.StringAttribute{
                // ...
            },
        },
    },
}

这表示具有给定属性的对象映射,因此上述模式类型等同于在使用 Terraform 语言的类型约束语法 编写的 Terraform 模块中可能写的以下类型约束:

map(
  object({
    name    = string
    env     = string
    id      = number
    project = string
  })
)
英文:

What you are trying to do here is not possbile with the legacy Terraform SDK that you are using. Maps can only be of primitive types: TypeString, TypeInt, TypeBool.

To create this structure you'll need to migrate to the new framework, which is built for the type system of modern Terraform rather than (as is the case for SDKv2) the type system of classic Terraform v0.11 and earlier.

In the Terraform Plugin Framework, the equivalent structure to what you tried to describe here is MapNestedAttribute, with the following describing the schema structure you showed in your question:

schema.MapNestedAttribute{
    NestedObject: schema.NestedAttributeObject{
        Attributes: map[string]schema.Attribute{
            "name": schema.StringAttribute{
                // ...
            },
            "env": schema.StringAttribute{
                // ...
            },
            "id": schema.NumberAttribute{
                // ...
            },
            "project": schema.StringAttribute{
                // ...
            },
        },
    },
}

This represents a map of objects with the given attributes, and so the above schema type is equivalent to the following type constraint as might be written in a Terraform module using the Terraform language's type constraint syntax:

map(
  object({
    name    = string
    env     = string
    id      = number
    project = string
  })
)

huangapple
  • 本文由 发表于 2023年2月16日 04:14:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/75465025.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定