LWRP纯ruby代码与其他cookbook资源执行顺序

时间:2014-09-30 05:51:40

标签: ruby chef cookbook lwrp

我在尝试理解发生了什么时遇到了麻烦,为什么首先执行纯ruby代码,尽管代码放在最后,这是action:install包含的一部分:

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

请忽略我没有放置变量定义的事实,并且知道它们定义得很好。问题是当执行lwrp的这部分时

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)

它无法找到#{installation_path}\\bin\\mysql.exe,因为它尚未安装,尽管该块已在行动的最后。

有谁能指出我的错误是什么?为什么另一个(在Windows LWRP中这种情况下已定义)资源在最后执行而不是开始执行? 我该如何解决?

2 个答案:

答案 0 :(得分:1)

Chef有两个通过系统,请参阅THIS

  • 第一遍&#39;编译&#39;配方并在集合中添加资源
  • 第二次通过&#39;收敛&#39;并为每个资源检查是否需要更新并采取相应行动。

在你的lwrp中,其中的ruby在处理后立即运行,将你的代码包含在ruby_block资源(DOC)中,以便在收敛时执行。

答案 1 :(得分:1)

LWRP与执行顺序的配方没有什么不同。因此,就像在配方中一样,任何不在资源内的ruby代码都将在“资源收集”阶段执行。在您的情况下,您需要将代码包装在ruby_blockexecute资源中,如下所示:

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    

这将导致此代码在运行时进行评估。您还需要向only_if添加not_ifaction :nothingruby_block,以确保它仅在需要时运行。基本上,not_ifonly_if将运行SQL代码来检查密码是否已设置,如果该块返回false,则密码更改将不会运行。

或者,您可以使用action :nothing将资源设置为不运行,然后使用通知或订阅来触发资源仅在安装mysql后运行。