FilBot3
FilBot3

Reputation: 3718

Chef - using a ruby script to edit multiple values programmatically

I'm attempting to write a ruby script so I can edit the run_lists of a bunch of nodes resulting from a knife search command. I was told to try to use knife exec, but I am yielding the same results as I am just executing the script.

I'm using a OS command dictated by the back ticks. The first command works using the knife search, but when I feed those results into to the following each_line block, it gives me the error in the comments of the script. So, obviously the first part is working, but the second is not even though its setup the exact same way.

#!/usr/bin/env ruby
#
#
#

# %CORPCERT% = C:\Users\myuser\Documents\test\knife.rb
# This contains all the pointers to the client.pem, and other required files.

output = `knife search node "fqdn:node*test*.example.net" -i -c %CORPCERT%`

output.each_line do |result|
    #puts result
    puts "Adding run_list to #{result}"
    `knife node run_list add #{result} "role[role_zabbix_agent_corp_prod]" -c %CORPCERT%`
    #puts "#{exitcode}"
end

#C:\U\P028300\Desktop> knife exec apply_run_list.rb -c %CORPCERT%
# => Adding run_list to 8 items found
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeSTtestST0.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeGWtestST0.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeGWtestST1.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeGWtestRT1.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeGWtestRT2.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeSTtestRT0.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeGWtestRT3.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem
# => Adding run_list to nodeGWtestRT0.example.net
# => WARNING: No knife configuration file found
# => ERROR: Your private key could not be loaded from C:\chef\client.pem

I know I'm not doing the knife exec command correctly, and the documentation is confusing to me. I haven't found any examples that are close, or related to what I am trying to do. How should I go about trying to programmatically search for nodes, and then update, or add items to their run_list?

Upvotes: 0

Views: 1336

Answers (3)

coderanger
coderanger

Reputation: 54267

A simple way of doing this:

knife exec -E 'nodes.transform("fqdn:WSO2*") { |n| n.run_list << "role[role_zabbix_agent_corp_prod]" }'

nodes.transform handles the search loop and the save (as long the block doesn't return nil/false) and RunList#<< already checks if it is already in the run list.

Upvotes: 3

FilBot3
FilBot3

Reputation: 3718

This is what I did to accomplish what I wanted to do after talking with some friends and IRC chat rooms.

# similar to knife search node "fqdn:WSO2*"
search("node", "fqdn:WSO2*").each do |search_node|
    # This looks at the array of the node information, and if the 
    # run_list already exists, do nothing and move on. 
    unless search_node.run_list.include?("role[role_zabbix_agent_corp_prod]")
        # This adds the listed role, or recipe to the end of the run_list
        search_node.run_list.push "role[role_zabbix_agent_corp_prod]"
        # Save the modifications.
        search_node.save
    end #=> End Unless
end #=> End Search
# Make sure to add this to the end, or it will continue to keep running. 
exit 0

Put the above script into a file named script.rb and run it as such:

knife exec script.rb

After doing reading through knife exec and also, chef-shell, I had to play around with the data structures and figure out how they were presented by Chef. The site here: http://www.bonusbits.com/main/Reference:Chef_Node_Data_Structure and http://www.bonusbits.com/main/Reference:Chef_Shell helped a lot as well. I hope this helps someone wanting to understand Chef a bit more.

Upvotes: 1

Mark O&#39;Connor
Mark O&#39;Connor

Reputation: 78021

A simpler solution is to use ridley, a ruby API library for chef server:

require 'ridley'

Ridley::Logging.logger.level = Logger.const_get 'ERROR'

ridley = Ridley.from_chef_config("C:\Users\myuser\Documents\test\knife.rb", {:ssl => {:verify => false}})

ridley.search(:node, "fqdn:node*test*.example.net").each { |n|
  n.merge_data(:run_list => ["role[role_zabbix_agent_corp_prod]"])
  n.save
}

Upvotes: 2

Related Questions