filesystem: improve Windows support (#3606)

* Improve filesystem.rb to support windows

improve filesystem.rb to support windows.
Split into 2 classes LinuxFileSystemResource / WindowsFileSystemResource
Add filesystem to verify a FS-type ( currently not for linux because missing test server )
Size on Windows is converted to GB - discussion about this welcome

update to reflect also windows os

* Create get-wmiobject-filesystem
* Delete get-wmiobject-filesystem

* Fix the testing code for filesystem.
Change its 'filesystem' to 'type' according to recommendation from @miah
Signed-off-by: Markus Hackethal <mh@it31.de>
This commit is contained in:
mhackethal 2018-11-19 19:32:59 +01:00 committed by Jared Quick
parent 3c557eac3f
commit 86cf55382b
5 changed files with 111 additions and 34 deletions

View file

@ -2,30 +2,103 @@ module Inspec::Resources
class FileSystemResource < Inspec.resource(1)
name 'filesystem'
supports platform: 'linux'
supports platform: 'windows'
desc 'Use the filesystem InSpec resource to test file system'
example "
describe filesystem('/') do
its('size') { should be >= 32000 }
its('type') { should eq false }
end
describe filesystem('c:') do
its('size') { should be >= 90 }
its('type') { should eq 'NTFS' }
end
"
attr_reader :partition
def initialize(partition)
@partition = partition
end
@cache = nil
# select file system manager
@fsman = nil
def size
@size ||= begin
cmd = inspec.command("df #{partition} --output=size")
raise Inspec::Exceptions::ResourceFailed, "Unable to get available space for partition #{partition}" if cmd.stdout.nil? || cmd.stdout.empty? || !cmd.exit_status.zero?
value = cmd.stdout.gsub(/\dK-blocks[\r\n]/, '').strip
value.to_i
os = inspec.os
if os.linux?
@fsman = LinuxFileSystemResource.new(inspec)
elsif os.windows?
@fsman = WindowsFileSystemResource.new(inspec)
else
raise Inspec::Exceptions::ResourceSkipped, 'The `filesystem` resource is not supported on your OS yet.'
end
end
def info
return @cache if !@cache.nil?
return {} if @fsman.nil?
@cache = @fsman.info(@partition)
end
def to_s
"Filesystem #{partition}"
"FileSystem #{@partition}"
end
def size
info = @fsman.info(@partition)
info[:size]
end
def type
info = @fsman.info(@partition)
info[:type]
end
def name
info = @fsman.info(@partition)
info[:name]
end
end
class FsManagement
attr_reader :inspec
def initialize(inspec)
@inspec = inspec
end
end
class LinuxFileSystemResource < FsManagement
def info(partition)
cmd = inspec.command("df #{partition} --output=size")
raise Inspec::Exceptions::ResourceFailed, "Unable to get available space for partition #{partition}" if cmd.stdout.nil? || cmd.stdout.empty? || !cmd.exit_status.zero?
value = cmd.stdout.gsub(/\dK-blocks[\r\n]/, '').strip
{
name: partition,
size: value.to_i,
type: false,
}
end
end
class WindowsFileSystemResource < FsManagement
def info(partition)
cmd = inspec.command <<-EOF.gsub(/^\s*/, '')
$disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='#{partition}'"
$disk.Size = $disk.Size / 1GB
$disk | select -property DeviceID,Size,FileSystem | ConvertTo-Json
EOF
raise Inspec::Exceptions::ResourceSkipped, "Unable to get available space for partition #{partition}" if cmd.stdout == '' || cmd.exit_status.to_i != 0
begin
fs = JSON.parse(cmd.stdout)
rescue JSON::ParserError => e
raise Inspec::Exceptions::ResourceFailed,
'Failed to parse JSON from Powershell. ' \
"Error: #{e}"
end
{
name: fs['DeviceID'],
size: fs['Size'].to_i,
type: fs['FileSystem'],
}
end
end
end

View file

@ -547,6 +547,9 @@ class MockLoader
# alpine package commands
'apk info -vv --no-network | grep git' => cmd.call('apk-info-grep-git'),
# filesystem command
'2df93b941844efec1eee05c311cb4b4e8e3fd8b31808b785a70bd1a46298c716' => cmd.call('get-wmiobject-filesystem'),
}
# ports on linux

View file

@ -4,10 +4,11 @@ if ENV['DOCKER']
end
if os.windows?
STDERR.puts "\033[1;33mTODO: Not running #{__FILE__.split("/").last} because we are not on Linux.\033[0m"
return
describe filesystem('c:') do
its('size') { should be >= 1 }
end
else
describe filesystem('/') do
its('size') { should be >= 1 }
end
end
describe filesystem('/') do
its('size') { should be >= 1 }
end

View file

@ -0,0 +1,5 @@
{
"DeviceID": "c:",
"Size": "100",
"FileSystem": "NTFS"
}

View file

@ -2,27 +2,22 @@ require 'helper'
require 'inspec/resource'
describe 'Inspec::Resources::FileSystemResource' do
describe 'when loading filesystem in linux' do
let (:resource) { load_resource('filesystem', '/') }
it 'resolves the / partition' do
_(resource.partition).must_equal '/'
end
it 'has more than 1 MB' do
_(resource.size).must_be :>=, 1
end
it 'must equal 28252316 MB' do
_(resource.size).must_equal 28252316
end
# arch linux
it 'verify filesystem on linux' do
resource = MockLoader.new(:ubuntu1404).load_resource('filesystem','/')
_(resource.size).must_be :>=, 1
_(resource.name).must_equal '/'
end
# arch windows
it 'verify filesystem on windows' do
resource = MockLoader.new(:windows).load_resource('filesystem','c:')
_(resource.size).must_be :>=, 1
_(resource.name).must_equal 'c:'
end
describe 'when loading filesystem in unsupported OS family' do
it 'fails on Windows' do
resource_fail = MockLoader.new(:windows).load_resource('filesystem', '/')
resource_fail.check_supports.must_equal false
end
# unsuported os
describe 'when loading filesystem in unsupported OS family' do
it 'fails on FreeBSD (unix-like)' do
resource_fail = MockLoader.new(:freebsd10).load_resource('filesystem', '/')
resource_fail.check_supports.must_equal false