# Copyright (c) HashiCorp, Inc. # SPDX-License-Identifier: BUSL-1.1 module VagrantPlugins module CommandServe module Service class ConfigService < ProtoService(SDK::ConfigService::Service) CONFIG_LOCATIONS = [ :config, :provider_configs, :provisioner_configs, :push_configs, ] def register(req, ctx) with_plugin(ctx, CONFIG_LOCATIONS, broker: broker) do |plugin| resp = SDK::Config::RegisterResponse.new Vagrant.plugin("2").local_manager.registered.each do |plg| plg.components.configs.each do |scope, registry| registry.each do |ident, val| if plugin == val resp.scope = scope unless scope == :top resp.identifier = ident break end end end end resp end end def init_spec(*_) funcspec( args: [ SDK::Args::ConfigData, ], result: SDK::Config::InitResponse ) end def init(req, ctx) with_plugin(ctx, :config, broker: broker) do |plugin| config_data_p = mapper.unfuncspec(req.args.first) config_data = mapper.map(config_data_p.data) instance = plugin.new config_data.each do |key, value| key = key.downcase.to_sym if instance.respond_to?("#{key}=".to_sym) instance.send("#{key}=".to_sym, value) elsif instance.respond_to?(key) instance.send(key, value) else logger.warn("unknown config key to apply: class: #{plugin} key: #{key}") end end SDK::Config::InitResponse.new(data: mapper.map(instance, to: SDK::Args::ConfigData)) end end def struct_spec(*_) funcspec( args: [ ], result: SDK::Config::StructResponse ) end def struct(req, ctx) SDK::Config::StructResponse.new(raw: true) end def merge_spec(*_) funcspec( args: [ SDK::Config::Merge, ], result: SDK::Args::ConfigData, ) end def merge(req, ctx) with_plugin(ctx, :config, broker: broker) do |plugin| m = mapper.unfuncspec(req.args.first) base = mapper.map(m.base, to: plugin) overlay = mapper.map(m.overlay, to: plugin) mapper.map(base.merge(overlay), to: SDK::Args::ConfigData) end end def finalize_spec(*_) funcspec( args: [ SDK::Config::Finalize, ], result: SDK::Args::ConfigData ) end def finalize(req, ctx) with_plugin(ctx, CONFIG_LOCATIONS, broker: broker) do |plugin| # Extract the proto from the funcspec f = mapper.unfuncspec(req.args.first) cproto = f.config # If the config data does not include a source class, we treat # the request as simply wanting the default finalized data if cproto.source.name.to_s.empty? config = plugin.new else config = mapper.map(cproto, to: plugin) end config.finalize! # This is just a marker for debugging that we were # responsible for the finalization config.instance_variable_set("@__service_finalized", true) SDK::Config::FinalizeResponse.new(data: mapper.map(config, to: SDK::Args::ConfigData)) end end end end end end