I have been struggling for over a week to solve this issue. Is there anyone who can help me out solving this.
I have a databag called mongo, the contents of the databag are:
{
"firstuser": {
"id": "firstuser",
"password": "123",
"db": "mydb",
"role": "readWrite"
},
"seconduser": {
"id": "seconduser",
"password": "123",
"db": "mydb",
"role": "readWrite"
},
"thirduser": {
"id": "thirduser",
"password": "123",
"db": "mydb",
"role": "read"
},
"id": "users"
}
I want to loop through this databag, in order to create users in MongoDB. How do I access the items for firstuser? For example id, password, db, role etc?
This is what I have come up with (and a lot more fruitless attempts)
data_bag('mongodb').each do |item|
repository = data_bag_item('mongodb', item)
log 'RARARARA: log message' do
if repository['firstuser']
Chef::Log.debug("RARAR DS.repository: #{repository['id']} ")
end
end
end
hi @rajanarkenbout
There are cookbooks out there that already do this, users springs to mind.
The structure in the data bag is the same as a Ruby hash, therefore you can use each_pair
users_databag = data_bag('mongodb', item)
users_databag.each_pair do | user, values |
log "user #{user} id #{values['id']} password #{values['password']}"
end
Hope this helps
1 Like
Cheers mate!
Some minor tweaking and it works
recipe:
data_bag(‘mongodb’).each do | item |
users_databag_item = data_bag_item(‘mongodb’, item)
users_databag_item.each_pair do | user, values |
log "user #{user} id #{values[‘id’]} password #{values[‘password’]}"
end
end
output:
log[user firstuser id firstuser password 123] action write
It seems that this issue is not resolved yet. Right now I am stuck with printing extra empty entries. Any ideas about that?
What´s got me baffled is the fact that I first get 2 empty records, than the 3 expected records and than another empty one…
Check out the output;
- log[db.createUser( { user: ‘’, pwd: ‘’, roles: [ { role: ‘’, db: ‘db’ } ] } )] action write
- log[db.createUser( { user: ‘’, pwd: ‘’, roles: [ { role: ‘’, db: ‘db’ } ] } )] action write
- log[db.createUser( { user: ‘firstuser’, pwd: ‘123’, roles: [ { role: ‘readWrite’, db: ‘mydb’ } ] } )] action write
- log[db.createUser( { user: ‘seconduser’, pwd: ‘123’, roles: [ { role: ‘readWrite’, db: ‘mydb’ } ] } )] action write
- log[db.createUser( { user: ‘thirduser’, pwd: ‘123’, roles: [ { role: ‘read’, db: ‘mydb’ } ] } )] action write
- log[db.createUser( { user: ‘’, pwd: ‘’, roles: [ { role: ‘’, db: ‘’ } ] } )] action write
Please advise
recipe code:
data_bag(‘mongodb’).each do | item |
users_databag_item = data_bag_item(‘mongodb’, item)
users_databag_item.each_pair do | user, values |
log "db.createUser( { user: ‘#{values[‘id’]}’, pwd: ‘#{values[‘password’]}’, roles: [ { role: ‘#{values[‘role’]}’, db: ‘#{values[‘db’]}’ } ] } )"
end
end
Hello @rajanarkenbout
I think your code should work, it’s similar to the code on the Chef data bag page which has two loops, the data bag and item https://docs.chef.io/data_bags.html#create-users
The users community cookbook is slightly different as it performs a search on the data bag to retrieve a list of items, as below
search('mongodb', "user:*") do |user|
log "id #{user['id']} pwd #{user['password']}"
end
Are you converging using Test Kitchen and Chef Zero or is this a node running against a Chef Server?
If you run the following from the command line
knife data bag show mongodb
Does it show three or five data bags?
Hi @chris_sullivan,
I am using Chef Server.
knife data bag show mongodb
keyfile
users
Which means that it loops through the keyfile item as well. Hence the reason for the empty records.
I’ll have a shot at something like this.
data_bag(‘mongodb’, ‘users’) do | item |
or
data_bag(‘mongodb’, ‘users’) do | item |
users_databag_item = data_bag_item(‘mongodb’, users)
Thanks again I really appreciate it.
Hello @rajanarkenbout
Glad you found out where the extra items are coming from.
Just as an aside, you can always use Chef search to filter the data bag items.
Search is available from a Chef recipe and also from the command line via knife search
knife search mongodb "id:users"
or in a recipe
users = search(:mongodb, "id:users")
or you can exclude data bags
knife search mongodb "NOT id:keyfile"
or in a recipe
users = search(:mongodb, "NOT id:keyfile")
Hope this helps.
@chris_sullivan
Using the following code I am faced with one ‘empty’ record… Some progress but not quite enough.
users_databag_item = data_bag_item(‘mongodb’, ‘users’)
users_databag_item.each_pair do | user, values |
log "db.createUser( { user: ‘#{values[‘id’]}’, pwd: ‘#{values[‘password’]}’, roles: [ { role: ‘#{values[‘role’]}’, db: ‘#{values[‘db’]}’ } ] } )"
end
Now I have been trying the search option you mentioned, but can seem to get it to log anything. The result is that the variables are empty. How would approach this? Can you give an example of the code?
Ihave tried to check if not empty,. but to no avail. No recordds are retrieved.
users_databag_item = data_bag_item(‘mongodb’, ‘users’)
users_databag_item.each_pair do | user, values |
if !values.empty? do
log "db.createUser( { user: ‘#{values[‘id’]}’, pwd: ‘#{values[‘password’]}’, roles: [ { role: ‘#{values[‘role’]}’, db: ‘#{values[‘db’]}’ } ] } )"
end
end
end
I believe the culprit is (“id”: “users”) in my databag. Is there a way to filter out this entry?
To prove this I have added
“id”: “users”, “password”: "123"
which resulted in 2 extra empty records.
So, I need to filter out: (“id”: “users”).
Hello @rajanarkenbout,
There are a couple of things you can do
- filter your hash and ignore keys with the value of id (using select, reject or just continue loop)
- modify the structure of your data bags an add an extra level called “users”
Example of 1.
data_bag('test').each do |item|
db = data_bag_item('test', item)
db.each_pair do |k,v|
next if k == 'id'
log "id #{v['id']} pwd #{v['password']}"
end
end
Example of 1. using search
db = search('test', 'NOT id:keyfile')
db.each do |item|
item.each_pair do |k,v|
next if k == 'id'
log "id #{v['id']} pwd #{v['password']}"
end
end
Example 2.
Change data bag to add extra layer in hash
{
"users": {
"firstuser": {
"id": "firstuser",
"password": "123",
"db": "mydb",
"role": "readWrite"
},
"seconduser": {
"id": "seconduser",
"password": "123",
"db": "mydb",
"role": "readWrite"
},
"thirduser": {
"id": "thirduser",
"password": "123",
"db": "mydb",
"role": "read"
}
},
"id": "users"
}
Code for extra layer
data_bag('test').each do |item|
next if item == 'keyfile'
db = data_bag_item('test', item)
db['users'].each_pair do |k,v|
next if k == 'id'
log "id #{v['id']} pwd #{v['password']}"
end
end
Hi, When iam using above code in my recipe.Its working fine.
When iam running spec test its saying each is undefined method .Failure.
Can you help on this