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.
312 lines
9.3 KiB
Ruby
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
|