Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(FACT-2809) Fixed output differences on solaris #2116

Merged
merged 1 commit into from
Oct 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/facter/facts/solaris/zones.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def call_the_resolver
end

resolved_facts << Facter::ResolvedFact.new('solaris_zones.zones', zones)
resolved_facts << Facter::ResolvedFact.new('zones', results.count.to_s, :legacy)
resolved_facts << Facter::ResolvedFact.new('zones', results.count, :legacy)

resolved_facts.flatten
end
Expand Down
7 changes: 5 additions & 2 deletions lib/facter/resolvers/mountpoints_resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class << self
private

def post_resolve(fact_name)
@fact_list.fetch(fact_name) { read_mounts }
@fact_list.fetch(fact_name) { read_mounts(fact_name) }
end

def root_device
Expand All @@ -26,7 +26,8 @@ def compute_device(device)
device
end

def read_mounts # rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
def read_mounts(fact_name)
mounts = []
FilesystemHelper.read_mountpoints.each do |fs|
device = compute_device(fs.name)
Expand All @@ -52,7 +53,9 @@ def read_mounts # rubocop:disable Metrics/AbcSize
.map { |v| binding.local_variable_get(v) })]
end
@fact_list[:mountpoints] = mounts
@fact_list[fact_name]
end
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
end
end
end
Expand Down
60 changes: 60 additions & 0 deletions lib/facter/resolvers/solaris/mountpoints.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true

module Facter
module Resolvers
module Solaris
class Mountpoints < BaseResolver
include Facter::FilesystemHelper
@fact_list ||= {}
@log = Facter::Log.new(self)
class << self
private

def post_resolve(fact_name)
@fact_list.fetch(fact_name) { read_mounts(fact_name) }
end

def root_device
cmdline = Util::FileHelper.safe_read('/proc/cmdline')
match = cmdline.match(/root=([^\s]+)/)
match&.captures&.first
end

def compute_device(device)
# If the "root" device, lookup the actual device from the kernel options
# This is done because not all systems symlink /dev/root
device = root_device if device == '/dev/root'
device
end

def read_mounts(fact_name) # rubocop:disable Metrics/AbcSize
mounts = []
FilesystemHelper.read_mountpoints.each do |fs|
device = compute_device(fs.name)
filesystem = fs.mount_type
path = fs.mount_point
options = fs.options.split(',').map(&:strip)

stats = FilesystemHelper.read_mountpoint_stats(path)
size_bytes = stats.bytes_total.abs
available_bytes = stats.bytes_available.abs

used_bytes = stats.bytes_used.abs
total_bytes = used_bytes + available_bytes
capacity = FilesystemHelper.compute_capacity(used_bytes, total_bytes)

size = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(size_bytes)
available = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(available_bytes)
used = Facter::FactsUtils::UnitConverter.bytes_to_human_readable(used_bytes)

mounts << Hash[FilesystemHelper::MOUNT_KEYS.zip(FilesystemHelper::MOUNT_KEYS
.map { |v| binding.local_variable_get(v) })]
end
@fact_list[:mountpoints] = mounts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should return @fact_list[fact_name]

@fact_list[fact_name]
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/facter/resolvers/solaris/networking.rb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def add_mtu(lifreq)

@log.debug("Error! #{::FFI::LastError.error}") if ioctl == -1

@interfaces[lifreq.name][:mtu] = lifreq[:lifr_lifru][:lifru_metric]
@interfaces[lifreq.name][:mtu] ||= lifreq[:lifr_lifru][:lifru_metric]
end

def load_netmask(lifreq)
Expand Down
2 changes: 1 addition & 1 deletion spec/facter/facts/solaris/zones_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
an_object_having_attributes(name: 'zone_global_status', value: result[:status], type: :legacy),
an_object_having_attributes(name: 'zone_global_brand', value: result[:brand], type: :legacy),
an_object_having_attributes(name: 'zone_global_iptype', value: result[:iptype], type: :legacy),
an_object_having_attributes(name: 'zones', value: '1', type: :legacy)
an_object_having_attributes(name: 'zones', value: 1, type: :legacy)
)
end
end
Expand Down
6 changes: 6 additions & 0 deletions spec/facter/resolvers/mountpoints_resolver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,10 @@
end
end
end

describe 'resolver key not found' do
it 'returns nil when resolver cannot find key' do
expect(Facter::Resolvers::Mountpoints.resolve(:inexistent_key)).to be_nil
end
end
end
115 changes: 115 additions & 0 deletions spec/facter/resolvers/solaris/mountpoints_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# frozen_string_literal: true

describe Facter::Resolvers::Solaris::Mountpoints do
let(:resolver) { Facter::Resolvers::Solaris::Mountpoints }
let(:mount) do
class_double(Sys::Filesystem::Mount,
mount_point: '/', mount_time: nil,
mount_type: 'ext4', options: 'rw,noatime', name:
'/dev/nvme0n1p2', dump_frequency: 0, pass_number: 0)
end

let(:stat) do
class_double(Sys::Filesystem::Stat,
path: '/', base_type: nil, fragment_size: 4096, block_size: 4096, blocks: 113_879_332,
blocks_available: -16_596_603, blocks_free: 22_398_776)
end

let(:fact) do
[{ available: '63.31 GiB',
available_bytes: 67_979_685_888,
capacity: '84.64%',
device: '/dev/nvme0n1p2',
filesystem: 'ext4',
options: %w[rw noatime],
path: '/',
size: '434.42 GiB',
size_bytes: 466_449_743_872,
used: '348.97 GiB',
used_bytes: 374_704_357_376 }]
end

let(:ignored_mount1) do
[
class_double(
Sys::Filesystem::Mount, mount_type: 'zfs', mount_point: '/system/', name: '/dev/ignore', options: 'rw'
)
]
end

let(:ignored_mount2) do
[
class_double(
Sys::Filesystem::Mount, mount_type: 'autofs', mount_point: '/mnt/auto', name: '/dev/ignore', options: 'rw'
)
]
end

before do
allow(Facter::Util::FileHelper).to receive(:safe_read)
.with('/proc/cmdline')
.and_return(load_fixture('cmdline_root_device').read)

allow(Facter::FilesystemHelper).to receive(:read_mountpoints).and_return([mount])
allow(Facter::FilesystemHelper).to receive(:read_mountpoint_stats).and_return(stat)

# mock sys/filesystem methods
allow(stat).to receive(:bytes_total).and_return(stat.blocks * stat.fragment_size)
allow(stat).to receive(:bytes_available).and_return(stat.blocks_available * stat.fragment_size)
allow(stat).to receive(:bytes_free).and_return(stat.blocks_free * stat.fragment_size)
allow(stat).to receive(:bytes_used).and_return(stat.bytes_total - stat.bytes_free)
resolver.invalidate_cache
end

it 'correctly builds the mountpoints fact' do
result = resolver.resolve(:mountpoints)

expect(result).to eq(fact)
end

it 'does not drop non-tmpfs mounts under /proc or /sys' do
allow(Facter::FilesystemHelper).to receive(:read_mountpoints).and_return(ignored_mount1)

resolver.resolve(:mountpoints)
expect(Facter::FilesystemHelper).to have_received(:read_mountpoint_stats).with('/system/')
end

it 'does not drop automounts mounts under /proc or /sys' do
allow(Facter::FilesystemHelper).to receive(:read_mountpoints).and_return(ignored_mount2)

resolver.resolve(:mountpoints)
expect(Facter::FilesystemHelper).to have_received(:read_mountpoint_stats).with('/mnt/auto')
end

describe '.root_device' do
let(:mount) do
class_double(
Sys::Filesystem::Mount, mount_point: '/', mount_type: 'ext4', options: 'rw,noatime', name: '/dev/root'
)
end

it 'looks up the actual device if /dev/root' do
result = resolver.resolve(:mountpoints)
expect(result.first[:device]).to eq('/dev/mmcblk0p2')
end

context 'when /proc/cmdline is not accessible' do
before do
allow(Facter::Util::FileHelper).to receive(:safe_read)
.with('/proc/cmdline')
.and_return('')
end

it 'returns device as nil' do
result = resolver.resolve(:mountpoints)
expect(result.first[:device]).to be(nil)
end
end
end

describe 'resolver key not found' do
it 'returns nil when resolver cannot find key' do
expect(resolver.resolve(:inexistent_key)).to be_nil
end
end
end
41 changes: 39 additions & 2 deletions spec/mocks/sys_filesystem_mock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,44 @@ module Sys
class Filesystem
def self.mounts; end

class Mount; end
class Stat; end
class Mount
def self.mount_point; end

def self.mount_type; end

def self.options; end

def self.mount_time; end

def self.name; end

def self.dump_frequency; end

def self.pass_number; end
end

class Stat
def self.path; end

def self.base_type; end

def self.fragment_size; end

def self.block_size; end

def self.blocks; end

def self.blocks_available; end

def self.blocks_free; end

def self.bytes_total; end

def self.bytes_available; end

def self.bytes_free; end

def self.bytes_used; end
end
end
end