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

LWRP纯ruby代码与其他cookbook资源执行顺序,ruby,chef-infra,cookbook,lwrp,Ruby,Chef Infra,Cookbook,Lwrp,我很难理解到底发生了什么,为什么纯ruby代码被先执行,尽管代码被放在最后,这是action:install包含的一部分: action :install do ... windows_package "#{installation_name}" do source "#{Chef::Config[:file_cache_path]}\\#{installer_filename}" options "INSTALLDIR=\"#{install

我很难理解到底发生了什么,为什么纯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
它找不到
#{installation\u path}\\bin\\mysql.exe
,因为它尚未安装,尽管该块位于操作的末尾

有人能告诉我我错在哪里吗?为什么其他资源(在本例中已在windows LWRP中定义)在末尾而不是在开头执行?
我如何修复它?

Chef有一个双通道系统,请参见

  • 首先通过“编译”食谱并在集合中添加资源
  • 第二步是“收敛”,并针对每个资源检查是否需要更新并采取相应行动

在您的lwrp中,它中的ruby一经处理就运行,将您的代码包含在
ruby_块
resource()中,以便在收敛时执行

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

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

这将导致此代码在运行时求值。您还需要在
ruby\u块中添加
only\u if
not\u if
,或
action:nothing
,以确保它仅在需要时运行。基本上,
not\u if
only\u if
将运行SQL代码检查密码是否设置,如果该块返回false,则密码更改将不会运行

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

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
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