diff --git a/lib/facts/freebsd/os/release.rb b/lib/facts/freebsd/os/release.rb new file mode 100644 index 000000000..17e4aa213 --- /dev/null +++ b/lib/facts/freebsd/os/release.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +module Facts + module Freebsd + module Os + class Release + FACT_NAME = 'os.release' + ALIASES = %w[operatingsystemmajrelease operatingsystemrelease].freeze + + def call_the_resolver + installed_userland = Facter::Resolvers::Freebsd::FreebsdVersion.resolve(:installed_userland) + + return [] if installed_userland.nil? + + value = build_release_hash_from_version(installed_userland) + + [Facter::ResolvedFact.new(FACT_NAME, value), + Facter::ResolvedFact.new(ALIASES.first, value[:major], :legacy), + Facter::ResolvedFact.new(ALIASES.last, installed_userland, :legacy)] + end + + private + + def build_release_hash_from_version(version_string) + version, branch_value = version_string.split('-', 2) + major_value, minor_value = version.split('.') + patchlevel_value = branch_value.split('-p')[1] + + value = { + full: version_string, + major: major_value, + branch: branch_value + } + + value[:minor] = minor_value if minor_value + value[:patchlevel] = patchlevel_value if patchlevel_value + + value + end + end + end + end +end diff --git a/lib/framework/detector/os_detector.rb b/lib/framework/detector/os_detector.rb index 01a5baab5..391997998 100644 --- a/lib/framework/detector/os_detector.rb +++ b/lib/framework/detector/os_detector.rb @@ -24,6 +24,8 @@ def detect :macosx when /linux/ detect_distro + when /freebsd/ + :freebsd when /bsd/ :bsd when /solaris/ diff --git a/lib/resolvers/freebsd/freebsd_version_resolver.rb b/lib/resolvers/freebsd/freebsd_version_resolver.rb new file mode 100644 index 000000000..a9e891bb7 --- /dev/null +++ b/lib/resolvers/freebsd/freebsd_version_resolver.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +module Facter + module Resolvers + module Freebsd + class FreebsdVersion < BaseResolver + @semaphore = Mutex.new + @fact_list ||= {} + + class << self + private + + def post_resolve(fact_name) + @fact_list.fetch(fact_name) { freebsd_version_system_call(fact_name) } + end + + def freebsd_version_system_call(fact_name) + output, _stderr, status = Open3.capture3('/bin/freebsd-version -kru') + return nil unless status.success? + + build_fact_list(output) + + @fact_list[fact_name] + rescue Errno::ENOENT + nil + end + + def build_fact_list(output) + freebsd_version_results = output.split("\n") + + @fact_list[:installed_kernel] = freebsd_version_results[0].strip + @fact_list[:running_kernel] = freebsd_version_results[1].strip + @fact_list[:installed_userland] = freebsd_version_results[2].strip + end + end + end + end + end +end diff --git a/os_hierarchy.json b/os_hierarchy.json index 5fa482fc2..f304837de 100644 --- a/os_hierarchy.json +++ b/os_hierarchy.json @@ -25,7 +25,11 @@ }, { "Solaris": [ - "Bsd" + { + "Bsd": [ + "Freebsd" + ] + } ] }, "Macosx", diff --git a/spec/facter/facts/freebsd/os/release_spec.rb b/spec/facter/facts/freebsd/os/release_spec.rb new file mode 100644 index 000000000..11970d3dc --- /dev/null +++ b/spec/facter/facts/freebsd/os/release_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +describe Facts::Freebsd::Os::Release do + describe '#call_the_resolver' do + subject(:fact) { Facts::Freebsd::Os::Release.new } + + before do + allow(Facter::Resolvers::Freebsd::FreebsdVersion).to receive(:resolve).with(:installed_userland).and_return(value) + end + + context 'when FreeBSD RELEASE' do + let(:value) { '12.1-RELEASE-p3' } + + it 'calls Facter::Resolvers::Freebsd::FreebsdVersion' do + fact.call_the_resolver + expect(Facter::Resolvers::Freebsd::FreebsdVersion).to have_received(:resolve).with(:installed_userland) + end + + it 'returns release fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Array).and \ + contain_exactly(an_object_having_attributes(name: 'os.release', value: { 'full' => value, + 'major' => '12', + 'minor' => '1', + 'branch' => 'RELEASE-p3', + 'patchlevel' => '3' }), + an_object_having_attributes(name: 'operatingsystemmajrelease', value: '12', + type: :legacy), + an_object_having_attributes(name: 'operatingsystemrelease', value: value, type: :legacy)) + end + end + + context 'when FreeBSD STABLE' do + let(:value) { '12.1-STABLE' } + + it 'calls Facter::Resolvers::Freebsd::FreebsdVersion' do + fact.call_the_resolver + expect(Facter::Resolvers::Freebsd::FreebsdVersion).to have_received(:resolve).with(:installed_userland) + end + + it 'returns release fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Array).and \ + contain_exactly(an_object_having_attributes(name: 'os.release', value: { 'full' => value, + 'major' => '12', + 'minor' => '1', + 'branch' => 'STABLE' }), + an_object_having_attributes(name: 'operatingsystemmajrelease', value: '12', + type: :legacy), + an_object_having_attributes(name: 'operatingsystemrelease', value: value, type: :legacy)) + end + end + + context 'when FreeBSD CURRENT' do + let(:value) { '13-CURRENT' } + + it 'calls Facter::Resolvers::Freebsd::FreebsdVersion' do + fact.call_the_resolver + expect(Facter::Resolvers::Freebsd::FreebsdVersion).to have_received(:resolve).with(:installed_userland) + end + + it 'returns release fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Array).and \ + contain_exactly(an_object_having_attributes(name: 'os.release', value: { 'full' => value, + 'major' => '13', + 'branch' => 'CURRENT' }), + an_object_having_attributes(name: 'operatingsystemmajrelease', value: '13', + type: :legacy), + an_object_having_attributes(name: 'operatingsystemrelease', value: value, type: :legacy)) + end + end + end +end diff --git a/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb b/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb new file mode 100644 index 000000000..326fecac3 --- /dev/null +++ b/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +describe Facter::Resolvers::Freebsd::FreebsdVersion do + before do + status = instance_double('Process::Status') + allow(status).to receive(:success?).and_return(true) + allow(Open3).to receive(:capture3) + .with('/bin/freebsd-version -kru') + .and_return(['13.0-CURRENT + 12.1-RELEASE-p3 + 12.0-STABLE', nil, status]) + end + + it 'returns installed kernel' do + result = Facter::Resolvers::Freebsd::FreebsdVersion.resolve(:installed_kernel) + + expect(result).to eq('13.0-CURRENT') + end + + it 'returns running kernel' do + result = Facter::Resolvers::Freebsd::FreebsdVersion.resolve(:running_kernel) + + expect(result).to eq('12.1-RELEASE-p3') + end + + it 'returns installed userland' do + result = Facter::Resolvers::Freebsd::FreebsdVersion.resolve(:installed_userland) + + expect(result).to eq('12.0-STABLE') + end +end