diff --git a/go_parse_vagrantfile_ex/main.pb.go b/go_parse_vagrantfile_ex/main.pb.go deleted file mode 100644 index 38fd96349..000000000 --- a/go_parse_vagrantfile_ex/main.pb.go +++ /dev/null @@ -1,162 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.23.0 -// protoc v3.13.0 -// source: vagrant-ruby/go_parse_vagrantfile_ex/main.proto - -package go_parse_vagrantfile_ex - -import ( - proto "github.com/golang/protobuf/proto" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type FileProvisioner struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Source string `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"` - Destination string `protobuf:"bytes,2,opt,name=destination,proto3" json:"destination,omitempty"` -} - -func (x *FileProvisioner) Reset() { - *x = FileProvisioner{} - if protoimpl.UnsafeEnabled { - mi := &file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FileProvisioner) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FileProvisioner) ProtoMessage() {} - -func (x *FileProvisioner) ProtoReflect() protoreflect.Message { - mi := &file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FileProvisioner.ProtoReflect.Descriptor instead. -func (*FileProvisioner) Descriptor() ([]byte, []int) { - return file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescGZIP(), []int{0} -} - -func (x *FileProvisioner) GetSource() string { - if x != nil { - return x.Source - } - return "" -} - -func (x *FileProvisioner) GetDestination() string { - if x != nil { - return x.Destination - } - return "" -} - -var File_vagrant_ruby_go_parse_vagrantfile_ex_main_proto protoreflect.FileDescriptor - -var file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDesc = []byte{ - 0x0a, 0x2f, 0x76, 0x61, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x2d, 0x72, 0x75, 0x62, 0x79, 0x2f, 0x67, - 0x6f, 0x5f, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x76, 0x61, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x66, - 0x69, 0x6c, 0x65, 0x5f, 0x65, 0x78, 0x2f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x12, 0x17, 0x70, 0x61, 0x72, 0x73, 0x65, 0x5f, 0x76, 0x61, 0x67, 0x72, 0x61, 0x6e, 0x74, - 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4b, 0x0a, 0x0f, 0x46, 0x69, - 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, - 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x26, 0x5a, 0x24, 0x76, 0x61, 0x67, 0x72, 0x61, - 0x6e, 0x74, 0x2d, 0x72, 0x75, 0x62, 0x79, 0x2f, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x72, 0x73, 0x65, - 0x5f, 0x76, 0x61, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x65, 0x78, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescOnce sync.Once - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescData = file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDesc -) - -func file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescGZIP() []byte { - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescOnce.Do(func() { - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescData = protoimpl.X.CompressGZIP(file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescData) - }) - return file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDescData -} - -var file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_goTypes = []interface{}{ - (*FileProvisioner)(nil), // 0: parse_vagrantfile_proto.FileProvisioner -} -var file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_init() } -func file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_init() { - if File_vagrant_ruby_go_parse_vagrantfile_ex_main_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FileProvisioner); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_goTypes, - DependencyIndexes: file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_depIdxs, - MessageInfos: file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_msgTypes, - }.Build() - File_vagrant_ruby_go_parse_vagrantfile_ex_main_proto = out.File - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_rawDesc = nil - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_goTypes = nil - file_vagrant_ruby_go_parse_vagrantfile_ex_main_proto_depIdxs = nil -} diff --git a/go_parse_vagrantfile_ex/main.proto b/go_parse_vagrantfile_ex/main.proto deleted file mode 100644 index 133e1dccf..000000000 --- a/go_parse_vagrantfile_ex/main.proto +++ /dev/null @@ -1,10 +0,0 @@ -syntax = "proto3"; - -package parse_vagrantfile_proto; - -option go_package = "vagrant-ruby/go_parse_vagrantfile_ex"; - -message FileProvisioner { - string source = 1; - string destination = 2; -} diff --git a/parse_vagrantfile.rb b/parse_vagrantfile.rb deleted file mode 100644 index f311db4a7..000000000 --- a/parse_vagrantfile.rb +++ /dev/null @@ -1,334 +0,0 @@ -require "vagrant" -require "vagrant/plugin/v2/plugin" -require "vagrant/vagrantfile" -require "vagrant/box_collection" -require "vagrant/config" -require "pathname" -require 'google/protobuf/well_known_types' - -require_relative "./plugins/commands/serve/command" - -vagrantfile_path = "/Users/sophia/project/vagrant-ruby/Vagrantfile" - -PROVIDER_PROTO_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::Provider -PROVISION_PROTO_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::Provisioner -SYNCED_FOLDER_PROTO_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::SyncedFolder -NETWORK_PROTO_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::Network - -CONFIG_VM_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::ConfigVM -CONFIG_SSH_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::ConfigSSH -CONFIG_WINRM_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::ConfigWinRM -CONFIG_WINSSH_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::ConfigWinssh -CONFIG_VAGRANT_CLS = Hashicorp::Vagrant::Sdk::Vagrantfile::ConfigVagrant - -def stringify_symbols(m) - m.each do |k,v| - if v.is_a?(Hash) - # All keys need to be strings - v.transform_keys!{|sk| sk.to_s} - stringify_symbols(v) - next - end - if v.is_a?(Array) - v.map!{|sk| sk.is_a?(Symbol) ? sk.to_s : sk} - stringify_symbols(v) - next - end - k = k.to_s if k.is_a?(Symbol) - m[k] = v.to_s if v.is_a?(Symbol) - end -end - -def clean_up_config_object(config) - protoize = config - stringify_symbols(protoize) - # Remote variables that are internal - protoize.delete_if{|k,v| k.start_with?("_") } - protoize -end - -def extract_provisioners(target, provisioners) - provisioners.each do |c| - proto = PROVISION_PROTO_CLS.new() - c.instance_variables_hash.each do |k, v| - begin - if k == "config" - protoize = clean_up_config_object(c.config.instance_variables_hash) - config_struct = Google::Protobuf::Struct.from_hash(protoize) - config_any = Google::Protobuf::Any.pack(config_struct) - proto.config = config_any - next - end - if !v.nil? - v = v.to_s if v.is_a?(Symbol) - proto.send("#{k}=", v) - end - rescue NoMethodError - # this is ok - end - end - target << proto - end -end - -# Network configs take the form -# [ -# [:type, {:id=>"tcp8080", ...}], ... -# ] -def extract_network(target, networks) - networks.each do |n| - type = n[0] - opts = n[1] - network_proto = NETWORK_PROTO_CLS.new(type: type, id: opts.fetch(:id, "")) - opts.delete(:id) - opts.transform_keys!(&:to_s) - config_struct = Google::Protobuf::Struct.from_hash(opts) - config_any = Google::Protobuf::Any.pack(config_struct) - network_proto.config = config_any - target << network_proto - end -end - -# Providers take the form -# { -# :type=> #, ... -# } -def extract_provider(target, vm_config) - #WARNING: hacks ahead - vm_config.define_singleton_method(:compiled_provider_configs) do - return @__compiled_provider_configs - end - - vm_config.compiled_provider_configs.each do |type, config| - c = clean_up_config_object(config.instance_variables_hash) - - provider_proto = PROVIDER_PROTO_CLS.new(type: type) - config_struct = Google::Protobuf::Struct.from_hash(c) - config_any = Google::Protobuf::Any.pack(config_struct) - provider_proto.config = config_any - target << provider_proto - end -end - -# Synced folders take the form of a hash map -# { -# "name"=>{:type=>:rsync, ...}, ... -# }, -def extract_synced_folders(target, synced_folders) - synced_folders.each do |k,v| - sf_proto = SYNCED_FOLDER_PROTO_CLS.new() - - # Need to set source and destination since they don't exactly map - sf_proto.source = v[:hostpath] - sf_proto.destination = v[:guestpath] - - # config_opts keep track of the config options specific to the synced - # folder type. They are in the form `type`__`option` - config_opts = {} - - v.each do |opt, val| - # already accounted for above - next if ["guestpath", "hostpath"].include?(opt.to_s) - - # match the synced folder specific options and store them in the - # config_opts - if opt.to_s.match(/#{v[:type]}__/) - config_opts[opt.to_s.split("__")[1]] = val - next - end - - sf_proto.send("#{opt.to_s}=", val) - end - config_struct = Google::Protobuf::Struct.from_hash(config_opts) - config_any = Google::Protobuf::Any.pack(config_struct) - sf_proto.config = config_any - target << sf_proto - end -end - -def extract_config_component(config_cls, config) - config_proto = config_cls.new() - config.instance_variables_hash.each do |k, v| - # Skip config that has not be set - next if v.class == Object - - # Going to deal with these seperately because they are more involved - next if ["provisioners", "networks", "synced_folders", "disks", "cloud_init_configs"].include?(k) - - # Skip all variables that are internal - next if k.start_with?("_") - - if v.nil? - # If v is nil, set it to the default value defined by the proto - v = config_proto.send(k) - end - - if v.is_a?(Range) - v = v.to_a - end - - if v.is_a?(Hash) - m = config_proto.send(k) - v.each do |k2,v2| - m[k2] = v2 - end - v = m - end - - if v.is_a?(Array) - m = config_proto.send(k) - v.each do |v2| - m << v2 - end - v = m - end - - begin - config_proto.send("#{k}=", v) - rescue NoMethodError - # Reach here when Hashicorp::Vagrant::VagrantfileComponents::ConfigVM does not - # have a config variable for one of the instance methods. This is ok. - end - end - config_proto -end - -def extract_communicator(config_cls, config) - protoize = config.instance_variables_hash - protoize.map do |k,v| - # Get embedded default struct - if v.is_a?(Vagrant.plugin("2", :config)) - hashed_config = v.instance_variables_hash - hashed_config.delete_if{|k,v| k.start_with?("_") } - protoize[k] = hashed_config - end - end - protoize = clean_up_config_object(protoize) - config_struct = Google::Protobuf::Struct.from_hash(protoize) - config_any = Google::Protobuf::Any.pack(config_struct) - config_cls.new(config: config_any) -end - - -def parse_vagrantfile(path) - # Load up/parse the vagrantfile - config_loader = Vagrant::Config::Loader.new( - Vagrant::Config::VERSIONS, Vagrant::Config::VERSIONS_ORDER) - config_loader.set(:root, path) - v = Vagrant::Vagrantfile.new(config_loader, [:root]) - - machine_configs = [] - # Get the config for each machine - v.machine_names.each do |mach| - machine_info = v.machine_config(mach, nil, nil, false) - root_config = machine_info[:config] - vm_config = root_config.vm - - # Get config.ssh.* - config_ssh_proto = extract_communicator(CONFIG_SSH_CLS, root_config.ssh) - - # Get config.winrm.* - config_winrm_proto = extract_communicator(CONFIG_WINRM_CLS, root_config.winrm) - - #Get config.winssh.* - config_winssh_proto = extract_communicator(CONFIG_WINSSH_CLS, root_config.winssh) - - # Get config.vagrant.* - config_vagrant_proto = extract_config_component(CONFIG_VAGRANT_CLS, root_config.vagrant) - - # Get's config.vm.* - config_vm_proto = extract_config_component(CONFIG_VM_CLS, vm_config) - extract_provisioners(config_vm_proto.provisioners, vm_config.provisioners) - extract_network(config_vm_proto.networks, vm_config.networks) - extract_synced_folders(config_vm_proto.synced_folders, vm_config.synced_folders) - extract_provider(config_vm_proto.providers, vm_config) - - machine_configs << Hashicorp::Vagrant::Sdk::Vagrantfile::MachineConfig.new( - name: mach.to_s, - config_vm: config_vm_proto, - config_vagrant: config_vagrant_proto, - config_ssh: config_ssh_proto, - config_winrm: config_winrm_proto, - config_winssh: config_winssh_proto, - - ) - end - - vagrantfile = Hashicorp::Vagrant::Sdk::Vagrantfile::Vagrantfile.new( - path: path, - # raw: raw, - current_version: Vagrant::Config::CURRENT_VERSION, - machine_configs: machine_configs, - ) - Hashicorp::Vagrant::ParseVagrantfileResponse.new( - vagrantfile: vagrantfile - ) -end - -def proto_to_provisioner(vagrantfile_proto, validate=false) - # Just grab the first provisioner - vagrantfile_proto.machine_configs.each do |m| - puts "MACHINE: #{m.name}" - m.config_vm.provisioners.each do |p| - plugin = Vagrant.plugin("2").manager.provisioners[p.type.to_sym] - if plugin.nil? - puts "No plugin available for #{p.type}\n" - next - end - raw_config = p.config.unpack(Google::Protobuf::Struct).to_h - puts p.type - puts raw_config - puts "\n" - # TODO: fetch this config - # if it doesn't exist, then pass in generic config - plugin_config = Vagrant.plugin("2").manager.provisioner_configs[p.type.to_sym] - # Create a new config - config = plugin_config.new - # Unpack the config from the proto - raw_config = p.config.unpack(Google::Protobuf::Struct).to_h - # Set config - config.set_options(raw_config) - if validate - # Ensure config is valid - config.validate("machine") - end - # Create new provisioner - provisioner = plugin.new("machine", config) - end - end -end - -def proto_to_provider(vagrantfile_proto, validate=false) - # Just grab the first provisioner - vagrantfile_proto.machine_configs.each do |m| - puts "MACHINE: #{m.name}" - m.config_vm.providers.each do |p| - plugin = Vagrant.plugin("2").manager.providers[p.type.to_sym] - if plugin.nil? - puts "No plugin available for #{p.type}\n" - next - end - raw_config = p.config.unpack(Google::Protobuf::Struct).to_h - puts p.type - puts raw_config - puts "\n" - # TODO: fetch this config - # if it doesn't exist, then pass in generic config - plugin_config = Vagrant.plugin("2").manager.provider_configs[p.type.to_sym] - # Create a new config - config = plugin_config.new - # Unpack the config from the proto - raw_config = p.config.unpack(Google::Protobuf::Struct).to_h - # Set config - config.set_options(raw_config) - if validate - # Ensure config is valid - config.validate("machine") - end - end - end -end - -parse_vagrantifle_response = parse_vagrantfile(vagrantfile_path) -# proto_to_provisioner(parse_vagrantifle_response.vagrantfile) -proto_to_provider(parse_vagrantifle_response.vagrantfile) diff --git a/parse_vagrantfile_proto.go b/parse_vagrantfile_proto.go deleted file mode 100644 index 2425a0df5..000000000 --- a/parse_vagrantfile_proto.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/hashicorp/vagrant/internal/server/proto/ruby_vagrant" - - "github.com/hashicorp/vagrant/go_parse_vagrantfile_ex" - "github.com/mitchellh/mapstructure" - "google.golang.org/protobuf/types/known/anypb" - "google.golang.org/protobuf/types/known/structpb" -) - -//go:generate protoc -I .. --go_opt=plugins=grpc --go_out=.. vagrant-ruby/go_parse_vagrantfile_ex/main.proto - -func main() { - // Setup an example proto - m, _ := structpb.NewValue(map[string]interface{}{ - "source": ".gitignore", - "destination": "/.gitignore", - }) - any, _ := anypb.New(m) - - testProto := &ruby_vagrant.VagrantfileComponents_Vagrantfile{ - Path: "", - Raw: "", - CurrentVersion: "2", - MachineConfigs: []*ruby_vagrant.VagrantfileComponents_MachineConfig{ - &ruby_vagrant.VagrantfileComponents_MachineConfig{ - Name: "a", - ConfigVm: &ruby_vagrant.VagrantfileComponents_ConfigVM{ - Box: "hashicorp/bionic64", - Provisioners: []*ruby_vagrant.VagrantfileComponents_Provisioner{ - &ruby_vagrant.VagrantfileComponents_Provisioner{ - Name: "", - Type: "file", - Before: "", - After: "", - CommunicatorRequired: true, - Config: any, - }, - }, - }, - }, - }, - } - for _, m := range testProto.MachineConfigs { - fmt.Println("got machine \"" + m.Name + "\"") - fmt.Println("got box " + m.ConfigVm.Box) - for _, p := range m.ConfigVm.Provisioners { - fmt.Println("got provisioner " + p.Type) - s2, _ := p.Config.UnmarshalNew() - s2structpb := s2.(*structpb.Value) - var result go_parse_vagrantfile_ex.FileProvisioner - s2struct := s2structpb.GetStructValue() - mapstructure.Decode(s2struct.AsMap(), &result) - fmt.Println("source: " + result.Source) - fmt.Println("destination: " + result.Destination) - } - } -} diff --git a/plugins/kernel_v2/config/vm_provisioner.rb b/plugins/kernel_v2/config/vm_provisioner.rb index 94c511302..906a37efd 100644 --- a/plugins/kernel_v2/config/vm_provisioner.rb +++ b/plugins/kernel_v2/config/vm_provisioner.rb @@ -100,19 +100,7 @@ module VagrantPlugins end def add_config(**options, &block) - if invalid? - add_invalid_config(**options, &block) - return - end - - current = @config_class.new - current.set_options(options) if options - block.call(current) if block - current = @config.merge(current) if @config - @config = current - end - - def add_invalid_config(**options, &block) + # Don't skip if config is invalid. It might be a valid non-Ruby plugin current = @config_class.new current.set_options(options) if options block.call(current) if block