Home > OS >  Ruby (Chef) Unable to pass a hash array into a Chef resource
Ruby (Chef) Unable to pass a hash array into a Chef resource

Time:10-11

I'm trying to create a recipe to deploy Remote Desktop Services to Windows Servers, everything is working as expected apart from the Application deployment resource I created - it's a simple resource but I'm having a lot of issues passing the applications to be deployed as a hash array.

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', ommandlinesetting: '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
    }
  }
  }]

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}" {-#{k.to_s.capitalize} #{v}}.join(' ')}"
  end
end

When running the recipe in Test Kitchen, I get the below error:

       ================================================================================
   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

Edit

Thanks to @seshadri_c for the help past the first hurdle, I've hit another issue which seems related to the attributes.

Here is the output of a kitchen converge

================================================================================
       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

Then there's this message at the end of the run:

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

CodePudding user response:

The reason for this error is that the array of hashes has different keys app1 and app2. So each time we iterate over rdapps we'll get a different key. This way we won't be able get the sub-elements such as app['options']['alias'].

So you can adjust the attribute to something like:

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',
      ommandlinesetting: '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
    }
  }
]

Then we can get this working as expected:

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
  • Related