Puppet技术问题:如何在动态变量路径中访问哈希键
Puppet中动态访问SSH密钥哈希的解决方案
咱们先聊聊你的场景:你现在在Puppet里用哈希存储用户的SSH密钥,类的定义是这样的:
class users::sshkeys { $user1 = { user1 => { key => 'AAAAAA', type => 'ssh-rsa' } } $user2 = { user2 => { key => 'BBBBBB', type => 'ed25519' } } }
静态访问的时候没问题,比如$users::sshkeys::user1['user1']['key']就能顺利拿到密钥,但想通过循环动态访问的时候,用getvar拿到的变量没办法直接取哈希键——这确实是个容易踩的小坑。
问题出在哪?
你用getvar("users::sshkeys::${user1}")的时候,其实是能拿到真正的哈希对象的,但你在notify里直接写"$mydynamicuser[$user]['key']"的话,Puppet会把整个表达式当成字符串拼接,不会解析里面的哈希访问逻辑,自然拿不到正确的密钥。
解决办法
方法1:正确使用getvar后链式访问哈希键
你可以先通过getvar拿到完整的哈希变量,再单独访问它的键值,别把哈希访问揉在字符串插值里:
$users = ['user1', 'user2'] $users.each |$user| { # 先拿到对应用户的哈希变量 $user_hash = getvar("users::sshkeys::${user}") # 再从哈希里取出密钥 $user_key = $user_hash[$user]['key'] notify { "User ${user} SSH key: ${user_key}": } }
这样$user_hash是真正的哈希对象,后续的键值访问就能正常解析了。
方法2:重构数据结构(更推荐)
其实你现在每个用户变量都是一个只包含自身的哈希,有点冗余。不如直接把所有用户的密钥存在一个大哈希里,动态访问会简单很多:
class users::sshkeys { $ssh_keys = { user1 => { key => 'AAAAAA', type => 'ssh-rsa' }, user2 => { key => 'BBBBBB', type => 'ed25519' } } }
之后动态访问根本不需要getvar,直接遍历这个大哈希就行:
# 遍历所有用户密钥 $users::sshkeys::ssh_keys.each |$user, $details| { notify { "User ${user} SSH key: ${details['key']}": } } # 如果需要从指定用户列表遍历的话: $users = ['user1', 'user2'] $users.each |$user| { $user_key = $users::sshkeys::ssh_keys[$user]['key'] notify { "User ${user} SSH key: ${user_key}": } }
这种结构不仅更清晰,还避免了分散的变量,后续维护起来也更方便。
额外小技巧
如果一定要保留原来的分散变量结构,还可以用dig函数简化访问,同时避免层级不存在时的报错:
$user_key = getvar("users::sshkeys::${user}").dig($user, 'key')
dig可以安全地嵌套访问哈希键,就算某个层级不存在,也只会返回undef而不是抛出错误。
内容的提问来源于stack exchange,提问作者tma
相关产品推荐
相关产品推荐

