# # Because we create configurations and operate on resulting machines during # the course of a single CLI command run we need to be able to reload the # configurations based on updates to fetch Vagrant VMs and run Vagrant machine # actions. TODO: Inquire about some form of inclusion in Vagrant core? # module Vagrant class Vagrantfile def reload @loader.clear_config_cache(@keys) @config, _ = @loader.load(@keys) end end module Config class Loader def clear_config_cache(sources = nil) @config_cache = {} if sources keep = {} sources.each do |source| keep[source] = @sources[source] if @sources[source] end @sources = keep end end end end end #------------------------------------------------------------------------------- module CORL module Vagrant module Config @@network = nil def self.network=network @@network = network end def self.network @@network end # # Gateway CORL configurator for Vagrant. # def self.register(directory, config, &code) ::Vagrant.require_version ">= 1.5.0" config_network = network config_network = load_network(directory) unless config_network if config_network # Vagrant settings unless configure_vagrant(config_network, config.vagrant) raise "Configuration of Vagrant general settings failed" end config_network.nodes(:vagrant, true).each do |node_name, node| config.vm.define node.id.to_sym do |machine| # VM settings unless configure_vm(node, machine) raise "Configuration of Vagrant VM failed: #{node_name}" end # SSH settings unless configure_ssh(node, machine) raise "Configuration of Vagrant VM SSH settings failed" end # Server shares unless configure_shares(node, machine) raise "Configuration of Vagrant shares failed: #{node_name}" end # Provisioner configuration unless configure_provisioner(network, node, machine, &code) raise "Configuration of Vagrant provisioner failed: #{node_name}" end end end end end #--- def self.load_network(directory) # Load network if it exists @@network = CORL.network(directory, CORL.config(:vagrant_network, { :directory => directory })) end #--- def self.configure_vagrant(network, vagrant) success = true Util::Data.hash(network.settings(:vagrant_config)).each do |name, data| if vagrant.respond_to?("#{name}=") data = Util::Data.value(data) #dbg(name, 'vagrant property') #dbg(data, 'vagrant property data') vagrant.send("#{name}=", data) else params = parse_params(data) #dbg(name, 'vagrant method') #dbg(params, 'vagrant method params') vagrant.send(name, params) end end success end #--- def self.configure_ssh(node, machine) success = true #dbg(node.user, 'ssh user') machine.ssh.username = node.user #dbg(node.ssh_port, 'ssh port') machine.ssh.guest_port = node.ssh_port if node.cache_setting(:use_private_key, false) #dbg(node.private_key, 'ssh private key') machine.ssh.private_key_path = node.private_key end Util::Data.hash(node.ssh).each do |name, data| if machine.ssh.respond_to?("#{name}=") data = Util::Data.value(data) #dbg(name, 'ssh property') #dbg(data, 'ssh property data') machine.ssh.send("#{name}=", data) else params = parse_params(data) #dbg(name, 'ssh method') #dbg(params, 'ssh method params') machine.ssh.send(name, params) end end success end #--- def self.configure_vm(node, machine) vm_config = Util::Data.hash(node.vm) success = true #dbg(node.hostname, 'VM hostname') machine.vm.hostname = node.hostname box = node.cache_setting(:box) box_url = node.cache_setting(:box_url) if box && box_url #dbg(box, 'VM box') machine.vm.box = box #dbg(box_url, 'VM box url') machine.vm.box_url = box_url else #dbg(node.image, 'VM box') machine.vm.box = node.image end unless vm_config.has_key?(:public_network) if node.public_ip #dbg(node.public_ip, 'private ip address') machine.vm.network :private_network, :ip => node.public_ip else #dbg('dhcp private ip address') machine.vm.network :private_network, :type => "dhcp" end end vm_config.each do |name, data| case name.to_sym # Network interfaces when :forwarded_ports data.each do |forward_name, info| forward_config = CORL::Config.new({ :auto_correct => true }).import(info) forward_config.keys do |key| forward_config[key] = Util::Data.value(forward_config[key]) end #dbg(forward_config.export, 'vm forwarded port config') machine.vm.network :forwarded_port, forward_config.export end when :usable_port_range low, high = data.to_s.split(/\s*--?\s*/) #dbg("#{low} <--> #{high}", 'vm usable port range') machine.vm.usable_port_range = Range.new(low, high) when :public_network #dbg('public network') machine.vm.network :public_network # Provider specific settings when :providers data.each do |provider, info| #dbg(provider, 'vm provider') machine.vm.provider provider.to_sym do |interface| info.each do |property, item| #dbg(property, 'vm property') #dbg(item, 'vm property item') if interface.respond_to?("#{property}=") interface.send("#{property}=", item) else params = parse_params(item) #dbg(params, 'vm method params') interface.send(property, params) end end end end # All other basic VM settings... else if machine.vm.respond_to?("#{name}=") #dbg(name, 'other property') #dbg(data, 'other property data') machine.vm.send("#{name}=", data) else params = parse_params(data) #dbg(name, 'other method') #dbg(params, 'other method params') machine.vm.send(name, params) end end end success end #--- def self.configure_shares(node, machine) bindfs_installed = Gems.exist?('vagrant-bindfs') success = true if bindfs_installed machine.vm.synced_folder ".", "/vagrant", disabled: true machine.vm.synced_folder ".", "/tmp/vagrant", :type => "nfs" machine.bindfs.bind_folder "/tmp/vagrant", "/vagrant" end Util::Data.hash(node.shares).each do |name, options| config = CORL::Config.ensure(options) share_type = config.get(:type, nil) local_dir = config.delete(:local, '') remote_dir = config.delete(:remote, '') config.init(:create, true) unless local_dir.empty? || remote_dir.empty? bindfs_options = config.delete(:bindfs, {}) share_options = {} config.keys.each do |key| share_options[key] = Util::Data.value(config[key]) end if share_type && share_type.to_sym == :nfs && bindfs_installed final_dir = remote_dir remote_dir = [ '/tmp', remote_dir.sub(/^\//, '') ].join('/') #dbg(remote_dir, 'vm bindfs local') #dbg(final_dir, 'vm bindfs remote') #dbg(bindfs_options, 'vm bindfs options') machine.bindfs.bind_folder remote_dir, final_dir, bindfs_options end #dbg(local_dir, 'vm share local') #dbg(remote_dir, 'vm share remote') #dbg(share_options, 'vm share options') machine.vm.synced_folder local_dir, remote_dir, share_options end end success end #--- def self.configure_provisioner(network, node, machine, &code) success = true # CORL provisioning machine.vm.provision :corl do |provisioner| provisioner.network = network provisioner.node = node code.call(node, machine, provisioner) if code end success end #--- def self.parse_params(data) params = data if data.is_a?(Hash) params = [] data.each do |key, item| unless Util::Data.undef?(item) params << ( key.match(/^\:/) ? key.gsub(/^\:/, '').to_sym : key.to_s ) unless Util::Data.empty?(item) value = item value = ((item.is_a?(String) && item.match(/^\:/)) ? item.gsub(/^\:/, '').to_sym : item) params << Util::Data.value(value) end end end end params end end end end