From abe29c4b48da811419e935bcfbad5c5266d6e489 Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Thu, 21 Mar 2024 16:00:03 -0400 Subject: [PATCH] Modernized Windows Support and documentation update --- README.md | 26 ++-------- facts/README.md | 101 ++++++++++++++++++++++++++++++++++++ facts/Vagrantfile | 37 +++++++++---- facts/Windows_README.md | 11 ---- facts/windows_get_facts.ps1 | 64 ++++++++++++++++++----- 5 files changed, 182 insertions(+), 57 deletions(-) create mode 100644 facts/README.md delete mode 100644 facts/Windows_README.md diff --git a/README.md b/README.md index 637c6877..8cda6f01 100644 --- a/README.md +++ b/README.md @@ -190,28 +190,8 @@ Where the number (1, 2 etc.) are the number of factsets for that OS and facter c ## Add new Operating System support -There is `Vagrantfile` to automagically populate `facts` directory by spawning a new VM and launches a provisioning scripts. - -``` -$ cd facts -$ vagrant up --provision -``` - -Create i386 facts from x86_64's ones - -``` -for file in facts/*/*-x86_64.facts; do cat $file | sed -e 's/x86_64/i386/' -e 's/amd64/i386/' > $(echo $file | sed 's/x86_64/i386/'); done -``` -Create RedHat, Scientific, OracleLinux facts from CentOS's ones - -``` -$ bundle exec rake rhel_alts -``` - -Then update the table in this README by running `bundle exec rake table` - -*NOTE*: When using Facter version 4, by default some "legacy facts" are hidden from the output. -To generate a fact set with the legacy facts use the command `puppet facts show --show-legacy` +There is `Vagrantfile` to automagically populate `facts` for all supported operating systems by spawning a new VM and launches a provisioning scripts. +Details of how to generate facts for each operating system are [here](facts/README.md). ## Supplying custom external facts @@ -306,7 +286,7 @@ powershell> $ENV:FACTERDB_INJECT_SOURCE = 'true' # Contributing -Please submit issues at https://github.com/camptocamp/facterdb/issues or PRs in the same repository. +Please submit issues at https://github.com/voxpupuli/facterdb/issues or PRs in the same repository. ## Release process diff --git a/facts/README.md b/facts/README.md new file mode 100644 index 00000000..0ca11f56 --- /dev/null +++ b/facts/README.md @@ -0,0 +1,101 @@ +# Building Facts for distribution + +There is `Vagrantfile` to automatically populate `facts` for all supported operating systems by spawning a new VM and launches a provisioning scripts. + +## Vagrant + +[Vagrant](https://www.vagrantup.com/) is a tool for creating reproducible virtual machine builds. +We use it to ensure facts are generated as similarly as possible every time. + +Vagrant starts by downloading a `box` - a pre-build skeleton of a virtual machine - and then running multiple steps on it. +Our workflow generally looks like this: + +1. One or more setup steps to make the VM ready to install puppet and generate facts (for example, setting up the network) +1. Calling the `get_facts` script which installs multiple versions of Puppet and generates facts for multiple versions of facter. +1. Shutting down the VM (Vagrant doesn't do this automatically). + +### Plugins + +The vagrant timezone plugin is recommended to prevent unnecessary changes to timezone facts: + +``` +vagrant plugin install vagrant-timezone +``` + +## Hypervisor + +The distributed facts are built using [VirtualBox](https://www.virtualbox.org/wiki/Downloads). +Building the facts will work with other visualization hosts, but will produce different results (eg. IP ranges) that will break spec tests. + +VirtualBox versions 6 and 7 have been tested. +The GPLv3 version of VirtualBox is sufficient - the proprietary `Oracle VM VirtualBox Extension Pack` is not required. + +## Building Facts + +To build new facts for all supported operating systems (except Windows) + +``` +$ cd facts +$ vagrant up --provision +``` + +You can build facts for only a single system or list of specific systems. + +``` +$ vagrant up --provision debian-11-x86_64 +``` + +Windows facts are not built by default, but can be run manually. + +``` +$ vagrant up --provision windows-server-2019-x86_64 windows-server-2022-x86_64 windows-10-x86_64 windows-11-x86_64 +``` + +Once new facts are built, the table listing supported facter versions and operating systems needs to be updated. + +``` +$ bundle exec rake table +``` + +### Converted Facts + +Not all facts can (or should) be built from VMs. +It often isn't necessary to run a separate VM to create some facts that won't be significantly different for existing facts. +Some operating systems are harder to run in VMs. + +#### Create i386 facts from x86_64's ones + +``` +for file in facts/*/*-x86_64.facts; do cat $file | sed -e 's/x86_64/i386/' -e 's/amd64/i386/' > $(echo $file | sed 's/x86_64/i386/'); done +``` + +#### Create OracleLinux facts from RedHat's ones + +``` +$ bundle exec rake rhel_alts +``` + +## Legacy Facts + +*NOTE*: When using Facter version 4, by default some "legacy facts" are hidden from the output. +To generate a fact set with the legacy facts use the command `puppet facts show --show-legacy` + +## OS-Specific Notes + +### Ubuntu 18.04 + +The default Ubuntu 18.04 `box` creates a console log. +Our `Vagrantfile` overrides this. +Newer Ubuntu `boxes` don't need this change. + +### Windows + +There are publicly available Windows `boxes` for Vagrant. + +We currently use publicly-availble `boxes` from Vagrant Community, but we also included packer templates so you can build your own (currently outdated). + +run `packer build .json` +followed by `vagrant add ` + +Once the box is added, change the `Vagrantfile` to use your new `box` and run `vagrant up ` + diff --git a/facts/Vagrantfile b/facts/Vagrantfile index 812d1e6a..c0014f56 100644 --- a/facts/Vagrantfile +++ b/facts/Vagrantfile @@ -296,26 +296,43 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| host.vm.provision 'shell', path: 'get_facts.sh' host.vm.provision 'shell', inline: '/sbin/shutdown -h now' end - config.vm.define 'windows-7-x86_64' do |host| + # Windows boxes can sometimes be picky, so don't include them automatically (autostart: false) + config.vm.define 'windows-server-2019-x86_64', autostart: false do |host| host.vm.hostname = 'foo' - host.vm.box = 'ferventcoder/win7pro-x64-nocm-lite' + host.vm.box = 'gusztavvargadr/windows-server-2019-standard-core' + host.vm.synced_folder '.', '/vagrant' + host.vm.communicator = 'winrm' + host.vm.guest = :windows + host.windows.set_work_network = true + host.vm.provision 'shell', path: 'windows_get_facts.ps1' + host.vm.provision 'shell', inline: 'shutdown -s -f -c "Fact Collection Complete"' + end + config.vm.define 'windows-server-2022-x86_64', autostart: false do |host| + host.vm.hostname = 'foo' + host.vm.box = 'gusztavvargadr/windows-server-2022-standard-core' + host.vm.synced_folder '.', '/vagrant' host.vm.communicator = 'winrm' host.vm.guest = :windows - host.vm.network :private_network, auto_network: true - host.vm.network 'forwarded_port', guest: 22, host: 2200, id: 'ssh', auto_correct: true host.windows.set_work_network = true host.vm.provision 'shell', path: 'windows_get_facts.ps1' - # host.vm.provision 'shell', inline: "Stop-Computer -AsJob" host.vm.provision 'shell', inline: 'shutdown -s -f -c "Fact Collection Complete"' - # host.vm.post_up_message = 'Note that windows machines do not automatically shutdown. You must run a \'vagrant destroy\' or \'vagrant halt\' to terminate/stop the build vm.' end - config.vm.define 'windows-2012r2-core-x86_64' do |host| + config.vm.define 'windows-10-x86_64', autostart: false do |host| host.vm.hostname = 'foo' - host.vm.box = 'windows-2012r2-core-x86_64' + host.vm.box = 'gusztavvargadr/windows-10' + host.vm.synced_folder '.', '/vagrant' + host.vm.communicator = 'winrm' + host.vm.guest = :windows + host.windows.set_work_network = true + host.vm.provision 'shell', path: 'windows_get_facts.ps1' + host.vm.provision 'shell', inline: 'shutdown -s -f -c "Fact Collection Complete"' + end + config.vm.define 'windows-11-x86_64', autostart: false do |host| + host.vm.hostname = 'foo' + host.vm.box = 'gusztavvargadr/windows-11' + host.vm.synced_folder '.', '/vagrant' host.vm.communicator = 'winrm' host.vm.guest = :windows - host.vm.network :private_network, auto_network: true - host.vm.network 'forwarded_port', guest: 22, host: 2200, id: 'ssh', auto_correct: true host.windows.set_work_network = true host.vm.provision 'shell', path: 'windows_get_facts.ps1' host.vm.provision 'shell', inline: 'shutdown -s -f -c "Fact Collection Complete"' diff --git a/facts/Windows_README.md b/facts/Windows_README.md deleted file mode 100644 index 79c0da65..00000000 --- a/facts/Windows_README.md +++ /dev/null @@ -1,11 +0,0 @@ -At the time of writing there are not suitable publicly available windows server -vagrant boxes that can be used to generate the facts. - -In order to make fact collection reproducible, I have included packer templates -so boxes can be rebuilt. - -run `packer build .json` -followed by `vagrant add ` - -Once the box is added a simple `vagrant up ` will collect all the facts in the same manner as the unix based hosts. - diff --git a/facts/windows_get_facts.ps1 b/facts/windows_get_facts.ps1 index 13e90108..e7411348 100644 --- a/facts/windows_get_facts.ps1 +++ b/facts/windows_get_facts.ps1 @@ -1,10 +1,29 @@ param( - [array]$puppetAgentVersions = ('1.1.1','1.2.2','1.4.0'), - [string]$baseUrl = 'https://downloads.puppetlabs.com/windows', + [array]$puppetAgentVersions = ('7.24.0','8.0.0','8.5.1'), + [string]$baseUrl = 'https://downloads.puppetlabs.com/windows/puppet{0}/puppet-agent-{1}-{2}.msi', [string]$fqdn = 'foo.example.com' ) -$PuppetInstallerPath = 'c:\vagrantshared\resources\installers' +$ComputerName = "foo" +$ComputerDomain = "example.com" + +Remove-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "Hostname" +Remove-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "NV Hostname" +Remove-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "Domain" + +Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\Computername\Computername" -name "Computername" -value $ComputerName +Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Control\Computername\ActiveComputername" -name "Computername" -value $ComputerName +Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "Hostname" -value $ComputerName +Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -name "NV Hostname" -value $ComputerName +Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name Domain -Value $ComputerDomain +Set-ItemProperty -path "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters" -Name DhcpDomain -Value $ComputerDomain + +# This doesn't work even though net use does??? +#New-SmbMapping -LocalPath 'X:' -RemotePath '\\VBOXSVR\vagrant' +net use X: \\VBOXSVR\vagrant + +$VagrantDataPath = 'X:\' +$WorkingDirectory = 'C:\vagrant_working_directory\' # Make sure we have enough privs to install the things. $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) @@ -14,21 +33,28 @@ if (! ($currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Admin } # Create our tmp dir if it's not found -if (!(Test-Path $PuppetInstallerPath)) { - Write-Host "Creating folder `'$PuppetInstallerPath`'" - $null = New-Item -Path "$PuppetInstallerPath" -ItemType Directory +if (!(Test-Path $WorkingDirectory)) { + Write-Host "Creating folder `'$WorkingDirectory`'" + $null = New-Item -Path "$WorkingDirectory" -ItemType Directory } # Install each puppet version & collect facts. foreach ($pupAgentVer in $puppetAgentVersions) { - $agentUrl = "$baseUrl/puppet-agent-$pupAgentVer-x64.msi" - $agentInstaller = Join-Path $PuppetInstallerPath "puppet-agent-$pupAgentVer-x64.msi" + + $agentUrl = $baseUrl -f $pupAgentVer[0], $pupAgentVer, "x64" + $agentName = "puppet-agent-{1}-{2}.msi" -f $pupAgentVer[0], $pupAgentVer, "x64" + $agentLogNameI = "puppet-{1}-install.log" -f $pupAgentVer[0], $pupAgentVer, "x64" + $agentLogNameU = "puppet-{1}-uninstall.log" -f $pupAgentVer[0], $pupAgentVer, "x64" + $agentInstaller = Join-Path $WorkingDirectory $agentName + $agentLogPathI = Join-Path $WorkingDirectory $agentLogNameI + $agentLogPathU = Join-Path $WorkingDirectory $agentLogNameU write-Host "Downloading `'$agentUrl`' to `'$agentInstaller`'" (New-Object Net.WebClient).DownloadFile("$agentUrl", "$agentInstaller") - #Install the actual agent, and - $install_args = @("/qn", "/norestart", "/i", "$agentInstaller", "PUPPET_AGENT_CERTNAME=$fqdn") + #Install the actual agent + $install_args = @("/l*v $agentLogPathI", "/qn", "/norestart", "/i", "$agentInstaller", "PUPPET_AGENT_CERTNAME=$fqdn") + $uninstall_args = @("/l*v $agentLogPathU", "/qn", "/norestart", "/x", "$agentInstaller") Write-Host "Installing Puppet. running msiexec.exe $install_args" $agentProcess = Start-Process -FilePath msiexec.exe -ArgumentList $install_args -Wait -PassThru if ($agentProcess.ExitCode -ne 0) { @@ -49,12 +75,24 @@ foreach ($pupAgentVer in $puppetAgentVersions) { # the domain name will fallback to the hypervisor's domain. $env:FACTER_fqdn = $fqdn - $facterArgs = @("-j") - $facterProcess = Start-Process -FilePath $facterBin -ArgumentList $facterArgs -Wait -PassThru -RedirectStandardOutput "C:\vagrant\$facterVer\$Os-$Osmaj-$Hw.facts" + $facterArgs = @("-j", "-p", "--show-legacy") + $facterProcess = Start-Process -FilePath $facterBin -ArgumentList $facterArgs -Wait -PassThru -RedirectStandardOutput "X:\$facterVer\$Os-$Osmaj-$Hw.facts" if ($facterProcess.ExitCode -ne 0) { Write-Host "Facter failed." Exit 1 } + + # dos2unix: `n in Powershell is a LF character + ((Get-Content "X:\$facterVer\$Os-$Osmaj-$Hw.facts") -join "`n") + "`n" | Set-Content -NoNewline "X:\$facterVer\$Os-$Osmaj-$Hw.facts" + Write-Host "Facts collected for $Os-$Osmaj-$Hw with facter $facterVer" -} + Write-Host "Uninstalling Puppet. running msiexec.exe $uninstall_args" + $agentProcess = Start-Process -FilePath msiexec.exe -ArgumentList $uninstall_args -Wait -PassThru + if ($agentProcess.ExitCode -ne 0) { + Write-Host "Installer failed." + Exit 1 + } + Write-Host "Puppet Agent $pupAgentVer successfully uninstalled." + +}