如何通过CHEF获取节点runlist详情及其中的cookbook/profiles名称
Great questions about retrieving Chef node runlist details—let's break this down step by step:
1. 获取节点Run List的详细信息
You have a couple of reliable ways to pull full runlist details, depending on whether you're working from the command line or within a Chef recipe/client context:
Command Line (Knife)
Use the knife node show command with verbose output to see the full runlist alongside other node attributes:
knife node show <your-node-name> -l
To get just the runlist in a clean, parsable format (like JSON), add the format flag:
knife node show <your-node-name> -F json | jq '.run_list'
Within a Chef Recipe/Client Runtime
If you're writing a recipe or using a Chef Client hook, access the raw runlist directly via the node object:
# Print the raw runlist as a human-readable string Chef::Log.info("Node runlist: #{node.run_list.to_s}") # Iterate through each individual item in the runlist node.run_list.each do |item| Chef::Log.info("Runlist entry: #{item}") end
2. Extract Cookbook/Profile Names from a Node's Run List
Extracting cookbook names requires handling both direct recipe entries and roles (which can contain nested recipes). Here's how to approach it:
Command Line Approach
For a quick extraction of unique cookbook names (ignoring roles for simplicity), use this jq command with the knife output:
knife node show <your-node-name> -F json | jq '.run_list[] | split("[")[0] | split("::")[0]' | sort | uniq
If you need to expand roles to get all cookbooks included via role runlists, use knife role expand to resolve role contents first:
# Resolve a single role's runlist knife role expand <role-name> -F json | jq '.run_list[] | split("::")[0]'
To automate combining the node's direct runlist with expanded roles, you can write a small Ruby script to loop through each role in the node's runlist and merge the results.
For InSpec Profiles
If you're referring to InSpec profiles referenced via the audit cookbook, pull those directly from the node's attributes:
knife node show <your-node-name> -a audit.profiles
3. Alternative to node['recipes'] for Run List Checks
You’re absolutely right that node['recipes'] only returns the executed recipes after role expansion and attribute overrides—not the original, stored runlist from the Chef Server. Here are better alternatives:
Access the Raw, Unexpanded Run List
Use node.run_list to get the original runlist entries (including roles and recipes as they were assigned to the node):
# Check if a specific role is in the runlist if node.run_list.include?('role[webserver]') Chef::Log.info("Webserver role is assigned to this node") end # Check if a specific recipe is directly listed if node.run_list.include?('recipe[apache::default]') Chef::Log.info("Apache default recipe is in the runlist") end
Get the Fully Expanded Recipe List
If you need the complete list of recipes that will be executed (after expanding all roles for the node's environment), use the expand() method:
expanded_recipes = node.run_list.expand(node.chef_environment).recipes Chef::Log.info("All recipes to be executed: #{expanded_recipes.join(', ')}") # Verify if a specific cookbook recipe is in the expanded list if expanded_recipes.include?('apache::default') Chef::Log.info("Apache recipe will run during the Chef Client converge") end
Pull Directly from Chef Server
If you need to check the latest runlist without running Chef Client on the node, use knife to fetch the stored state (this reflects what’s on the server, not necessarily what’s been applied locally yet):
knife node show <your-node-name> -F json | jq '.run_list'
内容的提问来源于stack exchange,提问作者blueowl

