Reputation: 789
I have json file which import as environment file to chef,
{
"mongodb": {
"replicaset": {
"nodes": [
"test-mongo1:27017",
"test-mongo2:27017"
]
}
}
}
I chef cookbook template added as below to build the mongo connection string,
"mongo": {
"url" : "mongodb://<% node['mongodb']['replicaset']['nodes'].each do |replica| -%>admin:123456@<%= replica %>/user_db1",
<% end %>
But output like below and not validating as JSON
"mongo": {
"url" : "mongodb://admin:123456@test-mongo1:27017/user_db1",
admin:123456@test-mongo2:27017/user_db1",
Expected Result:
"mongo": {
"url" : "mongodb://admin:123456@test-mongo1:27017/user_db1,admin:123456@test-mongo2:27017/user_db1",
Followed How to Run for each loop in template chef, But my ruby isn't the best because I'm just starting out with all of this stuff. Any help would be great, thanks.
Upvotes: 2
Views: 357
Reputation: 55908
At first, we can attempt to fix the loop so that only the necessary parts are included in the inner block:
"mongo": {
"url" : "mongodb://<% node['mongodb']['replicaset']['nodes'].each do |replica| -%>admin:123456@<%= replica %>/user_db1,<% end %>",
This however still results in a problem: There is a trailing comma since we always add it after each iteration.
A better approach would thus be to first build a list of URLs and then join them with a comma to a single string. That way, there is only a comma added between elements. This should work instead:
"mongo": {
"url" : "mongodb://<%= node['mongodb']['replicaset']['nodes'].map { |replica| "admin:123456@#{replica}/user_db1" }.join(",") %>",
Basically, what this code does is the following:
output = ""
output << "\"mongo\": {\n"
output << " \"url\" : \"mongodb://"
urls = node['mongodb']['replicaset']['nodes'].map do |replica|
output << "admin:123456@"
output << replica
output << "/user_db1"
end
output << urls.join(", ")
output << "\","
Here, output
represents the output of the ERB template. In the actual ERB implementation, there is a bit more logic involved, but the basic logic works similar to that.
When doing this in an actual cookbook, usually a better approach is to build the URLs in your recipe already and pass them to your template prebuild:
In recipes/default.rb
:
urls = node['mongodb']['replicaset']['nodes'].map do |replica|
"admin:123456@#{replica}/user_db1"
end
template '/path/to/mongo.json' do
source 'my_template.json.erb'
variables mongo_urls: urls
end
In templates/default/my_template.json.erb
:
"mongo": {
"url" : "mongodb://<%= @mongo_urls.join(",") %>",
Upvotes: 4