vaguerent/lib/vagrant/shared_helpers.rb
Chris Roberts e958c6183a Adds initial HCP config support
Adds initial basic support for HCP based configuration in vagrant-go.
The initalization process has been updated to remove Vagrantfile parsing
from the client, moving it to the runner using init jobs for the basis
and the project (if there is one). Detection is done on the file based
on extension for Ruby based parsing or HCP based parsing.

Current HCP parsing is extremely simple and currently just a base to
build off. Config components will be able to implement an `Init`
function to handle receiving configuration data from a non-native source
file. This will be extended to include a default approach for injecting
defined data in the future.

Some cleanup was done in the state around validations. Some logging
adjustments were applied on the Ruby side for better behavior
consistency.

VirtualBox provider now caches locale detection to prevent multiple
checks every time the driver is initialized.
2023-09-07 17:26:10 -07:00

312 lines
9.3 KiB
Ruby

# Copyright (c) HashiCorp, Inc.
# SPDX-License-Identifier: BUSL-1.1
require "pathname"
require "tempfile"
require "thread"
module Vagrant
@@global_lock = Mutex.new
# This is the default endpoint of the Vagrant Cloud in
# use. API calls will be made to this for various functions
# of Vagrant that may require remote access.
#
# @return [String]
DEFAULT_SERVER_URL = "https://vagrantcloud.com".freeze
# Max number of seconds to wait for joining an active thread.
#
# @return [Integer]
# @note This is not the maximum time for a thread to complete.
THREAD_MAX_JOIN_TIMEOUT = 60
# This holds a global lock for the duration of the block. This should
# be invoked around anything that is modifying process state (such as
# environmental variables).
def self.global_lock
@@global_lock.synchronize do
return yield
end
end
# This returns a true/false showing whether we're running from the
# environment setup by the Vagrant installers.
#
# @return [Boolean]
def self.in_installer?
!!ENV["VAGRANT_INSTALLER_ENV"]
end
# This returns a true/false if we are running within a bundler environment
#
# @return [Boolean]
def self.in_bundler?
!!ENV["BUNDLE_GEMFILE"] &&
!defined?(::Bundler).nil?
end
# Returns the path to the embedded directory of the Vagrant installer,
# if there is one (if we're running in an installer).
#
# @return [String]
def self.installer_embedded_dir
return nil if !Vagrant.in_installer?
ENV["VAGRANT_INSTALLER_EMBEDDED_DIR"]
end
# Should the plugin system be initialized
#
# @return [Boolean]
def self.plugins_init?
!ENV['VAGRANT_DISABLE_PLUGIN_INIT']
end
# This returns whether or not 3rd party plugins should and can be loaded.
#
# @return [Boolean]
def self.plugins_enabled?
!ENV["VAGRANT_NO_PLUGINS"]
end
# Whether or not super quiet mode is enabled. This is ill-advised.
#
# @return [Boolean]
def self.very_quiet?
!!ENV["VAGRANT_I_KNOW_WHAT_IM_DOING_PLEASE_BE_QUIET"]
end
# The current log level for Vagrant
#
# @return [String]
def self.log_level
ENV.fetch("VAGRANT_LOG", "fatal").downcase
end
# Returns the URL prefix to the server.
#
# @return [String]
def self.server_url(config_server_url=nil)
result = ENV["VAGRANT_SERVER_URL"]
result = config_server_url if result == "" or result == nil
result || DEFAULT_SERVER_URL
end
# The source root is the path to the root directory of the Vagrant source.
#
# @return [Pathname]
def self.source_root
@source_root ||= Pathname.new(File.expand_path('../../../', __FILE__))
end
# This returns the path to the ~/.vagrant.d folder where Vagrant's
# per-user state is stored.
#
# @return [Pathname]
def self.user_data_path
# Use user specified env var if available
path = ENV["VAGRANT_HOME"]
# On Windows, we default to the USERPROFILE directory if it
# is available. This is more compatible with Cygwin and sharing
# the home directory across shells.
if !path && ENV["USERPROFILE"]
path = "#{ENV["USERPROFILE"]}/.vagrant.d"
end
# Fallback to the default
path ||= "~/.vagrant.d"
Pathname.new(path).expand_path
end
# This returns true/false if the running version of Vagrant is
# a pre-release version (development)
#
# @return [Boolean]
def self.prerelease?
Gem::Version.new(Vagrant::VERSION).prerelease?
end
# This returns true/false if the Vagrant should allow prerelease
# versions when resolving plugin dependency constraints
#
# @return [Boolean]
def self.allow_prerelease_dependencies?
!!ENV["VAGRANT_ALLOW_PRERELEASE"]
end
# This allows control over dependency resolution when installing
# plugins into vagrant. When true, dependency libraries that Vagrant
# core relies upon will be hard constraints.
#
# @return [Boolean]
def self.strict_dependency_enforcement
if ENV["VAGRANT_DISABLE_STRICT_DEPENDENCY_ENFORCEMENT"]
false
else
true
end
end
# Automatically install locally defined plugins instead of
# waiting for user confirmation.
#
# @return [Boolean]
def self.auto_install_local_plugins?
if ENV["VAGRANT_INSTALL_LOCAL_PLUGINS"]
true
else
false
end
end
# Use Ruby Resolv in place of libc
#
# @return [boolean] enabled or not
def self.enable_resolv_replace
if ENV["VAGRANT_ENABLE_RESOLV_REPLACE"]
if !ENV["VAGRANT_DISABLE_RESOLV_REPLACE"]
begin
require "resolv-replace"
true
rescue
false
end
else
false
end
end
end
# Set the global logger
#
# @param log Logger
# @return [Logger]
def self.global_logger=(log)
@_global_logger = log
end
# Get the global logger instance
#
# @return [Logger]
def self.global_logger
if @_global_logger.nil?
require "log4r"
@_global_logger = Log4r::Logger.new("vagrant::global")
end
@_global_logger
end
# Add a new block of default CLI options which
# should be automatically added to all commands
#
# @param [Proc] block Proc instance containing OptParser configuration
# @return [nil]
def self.add_default_cli_options(block)
if !block.is_a?(Proc)
raise TypeError,
"Expecting type `Proc` but received `#{block.class}`"
end
if block.arity != 1 && block.arity != -1
raise ArgumentError,
"Proc must accept OptionParser argument"
end
@_default_cli_options = [] if !@_default_cli_options
@_default_cli_options << block
nil
end
# Array of default CLI options to automatically
# add to commands.
#
# @return [Array<Proc>] Default optparse options
def self.default_cli_options
@_default_cli_options = [] if !@_default_cli_options
@_default_cli_options.dup
end
# Check if Vagrant is running in server mode
#
# @return [Boolean]
def self.server_mode?
!!@_server_mode
end
# Flag Vagrant as running in server mode
#
# @return [true]
def self.enable_server_mode!
if !server_mode?
Util::HCLogOutputter.new("hclog")
Log4r::Outputter["hclog"].formatter = Util::HCLogFormatter.new
Log4r::Outputter.stderr.formatter = Log4r::Outputter["hclog"].formatter
Log4r::RootLogger.instance.outputters = Log4r::Outputter["hclog"]
Log4r::Logger.each_logger do |l|
l.outputters = Log4r::Outputter["hclog"] #if l.parent&.is_root?
end
Log4r::Logger::Repository.class_eval do
def self.[]=(n, l)
self.synchronize do
l.outputters = Log4r::Outputter["hclog"] # if l.parent&.is_root?
instance.loggers[n] = l
end
end
end
# By default only display error logs from the mappers unless explicitly
# requested due to their verbosity
if ENV["VAGRANT_LOG_MAPPER"].to_s == ""
l = Log4r::Logger.factory("vagrantplugins::commandserve::mappers")
l.level = Log4r::ERROR
end
end
Log4r::Logger.factory("vagrant").trace("service logger initialization")
Log4r::Logger.factory("vagrantplugins").trace("service logger initialization")
load_vagrant_proto!
SERVER_MODE_CALLBACKS.each(&:call)
@_server_mode = true
end
# Load the vagrant proto messages
def self.load_vagrant_proto!
return if @_vagrant_proto_loaded
# Update the load path so our protos can be located
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs").to_s
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs/proto").to_s
$LOAD_PATH << Vagrant.source_root.join("lib/vagrant/protobufs/proto/vagrant_plugin_sdk").to_s
# Load our protos so they are available
require 'vagrant/protobufs/proto/vagrant_server/server_pb'
require 'vagrant/protobufs/proto/vagrant_server/server_services_pb'
require 'vagrant/protobufs/proto/ruby_vagrant/ruby-server_pb'
require 'vagrant/protobufs/proto/ruby_vagrant/ruby-server_services_pb'
require 'vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_pb'
require 'vagrant/protobufs/proto/vagrant_plugin_sdk/plugin_services_pb'
require 'vagrant/protobufs/proto/plugin/grpc_broker_pb'
require 'vagrant/protobufs/proto/plugin/grpc_broker_services_pb'
@_vagrant_proto_loaded = true
end
SERVER_MODE_CALLBACKS = [
->{ Vagrant::Box.prepend(Vagrant::Box::Remote) },
->{ Vagrant::BoxCollection.prepend(Vagrant::BoxCollection::Remote) },
->{ Vagrant::BoxMetadata.prepend(Vagrant::BoxMetadata::Remote) },
->{ Vagrant::Guest.prepend(Vagrant::Guest::Remote) },
->{ Vagrant::Host.prepend(Vagrant::Host::Remote) },
->{ Vagrant::Machine.prepend(Vagrant::Machine::Remote) },
->{ Vagrant::Environment.prepend(Vagrant::Environment::Remote) },
->{ Vagrant::MachineIndex.prepend(Vagrant::MachineIndex::Remote) },
->{ Vagrant::MachineIndex::Entry.prepend(Vagrant::MachineIndex::Entry::Remote::InstanceMethods) },
->{ Vagrant::MachineIndex::Entry.extend(Vagrant::MachineIndex::Entry::Remote::ClassMethods) },
->{ Vagrant::Action::Builtin::MixinSyncedFolders.prepend(Vagrant::Action::Builtin::Remote::MixinSyncedFolders) },
->{ Vagrant::Action::Builtin::SSHRun.prepend(Vagrant::Action::Builtin::Remote::SSHRun) },
->{ Vagrant::Vagrantfile.prepend(Vagrant::Vagrantfile::Remote) },
->{ Vagrant::Util::SSH.prepend(Vagrant::Util::Remote::SSH) },
->{ Vagrant::Util::SafePuts.prepend(Vagrant::Util::Remote::SafePuts) },
].freeze
end