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
相关产品推荐
相关产品推荐

