class Kitchen::Provisioner::Chef::CommonSandbox
@api private
@author Fletcher Nichol <fnichol@nichol.ca>
Chef-related provisioners.
Internal object to manage common sandbox preparation for
def all_files_in_cookbooks
- Api: - private
Returns:
-
(Array- an array of absolute paths to files)
def all_files_in_cookbooks Util.list_directory(tmpbooks_dir, include_dot: true, recurse: true) .select { |fn| File.file?(fn) } end
def berksfile
- Api: - private
Returns:
-
(String)- an absolute path to a Berksfile, relative to the
def berksfile basename = config[:berksfile_path] || "Berksfile" File.expand_path(basename, config[:kitchen_root]) end
def cookbooks_dir
- Api: - private
Returns:
-
(String)- an absolute path to a cookbooks/ directory, relative
def cookbooks_dir File.join(config[:kitchen_root], "cookbooks") end
def cp_cookbooks
- Api: - private
def cp_cookbooks info("Preparing cookbooks from project directory") debug("Using cookbooks from #{cookbooks_dir}") FileUtils.mkdir_p(tmpbooks_dir) FileUtils.cp_r(File.join(cookbooks_dir, "."), tmpbooks_dir) cp_site_cookbooks if File.directory?(site_cookbooks_dir) cp_this_cookbook if File.exist?(metadata_rb) end
def cp_site_cookbooks
- Api: - private
def cp_site_cookbooks info("Preparing site-cookbooks from project directory") debug("Using cookbooks from #{site_cookbooks_dir}") FileUtils.mkdir_p(tmpsitebooks_dir) FileUtils.cp_r(File.join(site_cookbooks_dir, "."), tmpsitebooks_dir) end
def cp_this_cookbook
- Api: - private
def cp_this_cookbook info("Preparing current project directory as a cookbook") debug("Using metadata.rb from #{metadata_rb}") cb_name = MetadataChopper.extract(metadata_rb).first || raise(UserError, "The metadata.rb does not define the 'name' key." \ " Please add: `name '<cookbook_name>'` to metadata.rb and retry") cb_path = File.join(tmpbooks_dir, cb_name) glob = Util.list_directory(config[:kitchen_root]) FileUtils.mkdir_p(cb_path) FileUtils.cp_r(glob, cb_path) end
def filter_only_cookbook_files
- Api: - private
def filter_only_cookbook_files info("Removing non-cookbook files before transfer") FileUtils.rm(all_files_in_cookbooks - only_cookbook_files) Util.list_directory(tmpbooks_dir, recurse: true) .reverse_each { |fn| FileUtils.rmdir(fn) if File.directory?(fn) && Dir.empty?(fn) } end
def initialize(config, sandbox_path, instance)
-
instance(Instance) -- an instance -
sandbox_path(String) -- path to local sandbox directory -
config(Hash) -- configuration hash
def initialize(config, sandbox_path, instance) @config = config @sandbox_path = sandbox_path @instance = instance end
def logger
- Api: - private
Returns:
-
(Logger)- the instance's logger or Test Kitchen's common
def logger instance ? instance.logger : Kitchen.logger end
def make_fake_cookbook
- Api: - private
def make_fake_cookbook info("Policyfile, Berksfile, cookbooks/, or metadata.rb not found " \ "so Chef Infra Client will run, but do nothing. Is this intended?") name = File.basename(config[:kitchen_root]) fake_cb = File.join(tmpbooks_dir, name) FileUtils.mkdir_p(fake_cb) File.open(File.join(fake_cb, "metadata.rb"), "wb") do |file| file.write(%{name "#{name}"\n}) end end
def metadata_rb
- Api: - private
Returns:
-
(String)- an absolute path to a metadata.rb, relative to the
def metadata_rb File.join(config[:kitchen_root], "metadata.rb") end
def only_cookbook_files
- Api: - private
Returns:
-
(Array- an array of absolute paths to files)
def only_cookbook_files glob = File.join("*", "{#{config[:cookbook_files_glob]}}") Util.safe_glob(tmpbooks_dir, glob, File::FNM_DOTMATCH) .select { |fn| File.file?(fn) && ! %w{. ..}.include?(fn) } end
def policyfile
- Api: - private
Returns:
-
(String)- an absolute path to a Policyfile, relative to the
def policyfile basename = config[:policyfile_path] || config[:policyfile] || "Policyfile.rb" File.expand_path(basename, config[:kitchen_root]) end
def populate
def populate prepare_json prepare_cache prepare_cookbooks prepare(:data) prepare(:data_bags) prepare(:environments) prepare(:nodes) prepare(:roles) prepare(:clients) prepare( :secret, type: :file, dest_name: "encrypted_data_bag_secret", key_name: :encrypted_data_bag_secret_key_path ) end
def prepare(component, opts = {})
- Api: - private
Options Hash:
(**opts)-
:dest_name(String) -- the destination file or directory -
:key_name(Symbol) -- the key name in the config hash from -
:type(Symbol) -- whether the component is a directory or
Parameters:
-
opts(Hash) -- optional configuration -
component(Symbol, String) -- a component name such as `:node`
def prepare(component, opts = {}) opts = { type: :directory }.merge(opts) key_name = opts.fetch(:key_name, "#{component}_path") src = config[key_name.to_sym] return if src.nil? info("Preparing #{component}") debug("Using #{component} from #{src}") dest = File.join(sandbox_path, opts.fetch(:dest_name, component.to_s)) case opts[:type] when :directory FileUtils.mkdir_p(dest) Array(src).each { |dir| FileUtils.cp_r(Util.list_directory(dir), dest) } when :file FileUtils.mkdir_p(File.dirname(dest)) Array(src).each { |file| FileUtils.cp_r(file, dest) } end end
def prepare_cache
- Api: - private
def prepare_cache FileUtils.mkdir_p(File.join(sandbox_path, "cache")) end
def prepare_cookbooks
- Api: - private
def prepare_cookbooks if File.exist?(policyfile) resolve_with_policyfile elsif File.exist?(berksfile) resolve_with_berkshelf elsif File.directory?(cookbooks_dir) cp_cookbooks elsif File.exist?(metadata_rb) cp_this_cookbook else make_fake_cookbook end filter_only_cookbook_files end
def prepare_json
- Api: - private
def prepare_json dna = if File.exist?(policyfile) update_dna_for_policyfile else config[:attributes].merge(run_list: config[:run_list]) end info("Preparing dna.json") debug("Creating dna.json from #{dna.inspect}") File.open(File.join(sandbox_path, "dna.json"), "wb") do |file| file.write(dna.to_json) end end
def resolve_with_berkshelf
- Api: - private
def resolve_with_berkshelf Kitchen.mutex.synchronize do Chef::Berkshelf.new(berksfile, tmpbooks_dir, logger:, always_update: config[:always_update_cookbooks]).resolve end end
def resolve_with_policyfile
- Api: - private
def resolve_with_policyfile Kitchen.mutex.synchronize do Chef::Policyfile.new( policyfile, sandbox_path, logger:, always_update: config[:always_update_cookbooks], policy_group: config[:policy_group], license: config[:chef_license] ).resolve end end
def site_cookbooks_dir
- Api: - private
Returns:
-
(String)- an absolute path to a site-cookbooks/ directory,
def site_cookbooks_dir File.join(config[:kitchen_root], "site-cookbooks") end
def tmpbooks_dir
- Api: - private
Returns:
-
(String)- an absolute path to a cookbooks/ directory in the
def tmpbooks_dir File.join(sandbox_path, "cookbooks") end
def tmpsitebooks_dir
- Api: - private
Returns:
-
(String)- an absolute path to a site cookbooks directory in the
def tmpsitebooks_dir File.join(sandbox_path, "cookbooks") end
def update_dna_for_policyfile
def update_dna_for_policyfile policy = Chef::Policyfile.new( policyfile, sandbox_path, logger:, always_update: config[:always_update_cookbooks], policy_group:, license: config[:chef_license] ) Kitchen.mutex.synchronize do policy.compile end policy_name = JSON.parse(File.read(policy.lockfile))["name"] policy_group = config[:policy_group] || "local" config[:attributes].merge(policy_name:, policy_group:) end