class Inspec::Resources::WindowsFeature

Public Class Methods

new(feature, method = nil) click to toggle source
# File lib/inspec/resources/windows_feature.rb, line 28
def initialize(feature, method = nil)
  @feature = feature
  @method = method
  @cache = nil
end

Public Instance Methods

info() click to toggle source

returns the package description

# File lib/inspec/resources/windows_feature.rb, line 40
def info
  return @cache unless @cache.nil?

  case @method
  when :powershell
    @cache = info_via_powershell(@feature)
    if @cache[:error]
      # TODO: Allow handling `Inspec::Exception` outside of initialize
      # See: https://github.com/inspec/inspec/issues/3237
      # The below will fail the resource regardless of what is raised
      raise Inspec::Exceptions::ResourceFailed, @cache[:error]
    end
  when :dism
    @cache = info_via_dism(@feature)
  else
    @cache = info_via_powershell(@feature)
    @cache = info_via_dism(@feature) if @cache[:error]
  end

  @cache
end
installed?() click to toggle source

returns true if the package is installed

# File lib/inspec/resources/windows_feature.rb, line 35
def installed?
  info[:installed] == true
end
to_s() click to toggle source
# File lib/inspec/resources/windows_feature.rb, line 62
def to_s
  "Windows Feature '#{@feature}'"
end

Private Instance Methods

info_via_dism(feature) click to toggle source
# File lib/inspec/resources/windows_feature.rb, line 68
def info_via_dism(feature)
  dism_command = "dism /online /get-featureinfo /featurename:#{feature}"
  cmd = inspec.command(dism_command)

  if cmd.exit_status != 0
    feature_info = {
      name: feature,
      description: "N/A",
      installed: false,
    }
  else
    result = cmd.stdout
    feature_name_regex = /Feature Name : (.*)(\r\n|\n)/
    description_regex = /Description : (.*)(\r\n|\n)/
    state_regex = /State : (.*)(\r\n|\n)/
    feature_info = {
      name: result.match(feature_name_regex).captures[0].chomp,
      description: result.match(description_regex).captures[0].chomp,
      installed: result.match(state_regex).captures[0].chomp == "Enabled",
    }
  end

  feature_info[:method] = :dism
  feature_info
end
info_via_powershell(feature) click to toggle source
# File lib/inspec/resources/windows_feature.rb, line 94
def info_via_powershell(feature)
  features_cmd = "Get-WindowsFeature | Where-Object {$_.Name -eq '#{feature}' -or $_.DisplayName -eq '#{feature}'} | Select-Object -Property Name,DisplayName,Description,Installed,InstallState | ConvertTo-Json"
  cmd = inspec.command(features_cmd)

  feature_info = {}

  # The `Get-WindowsFeature` command is not available on the Windows
  # non-server OS. This attempts to use the `dism` command to get the info.
  if cmd.stderr =~ /The term 'Get-WindowsFeature' is not recognized/
    feature_info[:name] = feature
    feature_info[:error] = "Could not find `Get-WindowsFeature`"
  else
    # We cannot rely on `cmd.exit_status != 0` because by default the
    # command will exit 1 even on success. So, if we cannot parse the JSON
    # we know that the feature is not installed.
    begin
      result = JSON.parse(cmd.stdout)

      feature_info = {
        name: result["Name"],
        description: result["Description"],
        installed: result["Installed"],
      }
    rescue JSON::ParserError => _e
      feature_info[:name] = feature
      feature_info[:installed] = false
    end
  end

  feature_info[:method] = :powershell
  feature_info
end