diff --git a/.github/actions/presuite.rb b/.github/actions/presuite.rb index 71e9495fd..be7b4f730 100644 --- a/.github/actions/presuite.rb +++ b/.github/actions/presuite.rb @@ -53,7 +53,6 @@ def install_puppet_agent presuite_file_path = "#{beaker_puppet_root.chomp}/setup/aio/010_Install_Puppet_Agent.rb" run("beaker exec pre-suite --pre-suite #{presuite_file_path} --preserve-state", './', env_path_var) - # run("facter -v", puppet_bin_dir) end def puppet_bin_dir @@ -86,7 +85,6 @@ def replace_facter_3_with_facter_4 message('CHANGE FACTER 3 WITH FACTER 4') extension = (HOST_PLATFORM.include? 'windows') ? '.bat' : '' - run("mv facter#{extension} facter-old#{extension}", puppet_bin_dir) run("mv facter-ng#{extension} facter#{extension}", puppet_bin_dir) # run("facter -v", puppet_bin_dir) end @@ -106,7 +104,7 @@ def install_latest_facter_4(gem_command) def run_acceptance_tests message('RUN ACCEPTANCE TESTS') - run('beaker exec tests --test-tag-exclude=server,facter_3 --test-tag-or=risk:high,audit:high', './', env_path_var) + run('beaker exec tests', './', env_path_var) end def message(message) diff --git a/.github/workflows/acceptance_tests.yml b/.github/workflows/acceptance_tests.yml index e7268d75e..33e0a0dcd 100644 --- a/.github/workflows/acceptance_tests.yml +++ b/.github/workflows/acceptance_tests.yml @@ -14,7 +14,7 @@ jobs: name: Platform strategy: matrix: - os: [windows-2019] + os: [macos-10.15, ubuntu-16.04, ubuntu-18.04, ubuntu-20.04, windows-2016, windows-2019] runs-on: ${{ matrix.os }} env: FACTER_3_ROOT: facter_3 diff --git a/lib/facts/linux/is_virtual.rb b/lib/facts/linux/is_virtual.rb new file mode 100644 index 000000000..0d8e9322f --- /dev/null +++ b/lib/facts/linux/is_virtual.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module Facts + module Linux + class IsVirtual + FACT_NAME = 'is_virtual' + HYPERVISORS_HASH = { 'VMware' => 'vmware', 'VirtualBox' => 'virtualbox', 'Parallels' => 'parallels', + 'KVM' => 'kvm', 'Virtual Machine' => 'hyperv', 'RHEV Hypervisor' => 'rhev', + 'oVirt Node' => 'ovirt', 'HVM domU' => 'xenhvm', 'Bochs' => 'bochs', 'OpenBSD' => 'vmm', + 'BHYVE' => 'bhyve' }.freeze + PHYSICAL_HYPERVISORS = %w[physical xen0 vmware_server vmware_workstation openvzhn vserver_host].freeze + + def call_the_resolver # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity + fact_value = check_docker_lxc || check_gce || retrieve_from_virt_what || check_vmware + fact_value ||= check_open_vz || check_vserver || check_xen || check_other_facts || check_lspci || 'physical' + + Facter::ResolvedFact.new(FACT_NAME, check_if_virtual(fact_value)) + end + + def check_gce + bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor) + 'gce' if bios_vendor&.include?('Google') + end + + def check_docker_lxc + Facter::Resolvers::DockerLxc.resolve(:vm) + end + + def check_vmware + Facter::Resolvers::Vmware.resolve(:vm) + end + + def retrieve_from_virt_what + Facter::Resolvers::VirtWhat.resolve(:vm) + end + + def check_open_vz + Facter::Resolvers::OpenVz.resolve(:vm) + end + + def check_vserver + Facter::Resolvers::VirtWhat.resolve(:vserver) + end + + def check_xen + Facter::Resolvers::Xen.resolve(:vm) + end + + def check_other_facts + product_name = Facter::Resolvers::Linux::DmiBios.resolve(:product_name) + bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor) + return 'kvm' if bios_vendor&.include?('Amazon EC2') + return unless product_name + + HYPERVISORS_HASH.each { |key, value| return value if product_name.include?(key) } + end + + def check_lspci + Facter::Resolvers::Lspci.resolve(:vm) + end + + def check_if_virtual(found_vm) + PHYSICAL_HYPERVISORS.count(found_vm).zero? + end + end + end +end diff --git a/lib/facts/linux/virtual.rb b/lib/facts/linux/virtual.rb index e8632dba4..75d0d8f8a 100644 --- a/lib/facts/linux/virtual.rb +++ b/lib/facts/linux/virtual.rb @@ -4,9 +4,14 @@ module Facts module Linux class Virtual FACT_NAME = 'virtual' + HYPERVISORS_HASH = { 'VMware' => 'vmware', 'VirtualBox' => 'virtualbox', 'Parallels' => 'parallels', + 'KVM' => 'kvm', 'Virtual Machine' => 'hyperv', 'RHEV Hypervisor' => 'rhev', + 'oVirt Node' => 'ovirt', 'HVM domU' => 'xenhvm', 'Bochs' => 'bochs', 'OpenBSD' => 'vmm', + 'BHYVE' => 'bhyve' }.freeze - def call_the_resolver + def call_the_resolver # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity fact_value = check_docker_lxc || check_gce || retrieve_from_virt_what || check_vmware + fact_value ||= check_open_vz || check_vserver || check_xen || check_other_facts || check_lspci || 'physical' Facter::ResolvedFact.new(FACT_NAME, fact_value) end @@ -27,6 +32,31 @@ def check_vmware def retrieve_from_virt_what Facter::Resolvers::VirtWhat.resolve(:vm) end + + def check_open_vz + Facter::Resolvers::OpenVz.resolve(:vm) + end + + def check_vserver + Facter::Resolvers::VirtWhat.resolve(:vserver) + end + + def check_xen + Facter::Resolvers::Xen.resolve(:vm) + end + + def check_other_facts + product_name = Facter::Resolvers::Linux::DmiBios.resolve(:product_name) + bios_vendor = Facter::Resolvers::Linux::DmiBios.resolve(:bios_vendor) + return 'kvm' if bios_vendor&.include?('Amazon EC2') + return unless product_name + + HYPERVISORS_HASH.each { |key, value| return value if product_name.include?(key) } + end + + def check_lspci + Facter::Resolvers::Lspci.resolve(:vm) + end end end end diff --git a/lib/resolvers/lspci.rb b/lib/resolvers/lspci.rb new file mode 100644 index 000000000..5fe25999f --- /dev/null +++ b/lib/resolvers/lspci.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module Facter + module Resolvers + class Lspci < BaseResolver + @semaphore = Mutex.new + @fact_list ||= {} + + REGEX_VALUES = { 'VirtualBox' => 'virtualbox', 'XenSource' => 'xenhvm', + 'Microsoft Corporation Hyper-V' => 'hyperv', 'Class 8007: Google, Inc' => 'gce', + 'VM[wW]are' => 'vmware', '1ab8:' => 'parallels', '[Pp]arallels' => 'parallels', + '(?i)(virtio)' => 'kvm' }.freeze + + class << self + private + + def post_resolve(fact_name) + @fact_list.fetch(fact_name) { lspci_command(fact_name) } + end + + def lspci_command(fact_name) + output = Facter::Core::Execution.execute('lspci', logger: log) + return if output.empty? + + @fact_list[:vm] = retrieve_vm(output) + @fact_list[fact_name] + end + + def retrieve_vm(output) + output.each_line { |line| REGEX_VALUES.each { |key, value| return value if line =~ /#{key}/ } } + end + end + end + end +end diff --git a/lib/resolvers/open_vz.rb b/lib/resolvers/open_vz.rb new file mode 100644 index 000000000..b66465845 --- /dev/null +++ b/lib/resolvers/open_vz.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module Facter + module Resolvers + class OpenVz < BaseResolver + # build + + @semaphore = Mutex.new + @fact_list ||= {} + + class << self + private + + def post_resolve(fact_name) + @fact_list.fetch(fact_name) { check_proc_vz(fact_name) } + end + + def check_proc_vz(fact_name) + if !Dir.exist?('/proc/vz') || !File.executable?('/proc/lve/list') || Dir.entries('/proc/vz').count.equal?(2) + return + end + + @fact_list[:vm] = read_proc_status + @fact_list[fact_name] + end + + def read_proc_status + proc_status_content = Facter::Util::FileHelper.safe_readlines('/proc/self/status', nil) + return unless proc_status_content + + proc_status_content.each do |line| + parts = line.split("\s") + next unless parts.size.equal?(2) + + next unless /^envID:/ =~ parts[0] + + return 'openvzhn' if parts[1] == '0' + + return 'openvzve' + end + end + end + end + end +end diff --git a/lib/resolvers/xen.rb b/lib/resolvers/xen.rb new file mode 100644 index 000000000..3489b0d48 --- /dev/null +++ b/lib/resolvers/xen.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module Facter + module Resolvers + class Xen < BaseResolver + @semaphore = Mutex.new + @fact_list ||= {} + + class << self + private + + def post_resolve(fact_name) + @fact_list.fetch(fact_name) { chech_xen_dirs(fact_name) } + end + + def chech_xen_dirs(fact_name) + xen_type = 'xen0' if File.exist?('/dev/xen/evtchn') + xen_type = 'xenu' if !xen_type && (File.exist?('/proc/xen') || File.exist?('/dev/xvda1')) + + @fact_list[:vm] = xen_type + @fact_list[fact_name] + end + end + end + end +end diff --git a/spec/facter/facts/linux/is_virtual_spec.rb b/spec/facter/facts/linux/is_virtual_spec.rb new file mode 100644 index 000000000..c6568e76e --- /dev/null +++ b/spec/facter/facts/linux/is_virtual_spec.rb @@ -0,0 +1,161 @@ +# frozen_string_literal: true + +describe Facts::Linux::IsVirtual do + describe '#call_the_resolver' do + subject(:fact) { Facts::Linux::IsVirtual.new } + + let(:vm) { 'docker' } + let(:value) { true } + + before do + allow(Facter::Resolvers::DockerLxc).to \ + receive(:resolve).with(:vm).and_return(vm) + end + + it 'calls Facter::Resolvers::DockerLxc' do + fact.call_the_resolver + expect(Facter::Resolvers::DockerLxc).to have_received(:resolve).with(:vm) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + + context 'when is gce' do + let(:vm) { nil } + let(:value) { true } + + before do + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return('Google Engine') + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when is vmware' do + let(:vm) { nil } + let(:vmware_value) { 'vmware_fusion' } + let(:value) { true } + + before do + allow(Facter::Resolvers::Vmware).to receive(:resolve).with(:vm).and_return(vmware_value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when is xen-hvm' do + let(:vm) { nil } + let(:virtwhat_value) { 'xenhvm' } + let(:value) { true } + + before do + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil) + allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vm).and_return(virtwhat_value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when is openVz' do + let(:vm) { nil } + let(:openvz_value) { 'openvzve' } + let(:value) { true } + + before do + allow(Facter::Resolvers::OpenVz).to receive(:resolve).with(:vm).and_return(openvz_value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when is vserver' do + let(:vm) { nil } + let(:virtwhat_value) { 'vserver_host' } + let(:value) { false } + + before do + allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vm).and_return(nil) + allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vserver).and_return(virtwhat_value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when is xen priviledged' do + let(:vm) { nil } + let(:xen_value) { 'xen0' } + let(:value) { false } + + before do + allow(Facter::Resolvers::Xen).to receive(:resolve).with(:vm).and_return(xen_value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when is bochs discovered with dmi product_name' do + let(:vm) { nil } + let(:value) { true } + + before do + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil) + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:product_name).and_return('Bochs Machine') + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when is hyper-v discovered with lspci' do + let(:vm) { nil } + let(:lspci_value) { 'hyperv' } + let(:value) { true } + + before do + allow(Facter::Resolvers::Lspci).to receive(:resolve).with(:vm).and_return(lspci_value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: value) + end + end + + context 'when resolvers return nil ' do + let(:vm) { false } + + before do + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil) + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:product_name).and_return(nil) + allow(Facter::Resolvers::Lspci).to receive(:resolve).with(:vm).and_return(nil) + end + + it 'returns virtual fact as nil' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'is_virtual', value: vm) + end + end + end +end diff --git a/spec/facter/facts/linux/virtual_spec.rb b/spec/facter/facts/linux/virtual_spec.rb index 1cff2a194..e88005e28 100644 --- a/spec/facter/facts/linux/virtual_spec.rb +++ b/spec/facter/facts/linux/virtual_spec.rb @@ -64,11 +64,85 @@ end end - context 'when resolver returns nil' do + context 'when is openVz' do let(:vm) { nil } + let(:value) { 'openvzve' } + + before do + allow(Facter::Resolvers::OpenVz).to receive(:resolve).with(:vm).and_return(value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'virtual', value: value) + end + end + + context 'when is vserver' do + let(:vm) { nil } + let(:value) { 'vserver_host' } + + before do + allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vm).and_return(nil) + allow(Facter::Resolvers::VirtWhat).to receive(:resolve).with(:vserver).and_return(value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'virtual', value: value) + end + end + + context 'when is xen priviledged' do + let(:vm) { nil } + let(:value) { 'xen0' } + + before do + allow(Facter::Resolvers::Xen).to receive(:resolve).with(:vm).and_return(value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'virtual', value: value) + end + end + + context 'when is bochs discovered with dmi product_name' do + let(:vm) { nil } + let(:value) { 'bochs' } + + before do + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil) + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:product_name).and_return('Bochs Machine') + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'virtual', value: value) + end + end + + context 'when is hyper-v discovered with lspci' do + let(:vm) { nil } + let(:value) { 'hyperv' } + + before do + allow(Facter::Resolvers::Lspci).to receive(:resolve).with(:vm).and_return(value) + end + + it 'returns virtual fact' do + expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \ + have_attributes(name: 'virtual', value: value) + end + end + + context 'when resolvers return nil ' do + let(:vm) { 'physical' } before do allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:bios_vendor).and_return(nil) + allow(Facter::Resolvers::Linux::DmiBios).to receive(:resolve).with(:product_name).and_return(nil) + allow(Facter::Resolvers::Lspci).to receive(:resolve).with(:vm).and_return(nil) end it 'returns virtual fact as nil' do diff --git a/spec/facter/resolvers/lspci_spec.rb b/spec/facter/resolvers/lspci_spec.rb new file mode 100644 index 000000000..4a237da9a --- /dev/null +++ b/spec/facter/resolvers/lspci_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +describe Facter::Resolvers::Lspci do + subject(:lspci_resolver) { Facter::Resolvers::Lspci } + + let(:log_spy) { instance_spy(Facter::Log) } + + before do + lspci_resolver.instance_variable_set(:@log, log_spy) + allow(Facter::Core::Execution).to receive(:execute).with('lspci', logger: log_spy).and_return(output) + end + + after do + lspci_resolver.invalidate_cache + end + + context 'when lspci fails' do + let(:output) { '' } + + it 'returns nil' do + expect(lspci_resolver.resolve(:vm)).to be_nil + end + end + + context 'when lspci detects vmware' do + let(:output) { load_fixture('lspci_vmware').read } + + it 'returns hypervisor name' do + expect(lspci_resolver.resolve(:vm)).to eq('vmware') + end + end + + context 'when lspci detects xen' do + let(:output) { load_fixture('lspci_aws').read } + + it 'returns hypervisor name' do + expect(lspci_resolver.resolve(:vm)).to eq('xenhvm') + end + end +end diff --git a/spec/facter/resolvers/open_vz_spec.rb b/spec/facter/resolvers/open_vz_spec.rb new file mode 100644 index 000000000..f63a7fffe --- /dev/null +++ b/spec/facter/resolvers/open_vz_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +describe Facter::Resolvers::OpenVz do + subject(:openvz_resolver) { Facter::Resolvers::OpenVz } + + let(:vz_dir) { true } + let(:list_executable) { true } + + after do + openvz_resolver.invalidate_cache + end + + before do + allow(Dir).to receive(:exist?).with('/proc/vz').and_return(vz_dir) + allow(File).to receive(:executable?).with('/proc/lve/list').and_return(list_executable) + allow(Dir).to receive(:entries).with('/proc/vz').and_return(vz_dir_entries) + end + + context 'when /proc/vz dir is empty' do + let(:vz_dir_entries) { ['.', '..'] } + + it 'returns nil' do + expect(openvz_resolver.resolve(:vm)).to be_nil + end + end + + context 'when /proc/vz dir is not empty' do + let(:vz_dir_entries) { ['.', '..', 'some_file.txt'] } + + before do + allow(Facter::Util::FileHelper).to receive(:safe_readlines).with('/proc/self/status', nil).and_return(status_file) + end + + context 'when /proc/self/status is nil' do + let(:status_file) { nil } + + it 'returns nil' do + expect(openvz_resolver.resolve(:vm)).to be_nil + end + end + + context 'when /proc/self/status is readable' do + let(:status_file) { load_fixture('proc_self_status').readlines } + + it 'returns openvzhn' do + expect(openvz_resolver.resolve(:vm)).to eql('openvzhn') + end + end + end +end diff --git a/spec/facter/resolvers/vmware_spec.rb b/spec/facter/resolvers/vmware_spec.rb index d223e755c..11a6e6720 100644 --- a/spec/facter/resolvers/vmware_spec.rb +++ b/spec/facter/resolvers/vmware_spec.rb @@ -3,7 +3,7 @@ describe Facter::Resolvers::Vmware do subject(:vmware_resolver) { Facter::Resolvers::Vmware } - let(:log_spy) { Facter::Log } + let(:log_spy) { instance_spy(Facter::Log) } before do vmware_resolver.instance_variable_set(:@log, log_spy) diff --git a/spec/facter/resolvers/xen_spec.rb b/spec/facter/resolvers/xen_spec.rb new file mode 100644 index 000000000..e8366287f --- /dev/null +++ b/spec/facter/resolvers/xen_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +describe Facter::Resolvers::Xen do + subject(:xen_resolver) { Facter::Resolvers::Xen } + + let(:proc_xen_file) { false } + let(:xvda1_file) { false } + + before do + allow(File).to receive(:exist?).with('/dev/xen/evtchn').and_return(evtchn_file) + allow(File).to receive(:exist?).with('/proc/xen').and_return(proc_xen_file) + allow(File).to receive(:exist?).with('/dev/xvda1').and_return(xvda1_file) + xen_resolver.invalidate_cache + end + + context 'when is priviledged xen' do + let(:evtchn_file) { true } + + it 'returns xen0' do + expect(xen_resolver.resolve(:vm)).to eq('xen0') + end + + it 'does not check other files' do + expect(File).not_to have_received(:exist?).with('/proc/xen') + end + end + + context 'when is unpriviledged xen' do + let(:evtchn_file) { false } + let(:xvda1_file) { true } + + it 'returns xenu' do + expect(xen_resolver.resolve(:vm)).to eq('xenu') + end + end +end diff --git a/spec/fixtures/lspci_aws b/spec/fixtures/lspci_aws new file mode 100644 index 000000000..7601ef692 --- /dev/null +++ b/spec/fixtures/lspci_aws @@ -0,0 +1,3 @@ +00:00.0 Host bridge: Intel Corporation FX PMC [Natoma] (rev 02) +00:02.0 VGA compatible controller: Cirrus Logic GD 5446 +00:03.0 Unassigned class [ff80]: XenSource, Inc. Xen Platform Device (rev 01) \ No newline at end of file diff --git a/spec/fixtures/lspci_vmware b/spec/fixtures/lspci_vmware new file mode 100644 index 000000000..3c18fa755 --- /dev/null +++ b/spec/fixtures/lspci_vmware @@ -0,0 +1,6 @@ +00:10.0 SCSI storage controller: LSI Logic / Symbios Logic 53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI (rev 01) +00:11.0 PCI bridge: VMware PCI bridge (rev 02) +00:18.5 PCI bridge: VMware PCI Express Root Port (rev 01) +00:18.6 PCI bridge: VMware PCI Express Root Port (rev 01) +00:18.7 PCI bridge: VMware PCI Express Root Port (rev 01) +03:00.0 Ethernet controller: VMware VMXNET3 Ethernet Controller (rev 01) \ No newline at end of file diff --git a/spec/fixtures/proc_self_status b/spec/fixtures/proc_self_status index 329cbcc9e..a87efa8aa 100644 --- a/spec/fixtures/proc_self_status +++ b/spec/fixtures/proc_self_status @@ -13,5 +13,6 @@ Groups: 4 20 24 25 27 29 30 44 46 108 114 1000 NStgid: 14437 NSpid: 14437 NSpgid: 14437 +envID: 0 NSsid: 14122 VxID: 0 \ No newline at end of file