lib/vagrant-betterhosts/BetterHosts.rb in vagrant-betterhosts-0.2.1 vs lib/vagrant-betterhosts/BetterHosts.rb in vagrant-betterhosts-1.1.6

- old
+ new

@@ -1,74 +1,78 @@ +# The core of the plugin require "rbconfig" require "open3" +require "resolv" +require "os" module VagrantPlugins module BetterHosts + # Plugin module module BetterHosts - def getIps + def get_ips ips = [] + if @machine.provider_name == :docker + @ui.info '[vagrant-betterhosts] Docker detected, adding 127.0.0.1 and ::1 IP addresses' + ip = "127.0.0.1" + ips.push(ip) unless ip.nil? or ips.include? ip + ip = "::1" + ips.push(ip) unless ip.nil? or ips.include? ip + return ips + end + if @machine.config.vm.networks.length == 0 @ui.error("[vagrant-betterhosts] No ip address found for this virtual machine") exit end @machine.config.vm.networks.each do |network| key, options = network[0], network[1] - ip = options[:ip] if (key == :private_network || key == :public_network) && options[:betterhosts] != "skip" - ips.push(ip) if ip if options[:betterhosts] == "skip" @ui.info '[vagrant-betterhosts] Skipped adding host entries (config.vm.network betterhosts: "skip" is set)' end - - @machine.config.vm.provider :hyperv do |v| - timeout = @machine.provider_config.ip_address_timeout - @ui.output("[vagrant-betterhosts] Waiting for the guest machine to report its IP address ( this might take some time, have patience )...") - @ui.detail("Timeout: #{timeout} seconds") - - options = { - vmm_server_address: @machine.provider_config.vmm_server_address, - proxy_server_address: @machine.provider_config.proxy_server_address, - timeout: timeout, - machine: @machine, - } - network = @machine.provider.driver.read_guest_ip(options) - if network["ip"] - ips.push(network["ip"]) unless ips.include? network["ip"] - end - end - - + ip = options[:ip] if (key == :private_network || key == :public_network) && options[:betterhosts] != "skip" + ips.push(ip) if ip end + if @machine.provider_name == :hyperv + ip = @machine.provider.driver.read_guest_ip["ip"] + @ui.info "[vagrant-betterhosts] Read guest IP #{ip} from Hyper-V provider" + ips.push(ip) unless ip.nil? or ips.include? ip + end return ips end - # https://stackoverflow.com/a/13586108/1902215 def get_os_binary - return os ||= (host_os = RbConfig::CONFIG["host_os"] - case host_os - when /mswin|msys|mingw|cygwin|bccwin|wince|emc/ - :'cli.exe' - when /darwin|mac os/ - :'cli_osx' - when /linux/ - :'cli' - else - raise Error::WebDriverError, "unknown os: #{host_os.inspect}" - end) + if OS.windows? + return 'cli.exe' + elsif OS.mac? + if Etc.uname[:version].include? 'ARM64' + return 'cli_arm64_osx' + else + return 'cli_amd64_osx' + end + elsif OS.linux? + if Etc.uname[:version].include? 'ARM64' + return 'cli_arm64_linux' + else + return 'cli_amd64_linux' + end + else + raise Error::WebDriverError, "unknown os: #{host_os.inspect}" + end end def get_cli binary = get_os_binary - path = File.expand_path(File.dirname(File.dirname(__FILE__))) + "/vagrant-betterhosts/bundle/" + path = format('%s%s', File.expand_path(File.dirname(File.dirname(__FILE__))), "/vagrant-betterhosts/bundle/") path = "#{path}#{binary}" return path end # Get a hash of hostnames indexed by ip, e.g. { 'ip1': ['host1'], 'ip2': ['host2', 'host3'] } - def getHostnames(ips) + def get_hostnames(ips) hostnames = Hash.new { |h, k| h[k] = [] } case @machine.config.betterhosts.aliases when Array hostnames[ips[0]] += @machine.config.betterhosts.aliases @@ -87,105 +91,153 @@ end hostnames end - def disableClean(ip_address) + def disable_clean(ip_address) unless ip_address.nil? return @machine.config.betterhosts.disable_clean end return true end - def addHostEntries - error = false - errorText = "" + def check_hostnames_to_add(ip_address, hostnames) + hostnames_to_add = Array.new + hostnames = hostnames.split + # check which hostnames actually need adding + hostnames.each do |hostname| + begin + address = Resolv.getaddress(hostname) + if address != ip_address + hostnames_to_add.append(hostname) + end + rescue StandardError => _e + hostnames_to_add.append(hostname) + end + rescue StandardError => _e + hostnames_to_add.append(hostname) + end + return hostnames_to_add.join(' ') + end + + def add_betterhost_entries(ip_address, hostnames) cli = get_cli - hostnames_by_ips = generateHostnamesByIps + if cli.include? ".exe" + clean = get_clean_parameter_by_system(ip_address, true) + command = "Start-Process '#{cli}' -ArgumentList \"add\",#{clean}\"#{ip_address}\",\"#{hostnames}\" -Verb RunAs" + stdin, stdout, stderr, wait_thr = Open3.popen3("powershell", "-Command", command) + else + clean = get_clean_parameter_by_system(ip_address, false) + command = "sudo '#{cli}' add #{clean} #{ip_address} #{hostnames}" + stdin, stdout, stderr, wait_thr = Open3.popen3(command) + end + return stdin, stdout, stderr, wait_thr, command + end + + def add_host_entries + error = false + error_text = '' + command = '' + hostnames_by_ips = generate_hostnames_by_ips - return if not hostnames_by_ips.any? + return if hostnames_by_ips.none? + @ui.info "[vagrant-betterhosts] Checking for host entries" + hostnames_by_ips.each do |ip_address, hostnames| if ip_address.nil? @ui.error "[vagrant-betterhosts] Error adding some hosts, no IP was provided for the following hostnames: #{hostnames}" next end - @ui.info "[vagrant-betterhosts] Adding #{hostnames} for address #{ip_address}" - if cli.include? ".exe" - clean = "\"--clean\"," - if disableClean(ip_address) - clean = '' - end - stdin, stdout, stderr, wait_thr = Open3.popen3("powershell", "-Command", "Start-Process '#{cli}' -ArgumentList \"add\",#{clean}\"#{ip_address}\",\"#{hostnames}\" -Verb RunAs") - else - clean = "--clean" - if disableClean(ip_address) - clean = '' - end - stdin, stdout, stderr, wait_thr = Open3.popen3("sudo '#{cli}' add #{clean} #{ip_address} #{hostnames}") - end - if !wait_thr.value.success? + + # filter out the hosts we've already added + hosts_to_add = check_hostnames_to_add(ip_address, hostnames) + next if hosts_to_add.empty? + + _stdin, _stdout, stderr, wait_thr, command = add_betterhost_entries(ip_address, hosts_to_add) + unless wait_thr.value.success? error = true - errorText = stderr.read.strip + error_text = stderr.read.strip end end - printReadme(error, errorText) + print_readme(error, error_text, command) end - def removeHostEntries - error = false - errorText = "" + def remove_betterhost_entries(ip_address, hostnames) cli = get_cli - hostnames_by_ips = generateHostnamesByIps + if cli.include? ".exe" + clean = get_clean_parameter_by_system(ip_address, true) + command = "Start-Process '#{cli}' -ArgumentList \"remove\",#{clean}\"#{ip_address}\",\"#{hostnames}\" -Verb RunAs" + stdin, stdout, stderr, wait_thr = Open3.popen3("powershell", "-Command", command) + else + clean = get_clean_parameter_by_system(ip_address, false) + command = "sudo '#{cli}' remove #{clean} #{ip_address} #{hostnames}" + stdin, stdout, stderr, wait_thr = Open3.popen3(command) + end + return stdin, stdout, stderr, wait_thr, command + end - return if not hostnames_by_ips.any? + def remove_host_entries + error = false + error_text = '' + command = '' + hostnames_by_ips = generate_hostnames_by_ips + return if hostnames_by_ips.none? + + @ui.info "[vagrant-betterhosts] Removing hosts" + hostnames_by_ips.each do |ip_address, hostnames| if ip_address.nil? @ui.error "[vagrant-betterhosts] Error adding some hosts, no IP was provided for the following hostnames: #{hostnames}" next end - if cli.include? ".exe" - clean = "\"--clean\"," - if disableClean(ip_address) - clean = '' - end - stdin, stdout, stderr, wait_thr = Open3.popen3("powershell", "-Command", "Start-Process '#{cli}' -ArgumentList \"remove\",#{clean}\"#{ip_address}\",\"#{hostnames}\" -Verb RunAs") - else - clean = "\"--clean\"," - if disableClean(ip_address) - clean = '' - end - stdin, stdout, stderr, wait_thr = Open3.popen3("sudo '#{cli}' remove #{clean} #{ip_address} #{hostnames}") - end - if !wait_thr.value.success? + + _stdin, _stdout, stderr, wait_thr, command = remove_betterhost_entries(ip_address, hostnames) + unless wait_thr.value.success? error = true - errorText = stderr.read.strip + error_text = stderr.read.strip end end - printReadme(error, errorText) + print_readme(error, error_text, command) end - def printReadme(error, errorText) - if error - cli = get_cli - @ui.error "[vagrant-betterhosts] Issue executing goodhosts CLI: #{errorText}" - @ui.error "[vagrant-betterhosts] Cli path: #{cli}" - if cli.include? ".exe" - @ui.error "[vagrant-betterhosts] Check the readme at https://github.com/ajxb/vagrant-betterhosts#windows-uac-prompt" - exit - else - @ui.error "[vagrant-betterhosts] Check the readme at https://github.com/ajxb/vagrant-betterhosts#passwordless-sudo" - end + def get_clean_parameter_by_system(ip_address, is_win) + clean = "--clean" + if is_win + clean = "\"--clean\"," end + + if disable_clean(ip_address) + clean = '' + end + return clean end - def generateHostnamesByIps() - ips = getIps + def print_readme(error, error_text, command) + unless error + @ui.info "[vagrant-betterhosts] Finished processing" + return false + end + + cli = get_cli + @ui.error "[vagrant-betterhosts] Issue executing goodhosts CLI: #{error_text}" + @ui.error "[vagrant-betterhosts] Command: #{command}" + @ui.error "[vagrant-betterhosts] Cli path: #{cli}" + if cli.include? ".exe" + @ui.error "[vagrant-betterhosts] Check the readme at https://github.com/betterhosts/vagrant#windows-uac-prompt" + exit + else + @ui.error "[vagrant-betterhosts] Check the readme at https://github.com/betterhosts/vagrant#passwordless-sudo" + end + end + + def generate_hostnames_by_ips + ips = get_ips return [] unless ips.any? hostnames_by_ips = {} - hostnames = getHostnames(ips) + hostnames = get_hostnames(ips) ips.each do |ip| hostnames_by_ips[ip] = hostnames[ip].join(' ') if hostnames[ip].any? end hostnames_by_ips