Chef中能否通过字符串变量批量执行不同自定义资源?
Absolutely! You can absolutely use a similar dynamic approach to execute different custom resources in Chef—this is actually a super handy pattern to keep your recipes clean, DRY, and flexible, just like how you handle dynamic recipe includes.
Under the hood, every Chef resource (including custom ones you define) is exposed as a Ruby method in your recipe context. That means you can use Ruby's send() method to call these resources dynamically using string variables, just like you do with include_recipe.
Basic Example: Looping Through Custom Resources
Let's say you have a few custom resources (my_web_server, my_database, my_cache) and you want to loop through them to configure each:
# Define the list of custom resource names you want to execute custom_resources = %w[my_web_server my_database my_cache] custom_resources.each do |resource_name| # Convert the string resource name to a symbol, then call it with send() send(resource_name.to_sym, "setup_#{resource_name}") do # Set properties specific to each resource (adjust as needed) case resource_name when 'my_web_server' port 80 domain 'example.com' when 'my_database' db_type 'postgresql' version '14' when 'my_cache' max_memory '2GB' enable_persistence true end end end
Advanced Example: Dynamic Configurations Per Resource
If you want to make it even more flexible—say, passing unique configurations per resource instance—you can use an array of hashes to store all resource details:
# Array of resource definitions with unique IDs and properties resource_configs = [ { resource: 'my_web_server', id: 'customer_portal', props: { port: 443, domain: 'portal.example.com', ssl_enabled: true } }, { resource: 'my_database', id: 'portal_db', props: { db_type: 'mysql', version: '8.0', max_connections: 100 } } ] resource_configs.each do |config| # Call the dynamic resource with its unique ID send(config[:resource].to_sym, config[:id]) do # Apply all properties dynamically without hardcoding config[:props].each do |prop, value| send(prop, value) end end end
Key Notes to Remember
- Ensure resources are loaded: Make sure the cookbook containing your custom resources is declared in your
metadata.rbwithdepends 'your_cookbook_name', or that the resources are defined in the same cookbook as your recipe. - Match resource names exactly: The string you use must match the exact name of your custom resource (underscores and all)—Chef won't correct typos for you!
- Symbol conversion: Since Ruby methods (and thus Chef resource calls) use symbols, we convert the string resource name to a symbol with
.to_symbefore passing it tosend().
This approach works just as smoothly as dynamic recipe includes, and it's a great way to avoid repeating identical resource blocks when you need to configure multiple instances or types of custom resources.
内容的提问来源于stack exchange,提问作者hfskappel

