I’m using the ‘user’ cookbook from the marketplace with a data bag to create users and it’s working great. But I have an issue. In some cases I’m only adding one account, but I have a .each do loop in another cookbook that will run against the account(s). It fails if I only add (1) account. If I add (2) or more accounts it works perfect.
Is there test I can add that if (1) account, don’t loop and if more than loop thru the accounts?
Thanks.
Maybe it would be more clear if you shared some code snippets, but I'm guessing that when you add just one thing you're passing just the one object, but when you add more, it's an Array?
If that's the case, I would recommend just using an array all the time, even for one object. Generally in Chef the overhead of ruby computation in your Chef code is negligible compared to the disk and network IO of the changes you make on the system, so the extra array object and loop are not a big deal. In return you don't have to worry about code to deal with different types.
If that's not an option for some reason, check out the Array()
method in the ruby documentation. It will coerce a thing to an Array for you. If all else fails, you can use thing.kind_of?(Array)
to check.
note: Generally in Ruby it's recommended you use the #respond_to?
method to check if the object you have responds to the methods you want to call on it. But in some cases, there are different kinds of things that respond to pretty much all the same methods but behave differently. For example, Array and Hash have a lot of the same methods, but they mostly don't work interchangeably. In these cases it's generally better to use kind_of?
even though it's regarded as an anti-pattern by some.
So the code I’m running is the following:
username = node[‘users’]
home_dir = “/home/#{username}”
Set GEM_HOME
execute “source_GEM_HOME” do
cwd "#{home_dir}/"
user "#{username}“
command <<-EOB
grep ‘^. /usr/local/rvm/scripts/rvm’ .bashrc || echo -e " \n#Setting GEM_HOME Variables\n. /usr/local/rvm/scripts/rvm”>> .bashrc
EOB
end
I’m setting the node[‘users’] as a override attribute in the role that calls the above code. When I was developing the code I had node[‘users’] set to multiple accounts and all was working. When I changed the default to a single account and run it I get the following:
NoMethodError
-------------
undefined method `each’ for “tuser”:String
Setting node[‘users’] to [“tuser”, “tuser2”] the error goes away.
I hope that makes more sense. Thanks.
I figured it out. In the role I had to set the Override Attribute to the following:
“override_attributes”: {
“users”: “[“test”]”
and I changed my code as follows:
Set variables
username = node[‘users’]
Set GEM_HOME for freedom
username.each do |user|
home_dir = "/home/#{user}"
execute “source_GEM_HOME” do
cwd "#{home_dir}/"
user "#{user}“
command <<-EOB
grep ‘^. /usr/local/rvm/scripts/rvm’ .bashrc || echo -e " \n#Setting GEM_HOME Variables\n. /usr/local/rvm/scripts/rvm”>> .bashrc
EOB
end
end
It now works with a single account or multiple accounts. Thanks