此对象没有名为 yaml 结构的属性
This object does not have an attribute named yaml structures
我想在一个 yaml 文件中构建我的组织结构,供 github 提供者管理团队、成员,一些团队包含子元素,如 subteams,有些不包含,因为循环错误“This object does not有一个名为“的属性,当 yaml 中的结构不相同时,我尝试使用 lookup()、contains()、if() 但我才刚刚开始使用 terraform,所以也许你可以帮助我如何实现这一点?
# cat locals.tf
locals {
teams = yamldecode(file("teams.yaml"))["teams"]
teams_flatten = flatten([
for team in local.teams :
{
team_name = team.name
description = lookup(team, "description", "")
privacy = lookup(team, "privacy", "closed")
}
])
subteams_flatten = flatten([
for team in local.teams : [
for subteam in team.subteams : {
team_name = team.name
subteam_name = subteam.name
description = lookup(subteam, "description", "")
privacy = lookup(subteam, "privacy", "closed")
}
]
])
}
│ on locals.tf line 16, in locals:
│ 16: for subteam in team.subteams : {
│
│ This object does not have an attribute named "subteams".
# cat teams.yaml
---
teams:
# Parent team
- name: Engineering
# This team has sub-teams
subteams:
- name: access
members:
- member: alex
role: maintainer
- member: bob
role: maintainer
- name: payments
members:
- member: alice
role: maintainer
# Parent team
- name: Marketing
# This team does not have any sub-teams
members:
- member: bob
role: maintainer
- member: alex
role: maintainer
# cat teams.tf
resource "github_team" "teams" {
for_each = {
for team in local.teams_flatten : team.team_name => team
}
name = each.value.team_name
description = each.value.description
privacy = each.value.privacy
}
resource "github_team" "subteams" {
depends_on = [github_team.teams]
for_each = {
for subteam in local.subteams_flatten : subteam.subteam_name => subteam
}
name = each.value.subteam_name
parent_team_id = lookup(github_team.teams, each.value.team_name)["id"]
description = each.value.description
privacy = each.value.privacy
}
当处理像这样结构不一定一致的原始人工编辑文件时,有时可以帮助首先明确规范化数据结构作为一个单独的步骤,然后在其他地方使用更一致的数据结构。这样就可以将密集的条件代码隔离在一个地方,从而有望使模块的其余部分更易于阅读。
例如:
locals {
teams_raw = yamldecode(file("${path.module}/teams.yaml"))["teams"]
teams = {
for team_raw in local.teams_raw : tostring(team_raw.name) => {
name = tostring(team_raw.name)
subteams = tomap({
for subteam_raw in try(team_raw.subteams, []) :
tostring(subteam_raw.name) => {
name = tostring(subteam_raw.name)
members = tomap({
for member_raw in subteam_raw.members :
tostring(member_raw.member) => {
name = tostring(member_raw.member)
role = tostring(member_raw.role)
}
})
}
})
members = tomap({
for member_raw in try(team_raw.members, []) :
tostring(member_raw.member) => {
name = tostring(member_raw.member)
role = tostring(member_raw.role)
}
})
}
}
}
上述 local.teams
定义的两个主要相关特征是:
- 它在几个地方使用
try
来为特定键不可用时提供备用值。这意味着生成的数据结构将始终具有该类型的属性,但它可能引用一个空映射,这比可能根本不存在的属性更容易处理。
- 它自由地使用
tomap
和 tostring
来断言每个属性的预期类型。因此,如果给定值不适合这些约束之一,这将允许 Terraform 尽早引发错误,并确保 Terraform 可以为您可以在其他地方依赖的数据结构推断出合适的静态类型。
有了这个新的规范化数据结构,您可以在所有元素上引用 members
和 subteams
,并且知道它总是被设置但可能被设置为空映射。
我想在一个 yaml 文件中构建我的组织结构,供 github 提供者管理团队、成员,一些团队包含子元素,如 subteams,有些不包含,因为循环错误“This object does not有一个名为“的属性,当 yaml 中的结构不相同时,我尝试使用 lookup()、contains()、if() 但我才刚刚开始使用 terraform,所以也许你可以帮助我如何实现这一点?
# cat locals.tf
locals {
teams = yamldecode(file("teams.yaml"))["teams"]
teams_flatten = flatten([
for team in local.teams :
{
team_name = team.name
description = lookup(team, "description", "")
privacy = lookup(team, "privacy", "closed")
}
])
subteams_flatten = flatten([
for team in local.teams : [
for subteam in team.subteams : {
team_name = team.name
subteam_name = subteam.name
description = lookup(subteam, "description", "")
privacy = lookup(subteam, "privacy", "closed")
}
]
])
}
│ on locals.tf line 16, in locals:
│ 16: for subteam in team.subteams : {
│
│ This object does not have an attribute named "subteams".
# cat teams.yaml
---
teams:
# Parent team
- name: Engineering
# This team has sub-teams
subteams:
- name: access
members:
- member: alex
role: maintainer
- member: bob
role: maintainer
- name: payments
members:
- member: alice
role: maintainer
# Parent team
- name: Marketing
# This team does not have any sub-teams
members:
- member: bob
role: maintainer
- member: alex
role: maintainer
# cat teams.tf
resource "github_team" "teams" {
for_each = {
for team in local.teams_flatten : team.team_name => team
}
name = each.value.team_name
description = each.value.description
privacy = each.value.privacy
}
resource "github_team" "subteams" {
depends_on = [github_team.teams]
for_each = {
for subteam in local.subteams_flatten : subteam.subteam_name => subteam
}
name = each.value.subteam_name
parent_team_id = lookup(github_team.teams, each.value.team_name)["id"]
description = each.value.description
privacy = each.value.privacy
}
当处理像这样结构不一定一致的原始人工编辑文件时,有时可以帮助首先明确规范化数据结构作为一个单独的步骤,然后在其他地方使用更一致的数据结构。这样就可以将密集的条件代码隔离在一个地方,从而有望使模块的其余部分更易于阅读。
例如:
locals {
teams_raw = yamldecode(file("${path.module}/teams.yaml"))["teams"]
teams = {
for team_raw in local.teams_raw : tostring(team_raw.name) => {
name = tostring(team_raw.name)
subteams = tomap({
for subteam_raw in try(team_raw.subteams, []) :
tostring(subteam_raw.name) => {
name = tostring(subteam_raw.name)
members = tomap({
for member_raw in subteam_raw.members :
tostring(member_raw.member) => {
name = tostring(member_raw.member)
role = tostring(member_raw.role)
}
})
}
})
members = tomap({
for member_raw in try(team_raw.members, []) :
tostring(member_raw.member) => {
name = tostring(member_raw.member)
role = tostring(member_raw.role)
}
})
}
}
}
上述 local.teams
定义的两个主要相关特征是:
- 它在几个地方使用
try
来为特定键不可用时提供备用值。这意味着生成的数据结构将始终具有该类型的属性,但它可能引用一个空映射,这比可能根本不存在的属性更容易处理。 - 它自由地使用
tomap
和tostring
来断言每个属性的预期类型。因此,如果给定值不适合这些约束之一,这将允许 Terraform 尽早引发错误,并确保 Terraform 可以为您可以在其他地方依赖的数据结构推断出合适的静态类型。
有了这个新的规范化数据结构,您可以在所有元素上引用 members
和 subteams
,并且知道它总是被设置但可能被设置为空映射。