Skip to content

Commit 22e07b9

Browse files
authored
Merge pull request #766 from joshcooper/private_windows
Update module to support puppetcore on Windows
2 parents 9f8469c + d00532f commit 22e07b9

File tree

9 files changed

+153
-47
lines changed

9 files changed

+153
-47
lines changed

REFERENCE.md

+20-21
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
### Classes
88

9+
#### Public Classes
10+
911
* [`puppet_agent`](#puppet_agent): Upgrades Puppet 4 and newer to the requested version.
1012
* [`puppet_agent::configure`](#puppet_agent--configure): Uses $puppet_agent::config to manage settings in puppet.conf.
1113
* [`puppet_agent::install`](#puppet_agent--install): This class is called from puppet_agent for install.
@@ -22,10 +24,13 @@
2224
* [`puppet_agent::osfamily::windows`](#puppet_agent--osfamily--windows): Determines the puppet-agent package location for Windows OSes.
2325
* [`puppet_agent::params`](#puppet_agent--params): Sets variables according to platform.
2426
* [`puppet_agent::prepare`](#puppet_agent--prepare): This class is called from puppet_agent to prepare for the upgrade.
25-
* [`puppet_agent::prepare::package`](#puppet_agent--prepare--package): Ensures correct puppet-agent package is downloaded locally.
2627
* [`puppet_agent::prepare::puppet_config`](#puppet_agent--prepare--puppet_config): Private class called from puppet_agent::prepare class.
2728
* [`puppet_agent::service`](#puppet_agent--service): Ensures that managed services are running.
2829

30+
#### Private Classes
31+
32+
* `puppet_agent::prepare::package`: Ensures correct puppet-agent package is downloaded locally.
33+
2934
### Resource types
3035

3136
* [`puppet_agent_end_run`](#puppet_agent_end_run): Stops the current Puppet run if a puppet-agent upgrade was performed. Used on platforms that manage the Puppet Agent upgrade with a package r
@@ -614,24 +619,6 @@ The puppet-agent version to install.
614619

615620
Default value: `undef`
616621

617-
### <a name="puppet_agent--prepare--package"></a>`puppet_agent::prepare::package`
618-
619-
for installation. This is used on platforms without package managers capable of
620-
working with a remote https repository.
621-
622-
#### Parameters
623-
624-
The following parameters are available in the `puppet_agent::prepare::package` class:
625-
626-
* [`source`](#-puppet_agent--prepare--package--source)
627-
628-
##### <a name="-puppet_agent--prepare--package--source"></a>`source`
629-
630-
Data type: `Variant[String, Array]`
631-
632-
The source file for the puppet-agent package. Can use any of the data types
633-
and protocols that the File resource's source attribute can.
634-
635622
### <a name="puppet_agent--prepare--puppet_config"></a>`puppet_agent::prepare::puppet_config`
636623

637624
Private class called from puppet_agent::prepare class.
@@ -993,6 +980,18 @@ Data type: `Optional[Integer]`
993980

994981
The number of retries in case of network connectivity failures
995982

983+
##### `username`
984+
985+
Data type: `Optional[String[1]]`
986+
987+
The username to use when downloading from a source location requiring authentication
988+
989+
##### `password`
990+
991+
Data type: `Optional[Sensitive[String[1]]]`
992+
993+
The password to use when downloading from a source location requiring authentication
994+
996995
### <a name="install_shell"></a>`install_shell`
997996

998997
Install the Puppet agent package
@@ -1063,13 +1062,13 @@ The number of retries in case of network connectivity failures
10631062

10641063
##### `username`
10651064

1066-
Data type: `Optional[String]`
1065+
Data type: `Optional[String[1]]`
10671066

10681067
The username to use when downloading from a source location requiring authentication
10691068

10701069
##### `password`
10711070

1072-
Data type: `Optional[String]`
1071+
Data type: `Optional[Sensitive[String[1]]]`
10731072

10741073
The password to use when downloading from a source location requiring authentication
10751074

manifests/init.pp

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
# @param arch
44
# The package architecture. Defaults to the architecture fact.
55
# @param collection
6-
# The Puppet Collection to track. Defaults to 'PC1'.
6+
# The Puppet Collection to track. Defaults to 'PC1'. Valid values are puppet7,
7+
# puppet8, puppet, puppet7-nightly, puppet8-nightly, puppet-nightly,
8+
# puppetcore7, puppetcore8.
79
# @param is_pe
810
# Install from Puppet Enterprise repos. Enabled if communicating with a PE master.
911
# @param manage_pki_dir

manifests/osfamily/windows.pp

+10-1
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,22 @@
2323
} else {
2424
if $puppet_agent::collection == 'PC1' {
2525
$source = "${puppet_agent::windows_source}/windows/${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-${puppet_agent::arch}.msi"
26+
} elsif $puppet_agent::collection =~ /core/ {
27+
$source = 'https://artifacts-puppetcore.puppet.com/v1/download'
2628
} else {
2729
$source = "${puppet_agent::windows_source}/windows/${puppet_agent::collection}/${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-${puppet_agent::arch}.msi"
2830
}
2931
}
3032

33+
$destination_name = if $puppet_agent::collection =~ /core/ {
34+
"${puppet_agent::package_name}-${puppet_agent::prepare::package_version}-${puppet_agent::arch}.msi"
35+
} else {
36+
undef
37+
}
38+
3139
class { 'puppet_agent::prepare::package':
32-
source => $source,
40+
source => $source,
41+
destination_name => $destination_name,
3342
}
3443

3544
contain puppet_agent::prepare::package

manifests/prepare/package.pp

+46-16
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,28 @@
22
# for installation. This is used on platforms without package managers capable of
33
# working with a remote https repository.
44
#
5-
# @param source
6-
# The source file for the puppet-agent package. Can use any of the data types
7-
# and protocols that the File resource's source attribute can.
5+
# @api private
86
class puppet_agent::prepare::package (
97
Variant[String, Array] $source,
8+
Optional[String[1]] $destination_name = undef
109
) {
1110
assert_private()
1211

1312
file { $puppet_agent::params::local_packages_dir:
1413
ensure => directory,
1514
}
1615

17-
# In order for the 'basename' function to work correctly we need to change
18-
# any \s to /s (even for windows UNC paths) so that it will correctly pull off
19-
# the filename. Since this operation is only grabbing the base filename and not
20-
# any part of the path this should be safe, since the source will simply remain
21-
# what it was before and we can still pull off the filename.
22-
$package_file_name = basename(regsubst($source, "\\\\", '/', 'G'))
16+
$package_file_name = if $destination_name {
17+
$destination_name
18+
} else {
19+
# In order for the 'basename' function to work correctly we need to change
20+
# any \s to /s (even for windows UNC paths) so that it will correctly pull off
21+
# the filename. Since this operation is only grabbing the base filename and not
22+
# any part of the path this should be safe, since the source will simply remain
23+
# what it was before and we can still pull off the filename.
24+
basename(regsubst($source, "\\\\", '/', 'G'))
25+
}
26+
2327
if $facts['os']['family'] =~ /windows/ {
2428
$local_package_file_path = windows_native_path("${puppet_agent::params::local_packages_dir}/${package_file_name}")
2529
$mode = undef
@@ -28,12 +32,38 @@
2832
$mode = '0644'
2933
}
3034

31-
file { $local_package_file_path:
32-
ensure => file,
33-
owner => $puppet_agent::params::user,
34-
group => $puppet_agent::params::group,
35-
mode => $mode,
36-
source => $source,
37-
require => File[$puppet_agent::params::local_packages_dir],
35+
if $puppet_agent::collection =~ /core/ and $facts['os']['family'] =~ /windows/ {
36+
$download_username = getvar('puppet_agent::username', 'forge-key')
37+
$download_password = unwrap(getvar('puppet_agent::password'))
38+
$dev = count(split($puppet_agent::prepare::package_version, '\.')) > 3
39+
40+
$_download_puppet = windows_native_path("${facts['env_temp_variable']}/download_puppet.ps1")
41+
file { $_download_puppet:
42+
ensure => file,
43+
content => Sensitive(epp('puppet_agent/download_puppet.ps1.epp')),
44+
}
45+
46+
exec { 'Download Puppet Agent':
47+
command => [
48+
"${facts['os']['windows']['system32']}\\WindowsPowerShell\\v1.0\\powershell.exe",
49+
'-ExecutionPolicy',
50+
'Bypass',
51+
'-NoProfile',
52+
'-NoLogo',
53+
'-NonInteractive',
54+
$_download_puppet
55+
],
56+
creates => $local_package_file_path,
57+
require => File[$puppet_agent::params::local_packages_dir],
58+
}
59+
} else {
60+
file { $local_package_file_path:
61+
ensure => file,
62+
owner => $puppet_agent::params::user,
63+
group => $puppet_agent::params::group,
64+
mode => $mode,
65+
source => $source,
66+
require => File[$puppet_agent::params::local_packages_dir],
67+
}
3868
}
3969
}

metadata.json

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
{
2424
"name": "puppetlabs-facts",
2525
"version_requirement": ">= 0.5.0 < 2.0.0"
26+
},
27+
{
28+
"name": "puppetlabs-powershell",
29+
"version_requirement": ">= 6.0.2 < 7.0.0"
2630
}
2731
],
2832
"operatingsystem_support": [

tasks/install_powershell.json

+8
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@
4242
"description": "The number of retries in case of network connectivity failures",
4343
"type": "Optional[Integer]",
4444
"default": 5
45+
},
46+
"username": {
47+
"description": "The username to use when downloading from a source location requiring authentication",
48+
"type": "Optional[String[1]]"
49+
},
50+
"password": {
51+
"description": "The password to use when downloading from a source location requiring authentication",
52+
"type": "Optional[Sensitive[String[1]]]"
4553
}
4654
},
4755
"supports_noop": true

tasks/install_powershell.ps1

+40-6
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,21 @@ Param(
77
[String]$install_options = 'REINSTALLMODE="amus"',
88
[Bool]$stop_service = $False,
99
[Int]$retry = 5,
10-
[Bool]$_noop = $False
10+
[Bool]$_noop = $False,
11+
[String]$username = 'forge-key',
12+
[String]$password
1113
)
1214
# If an error is encountered, the script will stop instead of the default of "Continue"
1315
$ErrorActionPreference = "Stop"
1416

17+
try {
18+
$os_version = (Get-WmiObject Win32_OperatingSystem).Version
19+
}
20+
catch [System.Management.Automation.CommandNotFoundException] {
21+
$os_version = (Get-CimInstance -ClassName win32_OperatingSystem).Version
22+
}
23+
$major_os_version = ($os_version -split '\.')[0]
24+
1525
try {
1626
if ((Get-WmiObject Win32_OperatingSystem).OSArchitecture -match '^32') {
1727
$arch = "x86"
@@ -27,9 +37,19 @@ catch [System.Management.Automation.CommandNotFoundException] {
2737
}
2838
}
2939

40+
$fips = 'false'
41+
try {
42+
if ((Get-ItemPropertyValue -Path 'HKLM:\System\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy' -Name Enabled) -ne 0) {
43+
$fips = 'true'
44+
}
45+
}
46+
catch {
47+
Write-Output "Failed to lookup FIPS mode, assuming it is disabled"
48+
}
49+
3050
function Test-PuppetInstalled {
3151
$rootPath = 'HKLM:\SOFTWARE\Puppet Labs\Puppet'
32-
try {
52+
try {
3353
if (Get-ItemProperty -Path $rootPath) { RETURN $true }
3454
}
3555
catch {
@@ -98,12 +118,21 @@ if (Test-RunningServices) {
98118
# Change windows_source only if the collection is a nightly build, and the source was not explicitly specified.
99119
if (($collection -like '*nightly*') -And -Not ($PSBoundParameters.ContainsKey('windows_source'))) {
100120
$windows_source = 'https://nightlies.puppet.com/downloads'
121+
} elseif (($collection -like '*puppetcore*') -And -Not ($PSBoundParameters.ContainsKey('windows_source'))) {
122+
$windows_source = 'https://artifacts-puppetcore.puppet.com/v1/download'
101123
}
102124

103125
if ($absolute_source) {
104126
$msi_source = "$absolute_source"
105-
}
106-
else {
127+
} elseif ($collection -like '*puppetcore*') {
128+
# dev param is case-sensitive, so don't use $True
129+
if (($version -split '\.').count -gt 3) {
130+
$dev = '&dev=true'
131+
} else {
132+
$dev = ''
133+
}
134+
$msi_source = "${windows_source}?version=${version}&os_name=windows&os_version=${major_os_version}&os_arch=${arch}&fips=${fips}${dev}"
135+
} else {
107136
$msi_source = "$windows_source/windows/${collection}/${msi_name}"
108137
}
109138

@@ -125,22 +154,27 @@ function Set-Tls12 {
125154
}
126155

127156
function DownloadPuppet {
128-
Write-Output "Downloading the Puppet Agent installer on $env:COMPUTERNAME..."
157+
Write-Output "Downloading the Puppet Agent installer on $env:COMPUTERNAME from ${msi_source}"
129158
Set-Tls12
130159

131160
$webclient = New-Object system.net.webclient
132-
161+
if ($password) {
162+
$credentials = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${username}:${password}"))
163+
$webclient.Headers.Add("Authorization", "Basic ${credentials}")
164+
}
133165
try {
134166
$webclient.DownloadFile($msi_source,$msi_dest)
135167
}
136168
catch [System.Net.WebException] {
169+
Write-Host "Download exception: $($_.Exception.Message)"
137170
For ($attempt_number = 1; $attempt_number -le $retry; $attempt_number++) {
138171
try {
139172
Write-Output "Retrying... [$attempt_number/$retry]"
140173
$webclient.DownloadFile($msi_source,$msi_dest)
141174
break
142175
}
143176
catch [System.Net.WebException] {
177+
Write-Host "Download exception: $($_.Exception.Message)"
144178
if($attempt_number -eq $retry) {
145179
# If we can't find the msi, then we may not be configured correctly
146180
if($_.Exception.Response.StatusCode -eq [system.net.httpstatuscode]::NotFound) {

tasks/install_shell.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,11 @@
4646
},
4747
"username": {
4848
"description": "The username to use when downloading from a source location requiring authentication",
49-
"type": "Optional[String]"
49+
"type": "Optional[String[1]]"
5050
},
5151
"password": {
5252
"description": "The password to use when downloading from a source location requiring authentication",
53-
"type": "Optional[String]"
53+
"type": "Optional[Sensitive[String[1]]]"
5454
}
5555
},
5656
"files": ["facts/tasks/bash.sh"],

templates/download_puppet.ps1.epp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
$body = @{
2+
"version" = "<%= $puppet_agent::prepare::package_version %>"
3+
"dev" = "<%= $puppet_agent::prepare::package::dev %>"
4+
"os_name" = "<%= $facts['os']['family'] %>"
5+
"os_version" = "<%= $facts['os']['release']['major'] %>"
6+
"os_arch" = "<%= $facts['os']['architecture'] %>"
7+
"fips" = "<%= $facts['fips_enabled'] %>"
8+
}
9+
$username = "<%= $puppet_agent::prepare::package::download_username %>"
10+
$password = ConvertTo-SecureString "<%= $puppet_agent::prepare::package::download_password %>" -AsPlainText -Force
11+
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
12+
try {
13+
Invoke-WebRequest -Uri "<%= $puppet_agent::prepare::package::source %>" `
14+
-Body $body `
15+
-Credential $credential `
16+
-OutFile "<%= $puppet_agent::prepare::package::local_package_file_path %>"
17+
} catch [System.Net.WebException] {
18+
Write-Host "Network-related error: $($_.Exception.Message)"
19+
exit 1
20+
}

0 commit comments

Comments
 (0)