有没有办法让 Chef 在 运行 期间了解存档文件的内容?

Is there a way for Chef to become aware of an archive file's contents during a run?

我有一个厨师食谱,它克隆了一个 git 存储库的特定分支,该存储库包含两个 .tgz 文件和一个 .sql 文件。回购中的文件名遵循约定,但带有时间戳,这意味着无法确定每个 运行 的确切名称。克隆存储库后,我希望 chef 提取两个 .tgz 文件。

我已经完成了所有工作,直到 chef 需要提取 .tgz 文件的部分。客户端 运行 总是出错,tgz 文件名为 nil。我认为问题在于,由于厨师的工作方式,厨师可能无法“发现”在 运行 阶段添加到目录的文件名。

在测试期间,我发现如果我在 厨师 运行 之前克隆 git 存储库 ,那么它的内容将存储在食谱的 files/ 目录,这些文件包含在 Chef 的缓存中,并按预期提取。我相信这是可行的,因为 .tgz 文件在这一点上为厨师所熟知;在 运行 期间 不提供它们。这个 我可以考虑作为最后手段的解决方案,但它并不理想,因为我想尽可能少地在最终用户的本地计算机上做工作。

我想知道我的理解是否正确,是否有办法实现我所概述的内容。这是我的代码:

# Clone the repository
execute "Cloning the #{backup_version} from the #{backup_repository_url} repository" do
    command "su #{user} -c 'git clone --single-branch --branch #{backup_version} #{backup_repository_url} #{backup_holding_area}'"
    cwd web_root
end

# I need all three files eventually, so find their paths in the directory 
# they were cloned to and store them in a hash
backup_files = Hash.new
["code", "media", "db"].each do |type|
    backup_files[type.to_sym] = Dir["#{backup_holding_area}/*"].find{ |file| file.include?(type) }
end

# I need to use all three files eventually, but only code and media are .tgz files
# This nil check is where chef fails
unless backup_files[:code].nil? || backup_files[:media].nil? || backup_files[:db].nil?
    backup_files.slice(:code, :media).each do |key, file|
        archive_file "Restore the backup from #{file}" do
            path file
            destination web_root
            owner user
            group group
            overwrite :auto
            only_if { ::File.exist?(file) }
        end
    end
end

厨师-客户有不同的阶段运行。 “编译”和“收敛”阶段是这种情况下的相关阶段。在 运行 期间,首先是“编译”阶段,然后是“收敛”阶段。

  • 编译阶段:不在 Chef 资源中的“代码”
  • 收敛阶段:Chef 资源中的“代码”

例如,下面的变量赋值将在编译阶段运行。

backup_files = Hash.new

execute 块(如下所示)在收敛期间将是 运行:

execute "Cloning the #{backup_version} from the #{backup_repository_url} repository" do
    command "su #{user} -c 'git clone --single-branch --branch #{backup_version} #{backup_repository_url} #{backup_holding_area}'"
    cwd web_root
end

由于所有的变量赋值都在资源块之外,所以在实际收敛之前很久就已经赋值了。即当文件甚至不在目标目录中时。所以他们没有我们期望的文件名。

确保我们获得文件名的一种方法是在 Chef 资源内部分配变量。其中一个 resourceruby_block 资源。

使用这个我们可以得到如下配方:

# use execute to clone or use the git resource with properties as required
git backup_holding_area do
  repository backup_repository_url
  revision backup_version
  action :checkout
end

# Iterating over files in directory is still ok as there only 3 files
ruby_block 'get and extract code and media tar files' do
  block do
    Dir.entries("#{backup_holding_area}").each do |file|
      if file.include?('tar.gz')
        # appropriate flags can be used for "tar" command as per requirement
        system("tar xzf #{backup_holding_area}/#{file} -C #{web_root}")
      end
    end
  end
end