Are all attribute files included even when their corresponding recipes are not?

Hi,

I’d like to use chef to setup my database. On some nodes (say,
production) the database is already set up and I don’t need to do
anything. On other nodes (say, development) I want to include the
mysql::server recipe, start a new mysql instance and create my
application database.

I tried this in my recipe:

if !node[:mysql][:server_root_password].empty?
mysql_database “create #{node[:app][:database][:name]} database” do
host node[:app][:database][:host]
username "root"
password node[:mysql][:server_root_password]
database node[:app][:database][:name]

    action :create_db
end

end

I don’t want to include the db root password in my attributes (it’s
not needed if the database is already created). I was happy to see
that the mysql::server password generates a root password. I was
expecting node[:mysql][:server_root_password] to only be set when I
included the mysql::server recipe and empty otherwise. To my surprise
it is set, even if I am only using the mysql client recipe.

Is it true that all attribute files are included when only some of the
recipes are used? When a recipe has a name like server.rb is there
any special treatment for an attribute file of the same name? How can
I tell chef to ignore this attribute file unless the server recipe is
being executed?

One solution may be to move the line that generates the password out
of the attributes and into the mysql::server recipe. Is this
reasonable?

Thanks,
Jay

Hello!
On Monday, April 25, 2011 at 11:48 PM, Jay Buffington wrote:

Is it true that all attribute files are included when only some of the
recipes are used? When a recipe has a name like server.rb is there
any special treatment for an attribute file of the same name? How can
I tell chef to ignore this attribute file unless the server recipe is
being executed?
Correct - all attributes from all cookbooks on the node are loaded when chef-client runs, regardless of a particular recipe that uses them is included in the run list or via an include_recipe.
One solution may be to move the line that generates the password out
of the attributes and into the mysql::server recipe. Is this
reasonable?
That is precisely where they should be set :). Hence this ticket:

http://tickets.opscode.com/browse/COOK-526

To further explain the reason why they should be in the recipe isn't just because they're only used by that recipe, but also because they are calculated. The attributes files are really meant to be as declarative as possible to set sane defaults for the cookbook so using the attributes can be done without causing some nil error on attributes that don't exist.

--
Opscode, Inc.
Joshua Timberman, Director of Training and Services
IRC, Skype, Twitter, Github: jtimberman

That is precisely where they should be set :). Hence this ticket:

http://tickets.opscode.com/browse/COOK-526

To further explain the reason why they should be in the recipe isn't just because they're only used by that recipe, but also because they are calculated. The attributes files are really meant to be as declarative as possible to set sane defaults for the cookbook so using the attributes can be done without causing some nil error on attributes that don't exist.

That makes a lot of sense. For now I've worked around it by putting
this in my recipe:

begin
dbh = ::Mysql.connect(node[:app][:database][:host],
node[:app][:database][:user], node[:app][:database][:password])
dbh.select_db( node[:app][:database][:name] )
rescue
log "looks like the #{node[:app][:database][:name]} database
doesn't exist, creating it and granting permissions to
#{node[:app][:database][:user]}"

# if the above throws, we need to provision the database
mysql_database "create #{node[:app][:database][:name]} database" do
    host node[:app][:database][:host]
    username "root"
    password node[:mysql][:server_root_password]
    database node[:app][:database][:name]

    sql "GRANT ALL ON #{node[:app][:database][:name]}.* TO

'#{node[:app][:database][:user]}'@'#{node[:app][:database][:host]}'
IDENTIFIED BY '#{node[:app][:database][:password]}'"

    action [:create_db, :query]
end

ensure
dbh.close if dbh
end

I removed the info line in the mysql lwrp that logs the query that is
being executed so my password doesn't show up in the logs.

Jay