From 8b6fccee92d29316d8b545fd19280ff53725ceb9 Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Sun, 20 Sep 2015 17:42:09 +0200 Subject: [PATCH 1/2] implement windows_feature resource --- lib/resources/windows_feature.rb | 75 ++++++++++++++++++++++++++++++++ lib/vulcano/resource.rb | 1 + 2 files changed, 76 insertions(+) create mode 100644 lib/resources/windows_feature.rb diff --git a/lib/resources/windows_feature.rb b/lib/resources/windows_feature.rb new file mode 100644 index 000000000..a96fa3b84 --- /dev/null +++ b/lib/resources/windows_feature.rb @@ -0,0 +1,75 @@ +# encoding: utf-8 + +# check for a Windows feature +# Usage: +# describe windows_feature('DHCP Server') do +# it{ should be_installed } +# end +# +# deprecated serverspec syntax: +# describe windows_feature('IIS-Webserver') do +# it{ should be_installed.by("dism") } +# end +# +# describe windows_feature('Web-Webserver') do +# it{ should be_installed.by("powershell") } +# end +# +# This implementation uses the Get-WindowsFeature commandlet: +# Get-WindowsFeature | Where-Object {$_.Name -eq 'XPS Viewer' -or $_.DisplayName -eq 'XPS Viewe +# r'} | Select-Object -Property Name,DisplayName,Description,Installed,InstallState | ConvertTo-Json +# { +# "Name": "XPS-Viewer", +# "DisplayName": "XPS Viewer", +# "Description": "The XPS Viewer is used to read, set permissions for, and digitally sign XPS documents.", +# "Installed": false, +# "InstallState": 0 +# } +class WindowsFeature < Vulcano.resource(1) + name 'windows_feature' + + def initialize(feature) + @feature = feature + @cache = nil + + # verify that this resource is only supported on Windows + return skip_resource 'The `windows_feature` resource is not supported on your OS.' if vulcano.os[:family] != 'windows' + end + + # returns true if the package is installed + def installed?(_provider = nil, _version = nil) + info[:installed] == true + end + + # returns the package description + def info + return @cache if !@cache.nil? + features_cmd = "Get-WindowsFeature | Where-Object {$_.Name -eq '#{@feature}' -or $_.DisplayName -eq '#{@feature}'} | Select-Object -Property Name,DisplayName,Description,Installed,InstallState | ConvertTo-Json" + cmd = vulcano.run_command(features_cmd) + + @cache = { + name: @feature, + type: 'windows-feature', + } + + # cannot rely on exit code for now, successful command returns exit code 1 + # return nil if cmd.exit_status != 0 + # try to parse json + begin + params = JSON.parse(cmd.stdout) + rescue JSON::ParserError => _e + return @cache + end + + @cache = { + name: params['Name'], + description: params['Description'], + installed: params['Installed'], + type: 'windows-feature', + } + end + + def to_s + "Windows feature '#{@feature}'" + end +end diff --git a/lib/vulcano/resource.rb b/lib/vulcano/resource.rb index 10626929a..634b0616c 100644 --- a/lib/vulcano/resource.rb +++ b/lib/vulcano/resource.rb @@ -52,4 +52,5 @@ require 'resources/registry_key' require 'resources/security_policy' require 'resources/service' require 'resources/ssh_conf' +require 'resources/windows_feature' require 'resources/yum' From baee8daae8f2de6047175fbf20df7fb30e4c9f72 Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Sun, 20 Sep 2015 17:42:56 +0200 Subject: [PATCH 2/2] add unit tests for windows feature --- test/helper.rb | 1 + test/unit/mock/cmd/get-windows-feature | 7 +++++++ test/unit/resource_windows_feature.rb | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 test/unit/mock/cmd/get-windows-feature create mode 100644 test/unit/resource_windows_feature.rb diff --git a/test/helper.rb b/test/helper.rb index 72bfcc693..d41643f5f 100644 --- a/test/helper.rb +++ b/test/helper.rb @@ -69,6 +69,7 @@ def loadResource (resource, *args) 'pip show jinja2' => cmd.call('pip-show-jinja2'), "Get-Package -Name 'Mozilla Firefox' | ConvertTo-Json" => cmd.call('get-package'), "New-Object -Type PSObject | Add-Member -MemberType NoteProperty -Name Service -Value (Get-Service -Name dhcp| Select-Object -Property Name, DisplayName, Status) -PassThru | Add-Member -MemberType NoteProperty -Name WMI -Value (Get-WmiObject -Class Win32_Service | Where-Object {$_.Name -eq 'dhcp' -or $_.DisplayName -eq 'dhcp'} | Select-Object -Property StartMode) -PassThru | ConvertTo-Json" => cmd.call('get-service-dhcp'), + "Get-WindowsFeature | Where-Object {$_.Name -eq 'dhcp' -or $_.DisplayName -eq 'dhcp'} | Select-Object -Property Name,DisplayName,Description,Installed,InstallState | ConvertTo-Json" => cmd.call('get-windows-feature'), } # load resource diff --git a/test/unit/mock/cmd/get-windows-feature b/test/unit/mock/cmd/get-windows-feature new file mode 100644 index 000000000..318359962 --- /dev/null +++ b/test/unit/mock/cmd/get-windows-feature @@ -0,0 +1,7 @@ +{ + "Name": "DHCP", + "DisplayName": "DHCP Server", + "Description": "Dynamic Host Configuration Protocol (DHCP) Server enables you to centrally configure, manage, and provide temporary IP addresses and related information for client computers.", + "Installed": false, + "InstallState": 0 +} diff --git a/test/unit/resource_windows_feature.rb b/test/unit/resource_windows_feature.rb new file mode 100644 index 000000000..988f7a252 --- /dev/null +++ b/test/unit/resource_windows_feature.rb @@ -0,0 +1,18 @@ +# encoding utf-8 + +require 'helper' +require 'vulcano/resource' + +describe 'Vulcano:Resources::Feature' do + describe 'feature' do + + let(:resource) { loadResource('windows_feature', 'dhcp') } + + # TODO: set windows as mock os + it 'verify windows feature parsing' do + pkg = { name: 'DHCP', description: 'Dynamic Host Configuration Protocol (DHCP) Server enables you to centrally configure, manage, and provide temporary IP addresses and related information for client computers.', installed: false, type: 'windows-feature' } + _(resource.info).must_equal pkg + _(resource.installed?).must_equal false + end + end +end