vagrant/plugins/provisioners/cfengine/provisioner.rb
Chris Roberts ea25996b21
Update Vagrant behavior outside of installers
Remove customized require behaviors and modify the bin executable
to check for missing tools that Vagrant expects to exist when
running outside of an installer.
2025-04-02 11:40:17 -07:00

142 lines
5.2 KiB
Ruby

# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
require "log4r"
module VagrantPlugins
module CFEngine
class Provisioner < Vagrant.plugin("2", :provisioner)
def provision
if @machine.config.vm.communicator == :winrm
raise Vagrant::Errors::ProvisionerWinRMUnsupported,
name: "cfengine"
end
@logger = Log4r::Logger.new("vagrant::plugins::cfengine")
@logger.info("Checking for CFEngine installation...")
handle_cfengine_installation
if @config.files_path
@machine.ui.info(I18n.t("vagrant.cfengine_installing_files_path"))
install_files(Pathname.new(@config.files_path).expand_path(@machine.env.root_path))
end
handle_cfengine_bootstrap if @config.mode == :bootstrap
if @config.mode == :single_run
# Just let people know
@machine.ui.info(I18n.t("vagrant.cfengine_single_run"))
end
if @config.run_file
@machine.ui.info(I18n.t("vagrant.cfengine_single_run_execute"))
path = Pathname.new(@config.run_file).expand_path(@machine.env.root_path)
machine.communicate.upload(path.to_s, @config.upload_path)
cfagent("-KI -f #{@config.upload_path}#{cfagent_classes_args}#{cfagent_extra_args}")
end
end
protected
# This runs cf-agent with the given arguments.
def cfagent(args, options=nil)
options ||= {}
command = "/var/cfengine/bin/cf-agent #{args}"
@machine.communicate.sudo(command, error_check: options[:error_check]) do |type, data|
if [:stderr, :stdout].include?(type)
# Output the data with the proper color based on the stream.
color = type == :stdout ? :green : :red
@machine.ui.info(
data,
color: color, new_line: false, prefix: false)
end
end
end
# Returns the arguments for the classes configuration if they are
# set.
#
# @return [String]
def cfagent_classes_args
return "" if !@config.classes
args = @config.classes.map { |c| "-D#{c}" }.join(" ")
return " #{args}"
end
# Extra arguments for calles to cf-agent.
#
# @return [String]
def cfagent_extra_args
return "" if !@config.extra_agent_args
return " #{@config.extra_agent_args}"
end
# This handles checking if the CFEngine installation needs to
# be bootstrapped, and bootstraps if it does.
def handle_cfengine_bootstrap
@logger.info("Bootstrapping CFEngine...")
if !@machine.guest.capability(:cfengine_needs_bootstrap, @config)
@machine.ui.info(I18n.t("vagrant.cfengine_no_bootstrap"))
return
end
# Needs bootstrap, let's determine the parameters
policy_server_address = @config.policy_server_address
if !policy_server_address
policy_server_address = @machine.guest.capability(:read_ip_address)
raise Vagrant::Errors::CFEngineCantAutodetectIP if !policy_server_address
@machine.ui.info(I18n.t("vagrant.cfengine_detected_ip", address: policy_server_address))
end
@machine.ui.info(I18n.t("vagrant.cfengine_bootstrapping",
policy_server: policy_server_address))
result = cfagent("--bootstrap #{policy_server_address}", error_check: false)
raise Vagrant::Errors::CFEngineBootstrapFailed if result != 0
# Policy hubs need to do additional things before they're ready
# to accept agents. Force that run now...
if @config.am_policy_hub
@machine.ui.info(I18n.t("vagrant.cfengine_bootstrapping_policy_hub"))
cfagent("-KI -f /var/cfengine/masterfiles/failsafe.cf#{cfagent_classes_args}")
cfagent("-KI #{cfagent_classes_args}#{cfagent_extra_args}")
end
end
# This handles verifying the CFEngine installation, installing it
# if it was requested, and so on. This method will raise exceptions
# if things are wrong.
def handle_cfengine_installation
if !@machine.guest.capability?(:cfengine_installed)
@machine.ui.warn(I18n.t("vagrant.cfengine_cant_detect"))
return
end
installed = @machine.guest.capability(:cfengine_installed)
if !installed || @config.install == :force
raise Vagrant::Errors::CFEngineNotInstalled if !@config.install
@machine.ui.info(I18n.t("vagrant.cfengine_installing"))
@machine.guest.capability(:cfengine_install, @config)
if !@machine.guest.capability(:cfengine_installed)
raise Vagrant::Errors::CFEngineInstallFailed
end
end
end
# This installs a set of files into the CFEngine folder within
# the machine.
#
# @param [Pathname] local_path
def install_files(local_path)
@logger.debug("Copying local files to CFEngine: #{local_path}")
@machine.communicate.sudo("rm -rf /tmp/cfengine-files")
@machine.communicate.upload(local_path.to_s, "/tmp/cfengine-files")
@machine.communicate.sudo("cp -R /tmp/cfengine-files/* /var/cfengine")
end
end
end
end