Skip to content
This repository was archived by the owner on Jun 19, 2020. It is now read-only.
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
18 changes: 18 additions & 0 deletions lib/facts/linux/hypervisors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module Facts
module Linux
class Hypervisors
FACT_NAME = 'hypervisors'

def call_the_resolver
fact_value = check_docker_lxc
Comment thread
BogdanIrimie marked this conversation as resolved.
Facter::ResolvedFact.new(FACT_NAME, fact_value)
end

def check_docker_lxc
Facter::Resolvers::DockerLxc.resolve(:hypervisor)
end
end
end
end
14 changes: 14 additions & 0 deletions lib/facts/linux/virtual.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

module Facts
module Linux
class Virtual
FACT_NAME = 'virtual'

def call_the_resolver
fact_value = Facter::Resolvers::DockerLxc.resolve(:vm)
Facter::ResolvedFact.new(FACT_NAME, fact_value)
end
end
end
end
49 changes: 49 additions & 0 deletions lib/resolvers/docker_lxc.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

module Facter
module Resolvers
class DockerLxc < BaseResolver
# :virtual
# :hypervisor

@semaphore = Mutex.new
@fact_list ||= {}
INFO = { 'docker' => 'id', 'lxc' => 'name' }.freeze

class << self
private

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

def read_cgroup(fact_name)
output_cgroup = Util::FileHelper.safe_read('/proc/1/cgroup', nil)
output_environ = Util::FileHelper.safe_read('/proc/1/environ', nil)
return if output_cgroup.nil? || output_environ.nil?

output_docker = %r{docker/(.+)}.match(output_cgroup)
output_lxc = %r{^/lxc/([^/]+)}.match(output_cgroup)
lxc_from_environ = /container=lxc/ =~ output_environ

info, vm = extract_vm_and_info(output_docker, output_lxc, lxc_from_environ)
@fact_list[:vm] = vm
@fact_list[:hypervisor] = { vm.to_sym => info } if vm
@fact_list[fact_name]
end

def extract_vm_and_info(output_docker, output_lxc, lxc_from_environ)
vm = nil
if output_docker
vm = 'docker'
info = output_docker[1]
end
vm = 'lxc' if output_lxc || lxc_from_environ
info = output_lxc[1] if output_lxc

[info ? { INFO[vm] => info } : {}, vm]
end
end
end
end
end
49 changes: 49 additions & 0 deletions spec/facter/facts/linux/hypervisors_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

describe Facts::Linux::Hypervisors do
describe '#call_the_resolver' do
subject(:fact) { Facts::Linux::Hypervisors.new }

before do
allow(Facter::Resolvers::DockerLxc).to \
receive(:resolve).with(:hypervisor).and_return(hv)
end

context 'when resolver returns docker' do
let(:hv) { { 'docker' => { 'id' => 'testid' } } }

it 'calls Facter::Resolvers::DockerLxc' do
fact.call_the_resolver
expect(Facter::Resolvers::DockerLxc).to have_received(:resolve).with(:hypervisor)
end

it 'returns virtual fact' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'hypervisors', value: hv)
end
end

context 'when resolver returns lxc' do
let(:hv) { { 'lxc' => { 'name' => 'test_name' } } }

it 'calls Facter::Resolvers::DockerLxc' do
fact.call_the_resolver
expect(Facter::Resolvers::DockerLxc).to have_received(:resolve).with(:hypervisor)
end

it 'returns virtual fact' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'hypervisors', value: hv)
end
end

context 'when resolver returns nil' do
let(:hv) { nil }

it 'returns virtual fact as nil' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'hypervisors', value: hv)
end
end
end
end
33 changes: 33 additions & 0 deletions spec/facter/facts/linux/virtual_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

describe Facts::Linux::Virtual do
describe '#call_the_resolver' do
subject(:fact) { Facts::Linux::Virtual.new }

let(:vm) { 'docker' }

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: 'virtual', value: vm)
end

context 'when resolver returns nil' do
let(:vm) { nil }

it 'returns virtual fact as nil' do
expect(fact.call_the_resolver).to be_an_instance_of(Facter::ResolvedFact).and \
have_attributes(name: 'virtual', value: vm)
end
end
end
end
74 changes: 74 additions & 0 deletions spec/facter/resolvers/docker_lxc_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# frozen_string_literal: true

describe Facter::Resolvers::DockerLxc do
subject(:docker_lxc_resolver) { Facter::Resolvers::DockerLxc }

before do
allow(Facter::Util::FileHelper).to receive(:safe_read)
.with('/proc/1/cgroup', nil)
.and_return(cgroup_output)
allow(Facter::Util::FileHelper).to receive(:safe_read)
.with('/proc/1/environ', nil)
.and_return(environ_output)
end

after do
docker_lxc_resolver.invalidate_cache
end

context 'when hypervisor is docker' do
let(:cgroup_output) { load_fixture('docker_cgroup').read }
let(:environ_output) { 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' }
let(:result) { { docker: { 'id' => 'ee6e3c05422f1273c9b41a26f2b4ec64bdb4480d63a1ad9741e05cafc1651b90' } } }

it 'return docker for vm' do
expect(docker_lxc_resolver.resolve(:vm)).to eq('docker')
end

it 'return docker info for hypervisor' do
expect(docker_lxc_resolver.resolve(:hypervisor)).to eq(result)
end
end

context 'when hypervisor is lxc and it is discovered by cgroup' do
let(:cgroup_output) { load_fixture('lxc_cgroup').read }
let(:environ_output) { 'PATH=/usr/local/sbin:/sbin:/bin' }
let(:result) { { lxc: { 'name' => 'lxc_container' } } }

it 'return lxc for vm' do
expect(docker_lxc_resolver.resolve(:vm)).to eq('lxc')
end

it 'return lxc info for hypervisor' do
expect(docker_lxc_resolver.resolve(:hypervisor)).to eq(result)
end
end

context 'when hypervisor is lxc and it is discovered by environ' do
let(:cgroup_output) { load_fixture('cgroup_file').read }
let(:environ_output) { 'container=lxcroot' }
let(:result) { { lxc: {} } }

it 'return lxc for vm' do
expect(docker_lxc_resolver.resolve(:vm)).to eq('lxc')
end

it 'return lxc info for hypervisor' do
expect(docker_lxc_resolver.resolve(:hypervisor)).to eq(result)
end
end

context 'when hypervisor is neighter lxc nor docker' do
let(:cgroup_output) { load_fixture('cgroup_file').read }
let(:environ_output) { 'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin' }
let(:result) { nil }

it 'return lxc for vm' do
expect(docker_lxc_resolver.resolve(:vm)).to eq(nil)
end

it 'return lxc info for hypervisor' do
expect(docker_lxc_resolver.resolve(:hypervisor)).to eq(result)
end
end
end
3 changes: 3 additions & 0 deletions spec/fixtures/cgroup_file
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
12:pids:/init.scope
11:cpu,cpuacct:/init.scope
10:rdma:/
3 changes: 3 additions & 0 deletions spec/fixtures/docker_cgroup
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
13:name=systemd:/docker/ee6e3c05422f1273c9b41a26f2b4ec64bdb4480d63a1ad9741e05cafc1651b90
12:pids:/docker/ee6e3c05422f1273c9b41a26f2b4ec64bdb4480d63a1ad9741e05cafc1651b90
11:hugetlb:/docker/ee6e3c05422f1273c9b41a26f2b4ec64bdb4480d63a1ad9741e05cafc1651b90
4 changes: 4 additions & 0 deletions spec/fixtures/lxc_cgroup
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
12:pids:/init.scope
11:cpu,cpuacct:/init.scope
10:rdma:/
/lxc/lxc_container/