Skip to content

Commit

Permalink
Merge pull request #257 from h0tw1r3/docker-dodo
Browse files Browse the repository at this point in the history
Cleanup docker support
  • Loading branch information
jordanbreen28 committed Feb 16, 2024
2 parents 00f0841 + 2c0ad58 commit d3b25f4
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 142 deletions.
55 changes: 55 additions & 0 deletions lib/docker_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# frozen_string_literal: true

require 'json'
require 'puppet_litmus'

def docker_exec(container, command)
run_local_command("docker exec #{container} #{command}")
end

def docker_image_os_release_facts(image)
os_release_facts = {}
begin
os_release = run_local_command("docker run --rm #{image} cat /etc/os-release")
# The or-release file is a newline-separated list of environment-like
# shell-compatible variable assignments.
re = '^(.+)=(.+)'
os_release.each_line do |line|
line = line.strip || line
next if line.nil? || line.empty?

_, key, value = line.match(re).to_a
# The values seems to be quoted most of the time, however debian only quotes
# some of the values :/. Parse it, as if it was a JSON string.
value = JSON.parse(value) unless value[0] != '"'
os_release_facts[key] = value
end
rescue StandardError
# fall through to parsing the id and version from the image if it doesn't have `/etc/os-release`
id, version_id = image.split(':')
id = id.sub(%r{/}, '_')
os_release_facts['ID'] = id
os_release_facts['VERSION_ID'] = version_id
end
os_release_facts
end

def docker_tear_down(node_name, inventory_location)
extend PuppetLitmus::InventoryManipulation
inventory_full_path = File.join(inventory_location, '/spec/fixtures/litmus_inventory.yaml')
raise "Unable to find '#{inventory_full_path}'" unless File.file?(inventory_full_path)

inventory_hash = inventory_hash_from_inventory_file(inventory_full_path)
node_facts = facts_from_node(inventory_hash, node_name)
remove_docker = "docker rm -f #{node_facts['container_id']}"
run_local_command(remove_docker)
remove_node(inventory_hash, node_name)
puts "Removed #{node_name}"
File.open(inventory_full_path, 'w') { |f| f.write inventory_hash.to_yaml }
{ status: 'ok' }
end

# Workaround for fixing the bash message in stderr when tty is missing
def docker_fix_missing_tty_error_message(container_id)
system("docker exec #{container_id} sed -i 's/^mesg n/tty -s \\&\\& mesg n/g' /root/.profile")
end
5 changes: 0 additions & 5 deletions lib/task_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,3 @@ def token_from_fogfile(provider = 'abs')
rescue StandardError
puts 'Failed to get token from .fog file'
end

# Workaround for fixing the bash message in stderr when tty is missing
def fix_missing_tty_error_message(container_id)
system("docker exec #{container_id} sed -i 's/^mesg n/tty -s \\&\\& mesg n/g' /root/.profile")
end
107 changes: 107 additions & 0 deletions spec/unit/docker_helper_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# frozen_string_literal: true

require 'docker_helper'
require 'stringio'

describe 'Docker Helper Functions' do
let(:container_id) { 'abc12345' }
let(:inventory_location) { '.' }
let(:full_inventory_location) { "#{inventory_location}/spec/fixtures/litmus_inventory.yaml" }
let(:inventory_yaml) do
<<-YAML
version: 2
groups:
- name: docker_nodes
targets:
- name: #{container_id}
uri: #{container_id}
config:
transport: docker
docker:
shell-command: bash -lc
connect-timeout: 120
facts:
provisioner: docker_exp
container_id: #{container_id}
platform: litmusimage/debian:12
os-release:
PRETTY_NAME: Debian GNU/Linux 12 (bookworm)
NAME: Debian GNU/Linux
VERSION_ID: '12'
VERSION: 12 (bookworm)
VERSION_CODENAME: bookworm
ID: debian
HOME_URL: https://www.debian.org/
SUPPORT_URL: https://www.debian.org/support
BUG_REPORT_URL: https://bugs.debian.org/
- name: ssh_nodes
targets: []
- name: winrm_nodes
targets: []
- name: lxd_nodes
targets: []
YAML
end

let(:os_release_facts) do
<<-FILE
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
FILE
end

describe '.docker_exec' do
it 'calls run_local_command' do
allow(self).to receive(:run_local_command).with("docker exec #{container_id} a command").and_return('some output')
expect(docker_exec(container_id, 'a command')).to eq('some output')
end
end

describe '.docker_image_os_release_facts' do
it 'returns parsed hash of /etc/os-release from container' do
allow(self).to receive(:run_local_command)
.with('docker run --rm litmusimage/debian:12 cat /etc/os-release')
.and_return(os_release_facts)
expect(docker_image_os_release_facts('litmusimage/debian:12')).to match(hash_including('PRETTY_NAME' => 'Debian GNU/Linux 12 (bookworm)'))
end

it 'returns minimal facts if parse fails for any reason' do
allow(self).to receive(:run_local_command)
.with('docker run --rm litmusimage/debian:12 cat /etc/os-release')
.and_return(StandardError)
expect(docker_image_os_release_facts('litmusimage/debian:12')).to match(hash_including('ID' => 'litmusimage_debian'))
end
end

describe '.docker_tear_down' do
it 'expect to raise error if inventory file is not found' do
allow(File).to receive(:file?).and_return(false)
expect { docker_tear_down(container_id, inventory_location) }.to raise_error(RuntimeError, "Unable to find '#{inventory_location}/spec/fixtures/litmus_inventory.yaml'")
end

it 'expect to return status ok' do
allow(File).to receive(:file?).with(full_inventory_location).and_return(true)
allow(File).to receive(:exist?).with(full_inventory_location).and_return(true)
allow(File).to receive(:open).with(full_inventory_location, anything).and_yield(StringIO.new(inventory_yaml.dup))
allow(self).to receive(:run_local_command).with("docker rm -f #{container_id}")
allow(self).to receive(:remove_node).and_return(nil)
expect {
expect(docker_tear_down(container_id, inventory_location)).to eql({ status: 'ok' })
}.to output("Removed #{container_id}\n").to_stdout
end
end

describe '.docker_fix_missing_tty_error_message' do
it 'execute command on container to disable mesg' do
allow(self).to receive(:system).with("docker exec #{container_id} sed -i 's/^mesg n/tty -s \\&\\& mesg n/g' /root/.profile")
expect(docker_fix_missing_tty_error_message(container_id)).to be_nil
end
end
end
3 changes: 2 additions & 1 deletion tasks/docker.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
}
},
"files": [
"provision/lib/task_helper.rb"
"provision/lib/task_helper.rb",
"provision/lib/docker_helper.rb"
]
}
Loading

0 comments on commit d3b25f4

Please sign in to comment.