Terraform:仅在变量设置时创建数据源的实现方案
Hetzner Terraform模块SSH密钥二选一配置问题
需求是实现两种SSH密钥使用方式:
- 提供已有Hetzner SSH密钥的指纹,直接复用
- 未提供指纹时,通过本地公钥路径创建新的SSH密钥
当前代码运行报错:
data.hcloud_ssh_key.existing: Reading...
╷
│ Error: please specify a id, a name, a fingerprint or a selector to lookup the sshkey
│
│ with data.hcloud_ssh_key.existing,
│ on main.tf line 11, in data "hcloud_ssh_key" "existing":
│ 11: data "hcloud_ssh_key" "existing" {
问题根源:无论ssh_key_existing_fingerprint是否为null,Terraform都会尝试执行data.hcloud_ssh_key.existing数据源读取操作,当指纹为空时,数据源缺少必要参数导致报错。
解决方案:条件化控制资源与数据源
通过Terraform的count参数,实现仅在满足条件时才创建/读取对应的资源或数据源:
1. 优化变量定义(可选)
给变量添加清晰描述和非空约束,避免歧义:
variable "ssh_key" { description = "本地SSH公钥路径,未提供已有密钥指纹时使用" type = string default = "~/.ssh/id_rsa.pub" nullable = false } variable "ssh_key_existing_fingerprint" { description = "已存在于Hetzner的SSH密钥指纹,优先使用" type = string default = null }
2. 修改main.tf实现条件化逻辑
# 仅当提供了已有密钥指纹时,才读取Hetzner上的密钥数据源 data "hcloud_ssh_key" "existing" { count = var.ssh_key_existing_fingerprint != null ? 1 : 0 fingerprint = var.ssh_key_existing_fingerprint } # 仅当未提供已有密钥指纹时,才在Hetzner创建新的SSH密钥 resource "hcloud_ssh_key" "default" { count = var.ssh_key_existing_fingerprint == null ? 1 : 0 name = "servers default ssh key" public_key = file(var.ssh_key) } resource "hcloud_server" "server" { name = var.server_name server_type = var.server_flavor image = var.server_image location = var.server_location # 根据条件选择密钥ID:已有指纹存在则用数据源ID,否则用新创建的密钥ID ssh_keys = [ var.ssh_key_existing_fingerprint != null ? data.hcloud_ssh_key.existing[0].id : hcloud_ssh_key.default[0].id ] }
原理说明
count = 条件 ? 1 : 0:满足条件时创建1个资源实例,否则创建0个(即不执行该资源/数据源)- 引用资源时通过
[0]索引访问,因为count为1时会生成列表形式的资源实例
额外优化:添加指纹格式验证(可选)
给ssh_key_existing_fingerprint添加格式校验,避免用户输入无效指纹:
variable "ssh_key_existing_fingerprint" { description = "已存在于Hetzner的SSH密钥指纹,优先使用" type = string default = null validation { condition = can(regex("^[a-f0-9]{2}(:[a-f0-9]{2})+$", var.ssh_key_existing_fingerprint)) || var.ssh_key_existing_fingerprint == null error_message = "SSH密钥指纹格式无效,需符合aa:bb:cc:...的十六进制冒号分隔格式。" } }
内容的提问来源于stack exchange,提问作者Michael Niemand
相关产品推荐
相关产品推荐

