1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362
|
require "log4r"
# Add patches to log4r to support trace level
require "vagrant/patches/log4r"
# Set our log levels and include trace
require 'log4r/configurator'
Log4r::Configurator.custom_levels(*(["TRACE"] + Log4r::Log4rConfig::LogLevels))
# Update the default formatter within the log4r library to ensure
# sensitive values are being properly scrubbed from logger data
class Log4r::BasicFormatter
alias_method :vagrant_format_object, :format_object
def format_object(obj)
Vagrant::Util::CredentialScrubber.desensitize(vagrant_format_object(obj))
end
end
require "optparse"
module Vagrant
# This is a customized OptionParser for Vagrant plugins. It
# will automatically add any default CLI options defined
# outside of command implementations to the local option
# parser instances in use
class OptionParser < ::OptionParser
def initialize(*_)
super
Vagrant.default_cli_options.each do |opt_proc|
opt_proc.call(self)
end
end
end
end
# Inject the option parser into the vagrant plugins
# module so it is automatically used when defining
# command options
module VagrantPlugins
OptionParser = Vagrant::OptionParser
end
# Load in our helpers and utilities
require "vagrant/shared_helpers"
require "rubygems"
require "vagrant/util"
require "vagrant/plugin/manager"
# Enable logging if it is requested. We do this before
# anything else so that we can setup the output before
# any logging occurs.
if ENV["VAGRANT_LOG"] && ENV["VAGRANT_LOG"] != ""
level = Log4r::LNAMES.index(ENV["VAGRANT_LOG"].upcase)
if level.nil?
level = Log4r::LNAMES.index("FATAL")
end
if !level
# We directly write to stderr here because the VagrantError system
# is not setup yet.
$stderr.puts "Invalid VAGRANT_LOG level is set: #{ENV["VAGRANT_LOG"]}"
$stderr.puts ""
$stderr.puts "Please use one of the standard log levels: debug, info, warn, or error"
exit 1
end
# Set the logging level on all "vagrant" namespaced
# logs as long as we have a valid level.
if level
# NOTE: We must do this little hack to allow
# rest-client to write using the `<<` operator.
# See https://github.com/rest-client/rest-client/issues/34#issuecomment-290858
# for more information
class VagrantLogger < Log4r::Logger
def << msg
debug(msg.strip)
end
end
["vagrant", "vagrantplugins"].each do |lname|
logger = VagrantLogger.new(lname)
if ENV["VAGRANT_LOG_FILE"] && ENV["VAGRANT_LOG_FILE"] != ""
logger.outputters = Log4r::FileOutputter.new("vagrant", filename: ENV["VAGRANT_LOG_FILE"])
else
logger.outputters = Log4r::Outputter.stderr
end
logger.level = level
end
base_formatter = Log4r::BasicFormatter.new
if ENV["VAGRANT_LOG_TIMESTAMP"]
base_formatter = Log4r::PatternFormatter.new(
pattern: "%d [%5l] %m",
date_pattern: "%F %T"
)
end
Log4r::Outputter.stderr.formatter = Vagrant::Util::LoggingFormatter.new(base_formatter)
end
end
require 'json'
require 'pathname'
require 'stringio'
require 'childprocess'
require 'i18n'
# OpenSSL must be loaded here since when it is loaded via `autoload`
# there are issues with ciphers not being properly loaded.
require 'openssl'
# Always make the version available
require 'vagrant/version'
global_logger = Log4r::Logger.new("vagrant::global")
Vagrant.global_logger = global_logger
global_logger.info("Vagrant version: #{Vagrant::VERSION}")
global_logger.info("Ruby version: #{RUBY_VERSION}")
global_logger.info("RubyGems version: #{Gem::VERSION}")
ENV.each do |k, v|
next if k.start_with?("VAGRANT_OLD")
global_logger.info("#{k}=#{v.inspect}") if k.start_with?("VAGRANT_")
end
# If the vagrant_ssl library exists, a recent version
# of openssl is in use and its needed to load all the
# providers needed
if File.exist?(File.expand_path("vagrant/vagrant_ssl.so", __dir__))
global_logger.debug("vagrant ssl helper found for loading ssl providers")
begin
require "vagrant/vagrant_ssl"
Vagrant.vagrant_ssl_load
global_logger.debug("ssl providers successfully loaded")
rescue LoadError => err
global_logger.warn("failed to load ssl providers, attempting to continue (#{err})")
rescue => err
global_logger.warn("unexpected failure loading ssl providers, attempting to continue (#{err})")
end
end
# We need these components always so instead of an autoload we
# just require them explicitly here.
require "vagrant/plugin"
require "vagrant/registry"
module Vagrant
autoload :Action, 'vagrant/action'
autoload :Alias, 'vagrant/alias'
autoload :BatchAction, 'vagrant/batch_action'
autoload :Box, 'vagrant/box'
autoload :BoxCollection, 'vagrant/box_collection'
autoload :BoxMetadata, 'vagrant/box_metadata'
autoload :Bundler, 'vagrant/bundler'
autoload :CLI, 'vagrant/cli'
autoload :CapabilityHost, 'vagrant/capability_host'
autoload :Config, 'vagrant/config'
autoload :Environment, 'vagrant/environment'
autoload :Errors, 'vagrant/errors'
autoload :Guest, 'vagrant/guest'
autoload :Host, 'vagrant/host'
autoload :Machine, 'vagrant/machine'
autoload :MachineIndex, 'vagrant/machine_index'
autoload :MachineState, 'vagrant/machine_state'
autoload :Plugin, 'vagrant/plugin'
autoload :Registry, 'vagrant/registry'
autoload :UI, 'vagrant/ui'
autoload :Util, 'vagrant/util'
autoload :Vagrantfile, 'vagrant/vagrantfile'
autoload :VERSION, 'vagrant/version'
# These are the various plugin versions and their components in
# a lazy loaded Hash-like structure.
PLUGIN_COMPONENTS = Registry.new.tap do |c|
c.register(:"1") { Plugin::V1::Plugin }
c.register([:"1", :command]) { Plugin::V1::Command }
c.register([:"1", :communicator]) { Plugin::V1::Communicator }
c.register([:"1", :config]) { Plugin::V1::Config }
c.register([:"1", :guest]) { Plugin::V1::Guest }
c.register([:"1", :host]) { Plugin::V1::Host }
c.register([:"1", :provider]) { Plugin::V1::Provider }
c.register([:"1", :provisioner]) { Plugin::V1::Provisioner }
c.register(:"2") { Plugin::V2::Plugin }
c.register([:"2", :command]) { Plugin::V2::Command }
c.register([:"2", :communicator]) { Plugin::V2::Communicator }
c.register([:"2", :config]) { Plugin::V2::Config }
c.register([:"2", :guest]) { Plugin::V2::Guest }
c.register([:"2", :host]) { Plugin::V2::Host }
c.register([:"2", :provider]) { Plugin::V2::Provider }
c.register([:"2", :provisioner]) { Plugin::V2::Provisioner }
c.register([:"2", :push]) { Plugin::V2::Push }
c.register([:"2", :synced_folder]) { Plugin::V2::SyncedFolder }
c.register(:remote) { Plugin::Remote::Plugin }
end
# Configure a Vagrant environment. The version specifies the version
# of the configuration that is expected by the block. The block, based
# on that version, configures the environment.
#
# Note that the block isn't run immediately. Instead, the configuration
# block is stored until later, and is run when an environment is loaded.
#
# @param [String] version Version of the configuration
def self.configure(version, &block)
Config.run(version, &block)
end
# This checks if a plugin with the given name is available (installed
# and enabled). This can be used from the Vagrantfile to easily branch
# based on plugin availability.
def self.has_plugin?(name, version=nil)
return false unless Vagrant.plugins_enabled?
if !version
# We check the plugin names first because those are cheaper to check
return true if plugin("2").manager.registered.any? { |p| p.name == name }
end
# Now check the plugin gem names
require "vagrant/plugin/manager"
Plugin::Manager.instance.plugin_installed?(name, version)
end
# Returns a superclass to use when creating a plugin for Vagrant.
# Given a specific version, this returns a proper superclass to use
# to register plugins for that version.
#
# Optionally, if you give a specific component, then it will return
# the proper superclass for that component as well.
#
# Plugins and plugin components should subclass the classes returned by
# this method. This method lets Vagrant core control these superclasses
# and change them over time without affecting plugins. For example, if
# the V1 superclass happens to be "Vagrant::V1," future versions of
# Vagrant may move it to "Vagrant::Plugins::V1" and plugins will not be
# affected.
#
# @param [String] version
# @param [String] component
# @return [Class]
def self.plugin(version, component=nil)
# Build up the key and return a result
key = version.to_s.to_sym
key = [key, component.to_s.to_sym] if component
result = PLUGIN_COMPONENTS.get(key)
# If we found our component then we return that
return result if result
# If we didn't find a result, then raise an exception, depending
# on if we got a component or not.
raise ArgumentError, "Plugin superclass not found for version/component: " +
"#{version} #{component}"
end
# @deprecated
def self.require_plugin(name)
puts "Vagrant.require_plugin is deprecated and has no effect any longer."
puts "Use `vagrant plugin` commands to manage plugins. This warning will"
puts "be removed in the next version of Vagrant."
end
# This checks if Vagrant is installed in a specific version.
#
# Example:
#
# Vagrant.version?(">= 2.1.0")
#
def self.version?(*requirements)
req = Gem::Requirement.new(*requirements)
req.satisfied_by?(Gem::Version.new(VERSION))
end
# This allows a Vagrantfile to specify the version of Vagrant that is
# required. You can specify a list of requirements which will all be checked
# against the running Vagrant version.
#
# This should be specified at the _top_ of any Vagrantfile.
#
# Examples are shown below:
#
# Vagrant.require_version(">= 1.3.5")
# Vagrant.require_version(">= 1.3.5", "< 1.4.0")
# Vagrant.require_version("~> 1.3.5")
#
def self.require_version(*requirements)
logger = Log4r::Logger.new("vagrant::root")
logger.info("Version requirements from Vagrantfile: #{requirements.inspect}")
if version?(*requirements)
logger.info(" - Version requirements satisfied!")
return
end
raise Errors::VagrantVersionBad,
requirements: requirements.join(", "),
version: VERSION
end
# This allows plugin developers to access the original environment before
# Vagrant even ran. This is useful when shelling out, especially to other
# Ruby processes.
#
# @return [Hash]
def self.original_env
{}.tap do |h|
ENV.each do |k,v|
if k.start_with?("VAGRANT_OLD_ENV")
key = k.sub(/^VAGRANT_OLD_ENV_/, "")
if !key.empty?
h[key] = v
end
end
end
end
end
end
# Default I18n to load the en locale
I18n.load_path << File.expand_path("templates/locales/en.yml", Vagrant.source_root)
if I18n.config.respond_to?(:enforce_available_locales=)
# Make sure only available locales are used. This will be the default in the
# future but we need this to silence a deprecation warning from 0.6.9
I18n.config.enforce_available_locales = true
end
if Vagrant.enable_resolv_replace
global_logger.info("resolv replacement has been enabled!")
else
global_logger.warn("resolv replacement has not been enabled!")
end
# A lambda that knows how to load plugins from a single directory.
plugin_load_proc = lambda do |directory|
# We only care about directories
next false if !directory.directory?
# If there is a plugin file in the top-level directory, then load
# that up.
plugin_file = directory.join("plugin.rb")
if plugin_file.file?
global_logger.debug("Loading core plugin: #{plugin_file}")
load(plugin_file)
next true
end
end
# Go through the `plugins` directory and attempt to load any plugins. The
# plugins are allowed to be in a directory in `plugins` or at most one
# directory deep within the plugins directory. So a plugin can be at
# `plugins/foo` or also at `plugins/foo/bar`, but no deeper.
Vagrant.source_root.join("plugins").children(true).each do |directory|
# Ignore non-directories
next if !directory.directory?
# Load from this directory, and exit if we successfully loaded a plugin
next if plugin_load_proc.call(directory)
# Otherwise, attempt to load from sub-directories
directory.children(true).each(&plugin_load_proc)
end
|