Skip to content

Instantly share code, notes, and snippets.

@RulerOf
Created March 29, 2025 23:13
Show Gist options
  • Save RulerOf/98d1e57bcb4436b7952e0b5e30ac479b to your computer and use it in GitHub Desktop.
Save RulerOf/98d1e57bcb4436b7952e0b5e30ac479b to your computer and use it in GitHub Desktop.
Dynamically generate a chef Berksfile from an existing Chef Policyfile.rb
require 'chef-cli/policyfile_services/install'
def policyfile_to_berksfile(policyfile_path)
pf = ChefCLI::PolicyfileServices::Install.new(policyfile: policyfile_path).policyfile_compiler
# Extract sources
sources = pf.default_source.map do |source|
case source
when ChefCLI::Policyfile::CommunityCookbookSource
"source \"#{source.uri}\""
when ChefCLI::Policyfile::ChefServerCookbookSource
"source :chef_server, \"#{source.uri}\""
else
nil
end
end.compact
# Extract cookbooks, excluding the current cookbook
current_cookbook_name = pf.dsl.name
cookbooks = pf.fixed_version_cookbooks_specs.map do |name, spec|
next if name == current_cookbook_name
case spec.source_type
when :path
"cookbook '#{name}', path: '#{spec.source_options[:path]}'"
when :git, :github
"cookbook '#{name}', git: '#{spec.source_options[:git]}'"
else
nil
end
end.compact
# Create Berksfile content
(sources + cookbooks + ["metadata"]).join("\n")
end
# Define the path to the Policyfile
# This makes the assumption that you're only interested in a single policyfile.
# That works fine for me, but you may have other needs. Modify appropriately.
policyfile_path = File.expand_path('../Policyfile.rb', __FILE__)
# Generate and evaluate the Berksfile content
eval(policyfile_to_berksfile(policyfile_path))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment