Skip to content

Instantly share code, notes, and snippets.

@Micronarrativ
Created December 20, 2017 18:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Micronarrativ/2bce53d0d32b5a6edf8f11fa151f0419 to your computer and use it in GitHub Desktop.
Save Micronarrativ/2bce53d0d32b5a6edf8f11fa151f0419 to your computer and use it in GitHub Desktop.
Script to show the configured IP addresses in a Vagrantfile
#!/usr/bin/env ruby
# 2017-11-27/dbv
# Script to parse a vagrant file and return the configured network addresses
#
# Can sort by node name (default) or confiured ip.
#
require 'thor'
class Vagrant < Thor
class_option 'sort-by-node', :aliases => '-n', :type => :boolean, :required => false, :desc => 'Sort output by node name.'
class_option 'sort-by-ip', :aliases => '-i', :type => :boolean, :required => false, :desc => 'Sort output by node ip.'
class_option :vagrantfile, :type => :string, :required => false, :desc => 'Vagrant file to parse.'
desc 'get_vagrant_file_path', 'Tries to fetch the vagant file path', :hide => true
def get_vagrant_file_path(filename = String.new)
# Check if a local pathname has been set.
if File.exists?(filename)
return filename
elsif filename == ''
# Try the fallback from hiera
filename = `hiera #{File.basename(__FILE__, '.*')}::vagrantfile`.chomp
if File.exists?(filename)
return filename
else
puts 'Error: Could not determine a Vagrant file.'
puts 'See help for examples or define in hiera: '
puts " #{File.basename(__FILE__, '.*')}::vagrantfile"
exit 1
end
else
puts 'Error: Could not find file: ' + filename
exit 1
end
end
desc 'parse_vagrant_file', 'Parse the Vagrant file'
def parse_vagrant_file()
if not options[:vagrantfile].nil?
filename = options[:vagrantfile]
else
filename = String.new
end
path_vagrant_file = get_vagrant_file_path(filename)
hosts = Hash.new
# Keeps track of the current host.
current = {
:config => nil,
:host => nil,
:pattern_end_match => nil,
}
# Parse the vagrant file into a hash
File.readlines(path_vagrant_file).each do |line|
# Pattern to match the lines defining a new host
pattern_define = /^(?<intendation>\s*)config(.)*define\s+(\"+)(?<hostname>.*)\"\s+do\s+\|(?<configname>.*)\|/
m = line.match(pattern_define)
# If the line matches the definition of a new host, put it in the list of hosts.
if not m.nil? and m[:hostname]
hosts[m[:hostname]] = { :configname => m[:configname], :ip => '0.0.0.0' }
current[:config] = m[:configname]
current[:host] = m[:hostname]
current[:pattern_end_match] = m[:intendation] + 'end'
end
# Grep for the IP in the current section
pattern_hostip = /^(\s*)#{current[:config]}.+network.*ip\:[\s\"]+(?<ip>\d+\.\d+\.\d+\.\d+)[\s\"]+/
m = line.match(pattern_hostip)
if not current[:config].nil? and
not m.nil? and
not m[:ip].nil? and
not current[:host].nil? and
not current[:config].nil?
hosts[current[:host]][:ip] = m[:ip]
end
# Reset the hostname and config, if the section has ended.
pattern_end_section = /^#{current[:pattern_end_match]}/
if line.match(pattern_end_section) and
not current[:host].nil?
current[:host] = nil
current[:config] = nil
current[:pattern_end_match] = nil
end
end
if options[':sort-by-ip']
# Sorting by node ip
hosts.sort_by {|k, v| v[:ip] }
longest_key = hosts.values
# This is one way putting out a hash. There's a function clled ljust for doing so.
# The other option is shown below.
hosts.each { |k, v| puts "#{v[:ip].ljust(16)} #{k}" }
else
# Sorting by node name
hosts.sort
# This method loops through the hash and prints out all the values
# The formatting is based on the longest value found.
longest_key = hosts.keys.max_by(&:length)
hosts.each do |key,value|
printf "%-#{longest_key.length}s %s\n", key, value[:ip]
end
end
end
default_task :parse_vagrant_file
end
Vagrant.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment