From 5723eec6b94a1a30e5e7e0da878d5b2ee6ba672e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Mon, 20 Apr 2020 18:32:41 -1000 Subject: [PATCH 1/2] (maint) Add os.release facts on FreeBSD --- lib/facts/freebsd/os/release.rb | 41 +++++++++++ lib/framework/detector/os_detector.rb | 2 + .../freebsd/freebsd_version_resolver.rb | 36 ++++++++++ os_hierarchy.json | 6 +- spec/facter/facts/freebsd/os/release_spec.rb | 71 +++++++++++++++++++ .../freebsd/freebsd_version_resolver_spec.rb | 29 ++++++++ 6 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 lib/facts/freebsd/os/release.rb create mode 100644 lib/resolvers/freebsd/freebsd_version_resolver.rb create mode 100644 spec/facter/facts/freebsd/os/release_spec.rb create mode 100644 spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb diff --git a/lib/facts/freebsd/os/release.rb b/lib/facts/freebsd/os/release.rb new file mode 100644 index 000000000..2a04bb656 --- /dev/null +++ b/lib/facts/freebsd/os/release.rb @@ -0,0 +1,41 @@ +# 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) + + 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 1a1ad8fb1..621054626 100644 --- a/lib/framework/detector/os_detector.rb +++ b/lib/framework/detector/os_detector.rb @@ -23,6 +23,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..7b7e67b57 --- /dev/null +++ b/lib/resolvers/freebsd/freebsd_version_resolver.rb @@ -0,0 +1,36 @@ +# 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, _status = Open3.capture2('/bin/freebsd-version -kru') + + build_fact_list(output) + + @fact_list[fact_name] + 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 f8f523596..65fedfb90 100644 --- a/os_hierarchy.json +++ b/os_hierarchy.json @@ -24,7 +24,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..6c1ef16d8 --- /dev/null +++ b/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +describe Facter::Resolvers::Freebsd::FreebsdVersion do + before do + allow(Open3).to receive(:capture2) + .with('/bin/freebsd-version -kru') + .and_return('13.0-CURRENT + 12.1-RELEASE-p3 + 12.0-STABLE') + 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 From ca9c35e66d3fe7ddfd50e1a4e52b659d6b62dc54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Romain=20Tarti=C3=A8re?= Date: Thu, 30 Apr 2020 13:15:10 -1000 Subject: [PATCH 2/2] (maint) Improve freebsd-version failure management This program is always supposed to be found and return the expected output on FreeBSD but make sure it runs successfully, catpure stderr in case it becomes used at some point, and do not raise exceptions if the resolver fails. --- lib/facts/freebsd/os/release.rb | 2 ++ lib/resolvers/freebsd/freebsd_version_resolver.rb | 5 ++++- .../resolvers/freebsd/freebsd_version_resolver_spec.rb | 8 +++++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/facts/freebsd/os/release.rb b/lib/facts/freebsd/os/release.rb index 2a04bb656..17e4aa213 100644 --- a/lib/facts/freebsd/os/release.rb +++ b/lib/facts/freebsd/os/release.rb @@ -10,6 +10,8 @@ class Release 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), diff --git a/lib/resolvers/freebsd/freebsd_version_resolver.rb b/lib/resolvers/freebsd/freebsd_version_resolver.rb index 7b7e67b57..a9e891bb7 100644 --- a/lib/resolvers/freebsd/freebsd_version_resolver.rb +++ b/lib/resolvers/freebsd/freebsd_version_resolver.rb @@ -15,11 +15,14 @@ def post_resolve(fact_name) end def freebsd_version_system_call(fact_name) - output, _status = Open3.capture2('/bin/freebsd-version -kru') + 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) diff --git a/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb b/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb index 6c1ef16d8..326fecac3 100644 --- a/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb +++ b/spec/facter/resolvers/freebsd/freebsd_version_resolver_spec.rb @@ -2,11 +2,13 @@ describe Facter::Resolvers::Freebsd::FreebsdVersion do before do - allow(Open3).to receive(:capture2) + 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 + .and_return(['13.0-CURRENT 12.1-RELEASE-p3 - 12.0-STABLE') + 12.0-STABLE', nil, status]) end it 'returns installed kernel' do