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.
145 lines
5.0 KiB
Ruby
145 lines
5.0 KiB
Ruby
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
require "optparse"
|
|
|
|
module VagrantPlugins
|
|
module CommandServe
|
|
autoload :Broker, Vagrant.source_root.join("plugins/commands/serve/broker").to_s
|
|
autoload :Client, Vagrant.source_root.join("plugins/commands/serve/client").to_s
|
|
autoload :Mappers, Vagrant.source_root.join("plugins/commands/serve/mappers").to_s
|
|
autoload :Service, Vagrant.source_root.join("plugins/commands/serve/service").to_s
|
|
autoload :Type, Vagrant.source_root.join("plugins/commands/serve/type").to_s
|
|
autoload :Util, Vagrant.source_root.join("plugins/commands/serve/util").to_s
|
|
autoload :SDK, Vagrant.source_root.join("plugins/commands/serve/constants").to_s
|
|
autoload :SRV, Vagrant.source_root.join("plugins/commands/serve/constants").to_s
|
|
autoload :Empty, Vagrant.source_root.join("plugins/commands/serve/constants").to_s
|
|
|
|
class << self
|
|
attr_accessor :broker
|
|
attr_accessor :server
|
|
attr_reader :cache
|
|
|
|
# Loads the required dependencies for this command. This is isolated
|
|
# into a method so that the dependencies can be loaded just in time when
|
|
# the command is actually executed.
|
|
def load_dependencies!
|
|
return if @dependencies_loaded
|
|
require 'grpc'
|
|
require 'grpc/health/checker'
|
|
require 'grpc/health/v1/health_services_pb'
|
|
|
|
# Add conversion patches
|
|
require Vagrant.source_root.join("plugins/commands/serve/util/direct_conversions.rb").to_s
|
|
|
|
# Mark dependencies as loaded
|
|
@dependencies_loaded = true
|
|
end
|
|
end
|
|
@cache = Util::Cacher.new
|
|
|
|
class Command < Vagrant.plugin("2", :command)
|
|
|
|
DEFAULT_BIND = "localhost"
|
|
DEFAULT_PORT_RANGE = 40000..50000
|
|
|
|
include Util::HasLogger
|
|
|
|
def self.synopsis
|
|
"start Vagrant server"
|
|
end
|
|
|
|
def execute
|
|
# Load dependencies before we start
|
|
CommandServe.load_dependencies!
|
|
|
|
options = {
|
|
bind: DEFAULT_BIND,
|
|
min_port: DEFAULT_PORT_RANGE.first,
|
|
max_port: DEFAULT_PORT_RANGE.last,
|
|
}
|
|
|
|
opts = OptionParser.new do |o|
|
|
o.banner = "Usage: vagrant serve"
|
|
o.separator ""
|
|
o.separator "Options:"
|
|
o.separator ""
|
|
|
|
o.on("--bind ADDR", "Bind to specific address. Default: #{DEFAULT_BIND}") do |addr|
|
|
options[:bind] = addr
|
|
end
|
|
|
|
o.on("--min-port PORT", "Minimum port number to use. Default: #{DEFAULT_PORT_RANGE.first}") do |port|
|
|
options[:min_port] = port
|
|
end
|
|
|
|
o.on("--max-port PORT", "Maximum port number to use. Default: #{DEFAULT_PORT_RANGE.last}") do |port|
|
|
options[:max_port] = port
|
|
end
|
|
end
|
|
|
|
# Parse the options
|
|
argv = parse_options(opts)
|
|
return if !argv
|
|
|
|
ports = options[:min_port].to_i .. options[:max_port].to_i
|
|
serve(options[:bind], ports)
|
|
end
|
|
|
|
private
|
|
|
|
def serve(bind_addr = "localhost", ports = DEFAULT_PORT_RANGE)
|
|
logger.info("Starting Vagrant GRPC service addr=#{bind_addr.inspect} ports=#{ports.inspect}")
|
|
s = GRPC::RpcServer.new
|
|
port = nil
|
|
ports.each do |p|
|
|
begin
|
|
port = s.add_http2_port("#{bind_addr}:#{p}", :this_port_is_insecure)
|
|
break
|
|
rescue RuntimeError
|
|
# Assuming port in use, trying next
|
|
end
|
|
end
|
|
raise "Failed to bind GRPC server listener" if port.nil?
|
|
|
|
health_checker = Grpc::Health::Checker.new
|
|
broker = Broker.new(bind: bind_addr, ports: ports)
|
|
CommandServe.broker = broker
|
|
logger.debug("vagrant grpc broker started for grpc service addr=#{bind_addr} ports=#{ports.inspect}")
|
|
|
|
[Broker::Streamer,
|
|
Service::CommandService,
|
|
Service::CommunicatorService,
|
|
Service::ConfigService,
|
|
Service::GuestService,
|
|
Service::HostService,
|
|
Service::InternalService,
|
|
Service::ProviderService,
|
|
Service::ProvisionerService,
|
|
Service::PushService,
|
|
Service::SyncedFolderService,
|
|
].each do |service_klass|
|
|
service = service_klass.new(broker: broker)
|
|
s.handle(service)
|
|
health_checker.add_status(service_klass,
|
|
Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING)
|
|
logger.debug("enabled Vagrant GRPC service: #{service_klass.name.split('::').last}")
|
|
end
|
|
|
|
s.handle(health_checker)
|
|
|
|
logger.debug("writing connection information to stdout for go-plugin")
|
|
STDOUT.puts "1|1|tcp|#{bind_addr}:#{port}|grpc"
|
|
STDOUT.flush
|
|
logger.info("Vagrant GRPC service is now running addr=#{bind_addr.inspect} port=#{port.inspect}")
|
|
VagrantPlugins::CommandServe.server = s
|
|
s.run_till_terminated_or_interrupted(['EXIT', 'HUP', 'INT', 'QUIT', 'ABRT'])
|
|
0
|
|
ensure
|
|
VagrantPlugins::CommandServe.server = nil
|
|
logger.info("Vagrant GRPC service shut down")
|
|
end
|
|
end
|
|
end
|
|
end
|