繁体   English   中英

厨师在 ruby 块中使用 cookbook_file

[英]Chef use cookbook_file in ruby block

我有以下代码来确定 Java 在盒子上的位置。 Java 随我们的应用程序一起提供,并且应用程序中包含的 Java 版本有所不同。

def app_java_home
  if Dir.exist?("#{app_home}/jre-server/linux")
    Dir.chdir("#{app_home}/jre-server/linux") do
      Dir.glob('jdk*').select { |f| File.directory? f }[0]
    end
  end
end

然后,在我的食谱中,我有

aws_s3_file "#{app_download_path}/#{app_s3['archive_file']}" do
  bucket app_s3['bucket']
  remote_path app_s3['remote_path']
  region aws_region
  not_if { ::Dir.exists?(app_bin_dir) }
  not_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end

execute 'extract' do
  user 'root'
  command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
  not_if { ::Dir.exists?("#{app_home}/ourapp") }
  only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end

execute 'move' do
  user 'root'
  command "mv #{app_download_path}/ourapp/ #{app_install_path}"
  not_if { ::Dir.exists?(app_home) }
end

cookbook_file "#{app_java_home}/jre/lib/security/local_policy.jar" do
  source %W[#{app_release}/local_policy.jar default/local_policy.jar]
  owner app_user_name
  group app_group_name
  mode 0755
end

cookbook_file "#{app_java_home}/jre/lib/security/US_export_policy.jar" do
  source %W[#{app_release}/US_export_policy.jar default/US_export_policy.jar]
  owner app_user_name
  group app_group_name
  mode 0755
end

但是,这两个cookbook_file资源失败,因为它找不到目录:

No such file or directory @ dir_chdir - /ourapp/jre-server/linux/

经过大量的谷歌搜索后,我得出的结论是,配方的编译时间和运行时间之间存在“不匹配”(?)。 基本上,如果我理解正确,它会首先尝试运行cookbook_file资源但失败。 所以永远不要下载、解压和安装应用程序工件。

当目录存在时,我尝试运行app_java_home ,它似乎确实按我想要的方式工作..

我尝试将cookbook_file资源放在ruby_block中,但后来我得到了:

undefined method `cookbook_file' for Chef::Resource::RubyBlock

app_java_home .. function (?) 曾经看起来像这样:

def app_java_home
  "#{app_home}/jre-server/linux/#{jdk_version}"
end

jdk_version来自数据包的位置。 这工作得很好,但是我们的系统中有一个长期存在的错误/功能请求,有时会发生“他们”得到他们放入数据包中的版本错误,导致各种问题.. 所以他们想要一种方法来删除这个依赖,而是动态地“解决这个问题”。

Ruby 和 Chef 不是我的强项,所以我不确定接下来要尝试什么。 我找到了对Chef::Resources::CookbookFile的引用(如果我理解的话,可以/应该在ruby_block中使用它),但找不到任何关于它的示例或文档。 RubyDocs 上的链接已损坏。

在此处添加答案以获得更好的解释。

  • 不在任何 Chef 资源中的任何 (Ruby) 代码都将在编译阶段运行

  • 所有资源声明都将按照定义的顺序在 Convergence 阶段运行

值得庆幸的是,如果需要,有一种方法可以使资源在编译阶段运行。 尽管恕我直言,但在特殊情况下应该谨慎行事。

根据您的评论aws_s3_fileexecute资源是解压应用程序(并创建目录)的资源。 在这种情况下,您似乎希望它们在编译阶段运行。


在 Chef 客户端 16.0 之前

run_action选项与应在编译时执行的操作一起使用。 例如execute资源采取行动:run

# Note action ":nothing" and "run_action"

execute 'extract' do
  user 'root'
  command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
  not_if { ::Dir.exists?("#{app_home}/ourapp") }
  only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
  action :nothing
end.run_action(:run)

Chef 客户端 16.0 及以上版本

我们可以为资源添加一个公共属性 execute资源示例:

# Note the extra property "compile_time"

execute 'extract' do
  user 'root'
  command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
  not_if { ::Dir.exists?("#{app_home}/ourapp") }
  only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
  compile_time true
end

最后回答问题的主题:

厨师在 ruby 块中使用 cookbook_file

这是不可能的。 请参阅顶部的第一点。 如果我们希望 Ruby 代码在收敛期间运行(而不是编译),我们将其放在ruby_block资源中。 所以它可以包含如下代码(例如):

ruby_block 'get directory' do
  block do
    def app_java_home
      "#{app_home}/jre-server/linux/#{jdk_version}"
    end
  end
end

在@seshadri_c 的帮助下,我终于设法解决了这个问题,这需要一些努力。 因为我一直误解建议等。

所以这就是我想出的(为了后代):

def jdk_version(required = true)
  base_dir = "#{app_home}/jre-server/linux"
  if Dir.exist?("#{base_dir}")
    Dir.chdir("#{app_home}/jre-server/linux") do
      Dir.glob("jdk*").each do |f|
        if File.directory?(f)
          return "#{f}"
        end
      end
    end
  end
end

def app_java_home
  return "#{app_home}/jre-server/linux/#{jdk_version}"
end

结果我只需要单独获取版本,所以我重新安排了一些功能。 我确信它可以写得更干净,但这里的诀窍是使用return而不是puts/print ,嗯,我是一名程序员。 但不是 Ruby 程序员所以不知道这是一个选项..

然后,在食谱中,我在需要的地方添加了.run_action() cookbook_file我不需要它们,这稍微简化了一些事情:

aws_s3_file "#{app_download_path}/#{app_s3['archive_file']}" do
  bucket app_s3['bucket']
  remote_path app_s3['remote_path']
  region aws_region
  not_if { ::Dir.exists?(app_bin_dir) }
  not_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end.run_action(:create)

execute 'extract' do
  user 'root'
  command "unzip #{app_download_path}/#{app_s3['archive_file']} > /dev/null"
  not_if { ::Dir.exists?("#{app_home}/app") }
  only_if { ::File.exists?("#{app_download_path}/#{app_s3['archive_file']}") }
end.run_action(:run)

execute 'move' do
  user 'root'
  command "mv #{app_download_path}/app/ #{app_install_path}"
  not_if { ::Dir.exists?(app_home) }
end.run_action(:run)


#  JCE Unlimited Strength Jurisdiction Policy Files
cookbook_file "#{app_java_home}/jre/lib/security/local_policy.jar" do
  source %W[#{app_release}/local_policy.jar default/local_policy.jar]
  owner app_user_name
  group app_group_name
  mode 0755
end

cookbook_file "#{app_java_home}/jre/lib/security/US_export_policy.jar" do
  source %W[#{app_release}/US_export_policy.jar default/US_export_policy.jar]
  owner app_user_name
  group app_group_name
  mode 0755
end

有了这一切,一切都在他们应该的时候运行,一切似乎都在工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM