You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chef部署RDS应用时哈希数组传递及属性验证问题

在Windows服务器上用Chef部署RDS远程应用的问题排查与修复

问题背景

编写Chef Recipe在Windows服务器部署Remote Desktop Services(RDS)时,其余功能正常,但通过哈希数组传递应用配置时出现多轮错误。


相关代码文件

属性文件(attributes\default.rb)

default['app']['app_options'] = [{
  app1:{
    connection_broker: 'serv-01',
    options: {
      collectionname: 'Terminal Services', alias: 'Acrobat', displayname: 'Adobe Acrobat', filepath: 'C:\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe', filevirtualpath: 'C:\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe', commandlinesetting: 'DoNotAllow', iconindex: 0, iconpath: '\\\\serv-01\\C$\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe', usergroups: ['domain\\group'], showinwebaccess: 1
    }
  },
  app2:{
    connection_broker: 'serv-01',
    options: {
      collectionname: 'Terminal Services', alias: 'Accounts', displayname: 'Accounts', foldername: 'Accounts', filepath: 'D:\\Accounts\\Accounts.bat', filevirtualpath: 'D:\\Accounts\\Accounts.bat', commandlinesetting: 'DoNotAllow', iconindex: 0, iconpath: 'C:\\Windows\\System32\\cmd.exe', usergroups: ['domain\\group'], showinwebaccess: 1
    }
  }
}]

Recipe文件(recipes\remote_desktop.rb)

rdapps = node.read('app', 'app_options') || []

rdapps.each do |app|
  remote_desktop_apps app['options']['alias'] do
    action :create
    connection_broker app['connection_broker']
    app_options app['options']
  end
end

自定义资源文件(resources\remote_desktop_apps.rb)

resource_name :remote_desktop_apps

property :connection_broker, String,
         desired_state: false

property :app_options, [String, Hash, Array],
         desired_state: false

action :create do
  app_options.each do |k,v|
          script << "New-RDRemoteApp -ConnectionBroker \"#{connection_broker}\" #{app_options.map { |key, val| "-#{key.to_s.capitalize} \"#{val}\"" }.join(' ')}"
  end
end

错误信息

首次运行错误(Test Kitchen)

================================================================================
Recipe Compile Error in C:/Users/ADMINI~1/AppData/Local/Temp/kitchen/cache/cookbooks/windows_/recipes/remote_desktop.rb
================================================================================

NoMethodError
-------------
undefined method `[]' for nil:NilClass

修复首个问题后出现的属性错误

================================================================================
Error executing action `create` on resource 'remote_desktop_apps[Acrobat]'
================================================================================

Chef::Exceptions::ValidationFailed
----------------------------------
name is a required property

Resource Declaration:
---------------------
# In C:/Users/ADMINI~1/AppData/Local/Temp/kitchen/cache/cookbooks/rh_windows/recipes/remote_desktop.rb

 76:   remote_desktop_apps app['options']['alias'] do
 77:     action :create
 78:     connection_broker app['connection_broker']
 79:     app_options app['options']
 80:   end
 81: end

Compiled Resource:
------------------
# Declared in C:/Users/ADMINI~1/AppData/Local/Temp/kitchen/cache/cookbooks/rh_windows/recipes/remote_desktop.rb:76:in `block in from_file'

remote_desktop_apps("Acrobat") do
  action [:create]
  default_guard_interpreter :default
  declared_type :remote_desktop_apps
  cookbook_name "windows_"
  recipe_name "remote_desktop"
  connection_broker "serv-01"
  app_options {"collectionname"=>"Terminal Services", "alias"=>"Acrobat", "displayname"=>"Adobe Acrobat", "filepath"=>"C:\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe", "filevirtualpath"=>"C:\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe", "commandlinesetting"=>"DoNotAllow", "iconindex"=>"0", "iconpath"=>"\\\\serv-01\\C$\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe", "usergroups"=>["domain\\group"], "showinwebaccess"=>"1"}
end

运行结束时的附加错误提示

FATAL: Chef::Exceptions::ValidationFailed: remote_desktop_apps[Acrobat] (rh_windows::remote_desktop line 76) had an error: Chef::Exceptions::ValidationFailed: name is a required property
$$$$$$ Exception calling "Read" with "3" argument(s): "Offset and length were out of bounds for the array or count is greater than the number of elements from index to the end of the source collection."
At line:100 char:11
$$$$$$ +       if ($fs.Read($bytes, 0, $fs.Length) -gt 0) {
$$$$$$ +           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ArgumentException

修复步骤

1. 修正属性数组结构

首次错误是因为属性数组嵌套错误:app_options是包含一个哈希的数组,哈希内又嵌套app1/app2键,导致遍历无法直接获取options。修改属性为直接存储应用对象的数组:

default['app']['app_options'] = [
  {
    connection_broker: 'serv-01',
    options: {
      collectionname: 'Terminal Services', alias: 'Acrobat', displayname: 'Adobe Acrobat', filepath: 'C:\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe', filevirtualpath: 'C:\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe', commandlinesetting: 'DoNotAllow', iconindex: 0, iconpath: '\\\\serv-01\\C$\\Program Files (x86)\\Adobe\\Acrobat 11.0\\Acrobat\\Acrobat.exe', usergroups: ['domain\\group'], showinwebaccess: 1
    }
  },
  {
    connection_broker: 'serv-01',
    options: {
      collectionname: 'Terminal Services', alias: 'Accounts', displayname: 'Accounts', foldername: 'Accounts', filepath: 'D:\\Accounts\\Accounts.bat', filevirtualpath: 'D:\\Accounts\\Accounts.bat', commandlinesetting: 'DoNotAllow', iconindex: 0, iconpath: 'C:\\Windows\\System32\\cmd.exe', usergroups: ['domain\\group'], showinwebaccess: 1
    }
  }
]

2. 修复自定义资源的name属性

Chef自定义资源默认要求name属性,需显式声明并修正脚本逻辑:

resource_name :remote_desktop_apps

# 声明name属性,使用资源名称作为默认值
property :name, String, name_property: true
property :connection_broker, String, desired_state: false
property :app_options, Hash, desired_state: false # 每个应用是单独哈希,无需Array类型

action :create do
  powershell_script "Create RDS App #{name}" do
    code <<-EOH
      New-RDRemoteApp -ConnectionBroker "#{connection_broker}" #{app_options.map { |key, val|
        # 处理数组类型参数(如usergroups)
        if val.is_a?(Array)
          "-#{key.to_s.capitalize} @('#{val.join("','")}')"
        else
          "-#{key.to_s.capitalize} \"#{val}\""
        end
      }.join(' ')}
    EOH
  end
end

3. 验证Recipe调用逻辑

保持Recipe代码不变,修正后的属性数组可被正确遍历,资源调用时app['options']['alias']能正常获取值作为资源名称。


内容的提问来源于stack exchange,提问作者lolcomputers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 09:40:25