Reputation: 4533
I'm having troubles trying to understand what's going on, why pure ruby code is executed first despite that the code is put last, this is a part of what the action :install contains:
action :install do
...
windows_package "#{installation_name}" do
source "#{Chef::Config[:file_cache_path]}\\#{installer_filename}"
options "INSTALLDIR=\"#{installation_path}\""
action :install
not_if {::Dir.exists?("#{installation_path}\\bin")}
end
env "MYSQL_PATH" do
value "#{installation_path}"
end
windows_path "#{installation_path}\\bin" do
action :add
end
windows_batch "Installing Service" do
code <<-EOH
set MYSQL_PATH="#{installation_path}"
call %MYSQL_PATH%\\bin\\mysqld-nt.exe --install MySQL
EOH
end
service "MySQL" do
action :start
end
service "MySQL" do
action :enable
end
change_pass_str = "call \"#{installation_path}\\bin\\mysql.exe\" -u root --execute \"UPDATE mysql.user SET Password=PASSWORD('#{root_password}') WHERE User='root';FLUSH PRIVILEGES;\""
puts change_pass_str
password_set_result = system(change_pass_str)
log !password_set_result ? "Password wasn't changed since root already have a password defined. Maybe there's still data from a previous installation." : "Password has been set!"
end
Please ignore the fact that i didn't put the variable definition, and know that they are well defined. The thing is that when this part of the lwrp is executed
change_pass_str = "call \"#{installation_path}\\bin\\mysql.exe\" -u root --execute \"UPDATE mysql.user SET Password=PASSWORD('#{root_password}') WHERE User='root';FLUSH PRIVILEGES;\""
puts change_pass_str
password_set_result = system(change_pass_str)
it can't find #{installation_path}\\bin\\mysql.exe
since it is not yet installed, in spite of that the block is at the end of the action.
Can anyone point me what is my mistake? why the other (already defined in this case in windows LWRP) resources are executed at the end instead of the begining? How can i fix it?
Upvotes: 0
Views: 506
Reputation: 4223
LWRPs are no different than recipes with regards to execution order. So, just like in a recipe, any ruby code that is not inside a resource will be executed during the 'resource gathering' phase. In your case, you need to wrap your code in a ruby_block
or execute
resource like this:
ruby_block 'change the password' do
block {
change_pass_str = "call \"#{installation_path}\\bin\\mysql.exe\" -u root --execute \"UPDATE mysql.user SET Password=PASSWORD('#{root_password}') WHERE User='root';FLUSH PRIVILEGES;\""
puts change_pass_str
password_set_result = system(change_pass_str)
end
end
OR
execute'change the password' do
command "call \"#{installation_path}\\bin\\mysql.exe\" -u root --execute \"UPDATE mysql.user SET Password=PASSWORD('#{root_password}') WHERE User='root';FLUSH PRIVILEGES;\""
end
That will cause this code to evaluate at run-time. You'll also want to add an only_if
, not_if
, or action :nothing
to that ruby_block
to ensure it only runs when needed. Basically, a not_if
or only_if
would run SQL code to check if the password was set or not, and if that block returned false, then the password change wouldn't run.
Alternately, you can use action :nothing
to set the resource to not run, and then use a notification or subscription to trigger the resource to run only after mysql is installed.
Upvotes: 1
Reputation: 15784
Chef has a two pass system see THIS
In your lwrp, the ruby in it is run as soon as being processed, include your code into a ruby_block
resource (DOC) for it to be executed at the converge time.
Upvotes: 1