Skip to content

Commit 2ddda63

Browse files
committed
Use package resource, remote_file
Previously a Powershell exec was used to install packages. This commit converts that task to a package-based resource. It allows cleaner, easier to read code. Switch from download_file to remote_file. This allows for better subscribe/notify of the dotnet defined type as remote_file does not have any intermediate file fragment resources which may be used or changed even if the file to download is not changed. The remote_file resource is also platform agnostic, unlike download_file, more meaning it may be accessible and familar to a wider range of potential users/contributors. Update for Puppet 4 and remove deps Use Puppet 4's type system to deal with validation and remove dependency on stdlib. Use the $::os fact to get Windows release version and remove dependency on windowsfacts. Add logic to prevent incompatible versions Some versions of .NET are in-place upgrades of others. Installation of .NET 4.5, for example, will replace the 4.0 package. In order to disallow Puppet from continuously trying to install .NET 4.0 in the event dotnet resources for both 4.0 and 4.5 have been added to the catalog, create a package=absent resource for each conflicting version. This will cause the conflict to be caught when a catalog is compiled for the node. Add ability to recognize built-in .NET versions Some OSes have some versions of .NET built in and so do not need to have it installed via package. It seems likely this was auto-detected based on registry key presence/absence via exec previously. Because we're now managing the package directly, we should be more explicit about whether or not the package actually needs to be installed. Clean up installation type detection Regex adjustments to make it easier to read which versions support which installation types. Only test on 4.x/future parser Set gemfile to use PUPPET_GEM_VERSION and set default to 4.0 Adjust tests to match updates This is not a comprehensive test overhaul, but does update the functional tests to work with the updated code. Logic correction - For 2008, .NET 3.5 is a package Previously the dotnet define logic would attempt to install .NET 3.5 as a feature on Server 2008. This was incorrect, as in Server 2008 .NET 3.5 was not available as a feature and needed the package installation. Add Dism install type for Windows 7 Windows 7 does not install .NET as a package, nor does it have the ServerManager module. Therefore provide an alternative means of managing the feature via DISM. Fix non-functional onlyif in powershell exec The Puppet Exec resource uses the return code of command, unless, and onlyif to determine success/failure or if action is necessary. Previously, the onlyif in dotnet::install::feature would never exit with a non-zero exit code, even if the Test-Path command returned a False object. Return object and exit code are not the same thing. This commit modifies the onlyif to ensure that if the Test-Path command returns false a non-zero exit code will occur. (style) Line up case blocks Add feature parameter to dotnet::install::feature This will allow specification of different feature names. Necessary specifically because the feature name to install .NET 3.5 on Server 2012 is not the same feature as to install 4.5. The feature name for .NET 3.5 in Server 2012 is not AS-NET-Framework, which we use as the default feature. This commit also updates the dotnet type to attempt installation of the correct feature when 3.5 is specified on Server 2012.
1 parent 1db0742 commit 2ddda63

File tree

14 files changed

+351
-622
lines changed

14 files changed

+351
-622
lines changed

.fixtures.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ fixtures:
22
repositories:
33
stdlib: https://github.com/puppetlabs/puppetlabs-stdlib
44
powershell: https://github.com/puppetlabs/puppetlabs-powershell
5-
win_facts: https://github.com/liamjbennett/puppet-win_facts
6-
download_file: https://github.com/opentable/puppet-download_file
5+
remote_file: https://github.com/lwf/puppet-remote_file
76
symlinks:
87
dotnet: "#{source_dir}"

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ matrix:
1212
fast_finish: true
1313
include:
1414
- rvm: 1.9.3
15-
env: PUPPET_VERSION="~> 3.0" STRICT_VARIABLES="yes" CHECK=test
15+
env: PUPPET_VERSION="~> 3.0" STRICT_VARIABLES="yes" CHECK=test FUTURE_PARSER="yes"
1616
- rvm: 2.1.6
17-
env: PUPPET_VERSION="~> 3.0" STRICT_VARIABLES="yes" CHECK=test
17+
env: PUPPET_VERSION="~> 3.0" STRICT_VARIABLES="yes" CHECK=test FUTURE_PARSER="yes"
1818
- rvm: 2.1.6
1919
env: PUPPET_VERSION="~> 4.0" STRICT_VARIABLES="yes" CHECK=test
2020
- rvm: 2.2.3

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ source 'https://rubygems.org'
1616

1717
group :test do
1818
gem 'rake'
19-
gem 'puppet', ENV['PUPPET_VERSION'] || '~> 3.8.0'
19+
gem 'puppet', ENV['PUPPET_VERSION'] || '~> 4.0'
2020
gem 'rspec-puppet', git: 'https://github.com/rodjek/rspec-puppet.git'
2121
gem 'puppetlabs_spec_helper'
2222
gem 'metadata-json-lint'

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ Ensures the state of .net on the system. Present or Absent.
6161
The version of .net that you want to be managed by this definition.
6262

6363
#####`package_dir`
64-
If installing .NET from a directory or a mounted network location then this is that directory
64+
If installing .NET from a directory or a mounted network location then this is
65+
that directory. If the version of .NET being installed is a Windows feature, it
66+
may sometimes be necessary to specify package\_dir as the path to installation
67+
media, such as `D:\sources\sxs`.
6568

6669
##Reference
6770

manifests/init.pp

Lines changed: 72 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,54 +31,95 @@
3131
# }
3232
#
3333
define dotnet(
34-
$ensure = 'present',
35-
$version = '',
36-
$package_dir = ''
37-
) {
34+
Enum['3.5', '4.0', '4.5', '4.5.1', '4.5.2']
35+
$version,
36+
37+
Enum['present', 'absent']
38+
$ensure = 'present',
3839

39-
validate_re($ensure,['^(present|absent)$'])
40-
validate_re($version,['^(3.5|4\.0|4\.5(\.\d)?)$'])
40+
Variant[String, Undef]
41+
$package_dir = undef,
42+
) {
4143

4244
include dotnet::params
4345

46+
if $::os['family'] != 'windows' {
47+
fail("dotnet ${version} is not supported on ${::os['family']}")
48+
}
49+
50+
$windows_version = $::os['release']['full']
51+
4452
case $version {
4553
'3.5': {
46-
case $::operatingsystemversion {
47-
/^Windows.Server.(2008|2012).?(R2)?.*/: { $type = 'feature' }
48-
/^Windows (XP|Vista|7|8|8.1).*/: { $type = 'package' }
49-
default: { $type = 'err' err("dotnet ${version} is not support on this version of windows") }
54+
case $windows_version {
55+
/^2012/: {
56+
$type = 'feature'
57+
$feature = 'NET-Framework-Features'
58+
}
59+
'2008 R2': { $type = 'feature' }
60+
'7', '8', '8.1': { $type = 'dism' }
61+
/^2003/, '2008', 'XP', 'Vista': { $type = 'package' }
62+
default: { $type = 'err' }
5063
}
5164
}
5265
'4.0': {
53-
case $::operatingsystemversion {
54-
/^Windows.(Server)?.?(2003|2008|2012|XP|Vista|7|8.*).?(R2)?.*/: { $type = 'package' }
55-
default: { $type = 'err' err("dotnet ${version} is not support on this version of windows") }
66+
case $windows_version {
67+
/^2012/, '8', '8.1': { $type = 'builtin' }
68+
/^2003/, /^2008/, 'XP', 'Vista', '7': { $type = 'package' }
69+
default: { $type = 'err' }
5670
}
5771
}
58-
/4\.5(\.\d)?/: {
59-
case $::operatingsystemversion {
60-
/^Windows.(Server)?.?(2008|2012|Vista|7|8.*).?(R2)?.*/: { $type = 'package' }
61-
default: { $type = 'err' err("dotnet ${version} is not support on this version of windows") }
72+
'4.5': {
73+
case $windows_version {
74+
/^2012/, '8', '8.1': { $type = 'builtin' }
75+
/^2003/, /^2008/, 'XP', 'Vista', '7': { $type = 'package' }
76+
default: { $type = 'err' }
6277
}
6378
}
64-
default: {
65-
$type = 'err'
66-
err("dotnet does not have a version: ${version}")
79+
'4.5.1': {
80+
case $windows_version {
81+
'2012 R2', '8.1': { $type = 'builtin' }
82+
/^2003/, /^2008/, '2012', 'XP', 'Vista', '7', '8': { $type = 'package' }
83+
default: { $type = 'err' }
84+
}
85+
}
86+
'4.5.2': {
87+
case $windows_version {
88+
/^2003/, /^2008/, /^2012/, 'XP', 'Vista', '7', '8', '8.1': { $type = 'package' }
89+
default: { $type = 'err' }
90+
}
6791
}
92+
default: { $type = 'err' }
6893
}
6994

70-
if $type == 'feature' {
71-
dotnet::install::feature { "dotnet-feature-${version}":
72-
ensure => $ensure,
73-
version => $version
95+
case $type {
96+
'feature': {
97+
dotnet::install::feature { "dotnet-feature-${version}":
98+
ensure => $ensure,
99+
version => $version,
100+
feature => $feature,
101+
source => $package_dir,
102+
}
74103
}
75-
} elsif $type == 'package' {
76-
dotnet::install::package { "dotnet-package-${version}":
77-
ensure => $ensure,
78-
version => $version,
79-
package_dir => $package_dir
104+
'dism': {
105+
dotnet::install::dism { "dotnet-dism-${version}":
106+
ensure => $ensure,
107+
version => $version,
108+
}
109+
}
110+
'package': {
111+
dotnet::install::package { "dotnet-package-${version}":
112+
ensure => $ensure,
113+
version => $version,
114+
package_dir => $package_dir,
115+
}
116+
}
117+
'builtin': {
118+
# This .NET version is built into the OS. No configuration required.
119+
}
120+
default: {
121+
fail("dotnet ${version} is not supported on windows ${windows_version}")
80122
}
81-
} else {
82-
83123
}
124+
84125
}

manifests/install/dism.pp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#
2+
define dotnet::install::dism (
3+
$ensure = 'present',
4+
$version = '',
5+
) {
6+
7+
if $ensure == 'present' {
8+
exec { "install-dotnet-dism-${version}":
9+
command => 'DISM /Online /Enable-Feature /FeatureName:NetFx3 /NoRestart',
10+
creates => "C:/Windows/Microsoft.NET/Framework/v${version}",
11+
provider => powershell,
12+
logoutput => true,
13+
}
14+
} else {
15+
exec { "uninstall-dotnet-dism-${version}":
16+
command => 'DISM /Online /Disable-Feature /FeatureName:NetFx3 /NoRestart',
17+
onlyif => "If (-Not(Test-Path C:/Windows/Microsoft.NET/Framework/v${version})) { Exit 1 }",
18+
provider => powershell,
19+
logoutput => true,
20+
}
21+
}
22+
23+
}

manifests/install/feature.pp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
#
22
define dotnet::install::feature(
3-
$ensure = 'present',
4-
$version = ''
3+
$version,
4+
$ensure = 'present',
5+
$feature = 'AS-NET-Framework',
6+
$source = undef,
57
) {
68

9+
$source_flag = $source ? {
10+
undef => '',
11+
default => "-source ${source}",
12+
}
13+
714
if $ensure == 'present' {
8-
exec { "install-feature-${version}":
9-
command => 'Import-Module ServerManager; Add-WindowsFeature as-net-framework',
15+
exec { "install-dotnet-feature-${version}":
16+
command => "Import-Module ServerManager; Add-WindowsFeature ${feature} ${source_flag}",
1017
provider => powershell,
1118
logoutput => true,
12-
unless => "Test-Path C:\\Windows\\Microsoft.NET\\Framework\\v${version}",
19+
creates => "C:/Windows/Microsoft.NET/Framework/v${version}",
1320
}
1421
} else {
15-
exec { "uninstall-feature-${version}":
16-
command => 'Import-Module ServerManager; Remove-WindowsFeature as-net-framework',
22+
exec { "uninstall-dotnet-feature-${version}":
23+
command => "Import-Module ServerManager; Remove-WindowsFeature ${feature}",
1724
provider => powershell,
1825
logoutput => true,
19-
onlyif => "Test-Path C:\\Windows\\Microsoft.NET\\Framework\\v${version}",
26+
onlyif => "If (-Not(Test-Path C:/Windows/Microsoft.NET/Framework/v${version})) { Exit 1 }",
2027
}
2128
}
2229

manifests/install/package.pp

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,47 @@
11
#
22
define dotnet::install::package(
3-
$ensure = 'present',
4-
$version = '',
3+
$ensure = 'present',
4+
$version = '',
55
$package_dir = ''
66
) {
77

88
include dotnet::params
99

10-
$url = $dotnet::params::version[$version]['url']
11-
$exe = $dotnet::params::version[$version]['exe']
12-
$key = $dotnet::params::version[$version]['key']
13-
10+
$url = $dotnet::params::version[$version]['url']
11+
$exe = $dotnet::params::version[$version]['exe']
12+
$package = $dotnet::params::version[$version]['package']
13+
$conflicts = $dotnet::params::version[$version]['conflicts']
1414

1515
if "x${package_dir}x" == 'xx' {
16-
$source_dir = 'C:\Windows\Temp'
17-
if $ensure == 'present' {
18-
download_file { "download-dotnet-${version}" :
19-
url => $url,
20-
destination_directory => $source_dir
21-
}
22-
} else {
23-
file { "C:/Windows/Temp/${exe}":
24-
ensure => absent
25-
}
16+
$source_file = "C:/Windows/Temp/${exe}"
17+
remote_file { $source_file:
18+
ensure => $ensure,
19+
source => $url,
2620
}
2721
} else {
28-
$source_dir = $package_dir
22+
$source_file = "${package_dir}/${exe}"
23+
}
24+
25+
package { $package:
26+
ensure => $ensure,
27+
source => $source_file,
28+
install_options => ['/q', '/norestart'],
29+
uninstall_options => ['/x', '/q', '/norestart'],
2930
}
3031

3132
if $ensure == 'present' {
32-
exec { "install-dotnet-${version}":
33-
command => "& ${source_dir}\\${exe} /q /norestart",
34-
provider => powershell,
35-
logoutput => true,
36-
unless => "if ((Get-Item -LiteralPath \'${key}\' -ErrorAction SilentlyContinue).GetValue(\'DisplayVersion\')) { exit 0 }"
37-
}
38-
} else {
39-
exec { "uninstall-dotnet-${version}":
40-
command => "& ${source_dir}\\${exe} /x /q /norestart",
41-
provider => powershell,
42-
logoutput => true,
43-
unless => "if ((Get-Item -LiteralPath \'${key}\' -ErrorAction SilentlyContinue).GetValue(\'DisplayVersion\')) { exit 1 }"
33+
# Some versions of .NET are in-place upgrades of others. Installation of
34+
# .NET 4.5, for example, will replace the 4.0 package. In order to disallow
35+
# Puppet from continuously trying to install .NET 4.0 in the event dotnet
36+
# resources for both 4.0 and 4.5 have been added to the catalog, create a
37+
# package=absent resource for each conflicting version. This will cause the
38+
# conflict to be caught when a catalog is compiled for the node.
39+
$conflicts.each |$conflict| {
40+
package { $dotnet::params::version[$conflict]['package']:
41+
ensure => absent,
42+
before => Package[$package],
43+
uninstall_options => ['/x', '/q', '/norestart'],
44+
}
4445
}
4546
}
4647

manifests/params.pp

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,38 @@
1111

1212
$version = {
1313
'3.5' => {
14-
'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe',
15-
'exe' => 'dotNetFx35setup.exe',
16-
'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{CE2CDD62-0124-36CA-84D3-9F4DCF5C5BD9}'
14+
'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe',
15+
'exe' => 'dotNetFx35setup.exe',
16+
'conflicts' => [ ],
17+
'package' => 'Microsoft .NET Framework 3.5',
1718
},
1819
'4.0' => {
19-
'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe',
20-
'exe' => 'dotNetFx40_Full_x86_x64.exe',
21-
'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E34682C-8118-31F1-BC4C-98CD9675E1C2}'
20+
'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe',
21+
'exe' => 'dotNetFx40_Full_x86_x64.exe',
22+
'conflicts' => ['4.5', '4.5.1', '4.5.2'],
23+
'package' => [
24+
'Microsoft .NET Framework 4 Extended',
25+
'Microsoft .NET Framework 4 Client Profile',
26+
],
2227
},
23-
'4.5' => {
24-
'url' => 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe',
25-
'exe' => 'dotnetfx45_full_x86_x64.exe',
26-
'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1AD147D0-BE0E-3D6C-AC11-64F6DC4163F1}'
28+
'4.5' => {
29+
'url' => 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe',
30+
'exe' => 'dotnetfx45_full_x86_x64.exe',
31+
'conflicts' => ['4.0', '4.5.1', '4.5.2'],
32+
'package' => 'Microsoft .NET Framework 4.5',
2733
},
2834
'4.5.1' => {
29-
'url' => 'http://download.microsoft.com/download/1/6/7/167F0D79-9317-48AE-AEDB-17120579F8E2/NDP451-KB2858728-x86-x64-AllOS-ENU.exe',
30-
'exe' => 'NDP451-KB2858728-x86-x64-AllOS-ENU.exe',
31-
'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7DEBE4EB-6B40-3766-BB35-5CBBC385DA37}'
35+
'url' => 'http://download.microsoft.com/download/1/6/7/167F0D79-9317-48AE-AEDB-17120579F8E2/NDP451-KB2858728-x86-x64-AllOS-ENU.exe',
36+
'exe' => 'NDP451-KB2858728-x86-x64-AllOS-ENU.exe',
37+
'conflicts' => ['4.0', '4.5', '4.5.2'],
38+
'package' => 'Microsoft .NET Framework 4.5.1',
3239
},
3340
'4.5.2' => {
34-
'url' => 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe',
35-
'exe' => 'NDP452-KB2901907-x86-x64-AllOS-ENU.exe',
36-
'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{26784146-6E05-3FF9-9335-786C7C0FB5BE}'
41+
'url' => 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe',
42+
'exe' => 'NDP452-KB2901907-x86-x64-AllOS-ENU.exe',
43+
'conflicts' => ['4.0', '4.5', '4.5.1'],
44+
'package' => 'Microsoft .NET Framework 4.5.2',
3745
}
3846
}
47+
3948
}

0 commit comments

Comments
 (0)