From c081b7b434c55a0801c8b6a414e2bcdceaffacf1 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Sat, 19 Sep 2015 14:43:22 -0700 Subject: [PATCH 01/15] 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. --- manifests/install/package.pp | 47 ++++++++++++------------------------ manifests/params.pp | 38 +++++++++++++++++------------ metadata.json | 6 ++--- 3 files changed, 42 insertions(+), 49 deletions(-) diff --git a/manifests/install/package.pp b/manifests/install/package.pp index 1f7ff4c..0d906f3 100644 --- a/manifests/install/package.pp +++ b/manifests/install/package.pp @@ -1,47 +1,32 @@ # define dotnet::install::package( - $ensure = 'present', - $version = '', + $ensure = 'present', + $version = '', $package_dir = '' ) { include dotnet::params - $url = $dotnet::params::version[$version]['url'] - $exe = $dotnet::params::version[$version]['exe'] - $key = $dotnet::params::version[$version]['key'] - + $url = $dotnet::params::version[$version]['url'] + $exe = $dotnet::params::version[$version]['exe'] + $key = $dotnet::params::version[$version]['key'] + $package = $dotnet::params::version[$version]['package'] if "x${package_dir}x" == 'xx' { - $source_dir = 'C:\Windows\Temp' - if $ensure == 'present' { - download_file { "download-dotnet-${version}" : - url => $url, - destination_directory => $source_dir - } - } else { - file { "C:/Windows/Temp/${exe}": - ensure => absent - } + $source_file = "C:/Windows/Temp/${exe}" + remote_file { $source_file: + ensure => $ensure, + source => $url, } } else { - $source_dir = $package_dir + $source_file = "${package_dir}/${exe}" } - if $ensure == 'present' { - exec { "install-dotnet-${version}": - command => "& ${source_dir}\\${exe} /q /norestart", - provider => powershell, - logoutput => true, - unless => "if ((Get-Item -LiteralPath \'${key}\' -ErrorAction SilentlyContinue).GetValue(\'DisplayVersion\')) { exit 0 }" - } - } else { - exec { "uninstall-dotnet-${version}": - command => "& ${source_dir}\\${exe} /x /q /norestart", - provider => powershell, - logoutput => true, - unless => "if ((Get-Item -LiteralPath \'${key}\' -ErrorAction SilentlyContinue).GetValue(\'DisplayVersion\')) { exit 1 }" - } + package { $package: + ensure => $ensure, + source => $source_file, + install_options => ['/q', '/norestart'], + uninstall_options => ['/x', '/q', '/norestart'], } } diff --git a/manifests/params.pp b/manifests/params.pp index 23f7b47..6679eba 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -11,29 +11,37 @@ $version = { '3.5' => { - 'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe', - 'exe' => 'dotNetFx35setup.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{CE2CDD62-0124-36CA-84D3-9F4DCF5C5BD9}' + 'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe', + 'exe' => 'dotNetFx35setup.exe', + 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{CE2CDD62-0124-36CA-84D3-9F4DCF5C5BD9}', + 'package' => [ ], }, '4.0' => { - 'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe', - 'exe' => 'dotNetFx40_Full_x86_x64.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E34682C-8118-31F1-BC4C-98CD9675E1C2}' + 'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe', + 'exe' => 'dotNetFx40_Full_x86_x64.exe', + 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E34682C-8118-31F1-BC4C-98CD9675E1C2}', + 'package' => [ + 'Microsoft .NET Framework 4 Extended', + 'Microsoft .NET Framework 4 Client Profile', + ], }, '4.5' => { - 'url' => 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe', - 'exe' => 'dotnetfx45_full_x86_x64.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1AD147D0-BE0E-3D6C-AC11-64F6DC4163F1}' + 'url' => 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe', + 'exe' => 'dotnetfx45_full_x86_x64.exe', + 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1AD147D0-BE0E-3D6C-AC11-64F6DC4163F1}', + 'package' => 'Microsoft .NET Framework 4.5', }, '4.5.1' => { - 'url' => 'http://download.microsoft.com/download/1/6/7/167F0D79-9317-48AE-AEDB-17120579F8E2/NDP451-KB2858728-x86-x64-AllOS-ENU.exe', - 'exe' => 'NDP451-KB2858728-x86-x64-AllOS-ENU.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7DEBE4EB-6B40-3766-BB35-5CBBC385DA37}' + 'url' => 'http://download.microsoft.com/download/1/6/7/167F0D79-9317-48AE-AEDB-17120579F8E2/NDP451-KB2858728-x86-x64-AllOS-ENU.exe', + 'exe' => 'NDP451-KB2858728-x86-x64-AllOS-ENU.exe', + 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7DEBE4EB-6B40-3766-BB35-5CBBC385DA37}', + 'package' => 'Microsoft .NET Framework 4.5.1', }, '4.5.2' => { - 'url' => 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe', - 'exe' => 'NDP452-KB2901907-x86-x64-AllOS-ENU.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{26784146-6E05-3FF9-9335-786C7C0FB5BE}' + 'url' => 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe', + 'exe' => 'NDP452-KB2901907-x86-x64-AllOS-ENU.exe', + 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{26784146-6E05-3FF9-9335-786C7C0FB5BE}', + 'package' => 'Microsoft .NET Framework 4.5.2', } } } diff --git a/metadata.json b/metadata.json index 22a93eb..c22d9c8 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "name": "puppet-dotnet", - "version": "1.0.1", + "version": "2.0.0", "author": "puppet-community", "license": "Apache 2.0", "summary": "'Module to manage the Microsoft .NET framework", @@ -27,8 +27,8 @@ "version_requirement": ">= 0.0.1 <2.0.0" }, { - "name": "opentable/download_file", - "version_requirement": ">= 1.0.0 <2.0.0" + "name": "lwf/remote_file", + "version_requirement": ">= 1.0.1 <2.0.0" } ] } From 3e1d5acb891fdce0fdd1b7dc06285a7f099de5e4 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Mon, 21 Sep 2015 09:57:35 -0700 Subject: [PATCH 02/15] 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. --- manifests/init.pp | 47 ++++++++++++++++++------------------ manifests/install/feature.pp | 4 +-- manifests/install/package.pp | 1 - manifests/params.pp | 6 +---- metadata.json | 18 ++++++++------ 5 files changed, 37 insertions(+), 39 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 6afee05..09870e8 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -31,54 +31,55 @@ # } # define dotnet( - $ensure = 'present', - $version = '', - $package_dir = '' -) { + Enum['present', 'absent'] + $ensure = 'present', + + Enum['3.5', '4.0', '4.5.1', '4.5.2'] + $version, - validate_re($ensure,['^(present|absent)$']) - validate_re($version,['^(3.5|4\.0|4\.5(\.\d)?)$']) + Variant[String, Undef] + $package_dir = undef, +) { include dotnet::params + $windows_version = $::os['release']['full'] case $version { '3.5': { - case $::operatingsystemversion { - /^Windows.Server.(2008|2012).?(R2)?.*/: { $type = 'feature' } - /^Windows (XP|Vista|7|8|8.1).*/: { $type = 'package' } - default: { $type = 'err' err("dotnet ${version} is not support on this version of windows") } + case $windows_version { + /^(2008|2012).?(R2)?.*/: { $type = 'feature' } + /^(XP|Vista|7|8|8.1).*/: { $type = 'package' } + default: { $type = 'err' } } } '4.0': { - case $::operatingsystemversion { - /^Windows.(Server)?.?(2003|2008|2012|XP|Vista|7|8.*).?(R2)?.*/: { $type = 'package' } - default: { $type = 'err' err("dotnet ${version} is not support on this version of windows") } + case $windows_version { + /^(2003|2008|2012|XP|Vista|7|8.*).?(R2)?.*/: { $type = 'package' } + default: { $type = 'err' } } } /4\.5(\.\d)?/: { - case $::operatingsystemversion { - /^Windows.(Server)?.?(2008|2012|Vista|7|8.*).?(R2)?.*/: { $type = 'package' } - default: { $type = 'err' err("dotnet ${version} is not support on this version of windows") } + case $windows_version { + /^(2008|2012|Vista|7|8.*).?(R2)?.*/: { $type = 'package' } + default: { $type = 'err' } } } - default: { - $type = 'err' - err("dotnet does not have a version: ${version}") - } + default: { $type = 'err' } } if $type == 'feature' { dotnet::install::feature { "dotnet-feature-${version}": ensure => $ensure, - version => $version + version => $version, } } elsif $type == 'package' { dotnet::install::package { "dotnet-package-${version}": ensure => $ensure, version => $version, - package_dir => $package_dir + package_dir => $package_dir, } } else { - + fail("dotnet ${version} is not supported on windows ${windows_version}") } + } diff --git a/manifests/install/feature.pp b/manifests/install/feature.pp index a0dd963..fcf027f 100644 --- a/manifests/install/feature.pp +++ b/manifests/install/feature.pp @@ -5,14 +5,14 @@ ) { if $ensure == 'present' { - exec { "install-feature-${version}": + exec { "install-dotnet-feature-${version}": command => 'Import-Module ServerManager; Add-WindowsFeature as-net-framework', provider => powershell, logoutput => true, unless => "Test-Path C:\\Windows\\Microsoft.NET\\Framework\\v${version}", } } else { - exec { "uninstall-feature-${version}": + exec { "uninstall-dotnet-feature-${version}": command => 'Import-Module ServerManager; Remove-WindowsFeature as-net-framework', provider => powershell, logoutput => true, diff --git a/manifests/install/package.pp b/manifests/install/package.pp index 0d906f3..14c6a6f 100644 --- a/manifests/install/package.pp +++ b/manifests/install/package.pp @@ -9,7 +9,6 @@ $url = $dotnet::params::version[$version]['url'] $exe = $dotnet::params::version[$version]['exe'] - $key = $dotnet::params::version[$version]['key'] $package = $dotnet::params::version[$version]['package'] if "x${package_dir}x" == 'xx' { diff --git a/manifests/params.pp b/manifests/params.pp index 6679eba..d53d36e 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -13,13 +13,11 @@ '3.5' => { 'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe', 'exe' => 'dotNetFx35setup.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{CE2CDD62-0124-36CA-84D3-9F4DCF5C5BD9}', 'package' => [ ], }, '4.0' => { 'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe', 'exe' => 'dotNetFx40_Full_x86_x64.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{8E34682C-8118-31F1-BC4C-98CD9675E1C2}', 'package' => [ 'Microsoft .NET Framework 4 Extended', 'Microsoft .NET Framework 4 Client Profile', @@ -28,20 +26,18 @@ '4.5' => { 'url' => 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe', 'exe' => 'dotnetfx45_full_x86_x64.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1AD147D0-BE0E-3D6C-AC11-64F6DC4163F1}', 'package' => 'Microsoft .NET Framework 4.5', }, '4.5.1' => { 'url' => 'http://download.microsoft.com/download/1/6/7/167F0D79-9317-48AE-AEDB-17120579F8E2/NDP451-KB2858728-x86-x64-AllOS-ENU.exe', 'exe' => 'NDP451-KB2858728-x86-x64-AllOS-ENU.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7DEBE4EB-6B40-3766-BB35-5CBBC385DA37}', 'package' => 'Microsoft .NET Framework 4.5.1', }, '4.5.2' => { 'url' => 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe', 'exe' => 'NDP452-KB2901907-x86-x64-AllOS-ENU.exe', - 'key' => 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{26784146-6E05-3FF9-9335-786C7C0FB5BE}', 'package' => 'Microsoft .NET Framework 4.5.2', } } + } diff --git a/metadata.json b/metadata.json index c22d9c8..3e6d26b 100644 --- a/metadata.json +++ b/metadata.json @@ -7,6 +7,16 @@ "source": "https://github.com/puppet-community/puppet-dotnet", "project_page": "https://github.com/puppet-community/puppet-dotnet", "issues_url": "https://github.com/puppet-community/puppet-dotnet/issues", + "requirements": [ + { + "name": "pe", + "version_requirement": ">=2015.2.0" + }, + { + "name": "puppet", + "version_requirement": ">=4.2.1" + } + ], "operatingsystem_support": [ { "operatingsystem": "windows", @@ -14,18 +24,10 @@ } ], "dependencies": [ - { - "name": "puppetlabs/stdlib", - "version_requirement": ">= 3.0.0 <5.0.0" - }, { "name": "puppetlabs/powershell", "version_requirement": ">= 1.0.0 <2.0.0" }, - { - "name": "liamjbennett/win_facts", - "version_requirement": ">= 0.0.1 <2.0.0" - }, { "name": "lwf/remote_file", "version_requirement": ">= 1.0.1 <2.0.0" From 0a314777f2ec2f7490ea44d1253d204ffcbb02e1 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Mon, 21 Sep 2015 10:16:08 -0700 Subject: [PATCH 03/15] 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. --- manifests/install/package.pp | 23 +++++++++++++++++++--- manifests/params.pp | 37 ++++++++++++++++++++---------------- 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/manifests/install/package.pp b/manifests/install/package.pp index 14c6a6f..45adc18 100644 --- a/manifests/install/package.pp +++ b/manifests/install/package.pp @@ -7,9 +7,10 @@ include dotnet::params - $url = $dotnet::params::version[$version]['url'] - $exe = $dotnet::params::version[$version]['exe'] - $package = $dotnet::params::version[$version]['package'] + $url = $dotnet::params::version[$version]['url'] + $exe = $dotnet::params::version[$version]['exe'] + $package = $dotnet::params::version[$version]['package'] + $conflicts = $dotnet::params::version[$version]['conflicts'] if "x${package_dir}x" == 'xx' { $source_file = "C:/Windows/Temp/${exe}" @@ -28,4 +29,20 @@ uninstall_options => ['/x', '/q', '/norestart'], } + if $ensure == 'present' { + # 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. + $conflicts.each |$conflict| { + package { $dotnet::params::version[$conflict]['package']: + ensure => absent, + before => Package[$package], + uninstall_options => ['/x', '/q', '/norestart'], + } + } + } + } diff --git a/manifests/params.pp b/manifests/params.pp index d53d36e..5eecc15 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -11,32 +11,37 @@ $version = { '3.5' => { - 'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe', - 'exe' => 'dotNetFx35setup.exe', - 'package' => [ ], + 'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe', + 'exe' => 'dotNetFx35setup.exe', + 'conflicts' => [ ], + 'package' => [ ], }, '4.0' => { - 'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe', - 'exe' => 'dotNetFx40_Full_x86_x64.exe', - 'package' => [ + 'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe', + 'exe' => 'dotNetFx40_Full_x86_x64.exe', + 'conflicts' => ['4.5', '4.5.1', '4.5.2'], + 'package' => [ 'Microsoft .NET Framework 4 Extended', 'Microsoft .NET Framework 4 Client Profile', ], }, - '4.5' => { - 'url' => 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe', - 'exe' => 'dotnetfx45_full_x86_x64.exe', - 'package' => 'Microsoft .NET Framework 4.5', + '4.5' => { + 'url' => 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe', + 'exe' => 'dotnetfx45_full_x86_x64.exe', + 'conflicts' => ['4.0', '4.5.1', '4.5.2'], + 'package' => 'Microsoft .NET Framework 4.5', }, '4.5.1' => { - 'url' => 'http://download.microsoft.com/download/1/6/7/167F0D79-9317-48AE-AEDB-17120579F8E2/NDP451-KB2858728-x86-x64-AllOS-ENU.exe', - 'exe' => 'NDP451-KB2858728-x86-x64-AllOS-ENU.exe', - 'package' => 'Microsoft .NET Framework 4.5.1', + 'url' => 'http://download.microsoft.com/download/1/6/7/167F0D79-9317-48AE-AEDB-17120579F8E2/NDP451-KB2858728-x86-x64-AllOS-ENU.exe', + 'exe' => 'NDP451-KB2858728-x86-x64-AllOS-ENU.exe', + 'conflicts' => ['4.0', '4.5', '4.5.2'], + 'package' => 'Microsoft .NET Framework 4.5.1', }, '4.5.2' => { - 'url' => 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe', - 'exe' => 'NDP452-KB2901907-x86-x64-AllOS-ENU.exe', - 'package' => 'Microsoft .NET Framework 4.5.2', + 'url' => 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe', + 'exe' => 'NDP452-KB2901907-x86-x64-AllOS-ENU.exe', + 'conflicts' => ['4.0', '4.5', '4.5.1'], + 'package' => 'Microsoft .NET Framework 4.5.2', } } From ede8ea4b884876530a97308eb46e67b1fbb8eba2 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Mon, 21 Sep 2015 13:07:38 -0700 Subject: [PATCH 04/15] 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. --- manifests/init.pp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 09870e8..b9005d2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -47,14 +47,15 @@ case $version { '3.5': { case $windows_version { - /^(2008|2012).?(R2)?.*/: { $type = 'feature' } + /^(2008|2012)( R2)?.*/: { $type = 'feature' } /^(XP|Vista|7|8|8.1).*/: { $type = 'package' } default: { $type = 'err' } } } '4.0': { case $windows_version { - /^(2003|2008|2012|XP|Vista|7|8.*).?(R2)?.*/: { $type = 'package' } + /^(2003|2008|XP|Vista|7)( R2)?.*/: { $type = 'package' } + /^(2012|8|8.1)( R2)?.*/: { $type = 'builtin' } default: { $type = 'err' } } } @@ -78,6 +79,8 @@ version => $version, package_dir => $package_dir, } + } elsif $type == 'builtin' { + # This .NET version is built into the OS. No configuration required. } else { fail("dotnet ${version} is not supported on windows ${windows_version}") } From 2e81e26ddcc8a579d8513ff8ea5d7e4cfaaac5a9 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Mon, 21 Sep 2015 13:52:32 -0700 Subject: [PATCH 05/15] Clean up installation type detection Regex adjustments to make it easier to read which versions support which installation types. --- manifests/init.pp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index b9005d2..b4c7bed 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -43,25 +43,44 @@ include dotnet::params + if $::os['family'] != 'windows' { + fail("dotnet ${version} is not supported on ${::os['family']}") + } + $windows_version = $::os['release']['full'] + case $version { '3.5': { case $windows_version { - /^(2008|2012)( R2)?.*/: { $type = 'feature' } - /^(XP|Vista|7|8|8.1).*/: { $type = 'package' } + /^2008/, /^2012/: { $type = 'feature' } + /^2003/, 'XP', 'Vista', '7', '8', '8.1': { $type = 'package' } default: { $type = 'err' } } } '4.0': { case $windows_version { - /^(2003|2008|XP|Vista|7)( R2)?.*/: { $type = 'package' } - /^(2012|8|8.1)( R2)?.*/: { $type = 'builtin' } + /^2012/, '8', '8.1': { $type = 'builtin' } + /^2003/, /^2008/, 'XP', 'Vista', '7': { $type = 'package' } + default: { $type = 'err' } + } + } + '4.5': { + case $windows_version { + /^2012/, '8', '8.1': { $type = 'builtin' } + /^2003/, /^2008/, 'XP', 'Vista', '7': { $type = 'package' } + default: { $type = 'err' } + } + } + '4.5.1': { + case $windows_version { + '2012 R2', '8.1': { $type = 'builtin' } + /^2003/, /^2008/, '2012', 'XP', 'Vista', '7', '8': { $type = 'package' } default: { $type = 'err' } } } - /4\.5(\.\d)?/: { + '4.5.2': { case $windows_version { - /^(2008|2012|Vista|7|8.*).?(R2)?.*/: { $type = 'package' } + /^2003/, /^2008/, /^2012/, 'XP', 'Vista', '7', '8', '8.1': { $type = 'package' } default: { $type = 'err' } } } From f693e5b314548b243ae4d4e75644c7e674e72e9e Mon Sep 17 00:00:00 2001 From: Spencer Krum Date: Mon, 28 Sep 2015 13:38:55 -0700 Subject: [PATCH 06/15] Only test on 4.x/future parser Set gemfile to use PUPPET_GEM_VERSION and set default to 4.0 --- .travis.yml | 10 ++++------ Gemfile | 2 +- manifests/init.pp | 6 +++--- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6204719..1dd2759 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,16 +7,14 @@ before_install: rm Gemfile.lock || true script: bundle exec rake test matrix: include: - - rvm: 1.8.7 - env: PUPPET_GEM_VERSION="~> 3.0" FACTER_GEM_VERSION="~> 1.7.0" - rvm: 1.9.3 - env: PUPPET_GEM_VERSION="~> 3.0" + env: PUPPET_GEM_VERSION="~> 4.0" - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.0" - - rvm: 2.0.0 - env: PUPPET_GEM_VERSION="~> 3.0" FUTURE_PARSER="yes" + env: PUPPET_GEM_VERSION="~> 4.0" - rvm: 2.1.0 env: PUPPET_GEM_VERSION="~> 3.0" STRICT_VARIABLES=yes FUTURE_PARSER="yes" + - rvm: 2.1.0 + env: PUPPET_GEM_VERSION="~> 4.0" deploy: provider: puppetforge diff --git a/Gemfile b/Gemfile index 7e5f4ca..848deaa 100644 --- a/Gemfile +++ b/Gemfile @@ -16,7 +16,7 @@ source "https://rubygems.org" group :test do gem "rake" - gem "puppet", ENV['PUPPET_VERSION'] || '~> 3.7.0' + gem "puppet", ENV['PUPPET_GEM_VERSION'] || '~> 4.0' gem "rspec-puppet", :git => 'https://github.com/rodjek/rspec-puppet.git' gem "puppetlabs_spec_helper" gem "metadata-json-lint" diff --git a/manifests/init.pp b/manifests/init.pp index b4c7bed..05fda4e 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -31,12 +31,12 @@ # } # define dotnet( - Enum['present', 'absent'] - $ensure = 'present', - Enum['3.5', '4.0', '4.5.1', '4.5.2'] $version, + Enum['present', 'absent'] + $ensure = 'present', + Variant[String, Undef] $package_dir = undef, ) { From 868fb772a7c4aa4a73168a03f8a4d566a1ba73ab Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Fri, 6 Nov 2015 16:21:18 -0800 Subject: [PATCH 07/15] Adjust tests to match updates This is not a comprehensive test overhaul, but does update the functional tests to work with the updated code. --- .fixtures.yml | 3 +- manifests/init.pp | 2 +- spec/defines/dotnet_spec.rb | 30 ++++-- spec/defines/four_spec.rb | 130 +++++++----------------- spec/defines/fourfive_spec.rb | 135 +++++++------------------ spec/defines/three_spec.rb | 184 ++++++++-------------------------- 6 files changed, 135 insertions(+), 349 deletions(-) diff --git a/.fixtures.yml b/.fixtures.yml index 2d8f86e..b51c0d3 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -2,7 +2,6 @@ fixtures: repositories: stdlib: https://github.com/puppetlabs/puppetlabs-stdlib powershell: https://github.com/puppetlabs/puppetlabs-powershell - win_facts: https://github.com/liamjbennett/puppet-win_facts - download_file: https://github.com/opentable/puppet-download_file + remote_file: https://github.com/lwf/puppet-remote_file symlinks: dotnet: "#{source_dir}" diff --git a/manifests/init.pp b/manifests/init.pp index 05fda4e..978dedf 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -31,7 +31,7 @@ # } # define dotnet( - Enum['3.5', '4.0', '4.5.1', '4.5.2'] + Enum['3.5', '4.0', '4.5', '4.5.1', '4.5.2'] $version, Enum['present', 'absent'] diff --git a/spec/defines/dotnet_spec.rb b/spec/defines/dotnet_spec.rb index 4db37af..5e52510 100644 --- a/spec/defines/dotnet_spec.rb +++ b/spec/defines/dotnet_spec.rb @@ -2,21 +2,17 @@ describe 'dotnet', :type => :define do - ['Windows Server 2012','Windows Server 2008 R2','Windows Server 2008', 'Windows Server 2003','Windows Server 2003 R2','Windows 8','Windows 7','Windows Vista','Windows XP'].each do |os| - context "with invalid custom param: os => #{os}, version => fubar" do - let :facts do - { :operatingsystemversion => os } - end + ['2012','2008 R2','2008', '2003','2003 R2','8','7','Vista','XP'].each do |release| + context "with invalid custom param: os.release.full => #{release}, version => fubar" do let :title do 'fubar' end let :params do { :version => 'fubar' } end - - it do - expect { - should contain_exec('install-dotnet-3.5') - }.to raise_error(Puppet::Error) + let :facts do + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } end + + it { expect { is_expected.to compile }.to raise_error(/Expected parameter .* to have type/) } end end @@ -37,4 +33,18 @@ end end end + + ['unknown'].each do |release| + context "with ensure => present, version => 4.5, os.release.full => #{release}" do + let :title do 'fubar' end + let :params do + { :version => '4.5.1', :ensure => 'present' } + end + let :facts do + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } + end + + it { expect { is_expected.to compile }.to raise_error(/is not supported on windows #{release}/) } + end + end end diff --git a/spec/defines/four_spec.rb b/spec/defines/four_spec.rb index f9b20bc..cbd03ed 100644 --- a/spec/defines/four_spec.rb +++ b/spec/defines/four_spec.rb @@ -10,118 +10,62 @@ @four_reg = '{8E34682C-8118-31F1-BC4C-98CD9675E1C2}' } - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows XP','Windows Vista','Windows 7','Windows 8'].each do |os| - context "with ensure => present, version => 4.0, os => #{os}, network package" do - let :title do 'dotnet4' end - let :params do - { :ensure => 'present', :version => '4.0', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } - end - - it { should contain_exec('install-dotnet-4.0').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_prog} /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 0 }" - )} - - end + let :title do 'dotnet4' end + let :params do + { :ensure => 'present', :version => '4.0' } end - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows XP','Windows Vista','Windows 7','Windows 8'].each do |os| - context "with ensure => present, version => 4.0, os => #{os}, download package" do - let :title do 'dotnet4' end - let :params do - { :ensure => 'present', :version => '4.0' } - end + ['2008', '2008 R2', '2012', '2012 R2', 'XP', 'Vista', '7', '8', '8.1'].each do |release| + context "with ensure => present, version => 4.0, os.release.full => #{release}" do let :facts do - { :operatingsystemversion => os } + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } end - it { should contain_download_file('download-dotnet-4.0').with( - 'url' => @four_url, - 'destination_directory' => 'C:\\Windows\\Temp' - ) } - - it { should contain_exec('install-dotnet-4.0').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_prog} /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 0 }" - )} - - end - end - - ['unknown'].each do |os| - context "with ensure => present, version => 4.0, os => #{os}" do - let :title do 'dotnet4' end - let :params do - { :ensure => 'present', :version => '4.0', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } + context "package" do + if ['2012', '2012 R2', '8', '8.1'].include? release + it { should_not contain_package('Microsoft .NET Framework 4 Extended') } + else + it { should contain_package('Microsoft .NET Framework 4 Extended').with( + 'ensure' => 'present', + )} + end end - it { should_not contain_exec('install-dotnet-4.0') } - end - end - - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows XP','Windows Vista','Windows 7','Windows 8'].each do |os| - context "with ensure => absent, version => 4.0, os => #{os}" do - let :title do 'dotnet4' end - let :params do - { :ensure => 'absent', :version => '4.0', :package_dir => "C:\\Windows\\Temp" } + context "download" do + if ['2012', '2012 R2', '8', '8.1'].include? release + it { should_not contain_remote_file('C:/Windows/Temp/dotNetFx40_Full_x86_x64.exe') } + else + it { should contain_remote_file('C:/Windows/Temp/dotNetFx40_Full_x86_x64.exe') } + end end - let :facts do - { :operatingsystemversion => os } - end - - it { should contain_exec('uninstall-dotnet-4.0').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_prog} /x /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 1 }" - )} end end - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows XP','Windows Vista','Windows 7','Windows 8'].each do |os| - context "with ensure => absent, version => 4.0, os => #{os}, download package" do - let :title do 'dotnet4' end + ['2008', '2008 R2', '2012', '2012 R2', 'XP', 'Vista', '7', '8', '8.1'].each do |release| + context "with ensure => absent, version => 4.0, os.release.full => #{release}" do let :params do { :ensure => 'absent', :version => '4.0' } end let :facts do - { :operatingsystemversion => os } + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } end - it { should contain_file("C:/Windows/Temp/#{@four_prog}").with( - 'ensure' => 'absent' - )} - - it { should contain_exec('uninstall-dotnet-4.0').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_prog} /x /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 1 }" - )} - end - end - - ['unknown'].each do |os| - context "with ensure => absent, version => 4.0, os => #{os}" do - let :title do 'dotnet4' end - let :params do - { :ensure => 'absent', :version => '4.0', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } + context "package" do + if not ['2012', '2012 R2', '8', '8.1'].include? release + it { should contain_package('Microsoft .NET Framework 4 Extended').with( + 'ensure' => 'absent', + )} + end end - it { should_not contain_exec('uninstall-dotnet-4.0') } + context "download" do + if not ['2012', '2012 R2', '8', '8.1'].include? release + it { should contain_remote_file('C:/Windows/Temp/dotNetFx40_Full_x86_x64.exe').with( + 'ensure' => 'absent', + )} + end + end end end + end diff --git a/spec/defines/fourfive_spec.rb b/spec/defines/fourfive_spec.rb index 1547a7c..f6233ed 100644 --- a/spec/defines/fourfive_spec.rb +++ b/spec/defines/fourfive_spec.rb @@ -2,124 +2,61 @@ describe 'dotnet', :type => :define do - before { - @hklm = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall' - - @four_five_url = 'http://download.microsoft.com/download/b/a/4/ba4a7e71-2906-4b2d-a0e1-80cf16844f5f/dotnetfx45_full_x86_x64.exe' - @four_five_prog = 'dotnetfx45_full_x86_x64.exe' - @four_five_reg = '{1AD147D0-BE0E-3D6C-AC11-64F6DC4163F1}' - } - - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows Vista','Windows 7','Windows 8'].each do |os| - context "with ensure => present, version => 4.5, os => #{os}, network package" do - let :title do 'dotnet45' end - let :params do - { :ensure => 'present', :version => '4.5', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } - end - - it { should contain_exec('install-dotnet-4.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_five_prog} /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_five_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 0 }" - )} - end + let :title do 'dotnet4' end + let :params do + { :ensure => 'present', :version => '4.5' } end - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows Vista','Windows 7','Windows 8'].each do |os| - context "with ensure => present, version => 4.5, os => #{os}, download package" do - let :title do 'dotnet45' end - let :params do - { :ensure => 'present', :version => '4.5' } - end + ['2008', '2008 R2', '2012', '2012 R2', 'XP', 'Vista', '7', '8', '8.1'].each do |release| + context "with ensure => present, version => 4.5, os.release.full => #{release}" do let :facts do - { :operatingsystemversion => os } + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } end - it { should contain_download_file('download-dotnet-4.5').with( - 'url' => @four_five_url, - 'destination_directory' => 'C:\\Windows\\Temp' - ) } - - it { should contain_exec('install-dotnet-4.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_five_prog} /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_five_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 0 }" - )} - end - end - - ['unknown','Windows Server 2003','Windows Server 2003 R2'].each do |os| - context "with ensure => present, version => 4.5, os => #{os}" do - let :title do 'dotnet45' end - let :params do - { :ensure => 'present', :version => '4.5', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } + context "package" do + if ['2012', '2012 R2', '8', '8.1'].include? release + it { should_not contain_package('Microsoft .NET Framework 4.5') } + else + it { should contain_package('Microsoft .NET Framework 4.5').with( + 'ensure' => 'present', + )} + end end - it { should_not contain_exec('install-dotnet-4.5') } - end - end - - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows Vista','Windows 7','Windows 8'].each do |os| - context 'with ensure => absent, version => 4.5' do - let :title do 'dotnet45' end - let :params do - { :ensure => 'absent', :version => '4.5', :package_dir => "C:\\Windows\\Temp" } + context "download" do + if ['2012', '2012 R2', '8', '8.1'].include? release + it { should_not contain_remote_file('C:/Windows/Temp/dotnetfx45_full_x86_x64.exe') } + else + it { should contain_remote_file('C:/Windows/Temp/dotnetfx45_full_x86_x64.exe') } + end end - let :facts do - { :operatingsystemversion => os } - end - - it { should contain_exec('uninstall-dotnet-4.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_five_prog} /x /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_five_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 1 }" - )} end end - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012','Windows Vista','Windows 7','Windows 8'].each do |os| - context 'with ensure => absent, version => 4.5, download package' do - let :title do 'dotnet45' end + ['2008', '2008 R2', '2012', '2012 R2', 'XP', 'Vista', '7', '8', '8.1'].each do |release| + context "with ensure => absent, version => 4.5, os.release.full => #{release}" do let :params do { :ensure => 'absent', :version => '4.5' } end let :facts do - { :operatingsystemversion => os } + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } end - it { should contain_file("C:/Windows/Temp/#{@four_five_prog}").with( - 'ensure' => 'absent' - )} - - it { should contain_exec('uninstall-dotnet-4.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@four_five_prog} /x /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@four_five_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 1 }" - )} - end - end - - ['unknown','Windows Server 2003','Windows Server 2003 R2'].each do |os| - context "with ensure => absent, version => 4.5, os => #{os}" do - let :title do 'dotnet45' end - let :params do - { :ensure => 'absent', :version => '4.5', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } + context "package" do + if not ['2012', '2012 R2', '8', '8.1'].include? release + it { should contain_package('Microsoft .NET Framework 4.5').with( + 'ensure' => 'absent', + )} + end end - it { should_not contain_exec('uninstall-dotnet-4.5') } + context "download" do + if not ['2012', '2012 R2', '8', '8.1'].include? release + it { should contain_remote_file('C:/Windows/Temp/dotnetfx45_full_x86_x64.exe').with( + 'ensure' => 'absent', + )} + end + end end end diff --git a/spec/defines/three_spec.rb b/spec/defines/three_spec.rb index bfc72e8..83e0b88 100644 --- a/spec/defines/three_spec.rb +++ b/spec/defines/three_spec.rb @@ -2,176 +2,72 @@ describe 'dotnet', :type => :define do - before { - @hklm = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall' - - @three_url = 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe' - @three_prog = 'dotNetFx35setup.exe' - @three_reg = '{CE2CDD62-0124-36CA-84D3-9F4DCF5C5BD9}' - } - - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012'].each do |os| - context "with ensure => present, version => 3.5, os => #{os}, server feature" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'present', :version => '3.5'} - end - let :facts do - { :operatingsystemversion => os } - end - - it { should contain_exec('install-feature-3.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "Import-Module ServerManager; Add-WindowsFeature as-net-framework", - 'unless' => "Test-Path C:\\Windows\\Microsoft.NET\\Framework\\v3.5" - )} - end + let :title do 'dotnet35' end + let :params do + { :ensure => 'present', :version => '3.5' } end - ['unknown','Windows Server 2003', 'Windows Server 2003 R2'].each do |os| - context "with ensure => present, version => 3.5, os => #{os}, server feature" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'present', :version => '3.5' } - end - let :facts do - { :operatingsystemversion => os } - end - - it { should_not contain_exec('install-feature-3.5') } - end - end - - ['Windows Server 2008', 'Windows Server 2008 R2', 'Windows Server 2012'].each do |os| - context "with ensure => absent, version => 3.5, os => #{os}, server feature" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'absent', :version => '3.5' } - end - let :facts do - { :operatingsystemversion => os } - end - - it { should contain_exec('uninstall-feature-3.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "Import-Module ServerManager; Remove-WindowsFeature as-net-framework", - 'onlyif' => "Test-Path C:\\Windows\\Microsoft.NET\\Framework\\v3.5" - )} - end - end - - ['Windows XP', 'Windows Vista', 'Windows 7','Windows 8'].each do |os| - context "with ensure => present, version => 3.5, os => #{os}, network package" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'present', :version => '3.5', :package_dir => "C:\\Windows\\Temp" } - end + ['2008', '2008 R2', '2012', '2012 R2'].each do |release| + context "with ensure => present, version => 3.5, os.release.full => #{release}" do let :facts do - { :operatingsystemversion => os } + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } end - it { should contain_exec('install-dotnet-3.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@three_prog} /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@three_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 0 }" + it { should contain_exec('install-dotnet-feature-3.5').with( + 'provider' => 'powershell', )} end end - ['Windows XP', 'Windows Vista', 'Windows 7','Windows 8'].each do |os| - context "with ensure => present, version => 3.5, os => #{os}, download package" do - let :title do 'dotnet35' end + ['2008', '2008 R2', '2012', '2012 R2'].each do |release| + context "with ensure => absent, version => 3.5, os.release.full => #{release}" do let :params do - { :ensure => 'present', :version => '3.5' } + { :ensure => 'absent', :version => '3.5' } end let :facts do - { :operatingsystemversion => os } + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } end - it { should contain_download_file('download-dotnet-3.5').with( - 'url' => @three_url, - 'destination_directory' => 'C:\\Windows\\Temp' - ) } - - it { should contain_exec('install-dotnet-3.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@three_prog} /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@three_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 0 }" + it { should contain_exec('uninstall-dotnet-feature-3.5').with( + 'provider' => 'powershell', )} end end - ['unknown'].each do |os| - context "with ensure => present, version => 3.5, os => #{os}" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'present', :version => '3.5', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } - end + pending("3.5 package-based install validation and code") do + ['2003', '2003 R2', 'XP', 'Vista', '7', '8', '8.7'].each do |release| + context "with ensure => present, version => 3.5, os.release.full => #{release}" do + let :facts do + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } + end - it { should_not contain_exec('install-dotnet-35')} - end - end + it { should contain_package('Microsoft .NET Framework 3.5').with( + 'ensure' => 'present', + )} - ['Windows XP', 'Windows Vista', 'Windows 7','Windows 8'].each do |os| - context "with ensure => absent, version => 3.5, os => #{os}" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'absent', :version => '3.5', :package_dir => "C:\\Windows\\Temp" } - end - let :facts do - { :operatingsystemversion => os } + it { should contain_remote_file('C:/Windows/Temp/dotNetFx35setup.exe').with( + 'ensure' => 'present', + )} end - - it { should contain_exec('uninstall-dotnet-3.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@three_prog} /x /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@three_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 1 }" - )} end - end - ['Windows XP', 'Windows Vista', 'Windows 7','Windows 8'].each do |os| - context "with ensure => absent, version => 3.5, os => #{os}, download package" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'absent', :version => '3.5' } - end - let :facts do - { :operatingsystemversion => os } - end - - it { should contain_file("C:/Windows/Temp/#{@three_prog}").with( - 'ensure' => 'absent' - )} + ['2003', '2003 R2', 'XP', 'Vista', '7', '8', '8.7'].each do |release| + context "with ensure => absent, version => 3.5, os.release.full => #{release}" do + let :params do + { :ensure => 'absent', :version => '3.5' } + end + let :facts do + { :os => {'family' => 'windows', 'release' => { 'full' => release } } } + end - it { should contain_exec('uninstall-dotnet-3.5').with( - 'provider' => 'powershell', - 'logoutput' => 'true', - 'command' => "& C:\\Windows\\Temp\\#{@three_prog} /x /q /norestart", - 'unless' => "if ((Get-Item -LiteralPath '#{@hklm}\\#{@three_reg}' -ErrorAction SilentlyContinue).GetValue('DisplayVersion')) { exit 1 }" - )} - end - end + it { should contain_package('Microsoft .NET Framework 3.5').with( + 'ensure' => 'absent', + )} - ['unknown'].each do |os| - context "with ensure => absent, version => 3.5, os => #{os}" do - let :title do 'dotnet35' end - let :params do - { :ensure => 'absent', :version => '3.5', :package_dir => "C:\\Windows\\Temp" } + it { should contain_remote_file('C:/Windows/Temp/dotNetFx35setup.exe').with( + 'ensure' => 'absent', + )} end - let :facts do - { :operatingsystemversion => os } - end - - it { should_not contain_exec('uninstall-dotnet-3.5')} end end From 842797a4605ed2ec1fec87c122ae0a1760ce0582 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Mon, 9 Nov 2015 09:26:06 -0800 Subject: [PATCH 08/15] 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. --- manifests/init.pp | 4 ++-- manifests/params.pp | 2 +- spec/defines/three_spec.rb | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 978dedf..c9bbe3b 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -52,8 +52,8 @@ case $version { '3.5': { case $windows_version { - /^2008/, /^2012/: { $type = 'feature' } - /^2003/, 'XP', 'Vista', '7', '8', '8.1': { $type = 'package' } + '2008 R2', /^2012/: { $type = 'feature' } + /^2003/, '2008', 'XP', 'Vista', '7', '8', '8.1': { $type = 'package' } default: { $type = 'err' } } } diff --git a/manifests/params.pp b/manifests/params.pp index 5eecc15..8555101 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -14,7 +14,7 @@ 'url' => 'http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe', 'exe' => 'dotNetFx35setup.exe', 'conflicts' => [ ], - 'package' => [ ], + 'package' => 'Microsoft .NET Framework 3.5', }, '4.0' => { 'url' => 'http://download.microsoft.com/download/9/5/A/95A9616B-7A37-4AF6-BC36-D6EA96C8DAAE/dotNetFx40_Full_x86_x64.exe', diff --git a/spec/defines/three_spec.rb b/spec/defines/three_spec.rb index 83e0b88..e7ca2e4 100644 --- a/spec/defines/three_spec.rb +++ b/spec/defines/three_spec.rb @@ -7,7 +7,7 @@ { :ensure => 'present', :version => '3.5' } end - ['2008', '2008 R2', '2012', '2012 R2'].each do |release| + ['2008 R2', '2012', '2012 R2'].each do |release| context "with ensure => present, version => 3.5, os.release.full => #{release}" do let :facts do { :os => {'family' => 'windows', 'release' => { 'full' => release } } } @@ -19,7 +19,7 @@ end end - ['2008', '2008 R2', '2012', '2012 R2'].each do |release| + ['2008 R2', '2012', '2012 R2'].each do |release| context "with ensure => absent, version => 3.5, os.release.full => #{release}" do let :params do { :ensure => 'absent', :version => '3.5' } @@ -35,7 +35,7 @@ end pending("3.5 package-based install validation and code") do - ['2003', '2003 R2', 'XP', 'Vista', '7', '8', '8.7'].each do |release| + ['2003', '2003 R2', '2008', 'XP', 'Vista', '7', '8', '8.7'].each do |release| context "with ensure => present, version => 3.5, os.release.full => #{release}" do let :facts do { :os => {'family' => 'windows', 'release' => { 'full' => release } } } @@ -51,7 +51,7 @@ end end - ['2003', '2003 R2', 'XP', 'Vista', '7', '8', '8.7'].each do |release| + ['2003', '2003 R2', '2008', 'XP', 'Vista', '7', '8', '8.7'].each do |release| context "with ensure => absent, version => 3.5, os.release.full => #{release}" do let :params do { :ensure => 'absent', :version => '3.5' } From 4849b246ea0b31d0d212e57aea187a6dcd60ab42 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Mon, 9 Nov 2015 10:50:31 -0800 Subject: [PATCH 09/15] 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. --- manifests/init.pp | 44 +++++++++++++++++++++++------------- manifests/install/dism.pp | 23 +++++++++++++++++++ manifests/install/feature.pp | 4 ++-- 3 files changed, 53 insertions(+), 18 deletions(-) create mode 100644 manifests/install/dism.pp diff --git a/manifests/init.pp b/manifests/init.pp index c9bbe3b..5e65fbc 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -52,9 +52,10 @@ case $version { '3.5': { case $windows_version { - '2008 R2', /^2012/: { $type = 'feature' } - /^2003/, '2008', 'XP', 'Vista', '7', '8', '8.1': { $type = 'package' } - default: { $type = 'err' } + '2008 R2', /^2012/: { $type = 'feature' } + '7', '8', '8.1': { $type = 'dism' } + /^2003/, '2008', 'XP', 'Vista': { $type = 'package' } + default: { $type = 'err' } } } '4.0': { @@ -87,21 +88,32 @@ default: { $type = 'err' } } - if $type == 'feature' { - dotnet::install::feature { "dotnet-feature-${version}": - ensure => $ensure, - version => $version, + case $type { + 'feature': { + dotnet::install::feature { "dotnet-feature-${version}": + ensure => $ensure, + version => $version, + } + } + 'dism': { + dotnet::install::dism { "dotnet-dism-${version}": + ensure => $ensure, + version => $version, + } + } + 'package': { + dotnet::install::package { "dotnet-package-${version}": + ensure => $ensure, + version => $version, + package_dir => $package_dir, + } + } + 'builtin': { + # This .NET version is built into the OS. No configuration required. } - } elsif $type == 'package' { - dotnet::install::package { "dotnet-package-${version}": - ensure => $ensure, - version => $version, - package_dir => $package_dir, + default: { + fail("dotnet ${version} is not supported on windows ${windows_version}") } - } elsif $type == 'builtin' { - # This .NET version is built into the OS. No configuration required. - } else { - fail("dotnet ${version} is not supported on windows ${windows_version}") } } diff --git a/manifests/install/dism.pp b/manifests/install/dism.pp new file mode 100644 index 0000000..596f47c --- /dev/null +++ b/manifests/install/dism.pp @@ -0,0 +1,23 @@ +# +define dotnet::install::dism ( + $ensure = 'present', + $version = '', +) { + + if $ensure == 'present' { + exec { "install-dotnet-dism-${version}": + command => 'DISM /Online /Enable-Feature /FeatureName:NetFx3 /NoRestart', + creates => "C:/Windows/Microsoft.NET/Framework/v${version}", + provider => powershell, + logoutput => true, + } + } else { + exec { "uninstall-dotnet-dism-${version}": + command => 'DISM /Online /Disable-Feature /FeatureName:NetFx3 /NoRestart', + onlyif => "If (-Not(Test-Path C:/Windows/Microsoft.NET/Framework/v${version})) { Exit 1 }", + provider => powershell, + logoutput => true, + } + } + +} diff --git a/manifests/install/feature.pp b/manifests/install/feature.pp index fcf027f..56f4c75 100644 --- a/manifests/install/feature.pp +++ b/manifests/install/feature.pp @@ -1,7 +1,7 @@ # define dotnet::install::feature( - $ensure = 'present', - $version = '' + $ensure = 'present', + $version = '', ) { if $ensure == 'present' { From 14a699bbef7c1a2672084939f4418b50073f3cc6 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Tue, 10 Nov 2015 11:37:37 -0800 Subject: [PATCH 10/15] 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. --- manifests/install/feature.pp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/manifests/install/feature.pp b/manifests/install/feature.pp index 56f4c75..4050b0b 100644 --- a/manifests/install/feature.pp +++ b/manifests/install/feature.pp @@ -9,14 +9,14 @@ command => 'Import-Module ServerManager; Add-WindowsFeature as-net-framework', provider => powershell, logoutput => true, - unless => "Test-Path C:\\Windows\\Microsoft.NET\\Framework\\v${version}", + creates => "C:/Windows/Microsoft.NET/Framework/v${version}", } } else { exec { "uninstall-dotnet-feature-${version}": command => 'Import-Module ServerManager; Remove-WindowsFeature as-net-framework', provider => powershell, logoutput => true, - onlyif => "Test-Path C:\\Windows\\Microsoft.NET\\Framework\\v${version}", + onlyif => "If (-Not(Test-Path C:/Windows/Microsoft.NET/Framework/v${version})) { Exit 1 }", } } From 0ec9c73ed5721404a84cbaf7581980ca2e2fde76 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Tue, 10 Nov 2015 14:00:00 -0800 Subject: [PATCH 11/15] (style) Line up case blocks --- manifests/init.pp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/manifests/init.pp b/manifests/init.pp index 5e65fbc..18543e1 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -39,6 +39,9 @@ Variant[String, Undef] $package_dir = undef, + + Variant[String, Undef] + $source = undef, ) { include dotnet::params @@ -60,29 +63,29 @@ } '4.0': { case $windows_version { - /^2012/, '8', '8.1': { $type = 'builtin' } + /^2012/, '8', '8.1': { $type = 'builtin' } /^2003/, /^2008/, 'XP', 'Vista', '7': { $type = 'package' } - default: { $type = 'err' } + default: { $type = 'err' } } } '4.5': { case $windows_version { - /^2012/, '8', '8.1': { $type = 'builtin' } + /^2012/, '8', '8.1': { $type = 'builtin' } /^2003/, /^2008/, 'XP', 'Vista', '7': { $type = 'package' } - default: { $type = 'err' } + default: { $type = 'err' } } } '4.5.1': { case $windows_version { - '2012 R2', '8.1': { $type = 'builtin' } + '2012 R2', '8.1': { $type = 'builtin' } /^2003/, /^2008/, '2012', 'XP', 'Vista', '7', '8': { $type = 'package' } - default: { $type = 'err' } + default: { $type = 'err' } } } '4.5.2': { case $windows_version { /^2003/, /^2008/, /^2012/, 'XP', 'Vista', '7', '8', '8.1': { $type = 'package' } - default: { $type = 'err' } + default: { $type = 'err' } } } default: { $type = 'err' } From c841b36081c22de7876d85af4debf0375731d1a5 Mon Sep 17 00:00:00 2001 From: Reid Vandewiele Date: Tue, 10 Nov 2015 14:00:19 -0800 Subject: [PATCH 12/15] 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. --- README.md | 5 ++++- manifests/init.pp | 11 +++++++---- manifests/install/feature.pp | 13 ++++++++++--- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 18f7464..2f4971b 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,10 @@ Ensures the state of .net on the system. Present or Absent. The version of .net that you want to be managed by this definition. #####`package_dir` -If installing .NET from a directory or a mounted network location then this is that directory +If installing .NET from a directory or a mounted network location then this is +that directory. If the version of .NET being installed is a Windows feature, it +may sometimes be necessary to specify package\_dir as the path to installation +media, such as `D:\sources\sxs`. ##Reference diff --git a/manifests/init.pp b/manifests/init.pp index 18543e1..076d4a2 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -39,9 +39,6 @@ Variant[String, Undef] $package_dir = undef, - - Variant[String, Undef] - $source = undef, ) { include dotnet::params @@ -55,7 +52,11 @@ case $version { '3.5': { case $windows_version { - '2008 R2', /^2012/: { $type = 'feature' } + /^2012/: { + $type = 'feature' + $feature = 'NET-Framework-Features' + } + '2008 R2': { $type = 'feature' } '7', '8', '8.1': { $type = 'dism' } /^2003/, '2008', 'XP', 'Vista': { $type = 'package' } default: { $type = 'err' } @@ -96,6 +97,8 @@ dotnet::install::feature { "dotnet-feature-${version}": ensure => $ensure, version => $version, + feature => $feature, + source => $package_dir, } } 'dism': { diff --git a/manifests/install/feature.pp b/manifests/install/feature.pp index 4050b0b..8a11dd3 100644 --- a/manifests/install/feature.pp +++ b/manifests/install/feature.pp @@ -1,19 +1,26 @@ # define dotnet::install::feature( + $version, $ensure = 'present', - $version = '', + $feature = 'AS-NET-Framework', + $source = undef, ) { + $source_flag = $source ? { + undef => '', + default => "-source ${source}", + } + if $ensure == 'present' { exec { "install-dotnet-feature-${version}": - command => 'Import-Module ServerManager; Add-WindowsFeature as-net-framework', + command => "Import-Module ServerManager; Add-WindowsFeature ${feature} ${source_flag}", provider => powershell, logoutput => true, creates => "C:/Windows/Microsoft.NET/Framework/v${version}", } } else { exec { "uninstall-dotnet-feature-${version}": - command => 'Import-Module ServerManager; Remove-WindowsFeature as-net-framework', + command => "Import-Module ServerManager; Remove-WindowsFeature ${feature}", provider => powershell, logoutput => true, onlyif => "If (-Not(Test-Path C:/Windows/Microsoft.NET/Framework/v${version})) { Exit 1 }", From e04a1b65b58b96d334ef743a9b451c73c15b870a Mon Sep 17 00:00:00 2001 From: Tim Miller Date: Thu, 10 Dec 2015 15:29:52 -0500 Subject: [PATCH 13/15] Handle .NET versions installed outside of package resource A custom fact 'dotnet4version' was created to pull specific version from windows registry. This is then used to determine if desired .NET version has already been installed via non-msi method (from windows update for example). If desired version is already installed, this prevents the downloading and attempted installation of the package from occurring on each agent run. --- lib/facter/dotnet4version.rb | 31 +++++++++++++++++++++++++++++++ manifests/init.pp | 8 +++++++- 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 lib/facter/dotnet4version.rb diff --git a/lib/facter/dotnet4version.rb b/lib/facter/dotnet4version.rb new file mode 100644 index 0000000..f4eebb9 --- /dev/null +++ b/lib/facter/dotnet4version.rb @@ -0,0 +1,31 @@ +Facter.add(:dotnet4version) do + confine :kernel => :windows + setcode do + require 'win32/registry' + keyname = 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full' + begin + Win32::Registry::HKEY_LOCAL_MACHINE.open(keyname) do |reg| + begin + value = reg['Release'].to_i + rescue + puts '4.0' + exit + end + case reg['Release'].to_i + when 378389 + '4.5' + when 378675,378675 + '4.5.1' + when 379893 + '4.5.2' + when 393295 + '4.6' + when 394254,394271 + '4.6.1' + else + 'unknown' + end + end + end + end +end \ No newline at end of file diff --git a/manifests/init.pp b/manifests/init.pp index 076d4a2..14934b9 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -32,7 +32,7 @@ # define dotnet( Enum['3.5', '4.0', '4.5', '4.5.1', '4.5.2'] - $version, + $version = '4.6', Enum['present', 'absent'] $ensure = 'present', @@ -50,6 +50,9 @@ $windows_version = $::os['release']['full'] case $version { + $::dotnet4version: { + $type = 'noaction' + } '3.5': { case $windows_version { /^2012/: { @@ -117,6 +120,9 @@ 'builtin': { # This .NET version is built into the OS. No configuration required. } + 'noaction': { + # Desired .NET version is already present + } default: { fail("dotnet ${version} is not supported on windows ${windows_version}") } From 6f1fa76bbf7717f7567cc8291ada8c1c3ae0bd03 Mon Sep 17 00:00:00 2001 From: Tim Miller Date: Thu, 10 Dec 2015 15:37:40 -0500 Subject: [PATCH 14/15] Fix typo that was inserted for testing purposes. --- manifests/init.pp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifests/init.pp b/manifests/init.pp index 14934b9..0464f19 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -32,7 +32,7 @@ # define dotnet( Enum['3.5', '4.0', '4.5', '4.5.1', '4.5.2'] - $version = '4.6', + $version, Enum['present', 'absent'] $ensure = 'present', From 686bf18044211878c23d8b801454e7dd8c521885 Mon Sep 17 00:00:00 2001 From: Tim Miller Date: Thu, 10 Dec 2015 15:51:24 -0500 Subject: [PATCH 15/15] Update dotnet4version fact to handle .NET 4.x not being installed. --- lib/facter/dotnet4version.rb | 4 +++- manifests/init.pp | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/facter/dotnet4version.rb b/lib/facter/dotnet4version.rb index f4eebb9..090e8ac 100644 --- a/lib/facter/dotnet4version.rb +++ b/lib/facter/dotnet4version.rb @@ -26,6 +26,8 @@ 'unknown' end end - end + rescue + puts 'not installed' + end end end \ No newline at end of file diff --git a/manifests/init.pp b/manifests/init.pp index 0464f19..8682427 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -127,5 +127,4 @@ fail("dotnet ${version} is not supported on windows ${windows_version}") } } - }