Skip to content

Instantly share code, notes, and snippets.

@bartku
Forked from jthurteau/Vagrantfile
Created November 26, 2022 19:54
Show Gist options
  • Save bartku/2b2573e2ea382e79538438e4ef957f04 to your computer and use it in GitHub Desktop.
Save bartku/2b2573e2ea382e79538438e4ef957f04 to your computer and use it in GitHub Desktop.
Vagrant with MrRogers
##
# Helps Manage Puppetized RHEL Vagrants
# https://puppet.com/docs/puppet/5.5/
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/ https://www.linux.ncsu.edu/rhel-unc-system/
# https://www.vagrantup.com/docs/
#
# You do not need Ruby on the guest for this module,
# you should not need Ruby installed on the guest aside from the runtime Vagrant uses
# https://gist.github.com/jthurteau/3c3d8e15208d93c0cf28cc2148c91b0b
#
module MrRogers
extend self
@tabs = ' '
@manifest_stack = ''
@manifests_path = 'puppet/manifests'
@manifest_build_file = 'default-dynamic.pp'
@built_manifest_token = 'puppet made this'
@facts_file = '.puppet_facts' #relative to vagrant, not puppet
@puppet_facts = nil
@ppp = []
@realm = nil
@rhel_org = ''
@realm_key = ''
@rhel_repo = ''
@realhostname = nil
@realdomain = nil
@collections_requested = false
@collection_source = [:rhel, :centos, :remi][2]
@when_to_chill = ['never', 'always'][1]
@when_to_reregister = ['never', 'always'][0]
@when_to_install_sc = ['once', 'never'][0]
@when_to_nano_enforce = 'once'
#TODO make the puppet modules/versions configurable
def self.init(stack, path, build)
@manifest_stack = stack
@manifests_path = path
@manifest_build_file = build
begin
# NOTE - an empty YAML file equates to nil,
# the facts_file must be an explicit empty hash {} if it has no value-keys
@puppet_facts = YAML.load_file(@facts_file)
rescue SystemCallError => e
print "#{@tabs}Warning: puppet facts not available (this is a critical error on up, reload, provision, or resume)\n\r"
end
@manifest_stack.split('-').each { |a| @ppp.push(a) }
end
def self.set_realm(new_realm, org, key, repo)
@realm = new_realm
@rhel_org = org
@realm_key = key
@rhel_repo = repo
end
#TODO this should probably be an instance (per app/machine) method
def self.box(box, config)
config.vm.box = @realm ? 'generic/rhel7' : 'centos/7'
config.vm.define ("#{box}-" + (@realm ? 'realm' : 'nomad')) do # |machine|
# only used in multi-machine builds
end
end
def self.passthrough_host(config)
fqdn = Socket.gethostbyname(Socket.gethostname).first.split('.')
hostname = fqdn.shift.downcase
domain = fqdn.join('.').downcase
public_ips = Socket.ip_address_list.reject{|i| !i.ipv4? || i.ipv4_loopback? || i.ipv4_multicast? || i.ipv4_private? }
ip = public_ips.any? ? public_ips.first&.ip_address : nil
realfqdn = ip ? (Resolv.getname ip).split('.') : nil
@realhostname = realfqdn ? realfqdn.shift.downcase : hostname
@realdomain = realfqdn ? realfqdn.join('.').downcase : domain
config.trigger.before [:up, :provision, :reload] do |trigger|
trigger.info = "Harvesting Host FQDN"
trigger.ruby do |env, machine|
if (!ip)
Socket.ip_address_list.map{ |i| print(i.inspect + "\n\r")}
print("#{@tabs}No public IPv4 detected, known IPs: \n\r");
end
print "#{@tabs}host fqdn detected as #{@realhostname} + #{@realdomain}" + (ip ? " (#{ip})" : '') + "\n\r"
end
end
config.vm.provision "set_hostname", type: :shell, inline: <<-SHELL
hostnamectl set-hostname #{@realhostname}
SHELL
if (@realm)
config.vm.provision "setup_domain", type: :shell, inline: <<-SHELL
if [ ! -e /etc/hosts ] || ! grep -q "needed for realm-puppet management" /etc/hosts
then
echo " " >> /etc/hosts
echo "## The line below is needed for realm-puppet management" >> /etc/hosts
echo "#{ip} #{@realhostname}.#{@realdomain} #{@realhostname}" >> /etc/hosts
echo " " >> /etc/hosts
fi
SHELL
end
end
def self.register(config)
self.passthrough_host(config) if (!@realhostname)
if (@realm)
config.vm.provision "rhel_setup", type: :shell, inline: <<-SHELL
yum install #{@rhel_repo} -y
if [[ $(subscription-manager identity) =~ "org ID: #{@rhel_org}" ]]
then
echo "RHEL already registered"
else
subscription-manager register --org="#{@rhel_org}" --activationkey="#{@realm_key}"
fi
SHELL
registration_update_inline = <<-SHELL
yum install http://rhn200cap.unity.ncsu.edu/pub/katello-ca-consumer-latest.noarch.rpm -y
if [[ $(subscription-manager identity) =~ "org ID: #{@rhel_org}" ]]
then
echo "Unregistering RHEL"
subscription-manager unregister
else
echo "RHEL not registered"
fi
subscription-manager register --org="#{@rhel_org}" --activationkey="#{@realm_key}"
subscription-manager clean
yum clean all
yum update -y
SHELL
else
config.vm.provision "centos_setup", type: :shell, inline: <<-SHELL
yum groups install "Development Tools" -y
SHELL
registration_update_inline = <<-SHELL
echo Unavailable in nomad mode
SHELL
end
config.vm.provision "registration_update", type: :shell, run: @when_to_reregister do |s|
s.inline = registration_update_inline
end
end
def self.add_collections(config, source = nil)
@collection_source = source if source
@collections_requested = true
if (@realm)
software_collections_inline = <<-SHELL
echo Inclusing the software_collections...
echo (currently broken)
# subscription-manager repos --enable rhel-server-rhscl-7-rpms
# subscription-manager repos --enable rhel-7-server-optional-rpms
SHELL
elsif ( @collection_source == :centos )
software_collections_inline = <<-SHELL
yum install centos-release-scl -y
yum update -y
SHELL
elsif ( @collection_source == :remi )
software_collections_inline = <<-SHELL
yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm -y
yum update -y
SHELL
else
software_collections_inline = <<-SHELL
echo no valid software collection specified (requested '#{source}')
SHELL
end
config.vm.provision "software_collections", type: :shell, run: @when_to_install_sc do |s|
s.inline = software_collections_inline
end
end
def self.puppetize(config, options = '')
MrRogers::add_collections(config) if (!@collections_requested)
config.trigger.before [:up, :provision, :reload, :resume] do |trigger|
trigger.info = "Checking, are Strings Attached?"
trigger.ruby do |env, machine|
if (!@puppet_facts)
print "#{@tabs}Error: Unable to load puppet facts. Exiting...\n\r"
exit(1)
end
print "#{@tabs}loaded facts from #{@facts_file}\n\r"
ldm_path = "#{@manifests_path}/#{@manifest_build_file}"
if !File.file?(ldm_path)
ldm_file = File.new(ldm_path, 'w+')
ldm_file.write("# #{@built_manifest_token}")
else
ldm_file = File.new(ldm_path, 'a+')
ldm_file.rewind
if (!ldm_file.readline.start_with?("# #{@built_manifest_token}"))
ldm_file.close
ldm_file = nil
print "#{@tabs}proceeding with manually written #{@manifest_build_file} \n\r"
end
end
if (ldm_file)
print "#{@tabs}building #{@manifest_build_file} \n\r"
ldm_file.truncate(ldm_file.pos + 1)
ppp_final = ['global'] + @ppp + ['override']
ppp_final.each do |pp|
if (File.file?("#{@manifests_path}/#{pp}.pp"))
print "#{@tabs} adding \"#{pp}\" manifest to #{@manifest_build_file}\n\r"
ldm_file.write("\n\r# from #{pp}.pp \n\r");
ldm_file.write(File.read("#{@manifests_path}/#{pp}.pp"))
else
print "#{@tabs} no \"#{pp}\" manifest available for #{@manifest_build_file}\n\r"
end
end
ldm_file.close
end
end
end
config.vm.provision "puppet_prep", type: :shell, inline: <<-SHELL
# rpm -ivh https://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm
rpm -Uvh https://yum.puppetlabs.com/puppet5/puppet5-release-el-7.noarch.rpm
yum install epel-release puppet -y
yum update -y
if [ ! -e /usr/bin/puppet ]
then
echo "linking puppet binary..."
ln -s /opt/puppetlabs/bin/puppet /usr/bin/puppet
fi
# # puppet 3.8 compat "supported"
# puppet module install puppetlabs-postgresql --version 4.9.0
# puppet module install puppetlabs-apache --version 1.11.1
# puppet module install puppetlabs-mysql --version 3.11.0
# puppet module install puppetlabs-vcsrepo --version 1.5.0
# # puppet 3.8 compat approved
# puppet module install puppet-python --version 2.2.2
# puppet 5.5 compat supported
puppet module install puppetlabs-postgresql --version 5.12.0
puppet module install puppetlabs-apache --version 4.0.0
puppet module install puppetlabs-mysql --version 8.0.0
puppet module install puppetlabs-vcsrepo --version 2.4.0
# puppet 5.5 compat approved
puppet module install puppet-python --version 2.2.2
puppet config set strict_variables true --section main
SHELL
config.vm.provision :puppet do |puppet|
puppet.manifests_path = @manifests_path
puppet.manifest_file = @manifest_build_file
puppet.options = options
puppet.facter = @puppet_facts
end
config.vm.provision "puppet-reset", type: :shell, run: 'never' do |s|
s.inline = <<-SHELL
puppet module uninstall puppetlabs-postgresql
puppet module uninstall puppetlabs-apache
puppet module uninstall puppetlabs-mysql
puppet module uninstall puppet-python
puppet module uninstall puppetlabs-vcsrepo
SHELL
end
end
def self.nano_please(config)
config.vm.provision "nano_setup", type: :shell do |s|
s.inline = <<-SHELL
yum install nano -y
SHELL
end
config.vm.provision "nano_make_default", type: :shell, run: @when_to_nano_enforce do |s|
s.inline = <<-SHELL
if [ ! -e ~/.bashrc ] || ! grep -q "set nano as the default editor" ~/.bashrc
then
echo " " >> ~/.bashrc
echo "## The (2) lines below set nano as the default editor" >> ~/.bashrc
echo "export EDITOR='nano'" >> ~/.bashrc
echo "export VISUAL='nano'" >> ~/.bashrc
echo " " >> ~/.bashrc
fi
SHELL
s.privileged = false
end
end
def self.os_friendly(config)
if Vagrant::Util::Platform.windows?
self.windows_host_friendly(config)
end
end
def self.windows_host_friendly(config)
config.vm.provision "windows_support", type: :shell do |s|
s.inline = <<-SHELL
if [ ! -e ~/.bashrc ] || ! grep -q "poor detection of vagrant windows host" ~/.bashrc
then
echo " " >> ~/.bashrc
echo "## The (2) lines below fix poor detection of vagrant windows host" >> ~/.bashrc
echo "stty sane" >> ~/.bashrc
echo "export TERM=linux" >> ~/.bashrc
echo " " >> ~/.bashrc
fi
SHELL
s.privileged = false
end
end
def self.add_helpers(config, additional = [])
additional.each do |a|
case a
when 'nano'
self.nano_please(config)
when 'os'
self.os_friendly(config)
else
print "#{tabs}unknown helper: #{a}"
end
end
config.vm.provision "reminders", type: :shell, run: 'always' do |s|
s.inline = <<-SHELL
echo To activate post-startup tasks on the guest VM use: vagrant up --provision-with start
SHELL
end
config.vm.provision "chill", type: :shell, run: @when_to_chill do |s|
s.inline = <<-SHELL
echo Toning down SELinux...
setenforce Permissive
systemctl stop firewalld.service
SHELL
end
config.vm.provision "start", type: :shell, run: 'never' do |s|
s.inline = <<-SHELL
echo Starting Services...
systemctl start httpd.service
SHELL
end
config.vm.provision "stop", type: :shell, run: 'never' do |s|
s.inline = <<-SHELL
echo Stopping Services...
systemctl stop httpd.service
SHELL
end
end
end
# -*- mode: ruby -*-
# vi: set ft=ruby :
require 'resolv'
require_relative 'puppet/mr_rogers'
# project settings
app_name = 'APPLICATION_NAME_HERE'
org_name = 'ORG_NAME_HERE'
realm_mode = false
puppet_stack = "#{org_name}-apache-php-#{app_name}"
log_to = ['console', 'file'][0]
# rhel settings (used in realm_mode)
realm_key = 'KEY_HERE'
rhel_org = 'RHEL_ORG_HERE'
rhel_repo = 'REPO_URL_HERE'
# vagrant/puppet specific preferences
vagrant_guest_path = '/vagrant'
logtime = DateTime.now.strftime('%Y-%m-%d-%H-%M-%S')
logfile = "#{vagrant_guest_path}/puppet/local-dev.puppet-provision-#{logtime}.log.json"
log_to = logfile if ('file' == log_to)
MrRogers::init(puppet_stack, 'puppet/manifests', 'local-dev.pp')
MrRogers::set_realm(org_name, rhel_org, realm_key, rhel_repo) if realm_mode
#MrRogers::version('5') #TODO manage puppet repo and module versions based on puppet version
Vagrant.configure('2') do |config|
MrRogers::box("#{app_name}-#{org_name}", config)
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Forwarded port mapping
config.vm.network 'forwarded_port', guest: 80, host: 8080, host_ip: '127.0.0.1'
config.vm.network 'forwarded_port', guest: 8001, host: 8081, host_ip: '127.0.0.1'
config.vm.synced_folder '.', vagrant_guest_path, owner: 'vagrant', group: 'vagrant', type: 'virtualbox'
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
config.vm.provider 'virtualbox' do |vb|
# Display the VirtualBox GUI when booting the machine
vb.gui = false
vb.memory = "1024"
end
# provisioners
MrRogers::register(config)
MrRogers::puppetize(config, "--verbose --debug --logdest #{log_to}")
# this is where custom provisioning typically happens
MrRogers::add_helpers(config, ['nano','os']) #optional (provisioners to manage apache, tone down selinux, etc.)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment