diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4aad8ea8..790d72ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,8 @@ jobs: - 'section' - 'site' - 'vdir' + - 'default-windowsfeatures-powershell' + - 'site-windowsfeatures-powershell' fail-fast: false steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c9e5668..ddc37734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ This file is used to list changes made in each version of the iis cookbook. ## Unreleased +- Allow specifying install method for windows_feature resources + ## 7.5.1 - *2021-03-25* - Cookstyle fixes diff --git a/README.md b/README.md index 8c7b2eb4..774a3fde 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ This cookbook is maintained by the Sous Chefs. The Sous Chefs are a community of - `node['iis']['pubroot']` - . default is `%SYSTEMDRIVE%\inetpub` - `node['iis']['docroot']` - IIS web site home directory. default is `%SYSTEMDRIVE%\inetpub\wwwroot` - `node['iis']['cache_dir']` - location of cached data. default is `%SYSTEMDRIVE%\inetpub\temp` +- `node['iis']['windows_feature_install_method']` - specify the install method that will be used by any windows_feature resources. If ommitted it will not be specified and will the windows_feature supply a default. Valid options are ':windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd'. Default is :windows_feature_dism ## Resources diff --git a/attributes/default.rb b/attributes/default.rb index aa2e948d..dc9a7390 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -27,3 +27,5 @@ default['iis']['source'] = nil default['iis']['recycle']['log_events'] = 'Time, Requests, Schedule, Memory, IsapiUnhealthy, OnDemand, ConfigChange, PrivateMemory' + +default['iis']['windows_feature_install_method'] = :windows_feature_dism diff --git a/documentation/iis_install.md b/documentation/iis_install.md index f0785120..e8de376f 100644 --- a/documentation/iis_install.md +++ b/documentation/iis_install.md @@ -16,6 +16,7 @@ Simple resource to install the IIS feature | ----------------------- | -------- | -------- | ------------------------------------ | | `source` | String | No | Source to install the features from. | | `additional_components` | Array | No | Features of IIS to install | +| `install_method` | :windows_feature_dism, :windows_feature_powershell | No | install_method to be used to any windows_features resources. Default is :windows_feature_dism | ## Examples diff --git a/documentation/iis_manager.md b/documentation/iis_manager.md index d78452d8..61c1eab5 100644 --- a/documentation/iis_manager.md +++ b/documentation/iis_manager.md @@ -17,6 +17,7 @@ Configures the IIS Manager service | `enable_remote_management` | true, false | `true` | If remote access allowed | | `log_directory` | String | | Optional. The directory to write log files to | | `port` | Integer | `8172` | The port the service listens on. | +| `install_method` | :windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd | `:windows_feature_dism` | Optional. install_method to be used to any windows_features resources | ## Examples diff --git a/kitchen.yml b/kitchen.yml index 4afb88de..508b8413 100644 --- a/kitchen.yml +++ b/kitchen.yml @@ -71,3 +71,21 @@ suites: - name: vdir run_list: - recipe[test::vdir] + - name: default-windowsfeatures-powershell + run_list: + - recipe[iis::default] + verifier: + inspec_tests: + - test/integration/default/spec + attributes: + iis: + windows_feature_install_method: windows_feature_powershell + - name: site-windowsfeatures-powershell + run_list: + - recipe[test::site] + verifier: + inspec_tests: + - test/integration/site + attributes: + iis: + windows_feature_install_method: windows_feature_powershell diff --git a/libraries/windowsfeature_helper.rb b/libraries/windowsfeature_helper.rb new file mode 100644 index 00000000..bd11d75f --- /dev/null +++ b/libraries/windowsfeature_helper.rb @@ -0,0 +1,42 @@ +# +# Cookbook:: iis +# Library:: windowsfeature_helper +# +# Copyright:: 2017-2021, Chef Software, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +module IISCookbook + module WindowsFeatureHelper + def transform_feature_name(install_method, names) + if install_method.to_sym == :windows_feature_powershell + Array(names).map do |name| + cmd = "Get-WindowsFeature | Where-Object {$_.AdditionalInfo.InstallName -Eq '#{name}' -or $_.Name -eq '#{name}'} | Select -Expand Name" + result = powershell_out cmd + if result.stderr.empty? + next result.stdout.strip + else + Chef::Log.warn("Unable to translate feature #{name}") + Chef::Log.warn(result.stderr) + next name + end + end + else + names + end + end + end +end + +::Chef::DSL::Recipe.include(IISCookbook::WindowsFeatureHelper) diff --git a/recipes/default.rb b/recipes/default.rb index 4c2d7041..7159261a 100644 --- a/recipes/default.rb +++ b/recipes/default.rb @@ -21,6 +21,7 @@ iis_install 'install IIS' do additional_components node['iis']['components'] source node['iis']['source'] + install_method node['iis']['windows_feature_install_method']&.to_sym end service 'iis' do diff --git a/recipes/mod_application_initialization.rb b/recipes/mod_application_initialization.rb index c98e39de..7451a3d6 100644 --- a/recipes/mod_application_initialization.rb +++ b/recipes/mod_application_initialization.rb @@ -19,5 +19,8 @@ # include_recipe 'iis' +install_method = node['iis']['windows_feature_install_method']&.to_sym -windows_feature 'IIS-ApplicationInit' +windows_feature transform_feature_name(install_method, 'IIS-ApplicationInit') do + install_method install_method +end diff --git a/recipes/mod_aspnet.rb b/recipes/mod_aspnet.rb index f085bd18..3fd3e4d4 100644 --- a/recipes/mod_aspnet.rb +++ b/recipes/mod_aspnet.rb @@ -21,8 +21,11 @@ include_recipe 'iis' include_recipe 'iis::mod_isapi' -windows_feature %w(IIS-NetFxExtensibility IIS-ASPNET) do +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, %w(IIS-NetFxExtensibility IIS-ASPNET)) do action :install all !IISCookbook::Helper.older_than_windows2012? source node['iis']['source'] unless node['iis']['source'].nil? + install_method install_method end diff --git a/recipes/mod_aspnet45.rb b/recipes/mod_aspnet45.rb index 6a3e7dbf..d6274063 100644 --- a/recipes/mod_aspnet45.rb +++ b/recipes/mod_aspnet45.rb @@ -21,4 +21,8 @@ include_recipe 'iis' include_recipe 'iis::mod_isapi' -windows_feature %w(NetFx4Extended-ASPNET45 IIS-NetFxExtensibility45 IIS-ASPNET45) +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, %w(NetFx4Extended-ASPNET45 IIS-NetFxExtensibility45 IIS-ASPNET45)) do + install_method install_method +end diff --git a/recipes/mod_auth_basic.rb b/recipes/mod_auth_basic.rb index 032aedbb..744f293a 100644 --- a/recipes/mod_auth_basic.rb +++ b/recipes/mod_auth_basic.rb @@ -20,7 +20,11 @@ include_recipe 'iis' -windows_feature 'IIS-BasicAuthentication' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-BasicAuthentication') do + install_method install_method +end iis_section 'unlocks basic authentication control in web.config' do section 'system.webServer/security/authentication/basicAuthentication' diff --git a/recipes/mod_auth_digest.rb b/recipes/mod_auth_digest.rb index 517a36e2..6f85d059 100644 --- a/recipes/mod_auth_digest.rb +++ b/recipes/mod_auth_digest.rb @@ -20,7 +20,11 @@ include_recipe 'iis' -windows_feature 'IIS-DigestAuthentication' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-DigestAuthentication') do + install_method install_method +end iis_section 'unlocks digest authentication control in web.config' do section 'system.webServer/security/authentication/digestAuthentication' diff --git a/recipes/mod_auth_windows.rb b/recipes/mod_auth_windows.rb index cba02fe9..fc18cdc7 100644 --- a/recipes/mod_auth_windows.rb +++ b/recipes/mod_auth_windows.rb @@ -20,7 +20,11 @@ include_recipe 'iis' -windows_feature 'IIS-WindowsAuthentication' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-WindowsAuthentication') do + install_method install_method +end iis_section 'unlocks windows authentication control in web.config' do section 'system.webServer/security/authentication/windowsAuthentication' diff --git a/recipes/mod_cgi.rb b/recipes/mod_cgi.rb index a29b7628..c84b7d03 100644 --- a/recipes/mod_cgi.rb +++ b/recipes/mod_cgi.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature 'IIS-CGI' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-CGI') do + install_method install_method +end diff --git a/recipes/mod_compress_dynamic.rb b/recipes/mod_compress_dynamic.rb index 991e86aa..186d5c1d 100644 --- a/recipes/mod_compress_dynamic.rb +++ b/recipes/mod_compress_dynamic.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature 'IIS-HttpCompressionDynamic' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-HttpCompressionDynamic') do + install_method install_method +end diff --git a/recipes/mod_compress_static.rb b/recipes/mod_compress_static.rb index 725fd17c..79328ea5 100644 --- a/recipes/mod_compress_static.rb +++ b/recipes/mod_compress_static.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature 'IIS-HttpCompressionStatic' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-HttpCompressionStatic') do + install_method install_method +end diff --git a/recipes/mod_ftp.rb b/recipes/mod_ftp.rb index 7c2161d2..0546318f 100644 --- a/recipes/mod_ftp.rb +++ b/recipes/mod_ftp.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature %w(IIS-FTPServer IIS-FTPSvc IIS-FTPExtensibility) +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, %w(IIS-FTPServer IIS-FTPSvc IIS-FTPExtensibility)) do + install_method install_method +end diff --git a/recipes/mod_iis6_metabase_compat.rb b/recipes/mod_iis6_metabase_compat.rb index b1df7e62..3475ee6e 100644 --- a/recipes/mod_iis6_metabase_compat.rb +++ b/recipes/mod_iis6_metabase_compat.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature %w(IIS-IIS6ManagementCompatibility IIS-Metabase) +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, %w(IIS-IIS6ManagementCompatibility IIS-Metabase)) do + install_method install_method +end diff --git a/recipes/mod_isapi.rb b/recipes/mod_isapi.rb index bffffd4c..9fe60750 100644 --- a/recipes/mod_isapi.rb +++ b/recipes/mod_isapi.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature %w(IIS-ISAPIFilter IIS-ISAPIExtensions) +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, %w(IIS-ISAPIFilter IIS-ISAPIExtensions)) do + install_method install_method +end diff --git a/recipes/mod_logging.rb b/recipes/mod_logging.rb index ba2d46c2..3654c137 100644 --- a/recipes/mod_logging.rb +++ b/recipes/mod_logging.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature 'IIS-CustomLogging' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-CustomLogging') do + install_method install_method +end diff --git a/recipes/mod_management.rb b/recipes/mod_management.rb index 7bcc9f3f..d48bdadb 100644 --- a/recipes/mod_management.rb +++ b/recipes/mod_management.rb @@ -20,7 +20,10 @@ include_recipe 'iis' -windows_feature %w(IIS-ManagementConsole IIS-ManagementService) do +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, %w(IIS-ManagementConsole IIS-ManagementService)) do action :install all !IISCookbook::Helper.older_than_windows2012? + install_method install_method end diff --git a/recipes/mod_security.rb b/recipes/mod_security.rb index 959a6c67..870108cd 100644 --- a/recipes/mod_security.rb +++ b/recipes/mod_security.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature %w(IIS-URLAuthorization IIS-RequestFiltering IIS-IPSecurity) +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, %w(IIS-URLAuthorization IIS-RequestFiltering IIS-IPSecurity)) do + install_method install_method +end diff --git a/recipes/mod_tracing.rb b/recipes/mod_tracing.rb index 6d35b595..4e849359 100644 --- a/recipes/mod_tracing.rb +++ b/recipes/mod_tracing.rb @@ -20,4 +20,8 @@ include_recipe 'iis' -windows_feature 'IIS-HttpTracing' +install_method = node['iis']['windows_feature_install_method']&.to_sym + +windows_feature transform_feature_name(install_method, 'IIS-HttpTracing') do + install_method install_method +end diff --git a/resources/install.rb b/resources/install.rb index 7d6d071e..b4d597fb 100644 --- a/resources/install.rb +++ b/resources/install.rb @@ -18,17 +18,20 @@ # include IISCookbook::Helper +include IISCookbook::WindowsFeatureHelper property :source, String property :additional_components, Array, default: [] +property :install_method, Symbol, required: false, equal_to: [:windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd], default: :windows_feature_dism action :install do - features_to_install = ['IIS-WebServerRole'].concat new_resource.additional_components + features_to_install = transform_feature_name(new_resource.install_method, ['IIS-WebServerRole'].concat(new_resource.additional_components)) windows_feature 'Install IIS and additional components' do feature_name features_to_install action :install all !IISCookbook::Helper.older_than_windows2012? source new_resource.source unless new_resource.source.nil? + install_method new_resource.install_method end end diff --git a/resources/manager.rb b/resources/manager.rb index cddef217..03e13f16 100644 --- a/resources/manager.rb +++ b/resources/manager.rb @@ -22,10 +22,12 @@ property :enable_remote_management, [true, false], default: true property :log_directory, String property :port, Integer, default: 8172 +property :install_method, Symbol, required: false, equal_to: [:windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd], default: :windows_feature_dism action :config do iis_install 'Web-Mgmt-Service' do additional_components ['IIS-ManagementService'] + install_method new_resource.install_method end # properties stored in the registry diff --git a/spec/unit/recipes/default_spec.rb b/spec/unit/recipes/default_spec.rb index cf7cdd16..e1f24a58 100644 --- a/spec/unit/recipes/default_spec.rb +++ b/spec/unit/recipes/default_spec.rb @@ -55,4 +55,18 @@ expect(chef_run).to start_service('iis').with(service_name: 'W3SVC') end end + + [:windows_feature_dism, :windows_feature_powershell, :windows_feature_servermanagercmd].each do |method| + context "When iis windows feature install method is provided as #{method}, on a unspecified platform" do + let(:chef_run) do + ChefSpec::SoloRunner.new do |node| + node.override['iis']['windows_feature_install_method'] = method + end.converge(described_recipe) + end + + it "installs windows features using #{method}" do + expect(chef_run).to install_iis_install('install IIS').with(install_method: method) + end + end + end end