hello,
hopefully not tl;dr :> … i’m approaching a task and i wonder if the
style is appropriate. and if the style is appropriate, why is it
throwing this exception?
i want to take certain actions on a host within a recipe depending on
what kind of role is defined for it. and by “role” i don’t mean a chef
role … necessarily. it’s what role a node plays in the environment.
let’s say i have hosts serving in various roles like: admin, app, proxy,
etc.
in particular, if a node is of role “admin”, then i want to place on
that node AWS credentials of a high privilege level. a node that is of
role “app” i want to place low privileged AWS creds.
in the recipe, i’m trying to create logic that detects the role from
node attr data. maybe this is the wrong approach and i’d like feedback on
that. but i also want to flesh out this approach to ask this question,
which i guess comes down to a question on ruby syntax and the non-presence
of certain node attr data.
(i will note that i just tried this by creating chef roles aws-role-admin
and aws-role-generic, therein setting override attrs, and assigning
those roles to my nodes. if the recipe calls upon attrs set by this
chef role, it works. but is that the right way to solve this?)
an additional data point is we have nodes that were launched with a
legacy form of ec2 userdata, and i want to change the userdata to JSON
going forward.
legacy: “-r rolename -h hostname -e environment -v vol-xxxxxx”
snippet from new JSON style:
"node_name": "test-kallen.dev.wewt.com",
"wewt": {
"role": "admin",
"environment": "dev",
"elip": "xx.xx.xx.xx",
"vol_list": [
"vol-xxxxx"
]
},
"chef_server": "https://10.xx.xx.xx",
"validation_client_name": "chef-validator",
"run_list": [
"role[base]",
"role[postfix-client]",
"recipe[and_so_on]"
]
my node launch process will take that userdata and populate it
as chef node (normal) attributes.
regardless of the style of userdata we pass in at launch time, that
userdata is in the node attribute data in chef, be it at the top level
under normal attr data or under [:ec2][:userdata]. so i figured i could
test for the values in node attr data in my recipe. but the way i’m
trying it is throwing an exception on legacy hosts for this line in
the recipe:
if node[:ec2][:userdata] =~ /-r admin/ || node[:wewt][:role] == "admin"
here’s a small test recipe that tries to detect the role as is present
in node attr data. it tries to be backward compatible for the legacy
userdata style.
if node[:ec2]
if node[:ec2][:userdata] =~ /-r admin/ || node[:wewt][:role] == "admin"
Chef::Log.debug(“HIGGS-BOSON: detected role admin”)
elsif node[:ec2][:userdata] =~ /-r app/ || node[:wewt][:role] == "app"
Chef::Log.debug(“HIGGS-BOSON: detected role app”)
else
Chef::Log.debug(“HIGGS-BOSON: no role detected!”)
end
end
successful run on test-kallen.dev.wewt.com which contains the new node
attributes via the new JSON userdata:
[Thu, 02 Feb 2012 02:16:26 +0000] DEBUG: Loading Recipe test_recipe via include_recipe
[Thu, 02 Feb 2012 02:16:26 +0000] DEBUG: Found recipe default in cookbook test_recipe
[Thu, 02 Feb 2012 02:16:26 +0000] DEBUG: HIGGS-BOSON: detected role dev
[Thu, 02 Feb 2012 02:16:26 +0000] DEBUG: Converging node test-kallen.dev.wewt.com
[Thu, 02 Feb 2012 02:16:26 +0000] DEBUG: Saving the current state of node test-kallen.dev.wewt.com
failed run on webapp01b.dev.wewt.com which does not contain the new
node attributes:
[Thu, 02 Feb 2012 02:16:28 +0000] DEBUG: Loading Recipe test_recipe via include_recipe
[Thu, 02 Feb 2012 02:16:28 +0000] DEBUG: Found recipe default in cookbook test_recipe
[Thu, 02 Feb 2012 02:16:28 +0000] ERROR: Running exception handlers
[Thu, 02 Feb 2012 02:16:28 +0000] FATAL: Saving node information to /var/cache/chef/failed-run-data.json
[Thu, 02 Feb 2012 02:16:28 +0000] ERROR: Exception handlers complete
[Thu, 02 Feb 2012 02:16:28 +0000] DEBUG: Re-raising exception: NoMethodError - undefined method []' for nil:NilClass /var/cache/chef/cookbooks/test_recipe/recipes/default.rb:34:in
from_file’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/cookbook_version.rb:578:in load_recipe' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/mixin/language_include_recipe.rb:40:in
include_recipe’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/mixin/language_include_recipe.rb:27:in each' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/mixin/language_include_recipe.rb:27:in
include_recipe’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/run_context.rb:72:in load' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/run_context.rb:69:in
each’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/run_context.rb:69:in load' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/client.rb:195:in
setup_run_context’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/client.rb:159:in run' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/application/client.rb:239:in
run_application’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/application/client.rb:229:in loop' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/application/client.rb:229:in
run_application’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/application.rb:67:in run' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/chef-client:26 /usr/bin/chef-client:19:in
load’
/usr/bin/chef-client:19
[Thu, 02 Feb 2012 02:16:28 +0000] FATAL: Stacktrace dumped to /var/cache/chef/chef-stacktrace.out
[Thu, 02 Feb 2012 02:16:28 +0000] DEBUG: NoMethodError: undefined method []' for nil:NilClass /var/cache/chef/cookbooks/test_recipe/recipes/default.rb:34:in
from_file’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/cookbook_version.rb:578:in load_recipe' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/mixin/language_include_recipe.rb:40:in
include_recipe’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/mixin/language_include_recipe.rb:27:in each' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/mixin/language_include_recipe.rb:27:in
include_recipe’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/run_context.rb:72:in load' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/run_context.rb:69:in
each’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/run_context.rb:69:in load' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/client.rb:195:in
setup_run_context’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/client.rb:159:in run' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/application/client.rb:239:in
run_application’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/application/client.rb:229:in loop' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/../lib/chef/application/client.rb:229:in
run_application’
/usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/…/lib/chef/application.rb:67:in run' /usr/lib/ruby/gems/1.8/gems/chef-0.10.4/bin/chef-client:26 /usr/bin/chef-client:19:in
load’
/usr/bin/chef-client:19
[Thu, 02 Feb 2012 02:16:28 +0000] FATAL: NoMethodError: undefined method `[]’ for nil:NilClass
so… why does this throw the exception? i’m not a savvy ruby coder,
but shouldn’t the “or” in that line address the fact that node[:wewt][:role]
doesn’t exist for this node?
if i edit this node’s attr data and add in the new-style attributes, the
run will succeed.
i could go back and populate this node attr data for all legacy hosts,
but i don’t want to if i don’t have to, if there’s a better answer.
thanks y’all,
kallen