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.
247 lines
6.5 KiB
Ruby
247 lines
6.5 KiB
Ruby
# Copyright (c) HashiCorp, Inc.
|
|
# SPDX-License-Identifier: BUSL-1.1
|
|
|
|
module VagrantPlugins
|
|
module CommandServe
|
|
class Mappers
|
|
class ConfigDataFromSpec < Mapper
|
|
def initialize
|
|
super(
|
|
inputs: [Input.new(type: SDK::FuncSpec::Value) { |arg|
|
|
arg.type == "hashicorp.vagrant.sdk.Args.ConfigData" &&
|
|
!arg&.value&.value.nil?
|
|
}
|
|
],
|
|
output: SDK::Args::ConfigData,
|
|
func: method(:converter),
|
|
)
|
|
end
|
|
|
|
def converter(fv)
|
|
SDK::Args::ConfigData.decode(fv.value.value)
|
|
end
|
|
end
|
|
|
|
class ConfigMergeFromSpec < Mapper
|
|
include Util::HasLogger
|
|
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: SDK::FuncSpec::Value) { |arg|
|
|
arg.type == "hashicorp.vagrant.sdk.Config.Merge" &&
|
|
!arg&.value&.value.nil?
|
|
}
|
|
],
|
|
output: SDK::Config::Merge,
|
|
func: method(:converter),
|
|
)
|
|
end
|
|
|
|
def converter(fv)
|
|
SDK::Config::Merge.decode(fv.value.value)
|
|
end
|
|
end
|
|
|
|
class ConfigFinalizeFromSpec < Mapper
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: SDK::FuncSpec::Value) { |arg|
|
|
arg.type == "hashicorp.vagrant.sdk.Config.Finalize" &&
|
|
!arg&.value&.value.nil?
|
|
}
|
|
],
|
|
output: SDK::Config::Finalize,
|
|
func: method(:converter),
|
|
)
|
|
end
|
|
|
|
def converter(fv)
|
|
SDK::Config::Finalize.decode(fv.value.value)
|
|
end
|
|
end
|
|
|
|
class ConfigFinalizeResponseProtoFromConfigDataProto < Mapper
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: SDK::Args::ConfigData),
|
|
],
|
|
output: SDK::Config::FinalizeResponse,
|
|
func: method(:converter),
|
|
)
|
|
end
|
|
|
|
def converter(c)
|
|
SDK::Config::FinalizeResponse.new(data: c)
|
|
end
|
|
end
|
|
|
|
class ConfigFromConfigDataProto < Mapper
|
|
include Util::HasLogger
|
|
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: SDK::Args::ConfigData),
|
|
],
|
|
output: Vagrant::Plugin::V2::Config,
|
|
func: method(:converter)
|
|
)
|
|
end
|
|
|
|
def converter(c)
|
|
c.to_ruby
|
|
end
|
|
end
|
|
|
|
class RootConfigToHashProto < Mapper
|
|
include Util::HasLogger
|
|
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: Vagrant::Config::V2::Root),
|
|
],
|
|
output: SDK::Args::Hash,
|
|
func: method(:converter),
|
|
)
|
|
end
|
|
|
|
def converter(c)
|
|
c.to_proto
|
|
end
|
|
end
|
|
|
|
class ConfigToProto < Mapper
|
|
include Util::HasLogger
|
|
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: Vagrant::Plugin::V2::Config),
|
|
Input.new(type: Mappers),
|
|
],
|
|
output: SDK::Args::ConfigData,
|
|
func: method(:converter),
|
|
)
|
|
end
|
|
|
|
def converter(c, m)
|
|
data = Hash.new.tap do |h|
|
|
c.instance_variables.each do |v|
|
|
h[v.to_s.sub('@', '')] = c.instance_variable_get(v)
|
|
end
|
|
end
|
|
|
|
# Include a unique identifier for this configuration instance. This
|
|
# will allow us to identifier it later when it is decoded.
|
|
if !data.key?("_vagrant_config_identifier")
|
|
data["_vagrant_config_identifier"] = SecureRandom.uuid
|
|
end
|
|
|
|
entries = data.map do |k, v|
|
|
begin
|
|
SDK::Args::HashEntry.new(
|
|
key: m.map(k, to: Google::Protobuf::Any),
|
|
value: m.map(v, to: Google::Protobuf::Any),
|
|
)
|
|
rescue Internal::Graph::Search::NoPathError, TypeError
|
|
logger.warn("failed to map '#{k}' value of type `#{v.class}'")
|
|
nil
|
|
end
|
|
end.compact
|
|
SDK::Args::ConfigData.new(
|
|
data: SDK::Args::Hash.new(entries: entries),
|
|
source: m.map(c.class, to: SDK::Args::Class),
|
|
)
|
|
end
|
|
end
|
|
|
|
class RawRubyValueToProto < Mapper
|
|
include Util::HasLogger
|
|
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: Object, origin_restricted: true),
|
|
Input.new(type: Mappers),
|
|
],
|
|
output: SDK::Config::RawRubyValue,
|
|
func: method(:converter)
|
|
)
|
|
end
|
|
|
|
def converter(o, m)
|
|
klass = m.map(o.class, to: SDK::Args::Class)
|
|
data = Hash.new.tap do |h|
|
|
o.instance_variables.each do |v|
|
|
h[v.to_s.sub('@', '')] = o.instance_variable_get(v)
|
|
end
|
|
end
|
|
|
|
entries = data.map do |k, v|
|
|
next if v.is_a?(Log4r::Logger)
|
|
begin
|
|
SDK::Args::HashEntry.new(
|
|
key: m.map(k, to: Google::Protobuf::Any),
|
|
value: m.map(v, to: Google::Protobuf::Any),
|
|
)
|
|
rescue Internal::Graph::Search::NoPathError, TypeError
|
|
logger.warn("failed to map '#{k}' value of type `#{v.class}'")
|
|
nil
|
|
end
|
|
end.compact
|
|
SDK::Config::RawRubyValue.new(
|
|
source: klass,
|
|
data: SDK::Args::Hash.new(entries: entries)
|
|
)
|
|
end
|
|
|
|
def extra_weight
|
|
1_000_000_000_000
|
|
end
|
|
end
|
|
|
|
class RawRubyValueFromProto < Mapper
|
|
include Util::HasLogger
|
|
|
|
def initialize
|
|
super(
|
|
inputs: [
|
|
Input.new(type: SDK::Config::RawRubyValue, origin_restricted: true),
|
|
Input.new(type: Mappers)
|
|
],
|
|
output: Object,
|
|
func: method(:converter),
|
|
)
|
|
end
|
|
|
|
def converter(r, m)
|
|
base_klass = m.map(r.source, to: Class)
|
|
if [0, -1].include?(base_klass.instance_method(:initialize).arity)
|
|
klass = base_klass
|
|
else
|
|
klass = Class.new(base_klass)
|
|
klass.class_eval("
|
|
def self.class
|
|
#{base_klass.name}
|
|
end
|
|
def initialize
|
|
end
|
|
")
|
|
end
|
|
instance = klass.new
|
|
data = m.map(r.data, to: Hash)
|
|
|
|
data.each_pair do |k, v|
|
|
instance.instance_variable_set("@#{k}", v)
|
|
end
|
|
instance
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|